日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

hikaridatasource 加密后登陆不上_渗透测试 | 突破前端JS加密限制

發布時間:2024/9/18 HTML 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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加密限制的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。