본문 바로가기

드림핵

[드림핵 워게임] csrf-2

https://dreamhack.io/wargame/challenges/269/

위의 문제를 다음과 같은 과정으로 풀어보았다.

 

 

1. 소스코드를 살펴보면 총 5개의 엔드포인트를 확인할 수 있다.

 

(1) 인덱스( / )

@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"}')

맨 마지막 줄에서 username이 admin인 경우에 flag를 출력하는 코드를 확인할 수 있다.

 

(2) /vuln

@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

xss_filter로 xss 공격에 쓰일 수 있는 3개의 키워드를 *로 대체함으로써 xss 공격에 대한 방어를 하고 있는 것을 확인할 수 있지만, 최종적으로 param 파라미터를 그대로 return 하고 있어 3개의 키워드에 포함되지 않는 코드를 활용한 공격에 대애서는 취약점을 갖고 있음을 알 수 있다.

 

(3) /flag

@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 에서는 GET과 POST 두가지 메소드에 대한 동작을 하고 있는데, 인덱스 페이지에서 login페이지의 링크를 타고 접속하면 GET으로 페이지가 요청되어 flag.html을 렌더링하여 보여주고, flag.html에서 url 값을 입력하여 제출하면 POST로 요청되어 session_id를 랜덤으로 생성하고 check_csrf() 함수를 실행하는 동작을 하는 것을 볼 수 있다.

 

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)

check_csrf() 함수에서는 param 파라미터로 전달받은 flag페이지에서의 입력값을 이용해 url을 생성하여 read_url() 함수를 통해 url을 방문하는 것을 확인할 수 있다. 이때 url은 취약점이 있는 vuln 페이지를 요청하고 있기 때문에 flag페이지에서 param 파라미터에 값을 입력할 때 익스플로잇 코드를 입력하면 vuln 페이지에 있는 취약점을 이용해 해당 코드를 실행시킬 수 있을 것이다.

 

(4) /login

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    elif request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        try:
            pw = users[username]
        except:
            return '<script>alert("not found user");history.go(-1);</script>'
        if pw == password:
            resp = make_response(redirect(url_for('index')) )
            session_id = os.urandom(8).hex()
            session_storage[session_id] = username
            resp.set_cookie('sessionid', session_id)
            return resp 
        return '<script>alert("wrong password");history.go(-1);</script>'

/login 에서도 /flag와 마찬가지로 GET, POST 두가지 메소드에 대한 동작을 하는데, GET으로 요청하여 렌더링된 페이지에 username, password를 올바르게 입력하여 로그인하면 index 페이지로 이동한다.

 

(5) /change_password

@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'
    
    
    
users = {
    'guest': 'guest',
    'admin': FLAG
}

/change_password에서는 사용자가 pw 파라미터로 입력한 값으로 users 딕셔너리 변수의 패스워드를 설정한다.

 

 

 

2. flag 페이지에서 익스플로잇 코드를 입력하여 제출한다.

flag 페이지의 url은 vuln 페이지를 요청하고 있다. 그러므로 /vuln에서 차단하고 있는 frame, script, on 키워드를 피해 img 태그를 활용하여 csrf 공격을 시도할 것이다. /change_password에 접속하여 admin 계정의 비밀번호를 'aa'로 지정하여 admin 계정을 탈취할 것이다.

<img src="/change_password?pw=aa">

 

위의 코드를 flag 페이지의 url 입력란에 작성하여 제출한다.

 

 

 

3. login 페이지에서 'username : admin, password : 설정한 pw'로 로그인한다.

username은 admin, password는 앞서 설정한 aa로 하여 로그인한다.

 

 

 

4. 인덱스 페이지에서 flag를 확인할 수 있다.

'드림핵' 카테고리의 다른 글

[드림핵 워게임] Mango  (0) 2022.10.01
[드림핵 워게임] simple-sqli  (1) 2022.09.24
[드림핵 워게임] csrf-1  (1) 2022.09.23
[드림핵 워게임] xss-2  (1) 2022.09.21
[드림핵 워게임] xss-1  (1) 2022.09.21