太久没碰pikachu了,没想到第一关就是暴力破解,明明从SQL注入开始讲会比较好的。在开始阅读之前,请确保自己已经掌握了BurpSuite对暴破的使用呐。
一、介绍
暴力破解,说白了就是用超多的认证信息尝试登录之类的功能,直到尝试出可以通过认证的数据。一般会用到一些工具和字典来帮助我们进行攻击。
这里给一个很好用,之后也会用到的字典链接。
TheKingOfDuck/fuzzDicts: Web Pentesting Fuzz 字典,一个就够了。 (github.com)
我们的教程并不是仅仅为了通关,所以会介绍很多其它的内容,要好好看完呐。
那么,就开始吧!
二、基于表单的暴力破解
说到暴力破解,一般就是用在尝试登录界面,就用pikachu的这一关举例,先看界面->

没有验证码可是非常不好的,这样的无法防止工具的自动化攻击,也许会留下日志,但用户的信息已经丢失,说什么都晚了。
我们来尝试随便输入用户名和密码

这里提示用户名和密码不存在,并且重复好几次都没有出现验证码,基本上就可以判断是一个漏洞百出的登录界面了。
先不急着进入攻击,讲讲别的知识点。当你随便输入用户名时,如果下面的提示信息是“用户名不存在”,而不是“用户名或密码不存在”,那么你就可以先去暴破用户名,然后再暴破密码。这样可以提升你的效率。
那么开始,首先Burp开始抓包,然后随便输入一个用户名和密码,将抓到的数据包右键发送到Intruder中。

来到Intruder,将用户名和密码作为参数,选择Cluster bomb模式。

然后来到Payloads模块下,在Payload set下分别对两个注入点设置字典,点load加载你的字典文件(这里为了方便用了小的字典,正常是要花上一段时间的)

然后,来到Settings模块,找到Grep-Match,勾选那个Flag开头的选项,然后点击Clear,最后在Add右侧的输入框输入登录失败时的提示信息。

这样暴破的准备就做好了,点击右上方的Start Attack。来看看结果。

看到上方的分栏中会多出一个我们添加的Flag,让数据按这一列排序,就可以看到两条没有被标记的,让我们来看看对应的界面。(怎么查看?点下方的Response->Render)

看到登录成功了,那么没有验证码的暴破就到此为止。
三、服务端与客户端的验证码绕过
也不知道这个翻译到底准不准确,还是喜欢说前端(client)和后端(server),所以之后就按照这个说法了。
那么我们如何判断验证码在前端还是后端呢?这里讲两种方法:
1. 我们可以查看网页的源代码,如果是使用JavaScript语言写在源代码中的就是前端验证。
2. 使用bp抓包,输入错误的验证码时,如果没有数据包通过,那么一般就是前端验证了。
这里既然已经告诉我们关卡对应的验证方式了,就跳过验证的步骤(懒)。咳咳,那么开始。
1.server
按顺序先说后端验证,先随便输账号密码,然后输入正确的验证码,抓个包先,右键把它送到Repeater中。

然后重放个两次,发现我们输入的验证码居然重放了还有效诶。(第二张图长得一样就不放了)

也就是说,至少一段时间内,后端的验证码不会刷新,那么我们就重复第一关的步骤,就可以了。


ok,这一关就这样过了
2.client
来看看第二关,额,这个验证码,完全可以用机器识别嘛,所谓前端的验证那能叫验证嘛?

既然是前端的验证码,那么让我们来想想它验证的思路:
用户输入账号密码验证码->前段验证->验证码正确发送数据包->后端判断账号密码是否正确
也就是说,只要前段验证码通过一次,就会发送数据包。数据包发出去之后我们要做什么,就由不得前端了。
实地验证一下,我们先随便输入账号密码,然后输入正确的验证码(额,这是I还是1还是l)

抓到包后放入Repeater(重放器),然后修改验证码,看看界面的提示是什么。

看果然提示用户不存在了,那之后的过程就不说了吧。再重复一遍,前端的验证不算验证,总有办法攻破的,我甚至可以把对应的判断用JavaScript语句删掉。
四、token防爆破?
首先来介绍一下token:它是一个用于代表用户身份、访问权限或其他授权信息的数据对象。又被叫做token令牌,它有很多种发放的方式,这里使用的是基于会话的令牌
也就是说,如果你的数据包中发送的token令牌不正确,就不会让你登录,就比如说这样↓

所以我们就要想办法得到用户的token令牌,在实战中可能会比较想,需要有一定的实战经验,不然真的会毫无头绪。不过既然token令牌会实时更新,那么你总得要发给我,我才能用吧,那么我们尝试在上一个数据包中找找看。
先随便发两三个数据包出去,看看发送的包中的token值和上一个Response(响应包)有什么关系。


这下就发现,这个数据包是从之前的Response中发送给我们的。那么我们只要在爆破时,设置使用前一个Response中的token令牌就好了。
开始具体的爆破,发个包到Intruder里,在Intruder->Settings中找到Grep-Extract(内容提取)。
Grep-Extract的功能是:用于从HTTP响应中提取和过滤特定的内容。
点击Add添加规则,按下图进行设置,左上是你要提取的值的开始与结尾特征(你也可以自己翻译一下意思),当不能定位到你想要的值的时候,可能要稍微的特征写长一点。

勾选Redirection(重定向)中的Always

回来设置爆破点,但这次要使用Pitchfork模式,因为如果还是使用Cluster bomb会导致token值一直不变。
对不起,我还没找到burp的解决办法,也许有办法但是这个时候我不会,就默认你已经得到用户名admin了QAQ,原谅我T_T。

其他Payload一样,主要是token的Payload设置,选择Recurisve grep(递归关键字筛选),会自动出现之前的规则,添加一个初始的token值,最好是取你Proxy->HTTPhistory中发送的最后一个数据包中的token值。

最后一步,非常重要,一定要用单线程,比较token是一个一个发的,你也不想爆破用的token乱来吧。你还可以在这个界面设置每个数据包之间的间隔时间等。设置完成就可以开始攻击了。

这样攻击就成功了。

好吧,下面是网上找到的Python的解决方法(下面有他的链接哦,感兴趣一定要去看看(*^▽^*)):
# requests 用于处理HTTP请求和响应,适用于与Web服务器通信。
# re 用于处理正则表达式,适用于在文本中查找、提取和处理特定模式。
import requests
import re
# 函数用于从页面中提取token和cookies
def get_token_and_cookie(url):
response = requests.get(url)
content = response.text
# 使用正则表达式从响应中提取token
pattern = r"(?<=value=\")\w+(?=\")"
token = re.search(pattern, content).group()
cookies = response.cookies
return token, cookies
# 目标页面的URL
url = "http://192.168.52.131:800/vul/burteforce/bf_token.php"
# 从本地txt字典文件中读取用户名列表
with open("usernames.txt", "r") as file:
users = file.read().splitlines()
# 从本地txt字典文件中读取密码列表
with open("passwords.txt", "r") as file:
passwds = file.read().splitlines()
# POST请求的数据字典
data = {"submit": "Login"}
# 遍历每个用户名和密码组合
for user in users:
for passwd in passwds:
# 更新数据字典,使用当前的用户名和密码
data["username"] = user
data["password"] = passwd
# 使用定义的函数获取token和cookies
data["token"], cookies = get_token_and_cookie(url)
cookies = cookies.get_dict()
# 设置请求的PHPSESSID cookie
headers = {"Cookie": "PHPSESSID=" + cookies["PHPSESSID"]}
# 发送带有当前数据和headers的POST请求
response = requests.post(url, data=data, headers=headers)
content = response.text
# 根据响应内容检查登录是否成功
if "login success" in content:
print("用户名:", user, "密码:", passwd)
果然还是自己编写Python脚本来的方便呀,本来想自己写一个的,但是还没想就看了别人的代码脑子里的思路就不停地往上面靠,感觉最后会写出差不多的东西。可恶,这可是抄袭啊!!! 所有就稍微整理了一下格式和注释,加了读取本地字典的功能就贴上来了
这里非常感谢Pikachu漏洞练习平台实验——暴力破解(一) - 那少年和狗 - 博客园 (cnblogs.com),编写的脚本。
看一下运行结果

五、后记
这样暴力破解就结束了,本来接下来打算将SQL注入的,但还是决定按照顺序一个一个讲下去,那么就XSS见咯 :-D
Comments | NOTHING