hikaridatasource 加密后登陆不上_渗透测试 | 突破前端JS加密限制
前言
现在前端开发为了提高爬虫的难度及加强安全性,都会在数据包提交前进行加密,最典型的就是传参加密,相信大家在测试的时候都遇到过,那么我们在抓取数据包并修改之后,修改之后的参数无法通过后端程序数据完整性的校验,就无法进行进一步测试。如果我们逆向解析出加密的过程,就可以模拟出相同的密文,通过后端接口的校验。
最近由于工作需要,在搜索资料的时候,学到了很多爬虫大佬们的关于JS逆向、APK逆向、代码分析等方面的经验和技巧,后续会分部分记录并总结下来。
0x01 常见加密算法
比较简单的base64、hex等这些编码就不再说了。
1.1 对称加密
常用算法:DES、DES3、AES
根据密钥长度不同又分为:AES-128、AES-192、AES-256
其中AES-192和AES-256在Java中使用需获取无政策限制权限文件
加密/解密使用相同的密钥
加密和解密的过程是可逆的
1.2 非对称加密
常用算法:RSA
使用公钥加密,使用私钥解密
公钥是公开的,私钥保密
加密处理安全,但是性能极差,单次加密长度有限制
RSA既可用于数据交换,也可用于数据校验
数据校验通常结合消息摘要算法 MD5withRSA 等
两种加密算法常见结合套路:1、随机生成密钥2、密钥用于AES/DES/3DES加密数据3、RSA对密钥加密4、提交加密后的密钥和加密后的数据给服务器
1.3 信息摘要算法/签名算法
常用算法:MD5、HMAC(HmacMD5、HmacSHA1、HmacSHA256)、SHA(SHA1、SHA256、SHA512)
不管明文多长,散列后的密文定长
明文不一样,散列后结果一定不一样
散列后的密文不可逆
一般用于校验数据完整性、签名 sign
由于密文不可逆,所以后台无法还原,也就是说他要验证,会在后台以跟前台一样的方式去重新签名一遍。也就是说他会把源数据和签名后的值一起提交到后台。所以我们要保证在签名时候的数据和提交上去的源数据一致,这种算法特喜欢在内部加入时间戳
0x02 JS逆向流程
以登录为例的基本流程:
如果网页有跳转,必须勾选
preserve log
(F12-Network)防止丢包看一下有没有框架,右键查看框架源代码(弹出式登陆界面)
登陆尽量使用错误密码,防止跳转
查看关键登陆包,分析哪些参数是加密的
使用别的浏览器分析哪些参数是固定的值
初步猜测加密的方法
搜索
直接搜索参数,比如:
pwd=
,pwd =
,pwd:
,pwd :
密码框地方右键 检查 查看 id name type
找到加密的地方(重点)
进行代码调试
找出所有的加密代码
从最后一步开始写起,缺啥找啥
如果找的是函数的话,search 要带上 function xxx
如果看到加密的地方有个类,并且之后是用 prototype 把方法加在原生对象上的话,要把 所有加在原生对象上的方法都找出来
函数找多了没关系,只要不报错不会影响结果,但是不能找少了
0x03 实例操作
打开网站,抓包
修改个数据,比如修改num为1000
有些杠精该说了:我渗透测试改这有毛用。
是没用,只是以此为例。。。
可以看到,修改过参数数据后,后端数据校验之后不合法,所以没有返回数据。
打开测试网站 -> F12控制台 -> 切换至 XHR
这里我们看下需要做的有什么?
请求中有token(t明显是时间戳),token和数据不匹配后端不返回数据
返回的数据是加密的,需要解密
接下来我们就定位具体的加密函数和解密函数。
按照上面提到的流程步骤
打开控制台 -> source ->搜索
搜索加密参数名 token
根据搜索结果的文件名判断,基本上就是第二个文件,点击打开
token的生成代码
var token = md5(String(page) + String(num) + String(timestamp));
设置断点,刷新
成功进入断点,没毛病了
根据加密函数,编写脚本
可以看到,生成的token和URL中的一致,至此,加密部分完成。
解密部分同样的道理,搜索返回包中的参数,直接搜索list发现有点多,不太好观察,还有一种方法
可以看到数据部分html的id为ip-list
,再次搜索
成功找到解密数据包的代码
设置断点,进一步确认
没毛病,可以看到decode_str
后就开始出现我们需要的明文数据了,所以这里的 decode_str 就是我们要的解密方法。剩下就是分析代码,编写解密脚本了。
function decode_str(scHZjLUh1) { scHZjLUh1 = Base64["\x64\x65\x63\x6f\x64\x65"](scHZjLUh1); key = '\x6e\x79\x6c\x6f\x6e\x65\x72'; len = key["\x6c\x65\x6e\x67\x74\x68"]; code = ''; for (i = 0; i < scHZjLUh1["\x6c\x65\x6e\x67\x74\x68"]; i++) { var coeFYlqUm2 = i % len; code += window["\x53\x74\x72\x69\x6e\x67"]["\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65"](scHZjLUh1["\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74"](i) ^ key["\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74"](coeFYlqUm2)) } return Base64["\x64\x65\x63\x6f\x64\x65"](code)}
先运行下看看
报错,提示Base64
未定义,设置断点,找到Base64
的具体代码
复制粘贴进代码,再次运行
艹,提示Windows未定义,根据流程,缺啥补啥,debug,找对应的值
可以看到分别对应的是String
和fromCharCode
那就是调用了String.fromCharCode
方法了,替换掉,再次运行
bingo~
成功解密获取到明文数据。
0x04 Python实现加密方法合集
关于上述第一部分的常见加密算法,GitHub有对应的仓库,直接可以用的
GitHub:https://github.com/dhfjcuff/R-A-M-D-D3-S-M-H/
# -*- coding:utf-8 -*-import base64import rsafrom Crypto.Cipher import AESfrom Crypto.PublicKey import RSAfrom pyDes import des, CBC, PAD_PKCS5from Crypto.Cipher import DES3import hashlibimport hmacclass USE_AES: """ AES 除了MODE_SIV模式key长度为:32, 48, or 64, 其余key长度为16, 24 or 32 详细见AES内部文档 CBC模式传入iv参数 本例使用常用的ECB模式 """ def __init__(self, key): if len(key) > 32: key = key[:32] self.key = self.to_16(key) def to_16(self, key): """ 转为16倍数的bytes数据 :param key: :return: """ key = bytes(key, encoding="utf8") while len(key) % 16 != 0: key += b'\0' return key # 返回bytes def aes(self): return AES.new(self.key, AES.MODE_ECB) # 初始化加密器 def encrypt(self, text): aes = self.aes() return str(base64.encodebytes(aes.encrypt(self.to_16(text))), encoding='utf8').replace('\n', '') # 加密 def decodebytes(self, text): aes = self.aes() return str(aes.decrypt(base64.decodebytes(bytes( text, encoding='utf8'))).rstrip(b'\0').decode("utf8")) # 解密class USE_RSA: """ 生成密钥可保存.pem格式文件 1024位的证书,加密时最大支持117个字节,解密时为128; 2048位的证书,加密时最大支持245个字节,解密时为256。 加密大文件时需要先用AES或者DES加密,再用RSA加密密钥,详细见文档 文档:https://stuvel.eu/files/python-rsa-doc/usage.html#generating-keys """ def __init__(self, number=1024): """ :param number: 公钥、私钥 """ self.pubkey, self.privkey = rsa.newkeys(number) def rsaEncrypt(self, text): """ :param test: str :return: bytes """ content = text.encode('utf-8') crypto = rsa.encrypt(content, self.pubkey) return crypto def rsaDecrypt(self, text): """ :param text:bytes :return: str """ content = rsa.decrypt(text, self.privkey) con = content.decode('utf-8') return con def savePem(self, path_name, text): """ :param path_name: 保存路径 :param text: str :return:bytes """ if "PEM" in path_name.upper(): path_name = path_name[:-4] with open('{}.pem'.format(path_name), 'bw') as f: f.write(text.save_pkcs1()) def readPem(self, path_name, key_type): """ :param path_name: 密钥文件 :param key_type:类型 :return: """ if 'pubkey' in key_type: self.pubkey = rsa.PublicKey.load_pkcs1(path_name) else: self.privkey = rsa.PublicKey.load_pkcs1(path_name) return True def sign(self, message, priv_key=None, hash_method='SHA-1'): """ 生成明文的哈希签名以便还原后对照 :param message: str :param priv_key: :param hash_method: 哈希的模式 :return: """ if None == priv_key: priv_key = self.privkey return rsa.sign(message.encode(), priv_key, hash_method) def checkSign(self, mess, result, pubkey=None): """ 验证签名:传入解密后明文、签名、公钥,验证成功返回哈希方法,失败则报错 :param mess: str :param result: bytes :param pubkey: :return: str """ if None == pubkey: pubkey = self.privkey try: result = rsa.verify(mess, result, pubkey) return result except: return Falseclass USE_DES: """ des(key,[mode], [IV], [pad], [pad mode]) key:必须正好8字节 mode(模式):ECB、CBC iv:CBC模式中必须提供长8字节 pad:填充字符 padmode:加密填充模式PAD_NORMAL or PAD_PKCS5 """ def __init__(self, key, iv): if not isinstance(key, bytes): key = bytes(key, encoding="utf8") if not isinstance(iv, bytes): iv = bytes(iv, encoding="utf8") self.key = key self.iv = iv def encrypt(self, text): """ DES 加密 :param text: 原始字符串 :return: 加密后字符串,bytes """ if not isinstance(text, bytes): text = bytes(text, "utf-8") secret_key = self.key iv = self.iv k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5) en = k.encrypt(text, padmode=PAD_PKCS5) return en def descrypt(self, text): """ DES 解密 :param text: 加密后的字符串,bytes :return: 解密后的字符串 """ secret_key = self.key iv = self.iv k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5) de = k.decrypt(text, padmode=PAD_PKCS5) return de.decode()class USE_DES3: """ new(key, mode, *args, **kwargs) key:必须8bytes倍数介于16-24 mode: iv:初始化向量适用于MODE_CBC、MODE_CFB、MODE_OFB、MODE_OPENPGP,4种模式 ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB``长度为8bytes ```MODE_OPENPGP```加密时8bytes解密时10bytes 未提供默认随机生成 nonce:仅在 ``MODE_EAX`` and ``MODE_CTR``模式中使用 ``MODE_EAX``建议16bytes ``MODE_CTR``建议[0, 7]长度 未提供则随机生成 segment_size:分段大小,仅在 ``MODE_CFB``模式中使用,长度为8倍数,未指定则默认为8 mac_len:适用``MODE_EAX``模式,身份验证标记的长度(字节),它不能超过8(默认值) initial_value:适用```MODE_CTR```,计数器的初始值计数器块。默认为**0**。 """ def __init__(self, key): self.key = key self.mode = DES3.MODE_ECB def encrypt(self, text): """ 传入明文 :param text:bytes类型,长度是KEY的倍数 :return: """ if not isinstance(text, bytes): text = bytes(text, 'utf-8') x = len(text) % 8 text = text+b'\0'*x cryptor = DES3.new(self.key, self.mode) ciphertext = cryptor.encrypt(text) return ciphertext def decrypt(self, text): cryptor = DES3.new(self.key, self.mode) plain_text = cryptor.decrypt(text) st = str(plain_text.decode("utf-8")).rstrip('\0') return stdef USE_MD5(test): if not isinstance(test, bytes): test = bytes(test, 'utf-8') m = hashlib.md5() m.update(test) return m.hexdigest()def USE_HMAC(key, text): if not isinstance(key, bytes): key = bytes(key, 'utf-8') if not isinstance(text, bytes): text = bytes(text, 'utf-8') h = hmac.new(key, text, digestmod='MD5') return h.hexdigest()def USE_SHA(text): if not isinstance(text, bytes): text = bytes(text, 'utf-8') sha = hashlib.sha1(text) encrypts = sha.hexdigest() return encryptsif __name__ == '__main__': aes_test = USE_AES("assssssssdfasasasasa") a = aes_test.encrypt("测试") b = aes_test.decodebytes(a) rsa_test = USE_RSA() a = rsa_test.rsaEncrypt("测试加密") b = rsa_test.rsaDecrypt(a) des_test = USE_DES(b"12345678", b"12345678") a = des_test.encrypt("测试加密") b = des_test.descrypt(a) des3_test = USE_DES3(b"123456789qazxswe") a = des3_test.encrypt("测试加密") b = des3_test.decrypt(a) md5_test = USE_MD5("测试签名") hmac_test = USE_HMAC("123456", "测试") sha_test = USE_SHA("测试加密")
参考资料
公众号:咸鱼学python
公众号:小周码字
hikaridatasource 加密后登陆不上_渗透测试 | 突破前端JS加密限制相关推荐
- hikaridatasource 加密后登陆不上_python测试开发django42.auth模块登陆认证
前言 在开发一个网站时,经常会用到用户的注册和登陆相关的账号管理功能,auth模块是Django提供的标准权限管理系统,可以提供用户身份认证, 用户组和权限管理. 像用户注册.用户登录.用户认证.注销 ...
- form标签的action之前 加密_口令爆破之突破前端JS加密
0x00 前言 近期安全测试时发现一个系统前台使用了SSO,但是在比较隐蔽API中发现了后台的登录接口,该接口未使用SSO,同时没有图形验证码等校验,通过分析最终爆破进入后台. 0x01 确认攻击途径 ...
- 2022年全国职业院校技能大赛“网络安全”竞赛试题文件上传渗透测试答案Flag
B-9任务九:文件上传渗透测试 *任务说明:仅能获取Server9的IP地址 1.通过渗透机Kali2.0对服务器场景Server9进行网站目录暴力枚举测试(使用工具DirBuster,扫描服务器80 ...
- 中职网络安全竞赛设备-----文件上传渗透测试
经典赛题-文件上传渗透测试 渗透机:(Kali Linux1)用户名:root 密码:toor 渗透机:(Kali Linux2)用户名:root 密码:toor 靶 机:(Windows 7)用 ...
- 加密后变成乱码解密_个人磁盘加密软件,使用VeraCrypt进行整盘加密介绍
为了加强日常工作文档的管控,需要对个人PC上的文件进行加密存储,防止电脑.硬盘.U盘等存储介质丢失,导致数据泄露. 市面上基于文件夹加密的工具软件,大多数采用的是隐藏文件或者隔离文件的方式进行加密存储 ...
- 输入一个四位数将其加密后输出c语言,输入一个四位数,将其加密后输出.方法是将该数每一位的数字加9,然后除以10取余作为该位上的新数字,最后将千位上的数字和十...
问题描述: 输入一个四位数,将其加密后输出.方法是将该数每一位的数字加9,然后除以10取余作为该位上的新数字,最后将千位上的数字和十位上的数字互换,组成加密后的新四位数. #include int m ...
- screnc加密后文件不能执行_芯片加密后还能不能再次使用【详细介绍】
随着信息技术的发展,信息的载体-芯片的运用也越来越多了,随之而来的芯片安全性的要求也越来越高了,各个芯片厂商对芯片保密性要求越来越高,芯片的加密,保证了芯片中的信息的安全性.经常有客户打电话过来问,这 ...
- sql server ssl安全错误_渗透测试 丨 SQL注入的攻与防
" 注入攻击漏洞,例如SQL,OS以及LDAP注入.这些攻击发生在当不可信的数据作为命令或者查询语句的一部分,被发送给解释器的时候.攻击者发送的恶意数据可以欺骗解释器,以执行计划外的命令或者 ...
- 复检网站_渗透测试项目分析手段
最近我们Sinesafe参加的几家机构的渗透测试防守方防护方案评估复查,部分防守方缺乏对攻击者的正确认知,攻击者的手法已经比较高超了,不扫描,不落地,污染日志等都很普及了.同时也要正确认知对手:攻防演 ...
最新文章
- flask中使用Flask-SQLALCHEMY-------一个简单的例子
- 小白搞懂了GC全过程,全靠阿里专家12张图
- isa 2006 下发布 owa
- QT的QMessageAuthenticationCode类的使用
- window.addeventlistener 不能调用方法_Java入门第十四课:如何定义”方法“
- git push到GitHub的时候遇到! [rejected] master -> master (non-fast-forward)的问题
- Metro 应用无法打开解决办法
- 计算机实训教学论文,计算机实训教学探索论文
- 2007年8月25日华为的几个面试题
- JetBrains(Intellij, pycharm)多行编辑模式
- 【TSP】基于matlab遗传算法求解中国35省会城市旅行商问题【含Matlab源码 1222期】
- 开源生产排程aps软件dream设计思路分析
- 树莓派的GPIO等接口
- 《机器学习》总结与心得
- 如何让你的YOLOV3模型更小更快?
- matlab中zeros()函数
- JQuery字符串文本替换并且加样式
- Linux C获取当前时间(精确到微秒)
- 智能AR场景模拟书法临摹系统
- 如何在android设备上insmod自己单独编译的.ko,解决签名问题