CTF

[n00bzCTF - WEB] Curl as a Service

estherseo 2022. 6. 9. 23:33

 

 

n00bzCTF에서는 공식 writeup을 제공한다..!😄😆

롸업 정리하면서 공부해보자 !

https://github.com/n00bzUnit3d/n00bzCTF-OfficialWriteups/tree/main/web/CaaS

 

 

 


1. 문제설명

remote: https://challs.n00bzunit3d.xyz:30533/

challenge: https://ctf.n00bzunit3d.xyz/attachments/CaaS/challenge_redacted.py

 

2. 웹서비스 분석

https://www.naver.com 입력

드림핵에 비슷한 문제가 있었다. blind command 였나???

그때는 입력칸에 들어가는 값이 curl 명령어의 인자로 들어갔는데 이 문제에서는 curl command라고 써져있긴 한데 동작이 좀 다른 것 같다. 

 

from flask import Flask, request, render_template, render_template_string, redirect
import subprocess
import urllib
app = Flask(__name__)
def blacklist(inp):
    blacklist = ['{{','}}','import','os','system','[','\x5f',']']
    for b in blacklist:
        inp = inp.replace(b, '')
    return inp
@app.route('/')
def main():
    return redirect('/curl')

@app.route('/curl',methods=['GET','POST'])
def curl():
    if request.method == 'GET':
        return render_template('curl.html')
    elif request.method == 'POST':
        inp = request.values['curl']
        #print(inp)

        #p = subprocess.Popen(["python3", "admin.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        #print('a')
        def admin():
            return inp
        print(admin())
        webUrl = urllib.request.urlopen(f'{inp}')
        data = webUrl.read()
        #print(data)
        #data = data.replace(b'\n',b'\r\n')
        return f'Am Admin, Going to visit "{inp}" fingers crossed, Result:{data}</p>'
@app.route('REDACTED')
def flag():
    return render_template('REDACTED')
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

소스코드를 보니까 curl이 아니라 webUrl = urllib.request.urlopen(f'{inp}')

입력한 값을 urllib.request.urlopen()으로 열어서 read 해준다. 

flag는 redacted?? 검색해보니까 중요한 정보를 지운다. 라는 뜻이라고 한다. 하여튼 flag가 안 보인다.

 

3. 취약점 분석

블랙리스트로 사용자가 입력한 값을 필터링하고 있다.

블랙리스트 필터링이어서 필터링하지 않는 문자들로 우회가 가능하다. 

 

4. 익스플로잇

urllib.request.urlopen() 문서를 찾아보자.

 

urllib.request — URL을 열기 위한 확장 가능한 라이브러리 — Python 3.10.5 문서

urllib.request — URL을 열기 위한 확장 가능한 라이브러리 소스 코드: Lib/urllib/request.py urllib.request 모듈은 복잡한 세계에서 URL(대부분 HTTP)을 여는 데 도움이 되는 함수와 클래스를 정의합니다 — 기

docs.python.org

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

url에는 https://, http://, file://, ftp:// 형식으로 입력할 수 있다고 한다.

- urllib의 많은 용도는 이렇게 간단합니다 (‘http:’ URL 대신 ‘ftp:’, ‘file:’ 등으로 시작하는 URL을 사용할 수 있음에 유의하십시오).

 

그렇다면 최종 목적은 flag파일을 읽는 거니까 file:// 을 사용해서 파일을 읽어보자!

flag가 flag.txt에 저장되어있지 않다고 하니까 flag파일의 이름을 알아야한다.

 

LFI 취약점을 이용해서 /etc/passwd, /proc/self/environ 등 시스템 파일들을 읽어보자.

(유용한 파일 -> 드림핵 웹해킹 로드맵 참고 )

file:///etc/passwd
file:///proc/self/environ
file:///proc/self/cmdline

/proc/self  :  현재 실행 중인 프로세스의 정보를 확인할 수 있다.

/proc/self/cmdline  :  실행 중인 프로세스의 명령줄

 

challenge.py 라는 파이썬 코드를 실행하고 있나보다.

문제 소스 코드 이름이 challenge_redacted.py 이고 flag가 redacted로 안보였으니까 challenge.py에는 flag가 보이지 않을까?

challenge.py 파일을 읽어보자!

 

이 파일이 저장된 곳 = 디렉터리를 알아야 한다.

/proc/self/cwd가 프로세스의 현재 실행 중인 디렉터리의 심볼릭 링크 파일이라고 한다.

https://man7.org/linux/man-pages/man5/proc.5.html

file:///proc/self/cwd/challenge.py  ,   file:///chall/challenge.py

challenge.py에 flag 파일의 이름이 나와있다. 

플래그!