날씨가 겨울이 온게 실감난다. 다들 감기 조심하시길..
47번째 문제 가자~
지피티야지피티야 SSTL이 뭐야
GPT:
SSTI (Server-Side Template Injection) 취약점은 웹 애플리케이션에서 서버 측 템플릿 엔진을 사용할 때 발생할 수 있는 보안 취약점입니다. 이 취약점은 악의적인 사용자가 템플릿에 악성 코드를 주입하여 서버에서 실행할 수 있게 하는 공격입니다.
### SSTI 취약점의 작동 원리
1. **템플릿 엔진**: 많은 웹 프레임워크는 HTML을 동적으로 생성하기 위해 템플릿 엔진을 사용합니다. 이러한 엔진은 사용자가 제공한 데이터를 템플릿에 삽입하여 최종 HTML을 생성합니다.
사용자가 제공한데이터 -> 템플릿에 삽입 -> HTML 최종 생성
2. **사용자 입력 검증 부족**: 템플릿 엔진이 사용자 입력을 적절히 검증하지 않거나 필터링하지 않으면, 공격자는 템플릿에 악성 코드를 삽입할 수 있습니다.
(여기서 악성 코드 삽입)
사용자가 제공한데이터 -> 템플릿에 삽입 -> HTML 최종 생성
3. **코드 실행**: 공격자는 템플릿 코드에 주입된 악성 스크립트를 통해 서버에서 임의의 코드를 실행하거나, 민감한 데이터를 노출할 수 있습니다.
(여기서 악성 코드 삽입) (보안 이슈 발생)
사용자가 제공한데이터 -> 템플릿에 삽입 -> HTML 최종 생성
### 예시
가장 일반적인 예시는 Jinja2와 같은 템플릿 엔진을 사용하는 Flask 웹 애플리케이션입니다.
#### 취약한 코드 예시:
```python
from flask import Flask, request, render_template_string
app = Flask(__name__)
@app.route('/')
def index():
user_input = request.args.get('name')
template = f'Hello, {user_input}!'
return render_template_string(template)
if __name__ == '__main__':
app.run()
```
위의 코드에서 사용자가 URL 파라미터로 입력한 `name` 값이 직접 템플릿에 삽입됩니다. 만약 공격자가 다음과 같이 요청하면:
```
http://localhost:5000/?name={{ config }}
```
서버는 `config`라는 Jinja2의 내장 객체를 통해 서버의 설정 정보를 출력하게 됩니다. 이를 통해 공격자는 서버 정보를 노출할 수 있습니다.
### SSTI 공격의 결과
1. **정보 노출**: 서버의 민감한 정보(환경 변수, 데이터베이스 크레덴셜 등)가 노출될 수 있습니다.
2. **임의 코드 실행**: 공격자는 서버에서 임의의 코드를 실행할 수 있게 되어, 데이터 손상 또는 데이터 유출 등의 결과를 초래할 수 있습니다.
3. **서비스 거부**: 악의적인 코드를 통해 서버를 중단시키거나, 서비스 거부 공격을 감행할 수 있습니다.
### 방어 방법
1. **입력 검증**: 사용자 입력을 철저히 검증하고, 예상하지 않은 입력을 차단합니다.
2. **출력 인코딩**: 사용자 데이터를 템플릿에 삽입할 때, HTML 인코딩을 적용하여 악성 코드를 방지합니다.
3. **템플릿 엔진의 보안 기능 활용**: 템플릿 엔진의 보안 기능을 적극 활용하고, 민감한 정보가 노출되지 않도록 설정합니다.
4. **최소 권한 원칙**: 서버에서 실행되는 코드는 최소한의 권한만 가지도록 설정하여, 공격자가 시스템에 접근할 수 있는 경로를 줄입니다.
SSTI는 웹 애플리케이션에서 주의해야 할 중요한 취약점 중 하나입니다. 추가적으로 궁금한 점이 있거나 더 자세한 설명이 필요하시면 언제든지 말씀해 주세요!
소스코드를 보자!
#!/usr/bin/python3
from flask import Flask, request, render_template, render_template_string, make_response, redirect, url_for
import socket
app = Flask(__name__)
try:
FLAG = open('./flag.txt', 'r').read()
except:
FLAG = '[**FLAG**]'
app.secret_key = FLAG
@app.route('/')
def index():
return render_template('index.html')
@app.errorhandler(404)
def Error404(e):
template = '''
<div class="center">
<h1>Page Not Found.</h1>
<h3>%s</h3>
</div>
''' % (request.path)
return render_template_string(template), 404
app.run(host='0.0.0.0', port=8000)
주어진 코드는 Flask 웹 애플리케이션의 간단한 구현을 보여줍니다. 이 코드를 분석하면 다음과 같은 주요 요소들이 있습니다:
### 1. **라이브러리 임포트**
- `Flask`: Flask 웹 프레임워크를 사용하여 웹 애플리케이션을 만들기 위해 임포트합니다.
- `request`, `render_template`, `render_template_string`, `make_response`, `redirect`, `url_for`: 다양한 Flask 기능을 사용하기 위해 임포트합니다.
### 2. **플라스크 앱 초기화**
```python
app = Flask(__name__)
```
- Flask 애플리케이션 객체를 생성합니다.
### 3. **FLAG 읽기**
```python
try:
FLAG = open('./flag.txt', 'r').read()
except:
FLAG = '[**FLAG**]'
```
- `flag.txt` 파일을 열어 내용을 읽고 `FLAG` 변수에 저장합니다. 파일을 찾지 못할 경우 기본값으로 `"[**FLAG**]"`를 사용합니다.
- 이 `FLAG`는 이후 `app.secret_key`에 사용되어 세션을 보호하는 데 사용됩니다.
### 4. **라우트 정의**
```python
@app.route('/')
def index():
return render_template('index.html')
```
- 웹 애플리케이션의 루트 URL(`/`)에 접근할 때 `index.html` 템플릿을 렌더링하여 반환합니다.
### 5. **404 오류 핸들러**
```python
@app.errorhandler(404)
def Error404(e):
template = '''
<div class="center">
<h1>Page Not Found.</h1>
<h3>%s</h3>
</div>
''' % (request.path)
return render_template_string(template), 404
```
- 404 오류(페이지를 찾을 수 없음)가 발생할 경우, 사용자에게 사용자 정의 HTML 템플릿을 렌더링하여 반환합니다.
- 요청한 경로(`request.path`)를 포함하여 사용자에게 알려줍니다.
### 6. **앱 실행**
```python
app.run(host='0.0.0.0', port=8000)
```
- 애플리케이션을 실행하며, `0.0.0.0` 주소에서 8000 포트를 통해 요청을 수신합니다. 이는 모든 IP 주소에서 접근할 수 있도록 설정한 것입니다.
### **주요 특징 및 보안 고려사항**
1. **`secret_key` 설정**: Flask의 `secret_key`는 세션 관리 및 CSRF 보호와 같은 보안 기능에 사용됩니다. 이 코드에서는 `FLAG` 파일의 내용을 `secret_key`로 사용하므로, 만약 이 값이 유출된다면 세션 탈취와 같은 공격에 취약해질 수 있습니다.
2. **에러 처리**: 404 오류에 대한 사용자 정의 처리기를 제공하여, 일반적인 오류 페이지 대신 사용자 친화적인 메시지를 반환합니다. 이는 사용자의 경험을 개선할 수 있습니다.
3. **파일 입출력**: `flag.txt` 파일을 읽기 위한 접근이 있지만, 파일의 경로가 하드코딩되어 있어 해당 경로에 대한 권한이 없는 사용자에게는 취약할 수 있습니다. 만약 이 파일의 내용을 유출하려는 공격이 발생한다면, 이를 방지할 수 있는 조치가 필요합니다.
4. **코드 가독성**: 코드가 간결하게 작성되어 있으며, 필요한 부분에 대한 주석을 추가하면 더욱 이해하기 쉬운 코드가 될 것입니다.
이 코드에 대한 추가 질문이나 특정 부분에 대한 더 자세한 설명이 필요하다면 언제든지 말씀해 주세요!
3번이 취약점이며 이걸 이용해서 풀어야할 것 같다.
https://keyme2003.tistory.com/entry/dreamhack-simple-ssti
KEYME 블로거분 글을 보면 보안 대응방안은 무엇이 좋은지 설명도 추가로 해놓으셨다! 나도 글에 이제 추가해야지!
SSTI가 발생하는 부분은 위와 같다.
요청 시, 전달 받은 request.path를 template에 넣어 render_template_string() 로 랜더링한다.
이 과정에서 request.path에 대한 검증을 수행하지 않고 render_template_string()을 사용하고 있으므로 {{}} 형태의 템플릿 코드를 입력한다면, 템플릿 코드가 실행되면서 서버 내부의 정보를 가져올 수 있다.
출처 ㅣ https://keyme2003.tistory.com/entry/dreamhack-simple-ssti
{{config.items()}} 명령어를 통해 현재 딕셔너리 형태로 설정되어 있는 config를 확인해보자.
출처: https://mokpo.tistory.com/121 [MSS:티스토리]
{{ config.items() }}는 일반적으로 Flask와 같은 웹 프레임워크에서 사용하는 템플릿 엔진인 Jinja2의 구문입니다. 이 구문은 config 객체의 모든 설정 항목을 템플릿에서 출력하기 위해 사용됩니다. 자세히 설명하자면:
1. config 객체
- config는 Flask 애플리케이션에서 설정 정보를 저장하는 딕셔너리입니다. 이 객체는 애플리케이션의 설정값(예: 디버그 모드, 데이터베이스 URI 등)을 키-값 쌍으로 저장합니다.
- app.config를 통해 접근할 수 있으며, 이는 Flask 애플리케이션을 구성하는 다양한 설정값을 포함합니다.
2. .items() 메서드
- .items() 메서드는 Python의 딕셔너리에서 사용되는 메서드로, 딕셔너리의 모든 키-값 쌍을 튜플의 리스트 형태로 반환합니다. 예를 들어, config.items()는 config에 있는 모든 설정의 목록을 반환합니다.
3. Jinja2 템플릿에서의 사용
- {{ ... }} 구문은 Jinja2에서 변수를 출력하는 방식입니다. 이 구문 안에 코드를 넣으면 해당 코드의 결과값이 HTML로 렌더링됩니다.
'Dreamhack > Dreamhack Wargame (Challenge)' 카테고리의 다른 글
[49] IT 비전공자 [dreamhack]XSS Filtering Bypass문제 풀기 (7) | 2024.10.28 |
---|---|
[48] IT 비전공자 [dreamhack]proxy-1문제 풀기 (4) | 2024.10.27 |
[46] IT 비전공자 [dreamhack]rev-basic-4문제 풀기 (2) | 2024.10.25 |
[45] IT 비전공자 [dreamhack]Return Address Overwrite문제 풀기 (2) | 2024.10.24 |
[44] IT 비전공자 [dreamhack]rev-basic-2 문제 풀기 (4) | 2024.10.23 |