創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),榆中企業(yè)網(wǎng)站建設(shè),榆中品牌網(wǎng)站建設(shè),網(wǎng)站定制,榆中網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,榆中網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
本文章中所有內(nèi)容僅供學(xué)習(xí)交流,抓包內(nèi)容、敏感網(wǎng)址、數(shù)據(jù)接口均已做脫敏處理,嚴(yán)禁用于商業(yè)用途和非法用途,否則由此產(chǎn)生的一切后果均與作者無(wú)關(guān),若有侵權(quán),請(qǐng)聯(lián)系我立即刪除!
目標(biāo):某政務(wù)服務(wù)網(wǎng)登錄接口
主頁(yè):aHR0cHM6Ly9sb2dpbi5obnp3ZncuZ292LmNuL3RhY3MtdWMvbG9naW4vaW5kZXg=
接口:aHR0cHM6Ly9sb2dpbi5obnp3ZncuZ292LmNuL3RhY3MtdWMvbmF0dXJhbE1hbi9sb2dpbk5v
逆向參數(shù):
Form Data:loginNo、loginPwd、code、requestUUID
Request Headers:token
本次逆向目標(biāo)來(lái)源于某位粉絲的求助:
隨便輸入賬號(hào)密碼點(diǎn)擊登陸,抓包發(fā)現(xiàn)接口的 Request Headers 有個(gè)加密參數(shù) token,F(xiàn)orm Data 里 loginNo、loginPwd、code、requestUUID 都是經(jīng)過(guò)加密處理了的,loginNo 和 loginPwd 應(yīng)該就是用戶名密碼了,由于登錄前需要過(guò)一下滑動(dòng)驗(yàn)證碼,因此可以猜測(cè)另外兩個(gè)參數(shù)與驗(yàn)證碼有關(guān),不過(guò)僅從抓包來(lái)看,另外兩個(gè)參數(shù)類似于 uuid 的格式,不太像驗(yàn)證碼的參數(shù)。
另外可以注意到登陸前,有兩次 csrfSave 和一次 verCode 的請(qǐng)求,正常請(qǐng)求成功就會(huì)返回一個(gè) JSON,里面有個(gè) data 參數(shù),后面應(yīng)該是會(huì)用到的。
先看 Form Data,搜索任意一個(gè)參數(shù),比如 loginNo,很容易在 login.js 里找到加密的地方,用戶名和密碼都經(jīng)過(guò)了 encrypt 這個(gè)函數(shù)進(jìn)行加密,backUrl 這個(gè)值,是利用 localStorage 屬性,從瀏覽器儲(chǔ)存的鍵值對(duì)的數(shù)據(jù)里取的,為空也不影響。
跟進(jìn) encrypt,可以看到用到了 JSEncrypt,標(biāo)準(zhǔn)的 RSA 加密:
再看看 loginCode,直接搜索這個(gè)值,可以看到是 verCode 這個(gè)請(qǐng)求返回的:
然后再看看 requestUUID,其值就是個(gè) UUID,直接在當(dāng)前文件(login.js)里搜索,可以看到定義的地方,有個(gè) uploadUUID()
方法,就是在設(shè)置 UUID 的值,方法里面是向一個(gè) uploadIdentifier 的接口發(fā)送了 post 請(qǐng)求:
這里注意,如果你直接全局搜索 UUID 的話,還可以在 common.js 里搜索到一個(gè)方法,經(jīng)過(guò)測(cè)試,直接使用這個(gè)方法生成一個(gè) uuid 也是可以請(qǐng)求通過(guò)的,這網(wǎng)站可能不嚴(yán)謹(jǐn),不會(huì)嚴(yán)格檢測(cè)這個(gè)值。
Form Data 解決了,再來(lái)看看 Request Headers 里的 token 參數(shù),由于它存在于請(qǐng)求頭里,所以我們可以通過(guò) Hook 的方式來(lái)查找其生成的地方:
(function () {
var org = window.XMLHttpRequest.prototype.setRequestHeader;
window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) {
if (key == 'token') {
debugger;
}
return org.apply(this, arguments);
};
})();
這里我們也可以直接搜索 token、setRequestHeader 之類的關(guān)鍵字,很容易在 common.js 里找到,當(dāng)我們點(diǎn)擊登陸,會(huì)有一個(gè) csrfSave 的請(qǐng)求,返回的 data 值,經(jīng)過(guò) encrypt 方法加密后就是登陸請(qǐng)求頭的 token 了。
這個(gè) token 參數(shù)在很多請(qǐng)求中都會(huì)用到,生成方法是一樣的,都是拿 csrfSave 請(qǐng)求返回的 data 經(jīng)過(guò) RSA 加密后得到的:
另外注意一點(diǎn)的就是,以上所有涉及到網(wǎng)絡(luò)請(qǐng)求的,Cookie 都需要一個(gè) SESSION 值,這個(gè)可以在首次訪問(wèn)頁(yè)面獲取到:
這里我們理一下登陸的流程:
這里第2步,也可以直接用 Python 或者 JS 生成一個(gè) uuid,網(wǎng)站校驗(yàn)不嚴(yán)格,也可以通過(guò),另外可以看出這個(gè)滑塊是假的,通過(guò)代碼可以無(wú)視滑塊進(jìn)行登錄。
GitHub 關(guān)注 K 哥爬蟲(chóng),持續(xù)分享爬蟲(chóng)相關(guān)代碼!歡迎 star !https://github.com/kgepachong/
以下只演示部分關(guān)鍵代碼,不能直接運(yùn)行! 完整代碼倉(cāng)庫(kù)地址:https://github.com/kgepachong/crawler/
/* ==================================
# @Time : 2022-01-11
# @Author : 微信公眾號(hào):K哥爬蟲(chóng)
# @FileName: encrypt.js
# @Software: PyCharm
# ================================== */
JSEncrypt = require("jsencrypt")
function encrypt(pwd){
var key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsgDq4OqxuEisnk2F0EJFmw4xKa5IrcqEYHvqxPs2CHEg2kolhfWA2SjNuGAHxyDDE5MLtOvzuXjBx/5YJtc9zj2xR/0moesS+Vi/xtG1tkVaTCba+TV+Y5C61iyr3FGqr+KOD4/XECu0Xky1W9ZmmaFADmZi7+6gO9wjgVpU9aLcBcw/loHOeJrCqjp7pA98hRJRY+MML8MK15mnC4ebooOva+mJlstW6t/1lghR8WNV8cocxgcHHuXBxgns2MlACQbSdJ8c6Z3RQeRZBzyjfey6JCCfbEKouVrWIUuPphBL3OANfgp0B+QG31bapvePTfXU48TYK0M5kE+8LgbbWQIDAQAB";
var encrypt = new JSEncrypt();
encrypt.setPublicKey(key);
var encrypted = encrypt.encrypt(pwd);
return encrypted;
}
// 測(cè)試樣例
// console.log(encrypt(""))
# ==================================
# @Time : 2022-01-11
# @Author : 微信公眾號(hào):K哥爬蟲(chóng)
# @FileName: hnzww_login.py
# @Software: PyCharm
# ==================================
import execjs
import requests
cookies = {}
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
with open("encrypt.js", encoding="utf-8") as f:
js = execjs.compile(f.read())
def csrf_save():
url = "脫敏處理,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler"
headers = {"User-Agent": UA}
response = requests.post(url=url, headers=headers, cookies=cookies).json()
data = response["data"]
return data
def get_session():
url = "脫敏處理,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler"
headers = {"User-Agent": UA}
response = requests.get(url=url, headers=headers)
cookies.update(response.cookies.get_dict())
def get_uuid():
url = "脫敏處理,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler"
headers = {
"User-Agent": UA,
"token": js.call("encrypt", csrf_save())
}
response = requests.post(url=url, headers=headers, cookies=cookies).json()
uuid = response["data"]
return uuid
def ver_code():
url = "脫敏處理,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler"
headers = {
"User-Agent": UA,
"token": js.call("encrypt", csrf_save())
}
response = requests.post(url=url, headers=headers, cookies=cookies).json()
data = response["data"]
return data
def login(phone, pwd, code, uuid):
url = "脫敏處理,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler"
headers = {
"User-Agent": UA,
"token": js.call("encrypt", csrf_save())
}
data = {
"backUrl": "",
"loginNo": js.call("encrypt", phone),
"loginPwd": js.call("encrypt", pwd),
"code": code,
"requestUUID": uuid,
"guoBanAuthCode": ""
}
response = requests.post(url=url, headers=headers, cookies=cookies, data=data)
print(response.json())
def main():
phone = input("請(qǐng)輸入賬號(hào):")
pwd = input("請(qǐng)輸入密碼:")
get_session()
uuid = get_uuid()
code = ver_code()
login(phone, pwd, code, uuid)
if __name__ == '__main__':
main()