yon11b

[DH] csrf-2 본문

보안/WRITE_UP

[DH] csrf-2

yon11b 2022. 5. 19. 23:17
반응형

코드 분석 전

script 문자열 자체를 *로 바꾼다.

나름 우회해 보려고 scrscripipt 사용했지만 실패

on도 *로 바꾼다

onerror인데*error가 됨

코드 분석

@app.route("/vuln")
def vuln():
    param = request.args.get("param", "").lower()
    xss_filter = ["frame", "script", "on"]
    for _ in xss_filter:
        param = param.replace(_, "*")
    return param

[필터링 되는 것들] (못 쓰는 거)

  • script
  • ScriPT
  • img src=z onerror

이런 건 안 되지만 잘 우회하면 js도 실행이 될 것 같다.

이걸 제외하고 쓸 수 있는 우회 기법은 아래와 같다. csrf-1에서 썼던 방법이다.

<img src="/admin/notice_flag?userid=admin">

이제 어디에서 무엇을 알아내야 할지를 보자.

users 정보이다. 계정은 guest, admin 두 가지가 있고, guest는 pw까지 나와 있다.

users = {
 'guest': 'guest',
'admin': FLAG
}
@app.route("/")
def index():
    session_id = request.cookies.get('sessionid', None)
    try:
        username = session_storage[session_id]
    except KeyError:
        return render_template('index.html', text='please login')

    return render_template('index.html', text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not an admin"}')

session에 저장된 값이 admin 이면 flag가 출력된다.

그렇다면 어떻게 session에 admin값이 들어오게 할 수 있을까?

로그인을 admin으로 하면 될 것이다.

지금 우리는 admin 의 pw를 모른다.

그러므로 우리가 지금 구해야 하는 것은 admin의 pw가 될 것이다.

@app.route("/change_password")
def change_password():
    pw = request.args.get("pw", "")
    session_id = request.cookies.get('sessionid', None)
    try:
        username = session_storage[session_id]
    except KeyError:
        return render_template('index.html', text='please login')

    users[username] = pw
    return 'Done'

물론 다른 방법도 있지만 /change_password가 있는 것으로 봐서 pw를 바꿔야 하는 것 같다.

pw를 파라미터로 받고 session을 요청한다.

그리고 username을 session에서 가져오고 session이 없다면 keyerror를 발생하고 종료하고

session이 있으면 users[username]에 pw를 집어넣는다.

 

가져올 session이 있어야 오류가 안 난다.

그렇다면 admin의 session이 생성되는 곳이 분명히 있을 것이다.

@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", "")
        session_id = os.urandom(16).hex() # 세션 생성
        session_storage[session_id] = 'admin'
        if not check_csrf(param, {"name":"sessionid", "value": session_id}):
            return '<script>alert("wrong??");history.go(-1);</script>'

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

/flag에서 post로 param를 받으면 admin의 session_id가 생성된다.

check_csrf 함수에서는 param과 cookie를 read_url로 전달한다.

url은 /vuln으로 보낸다.

def check_csrf(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)

정리

  • /flag에서 post로 전달하면 admin의 session이 생김
  • /change_password에서 pw를 파라미터로 전달하면 session을 요청하고 응답받은 session값의 pw를 바꾼 pw로 변경한다.
    • 응답받은 session값이 admin이면, admin의 pw를 지정할 수 있는 것이다.
  • session 값이 admin이면 (admin으로 로그인하면) flag가 뜬다

해야할 일

  • /flag에서 post로 /change_password?pw=test로 하고
  • /login 페이지에서 admin, test로 로그인한다.

핵심

http://127.0.0.1:8000/vuln?param=<img src="/change_password?pw=test">

야호

728x90

'보안 > WRITE_UP' 카테고리의 다른 글

[DH] simple-ssti  (0) 2022.07.28
[DH] Mango  (0) 2022.07.28
[webhacking.kr] old-25  (0) 2022.05.19
[webhacking.kr] g00gle2  (1) 2022.05.19
[webhacking.kr] g00gle1  (1) 2022.05.19