登录加密算法破解秘籍
0x00 前言
接上篇sm0nk的《Web攻防之暴力破解》
(http://mp.weixin.qq.com/s/_zzHPAeWvSp4ckDz0_PltQ),
在日常WEB登录的用户/口令破解中,我们多使用burpSuite针对明文传输、base64加密、MD5加密等进行暴力爆破;
查看Burp支持的playload加密方式中包括:URLencode、Base64、SHA、MD5、MD2等:
但在日常渗透测试中对WEB系统进行用户或密码暴力破解时,常常会遇到譬如这样的情况:
userName=3633756E89341C6CBEF634D91E44139D87481E1E6BE250A75231CB752541B7E565F23A8BF2E89596C733A2259FC205D7ADA92CB564AE13DC8862CD7E79468D834339A7E642930FC707F2455B4068252693AEBE48D31580A5DDB01B54312F4CB3EA32672706D80D53DB724AA4D79ABBA9EC78A5ABCD9F916C452D78FBFA5FF914726A211CE5656E95B20B39B51DE947CA7A57ABE9E8F886FD3F7445504F30099D2B0BA0A9CA9E6D98968904ECF6D30CF32B0BA0A9CA9E6D98F53EAF05FFC6B5ED2283342C5D4CF1FF1E48370FA03DBF27&token=6afd3e8e44d847dc913d960a352e40b0&validateCode=3029 |
又如:
userId=admin&pass=b6dcdf25c7fd79d08ffd8abc1d0ed3ed&signIn=%E7%99%BB%E5%BD%95
将疑似MD5的字符串(b6dcdf25c7fd79d08ffd8abc1d0ed3ed)尝试在线解密:
提示未查到,可是我分明输入的admin/123456
再者,当遇到采取两次MD5加密或其他更复杂的加密方式进行数据传输时,我们还得自己动手小脚本,把明文字典按照指定算法生成一定格式的密文字典,配合burp丰衣足食,
0x0.5 使用场景
1.无验证码或验证码失效的情况下,按照算法规则生成对应用户名、密码的加密密文,直接加载到burp中暴力破解
- 无验证码或验证码失效,但算法参数动态变化的情况下(如hmac的key值),构造脚本工具,进行暴力破解
3.存在验证码且有效,通过附加验证码识别模块(参照@浮萍:http://mp.weixin.qq.com/s/ApPBnOMCUI_iPcBU1ApoSQ),构造脚本工具进行暴力破解
4.其他
注:本文仅从加密算法上着手,千万不要用Seleinum揍我←_←
0x01 如何获取数据传输算法
通过参看网页源码(view-source:)分析是否在JS中泄漏算法甚至密钥
如其中包含DES算法的源码中,时常存在strEnc,我们也可以次为依据
以下列举了收集的部分WEB系统登陆处中常见的加密方式、对应脚本及技巧:
0x02 常见登录处算法和处理脚本
MD5
名词解释:
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
关键JS代码:
加密传输示例:
python处理脚本:
import hashlib
def simaple_md5(str):
m2 = hashlib.md5()
m2.update(str)
res=m2.hexdigest()
return res
HMAC
名称解释:
HMAC是密钥相关的哈希运算消息认证码,HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。
hmac主要应用在身份验证中,使用方法如下:
(1) 客户端发出登录请求(假设是浏览器的GET请求)
(2) 服务器返回一个随机值,并在会话中记录这个随机值
(3) 客户端将该随机值作为密钥,用户密码进行hmac运算,然后提交给服务器
(4) 服务器读取用户数据库中的用户密码和步骤(2)中发送的随机值做与客户端一样的hmac运算,然后与用户发送的结果比较,如果结果一致则验证用户合法
关键JS代码:
加密传输示例:
python处理脚本:
import hmac import hashlib def hmac_md5(ekey,data): to_enc = simaple_md5(data) enc_res = hmac.new(ekey, to_enc, hashlib.md5).hexdigest() return enc_res
RSA
名词解释:
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出。1987年7月首次在美国公布。
RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
RSA的算法涉及三个参数,n、e1、e2。
其中,n是两个大质数p、q的积,n的二进制表示时所占用的位数,就是所谓的密钥长度。
e1和e2是一对相关的值,e1可以任意取,但要求e1与(p-1)*(q-1)互质;再选择e2,要求(e2×e1)≡1(mod(p-1)×(q-1))。
(n,e1),(n,e2)就是密钥对。其中(n,e1)为公钥,(n,e2)为私钥。
RSA加解密的算法完全相同,设A为明文,B为密文,则:A≡B^e2( mod n);B≡A^e1 (mod n);(公钥加密体制中,一般用公钥加密,私钥解密)
e1和e2可以互换使用,即:
A≡B^e1 (mod n);B≡A^e2( mod n);
关键JS代码:
大多数js的rsa库采用传入指数模数方式进行加解密;rsa加密模块使用是指数,模数方式,其中作为指数的exponent默认多数时候是10001,转换为十进制即是65537
加密传输示例
python处理脚本
def rsaenc (plaintext_text, public_modulus_hex, public_exponent_hex):
public_modulus = int(public_modulus_hex, 16)
public_exponent = int(public_exponent_hex, 16)
# Beware, plaintext must be short enough to fit in a single block!
plaintext = int(plaintext_text[::-1].encode('hex'), 16)
ciphertext = pow(plaintext, public_exponent, public_modulus)
return '%X' % ciphertext # return hex representation
DES
名词解释:
DES算法为密码体制中的对称密码体制,又被称为美国数据加密标准,是1972年美国IBM公司研制的对称密码体制加密算法。
明文按64位进行分组,密钥长64位,密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位, 使得每个密钥都有奇数个1)分组后的明文组和56位的密钥按位替代或交换的方法形成密文组的加密方法。
关键JS代码:
在WEB系统中的DES算法通常会为数据设定firstkey、secondkey、thirdkey,一般只会为firstkey设值,但也有三个key都设值的情况。
加密传输示例
python处理脚本
代码详见附件脚本
0x03其他便捷方法[python]
除了利用加密算法制作脚本生成对应密文,我们还可以使用第三方模块来直接调用JS,来更好的应对各种多变的密文算法计算
1、pyexecjs
安装
pip install pyexecjs
使用示例
#coding:utf8
import execjs
#读取本地的js(也可直接粘贴js内容,或是通过urllib读取)
def get_js():
f = open("encdec.js", 'r')
line = f.readline()
htmlstr = ''
while line:
htmlstr = htmlstr + line
line = f.readline()
return htmlstr
jsstr = get_js()
ctx = execjs.compile(jsstr) #调用js
print ctx.call('des','123','abc')#第一个参数“des”为调用的方法名,后面的参数为js方法所需的参数
若js中关键代码如下,则ctx.call(‘des’,’123′)
function des(data) {
var key1 = "abc";
var key2 = "123";
var key3 = "hhh";
var enResult = strEnc(data, key1, key2, key3);
return enResult
}
若js中关键代码如下,则ctx.call(‘des’,’123′,’abc’)
function des(data,data2) {
var key2 = "123";
var key3 = "hhh";
var enResult = strEnc(data, data2, key2, key3);
return enResult
}
2、PyV8
安装 pip install pyv8
使用import PyV8
# coding=utf-8
import PyV8
ctxt = PyV8.JSContext()
ctxt.enter()
def encode_keywoed(ukey,udata):
func = ctxt.eval('''
(function(){
#此处粘贴js算法文件全部内容
return hex_hmac_md5('__keyword__','__data__');#调用JS中的执行函数
}
)
'''.replace('__keyword__',ukey) .replace('__ data __', udata)#传参,替换js中的参数
)
return func()
print encode_keywoed('123456', '123456')
如果是通过直接读取在线js,稍微进行下改变即可:
# coding=utf-8
import PyV8
import urllib
ctxt = PyV8.JSContext()
ctxt.enter()
def encode_keywoed(keyword,data,html):
func = ctxt.eval('''
(function(){
__myjs__
return hex_hmac_md5('__keyword__','__data__');
})
'''.replace('__keyword__',keyword).replace('__data__',data).replace('__myjs__',html)
)
return func()
html=urllib.urlopen('http://110.lt/js/hmac_md5.js').read()
print encode_keywoed('23336015cc6aae7329c784829e7acd8e','123456',html)
0x04 相关参考
https://pypi.python.org/pypi/PyExecJS
https://code.google.com/archive/p/pyv8/downloads
https://zhuanlan.zhihu.com/auxten/20064358
http://bbs.csdn.net/topics/320247796
https://baike.baidu.com/item/hmac
https://www.cnblogs.com/songwenlong/p/5944139.html
https://baike.baidu.com/item/RSA%E7%AE%97%E6%B3%95
附脚本:
根据实际场景,分别调用脚本中的函数simaple_md5()、hmac_md5()、rsaEnc()、desEnc()
https://github.com/hkylin/loginCrypy
使用方法:
import LoginCrypt #调用LoginCrypt.py
simaple_md5():
正常的MD5加密,如:
LoginCrypt.simaple_md5md5(‘12346’)
hmac_md5():
函数第一个参数为随机密钥值,该值在网页源码中查找即可,第二个参数为待加密的明文,如:
LoginCrypt.hmac_md5(‘23336015cc6aae7329c784829e7acd8e’,’123456′)
rsaEnc():
函数第一个参数为待加密的明文,第二个参数为modulus即n值,第三个参数为exponent即e值,后面两个参数皆存在源码或js文件中,其中e值通常默认为十六进制的10001,如:
LoginCrypt.rsaEnc(‘admin’,’8246a46f44fc4d961e139fd70f4787d272d374532f4d2d9b7cbaad6a15a8c1301319aa6b3f30413b859351c71938aec516fa7147b69168b195e81df46b6bed7950cf3a1c719d42175f73d7c97a85d7d20a9e83688b92f05b3059bb2ff75cd7190a042cd2db97ebc2ab4da366f2a7085556ed613b5a39c9fdd2bb2595d1dc23b5′,’10001′)
desEnc():
函数第一个参数为待加密的明文,后面三个参数分别为需要输入的key,同样存在于源码或js文件中,如:
LoginCrypt.utf16to8(LoginCrypt.desEnc(‘admin’, ‘123456’, None, None))