warGame/Webhacking.kr 문제 풀이

[Dreamhack] QR Online 힌트

jalni_k 2023. 10. 12. 13:41

해당 글은 답지를 보고 싶진 않지만 문제를 너무 풀고 싶은 사람들을 위한 글입니다. 필요한 기반 지식, 팁, 방향성 등을 담았습니다.

 

1. 문제 분석

1. 랜덤한 유저 디렉터리 생성
@app.before_request
def init_session():
    if session:
        return
    session['id'] = os.urandom(32).hex()
    os.mkdir('static/users/' + session['id'])

os.urandom을 사용해서 {static/users/랜덤값} 으로 디렉터리를 생성한다.

 

 

2. QR code로 생성할 url 주소를 받음
@app.route('/qr_generator', methods=['GET', 'POST'])
def qr_generator():
    if request.method == 'GET':
        return render_template('qr_generator.html')

    # POST
    url = request.form.get('url')
    if not isinstance(url, str):
        abort(400)

    try:
        norm_url = normalize(url)
        cache = get_cache(norm_url)
        # Cache Hit
        dst = 'static/users/' + session['id'] + '/qr_code.png'
        shutil.copyfile(cache, dst)


    except CacheMiss:
        img = qrcode.make(url)
        src = f'static/cache/{norm_url}'
        img.save(src)
        dst = 'static/users/' + session['id'] + '/qr_code.png'
        shutil.copyfile(src, dst)

    except:
        abort(500)

    finally:
        if url.startswith('http://') or url.startswith('https://'):
            with open(dst, 'rb') as f:
                img_data = base64.b64encode(f.read()).decode('utf-8')
            return f'<img src="data:image/png;base64,{img_data}">'

        return 'url must starts with "http://" or "https://".'

try:

  • get_cache 함수를 통하여 파일의 존재 유무를 확인
  • 만약 존재한다면 static/users/session['id']/qr_code.png로 저장

catch(CASHE RAISE) :

  • 만약 get_cache 함수를 통해서 파일의 존재 유무를 파악했을 때, 파일이 없다면 새로운 qrcode를 생성하고 /static/cache/{nomalize 된 파일이름} 으로 저장, static/users/session['id']/qr_code.png로 복사함

catch exception:

  • 그 외 에러는 500 에러를 응답

finally

  • 만약 입력값이 http:// or https:// 로 시작한다면 users/session/qr_code.png 를 읽어서 이미지를 도출함

따라서 500 error만 발생하지 않는다면 try 구문이나 catch(CASHE RAISE) 구문은 수행한다는 뜻

 

2. 팁

urlparse 분석

urlparse를 사용해보면 여러가지 섹션이 존재함. 여기서 nomalize 함수가 어떤 부분을 어떻게 참조하는지, 섹션 데이터를어떻게 바꾸는지 알면 좋음

 

Flask Session Parse
#kali
apt-get install flask-unsign
flask-unsign -d -c {세션 값} -> JSON으로 구성된 세션 내부 정보 확인 가능

FLASK의 경우 JWT랑 구조가 매우 유사함, 세션에 저장되는 값을 JSON형태로 저장해서 FLASK에 존재하는 시크릿 키로 서명한다고 볼 수 있음. 

여기서 flask-unsign을 사용해서 세션을 디컴파일하면, 세션에 저장되는 값을 알아낼 수 있음.

 

Broken Access Control

해당 웹서버는 was를 사용하고 있지 않음. 따라서 경로 접근 제어에 대한 의존이 Flask에 의해서 수행되고 있음.

 

 

3. 방향성

해당 문제의 경우 urlparse의 취약점을 찾으려고 노력하는 부분을 너무 딥하게 들어가지 않는게 좋음. (제가 CVE까지 찾아봐서 이런소리를 하는건 아닙니다.) 왜냐면 문제는 플랫폼이나 라이브러리에 존재하는 취약점으로 Vector을 구성할 경우, 해당 취약점이 패치가 되면 문제가 발생하기 때문

 

 

 

제가 너무 많은 힌트를 줬다고 생각하는 풀이자 분은 댓글을 남겨주시면 반영하겠습니다.

오늘도 즐거운 워게임 되시길 바랍니다.