登录加密算法破解秘籍

0x00 前言

在日常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丰衣足食,

0x01 使用场景

1.无验证码或验证码失效的情况下,按照算法规则生成对应用户名、密码的加密密文,直接加载到burp中暴力破解

2.无验证码或验证码失效,但算法参数动态变化的情况下(如hmac的key值),构造脚本工具,进行暴力破解

3.存在验证码且有效,通过附加验证码识别模块(参照@浮萍:http://mp.weixin.qq.com/s/ApPBnOMCUI_iPcBU1ApoSQ),

构造脚本工具进行暴力破解

4.其他

注:本文仅从加密算法上着手,请不要用Seleinum揍我,仅做科学的搬运工。

0x02 如何获取数据传输算法

通过参看网页源码(view-source:)分析是否在JS中泄漏算法甚至密钥

如其中包含DES算法的源码中,时常存在strEnc,我们也可以次为依据

以下列举了收集的部分WEB系统登陆处中常见的加密方式、对应脚本及技巧:

0x03 常见登录处算法和处理脚本

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处理脚本

代码详见附件脚本

0x04其他便捷方法[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)

0x05 相关参考

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

本脚本主要为提供的加密算法生成字典,可以利用自编写脚本或者Burp类工具进一步爆破的实现。

使用方法:

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))

本站所有文章均为原创,转载请注明出处

更多技术文章,敬请关注猎户安全实验室微信公众号:

发表评论

电子邮件地址不会被公开。 必填项已用*标注