> For the complete documentation index, see [llms.txt](https://docs.cooku222.kr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cooku222.kr/security/web-hacking/dreamhack/dreamhack-session.md).

# \[Dreamhack] session

#### 문제&#x20;

<figure><img src="https://blog.kakaocdn.net/dna/48tYc/btsM22pIaYO/AAAAAAAAAAAAAAAAAAAAANkUPygStPm0y4M_r2bmwBUdaccAcYYv8gfAtwwoN-9L/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=GM7q3Yg3LbU1Y7A03U8EvHTl1qU%3D" alt="" height="740" width="1596"><figcaption></figcaption></figure>

#### 문제 링크

<https://dreamhack.io/wargame/challenges/266>

[ session쿠키와 세션으로 인증 상태를 관리하는 간단한 로그인 서비스입니다. admin 계정으로 로그인에 성공하면 플래그를 획득할 수 있습니다. Reference Background: Cookie & Sessiondreamhack.io](https://dreamhack.io/wargame/challenges/266)

&#x20;

***

<figure><img src="https://blog.kakaocdn.net/dna/pTB8k/btsM4dRpDxy/AAAAAAAAAAAAAAAAAAAAAFVZV591oPt5xKiP39USnVF-boVo0rx-HMmyExfxAAp4/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=hJt3WwKczCxYogFzGR4ZTNdiR84%3D" alt="" height="278" width="1533"><figcaption></figcaption></figure>

페이지에 접속하면 간단한 로그인 기능만 있는 화면이 나온다.&#x20;

<figure><img src="https://blog.kakaocdn.net/dna/b89TXc/btsM1Loxo1O/AAAAAAAAAAAAAAAAAAAAAFu5Br2rvGRMyY9ebqNq48gHoLMQXRCuxFGuERgxTdK3/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=GZEreQbaV9ow0BaJRfuOQPiho2w%3D" alt="" height="618" width="1511"><figcaption></figcaption></figure>

드림핵 문제에서 이런거 보면 보통 guest 권한이나 admin 권한에 차이를 두어 admin에서 flag를 얻을 수 있게 해놓기도 한다. 관련 소스코드도 문제에서 제공을 해주니, 압축 해제후 vscode로 열어본다.

```
users = {
    'guest': 'guest',
    'user': 'user1234',
    'admin': FLAG
}
```

코드 세부사항을 확인해보니 계정이 세 개 존재한다.\
아이디가 guest인 경우, 비밀번호가 guest

<figure><img src="https://blog.kakaocdn.net/dna/QXqga/btsM3VcrWfg/AAAAAAAAAAAAAAAAAAAAAMafa0dws2VfGhoJGeyLewS6xK9TGxkV_SaeLowVPJpv/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=VxtEBlsrb5S6c%2FnEvAOfq%2FxYXnI%3D" alt="" height="437" width="1242"><figcaption></figcaption></figure>

<figure><img src="https://blog.kakaocdn.net/dna/ctZg7d/btsM4nl7Nlr/AAAAAAAAAAAAAAAAAAAAADMHBeRLV5I9fHI5T66KOmwPFf9gXL7kv6B8GrkG29PN/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=N55L46UPMW9%2BnHyawBF3Rosy0oM%3D" alt="" height="370" width="985"><figcaption></figcaption></figure>

아마 user로 로그인하게 되면 비밀번호는 user1234일 것이고, 다른 화면이 뜨거나 권한이 다를 것이다.

<figure><img src="https://blog.kakaocdn.net/dna/AakUR/btsM11ryXBO/AAAAAAAAAAAAAAAAAAAAAEk1ty5GY756OJqFNkbYWrLK0ZtbvAtGx6R5fuoQxALn/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=Cz1yRwzUgc1xtYrOaKQ5FEfuFkE%3D" alt="" height="461" width="1282"><figcaption></figcaption></figure>

<figure><img src="https://blog.kakaocdn.net/dna/bptEn8/btsM399k8dm/AAAAAAAAAAAAAAAAAAAAAC-iMNvY4uBKf-FO8C3lXjEmreFy81d0BU0D2jttBPyd/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=YNa8mMA5sqxCXy8MwFpVEIhbcRM%3D" alt="" height="482" width="1043"><figcaption></figcaption></figure>

역시나… 근데 솔직히 권한이 무슨 차이가 있는진 모르지만 로그인의 힌트가 될 수는 있겠다\~ 정도\
user와 guest 차이를 재차 확인하기 위해 소스코드로 돌아가서 분석해본다.

<figure><img src="https://blog.kakaocdn.net/dna/ldhrM/btsM11E6ZRM/AAAAAAAAAAAAAAAAAAAAALYCrcRRoYcwhgoQCjGQf0oAFDOn-ZrXBuCjNyEW4ZNE/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=ZB%2Bv8G%2F3r77RQjp%2FOAZnphhhAVY%3D" alt="" height="590" width="867"><figcaption></figcaption></figure>

-> user가 되었든 guest가 되었든 예상한대로 admin 계정의 권한을 얻는게 최종 목적

```
if __name__ == '__main__':
    import os
    session_storage[os.urandom(1).hex()] = 'admin'
    print(session_storage)
    app.run(host='0.0.0.0', port=8000)
```

이 부분이 핵심인데 하나씩 뜯어보자면

```
session_storage[os.urandom(1).hex()] = 'admin'
```

-> 1바이트 랜덤 바이트를 형성하는데 (os.urandom(1)) -> hex()적용 -> 16진수 -> 총 256가지(hex자체가 2자리 16진수가 기본값이라고 이해하면 되는 거 같다)\
-> 랜덤값 : 일정한 패턴이 없는 값이며, 자릿수가 한정되어있다.\
-> 브루트포스 기법을 사용한다.\
브루트포스란?\
: 가능한 모든 경우의 수를 하나하나 대입하는 공격(여기선 한땀한땀 대입할 수 없으니.. burp suite 툴을 사용한다.)\
-> 자릿수가 너무 크면 브루트포스도 오래걸린다. 경우의 수가 제곱으로 정말 높아지기 때문에, 이렇게 2자리 한정적인 경우에 사용하기 좋은 기법이다.\
&#x20;

<figure><img src="https://blog.kakaocdn.net/dna/bFqlh9/btsM2vZQVHV/AAAAAAAAAAAAAAAAAAAAABjY_ZNqqXmUbS3ja4gNksWyxttUWuSjBEitcFngfyS5/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=uvkOkxY00Mm1ulgRpEZQRBeTEeU%3D" alt="" height="1023" width="1919"><figcaption><p>[main]-[Proxy]-[Intercept]-[Intercept on]-[Open browser]</p></figcaption></figure>

\*아 참고로 초반에 설정을 제대로 안 해주면 수동으로 ctrl+T를 눌러 프록시 설정을 끄고 브라우저 주소를 복사 붙여넣기 해서 열어야 하는데 귀찮아지니... 설정 단계를 꼼꼼하게 거친다.

<figure><img src="https://blog.kakaocdn.net/dna/rO0wz/btsM3TFGTe3/AAAAAAAAAAAAAAAAAAAAAPHXitw9wbDOyXB46GvnUXRuKbSe7iu7SnWq4E6Ni7Tg/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=Scb0d6UJCicJWLgY9VsucmomzO4%3D" alt="" height="998" width="1912"><figcaption></figcaption></figure>

정상적으로 설치를 마쳤으면, 브라우저가 새로 열리면서 포트스위거(버프스위트 제작사) 마크가 좌측 상단에 뜨고, 크롬과 비슷한 UI?의 화면이 나온다. 여기에 기존 화면의 도메인 주소를 복사 붙여넣기 한다.

<figure><img src="https://blog.kakaocdn.net/dna/sAK0T/btsM2Zl5cK1/AAAAAAAAAAAAAAAAAAAAAFauLznJ3oO23Ist6LOg8zN1deoG1bXlqlgFvnGKaoPR/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=CuzwgwEuq8VMvXbwllCKF4LnsyY%3D" alt="" height="1020" width="1919"><figcaption><p>[Proxy]-[Http history]-제 로컬 기준 15행</p></figcaption></figure>

여기서 왜 15행을 봐야하냐 할 수 있는데 다시 문제에서 주어진 소스코드로 롤백을 해보자.

```
@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(4).hex()
            session_storage[session_id] = username
            resp.set_cookie('sessionid', session_id)
            return resp 
        return '<script>alert("wrong password");history.go(-1);</script>'
```

해당 코드 중

```
        if pw == password:
            resp = make_response(redirect(url_for('index')) )
            session_id = os.urandom(4).hex()
            session_storage[session_id] = username
            resp.set_cookie('sessionid', session_id)
            return resp 
        return '<script>alert("wrong password");history.go(-1);</script>'
```

메커니즘이 세션 ID 생성 → 저장소에 등록 → 쿠키로 클라이언트에 전달 → index 페이지로 리다이렉트\~로 동작한다.\
다시 처음으로 돌아가서,&#x20;

<figure><img src="https://blog.kakaocdn.net/dna/baWVIE/btsM2WQvjsy/AAAAAAAAAAAAAAAAAAAAAOub3TgYINI3cD1f_87QDXyin1JvBz0biKxSQ1EJ3mpJ/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=arxXh6lOvo6A7v4nOCz55wZbqH8%3D" alt="" height="370" width="985"><figcaption></figcaption></figure>

이 화면에 리다이렉트 된다는 건데 이 화면 탭 이름이 index Session이다.&#x20;

<figure><img src="https://blog.kakaocdn.net/dna/bkFZSv/btsM3EhEMR7/AAAAAAAAAAAAAAAAAAAAAI87thsMJMKEd3KrjY9mIMyjL3x1K2Ok93pKQBxm6mBQ/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=FtP0GMzT0CArhH6GdCUY7%2FOfi70%3D" alt="" height="51" width="178"><figcaption></figcaption></figure>

해당 코드의 내용에 따라 index Session title이 있는 로그를 확인해보면 플래그의 단서가 있지 않을까\~하고 유추해본다.

<figure><img src="https://blog.kakaocdn.net/dna/bAe9h1/btsM1buvPXH/AAAAAAAAAAAAAAAAAAAAAPYJFWOmW35Y6EpOUe55qetDL_Rx3p_ekTtMLQlef0ZJ/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=W%2BZCNDZ5hKJYicsnvADrhWDW5C8%3D" alt="" height="1020" width="1919"><figcaption></figcaption></figure>

다시 돌아와서 15행의 request를 intruder로 보낸다. \
마우스 우클릭하면 send to Intruder가 뜬다.\
Q. intruder를 사용하는 이유와 그 원리?\
A. 이걸 제대로 이해하려면 또 앞에 언급한 소스코드를 까봐야하는데...

```
session_storage[os.urandom(1).hex()] = 'admin'
```

session\_storage\[...] = 'admin'\
-> 세션 스토리지에 랜덤값을 넣어서 admin을 생성\
-> 랜덤 키값을 가진 admin 세션이 존재하는데 이를 탈취하기 위해서 intruder를 이용해 brute force 공격을 시행하면 플래그 값을 구할 수 있다고 추론 가능

<figure><img src="https://blog.kakaocdn.net/dna/c5AjWX/btsM1RvYRkJ/AAAAAAAAAAAAAAAAAAAAALVuvPPlcaZfuSSBcj13pBmynburM63kZPz0cvvgdv9J/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=Up5hEKvFax3JeXdYoiBjSwda%2BY4%3D" alt="" height="1014" width="1917"><figcaption></figcaption></figure>

\[intruder]가 주황색으로 변하는데 창이 아마 두번째로 기준이 잡힐 것이다(좌측 상단에 보면 숫자에 따라 창의 순번이 표시되는데, 현재 표시창 기준이 맞을 것이다. \
2자릿수 16진수라 했으니까 a\~f, 0\~9로 설정한다. Min Length, Max Length 각각 2로 설정(어차피 2자릿수에서 변동이 없다. 이것도 소스코드에 나온 os.urandom(1).hex()에서 근거를 얻을 수 있음.)\
Payload Position이 설정이 안 되는 경우도 있는데, sessionid = "", "" 구간을 한번 블록 처리하고 로우 데이터 위쪽에 add $ 버튼을 눌러보자. 아마 All Payloads positions되면서 start attack 누르면 잘 작동할 것이다.\
+)

<figure><img src="https://blog.kakaocdn.net/dna/otqjI/btsM3lCGzL5/AAAAAAAAAAAAAAAAAAAAAHBi7wtKLaeB4zZy-DqZnvDYROJFt-oY5s1UEz9bijSL/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=kvPuPAmp2FRfuVg9DQLoztA%2FEms%3D" alt="" height="1012" width="1919"><figcaption></figcaption></figure>

F12 개발자도구를 열어 application -> cookies를 확인하면 guest로 입력한 화면에 뜨는 sessionid를 확인해준다. 이 sessionid와 일치하는 창이면 올바르게 뜬 것이다(이거 캡쳐 시기에는 로그인 시간이 달라서 다르게 뜨는거라;;; 같은지 대략 확인해보면 된다)\
&#x20;\
다시 돌아와서

<figure><img src="https://blog.kakaocdn.net/dna/PRq49/btsM2vMnfxe/AAAAAAAAAAAAAAAAAAAAAJOr5l8VIFvpEUKMvjrWLeXZHyNkE-G8pB5vefO4piYF/img.jpg?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=oBgOEKfKVZUGRF%2FC4DLCF1BOpLE%3D" alt="" height="973" width="1798"><figcaption></figcaption></figure>

밑에 finished 색이 다 채워지면 256가짓수가 다 나온다.\
Length가 특별하게 1505로 나오는 경우의 수가 하나 있다(언제 나올지는 로컬 컴퓨터에 따라 다 다르다.. 근데 만약 Length가 모두 동일하게 나오면 admin 값을 발견 못한거라 한 번 재부팅하고 재시도 해보길 바란다. 본인도 그렇게 해결했다.)\
다른 sessionid일때는 guest권한이지만 length가 다른 저 100번에서 admin 세션을 가지고 있어서 다르게 나오겠구나\~하고 response를 열어본다.&#x20;

<figure><img src="https://blog.kakaocdn.net/dna/bVWYrj/btsM2y97HiD/AAAAAAAAAAAAAAAAAAAAAEWcGrW32tWM4bxPgU_zqjeWuKilPurMHBFUohZZLT8p/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&#x26;expires=1782831599&#x26;allow_ip=&#x26;allow_referer=&#x26;signature=a725IfkTYFq2HJ621o%2FbS%2BqxsT4%3D" alt="" height="482" width="778"><figcaption></figcaption></figure>

쭉 내려보니 플래그 값이 뜬다.\
정답\~\
기존 컴퓨터가 용량이 오래되어서 버프스위트 설치에 애를 먹었는데(지금도 모르는게 너무 많지만 그때는 컴퓨터의 ㅋ도 모르던 시절이었다..설정 건드리는게 너무 무섭던 어린 시절,,) ssd 용량 2배인거 구매하고 그냥 초기화하고 1년 반만에 다시 설치하고 프록시 건드려줬더니 해결이 되었다.&#x20;

<br>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.cooku222.kr/security/web-hacking/dreamhack/dreamhack-session.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
