02.对有 token 防御的网站爆破密码

对有 token 防御的网站爆破密码

有的网站后台存在 token 值,这个 token 通俗的名字叫令牌,每次刷新页面都会随机变化。提交请求时必须携带这个 token 值,可以利用这点避免后台进行直接穷举和防止 csrf 攻击。

在有token的网站中每次登录抓包可以发现有个token字段的值在随机变化且不能重复使用

第一次拦截:

第二次拦截:

而且token不能重复使用

将请求包拦截后发送到Repeater模块,第一次提交(跟随重定向)后响应结果是登陆失败,并返回了新的token,这说明提交时token是正常的只是密码错误的原因:

第二次提交不再提示登陆失败,因为并没有验证密码是否正确,而是在验证token时就已经失败了(此时也有新的token返回)

要想在这种情况下进行密码爆破就需要每次不仅输入新的密码而且还需要输入一个新的token值,使用burp有两种方式进行实现,其一是变量的递归提取;其二是使用burp的宏。

1.变量的递归提取:

填写账号和密码,提交

Burp Suite - Intruder暴力破解模块的4种攻击类型_burp suite学习之intruder的4种攻击模式-CSDN博客

拦截请求包,转发到Intruder模块,选择攻击模式:Pitchfork,将密码字段和token字段的值都标记为变量:

设置payload,password是第一个需要设置的变量,默认simpl list类型,load加载密码字典:

切换到第二个变量的设置页,将payload类型设置为Recursive grep类型

在设置页面将跟随重定向设置为“总是”

在Grep-Extra中添加内容:点击“Refetch response”获取(重定向后的)响应,在响应中标记user_token字段的值,然后就“OK”

返回变量设置页,可以看到变量token也设置好了(每次提交的token值是上一次请求发送后其响应中的token):

然后便可以开始爆破,爆破结果如下,可以看到每次测试的Payload2的值都与上次尝试测试中的(token字段)value值相同,且密码正确的那次测试不返回token

重要的是,递归提取这种方式的结果不受线程数量影响

2.使用宏进行密码爆破:

使用宏不用将token字段的值标记为变量,攻击模式为Sniper,只设置密码这一个变量,并为其加载字典。

设置=>project=>Sessions=>Macros=>add

选择“Record Macro”,然后选择登录页面的url(选状态码为200,页面跳转过的)

Configure item=>Add 标记响应中的token值,并为该变量取个名字

添加规则来运行这个宏

Session=>Session handling rules=>Add=>Run a macro

选中之前设置的宏,然后选择Update only the following parameters and headers,然后编辑,添加请求包中的token字段名“user_token”(不能出错),然后“OK”(运行宏得到的变量值用于更新该字段的值)

选择当前规则应用的url,可以是所有url也可以是应用设置的范围url,不过需要先将目标url添加到范围

设置跟随重定向:

使用宏获取token进行爆破多线程容易出错:

设置单线程:

单线程却不会出错:

3.使用脚本对带token的网站进行密码爆破:

原理:每次页面生成, user_token 存放在 seesion 里面,每次验证先从 session 里取出来,如果验证成功就进行密码匹配。

#coding:utf-8

import requests

import re

url = "http://www.c3moon.com/login.php"

def login(password):

session = requests.session()

req=session.get(url)

user_token=re.search("[a-z0-9]{32}",req.text).group(0) #32md5

data={"username":"admin","password":password,"Login":"Login",'user_token':user_token}

req=session.post(url=url,data=data,allow_redirects=True)

html = req.text

return html

with open('top1000.txt') as p:

passlist =p.readlines()

p.close()

for line in passlist:

line = line.strip("\n")

print(line)

if 'File Upload' in login(line):

print( "[* 密码 is %s *]" % line )

break

下面这三行Python代码是用于从网页中提取用户令牌(token)的,具体解释如下:

1. `session = requests.session()`

这行代码创建了一个`requests`库的`Session`对象。`Session`对象允许你跨请求保持某些参数,它会在同一个Session实例发出的所有请求之间保持cookie。这使得在进行多个请求时,如登录后访问需要身份验证的页面,可以更加方便地处理。

2. `req=session.get(url)`

这行代码使用上面创建的`Session`对象来发送一个GET请求到指定的`url`。请求的结果(响应)将被存储在变量`req`中。这个响应包含了请求的网页内容,状态码,头部等信息。

3. `user_token=re.search("[a-z0-9]{32}",req.text).group(0) #32md5`

这行代码使用了正则表达式来搜索`req.text`中的字符串。`re.search`函数会在字符串中搜索与正则表达式匹配的第一个实例。这里的正则表达式`"[a-z0-9]{32}"`意味着它将搜索长度为32的,由小写字母和数字组成的字符串。这通常是用来匹配MD5哈希值的格式。当找到匹配的字符串时,`.group(0)`将返回匹配的整个表达式,这里即32个字符的字符串。这个字符串被假定为用户令牌,并被赋值给变量`user_token`。

posted @ 2024-08-25 22:37  stalee  阅读(41)  评论(0)    收藏  举报