京東post登陸引數js分析,密碼加密的RSA加密實現
阿新 • • 發佈:2019-01-14
老規矩先用錯誤資訊登陸一下抓一下包,看看有那些post欄位:
uuid: cf0d4f92-c83b-451a-bc31-be4bf9c546a5
eid: 5535JQZQ4ZUMHJEPDFQ7EIQIP4PRSWDLEXGJCVNFQRGNKOKGFFSFHLYDURV5EQVE4JDMIAR3NVD4QEBFQDBSP33GOQ
fp: 2fe86fc6a5b0410641970234f8438902
_t: _t
loginType: c
loginname: 18328491111
nloginpwd: HYnD8Fa/t/8MYKyv3/W7CBix2ILU9WXxgTHyfAVHHWUqbSCd0lVogVWMG4Xmb3fnAM/ILQeiiEeEfP0zWvO0udtgsWANcwEMm55hpFzUnN7xqZIFvpA7F+pRJBaeVfJASCQkzK2jn3vyegTj63UrSv/UQn13mOoX5Xta/XY1Zl4=
authcode: d6f9605df4d24876bf0cff329def7eea
pubKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC7kw8r6tq43pwApYvkJ5laljaN9BZb21TAIfT/vexbobzH7Q8SUdP5uDPXEBKzOjx2L28y7Xs1d9v3tdPfKI2LR7PAzWBmDMn8riHrDDNpUpJnlAGUqJG9ooPn8j7YNpcxCa1iybOlc2kEhmJn5uwoanQq+CA6agNkqly2H4j6wIDAQAB
sa_token: B68C442BE645754F33277E701208059080DD726A94A73F76DEC3053A838549C06EB7D3797CE1C5BBE7C2B2EF9CA7D467C4B841002F8A2DEA0DD3ACC5BA959244A539E8B9D2CB176B62FE436B89B8310978A5D9B99A4545B16012582BCDF61F8FC7A8AE9D3A8CC2F220C2541A6395F39025E34AF37F7AC4996E097D59805880B3433423EAC0F6B09DF302DF2D79502CDAA1528E521CF020D4343C933BA246CA2B2824E2577586610927E2018CCCA818EAC6184A835CB655204F760815434F73028152A1D4D141189661606E03FEC5BF7C4B63EFE990F4D2A5FABD155127ECD0DAD87083218C461051CC16BBFADBDDBF9212BC64BA81312BD0D8C0824AACEB0048489A5E5E6352A8BCE3D1A9EEB9030DA9219B6CBDD6E7013BBB221FEEF4C4CDD4F5C8E878F1BC817248E69ECD43E940B45306C151EB74FE74F48CD4F972B22787917C0746B4ADA5B9A412264B12B8E12EC493B0A29C202099940E5CAB365AF68C04130EB930CDFA7E27D503E05FE442E8B6AF6B91882A1C84E9E99F82AA03A8DB4837C97C0F36949B288E7ABF68DAC81B0C4988D0A84A9D6AA1A1FBD13AAFC98AF1AD4CC6B8D6A286620DE2EF28C9C82908780E850CE7F726436541285F93925861F3B6F8F06041C0A74B83CD64DD588D
seqSid: 512437118155683888
useSlideAuthCode: 1
大概我們就知道我們要分析的欄位有nloginpwd其餘欄位還不清楚,就在上下在看看其他資料包,根據pubkey我們猜測加密方式大概是RSA,繼續檢視其他資料包,找到一個有價值的get包
資訊是:
api_server: "//iv.jd.com/"
bg: "iVBORw0KGgoAAAANSUhEUgAAAWgAAACMCAYAAABRRzP1AABHtU"
challenge: "7eaf1e6f6c1f4cd2a8dae900e3c95837"
message: "success"
o: "loginname"
patch: "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"
static_servers: "//iv.jd.com/"
success: "1"
y: 47
沒有發現明確的關鍵字,但是可以猜想bg、challenge、patch應該和我們的加密引數相關,但是不確定,只有繼續分析加密的js片段:
$.ajax({
type: "POST",
dataType: "text",
url: "../uc/loginService?nr=1&uuid=" + uuid + "&" + location.search.substring(1) + "&r=" + Math.random() + "&version=2015",
contentType: "application/x-www-form-urlencoded; charset=utf-8",
data: {
uuid:$('#uuid').val(),
eid:$('#eid').val(),
fp:$('#sessionId').val(),
_t:$('#token').val(),
loginType:$('#loginType').val(),
loginname:$('#loginname').val(),
nloginpwd:getEntryptPwd($('#nloginpwd').val()),
authcode:authcode,
pubKey:$('#pubKey').val(),
sa_token:$('#sa_token').val(),
seqSid:window._jdtdmap_sessionId,
useSlideAuthCode:$("#useSlideAuthCode").val()
},
其中好幾個欄位都是$("#??")格式,這種表示是來自頁面的,那在看看網頁原始碼
果然發現了很多有價值的東西在post表單中的,其中只有兩個引數是需要單獨獲取的,其餘都是從html原始碼裡面解析出來的
authcode來源
var authcode;
if(useSlideAuthCode){
// authcode = $("#s-authcode").attr('data-code');
authcode = $("#loginsubmit").attr('data-code');
}else{
authcode = $('#authcode').val();
}
是獲取的原始碼中的一個值,再看原始碼 ![在這裡插入圖片描述](https://mmbiz.qpic.cn/mmbiz_png/ibn1F3EPLriax7jlNZ5iaMkjlcsZEquY5aC4LOy3ra2hSnB6SuO9RAFkKPgqPuYswDBnoPxTrQeNIxpMpWkJIwFFQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
看樣子是在驗證碼操作的時候觸發的一個請求,返回的authcode的值,檢視authcode請求的資料包
d: 0hE005mmwo5~7410o0110000101000001e10h000000y107101000g109101000h107101000h104000000g102000000h104000000h105102000g106000000g104000000h106000000h104000000i103101000g102000000g1020000017104000000f10a103000f10e102000i105000000f102000000g104000000h101000000h102102000g104000000h102000000i102101000g000000005j
c: 9c1dc65956154419917df6319a6dd8cd
w: 278
appId: 1604ebb2287
scene: login
product: click-bind-suspend
e: 5535JQZQ4ZUMHJEPDFQ7EIQIP4PRSWDLEXGJCVNFQRGNKOKGFFSFHLYDURV5EQVE4JDMIAR3NVD4QEBFQDBSP33GOQ
s: 5773112901220889029
o: 18328491111
callback: jsonp_04645774203955564
這個請求看起來不是那麼友好,有好幾個疑似加密欄位,這個引數暫時放放,繼續分析我們的passWord的加密。
繼續深入getEntryptPwd($(’#nloginpwd’).val()),檢視原始碼
function getEntryptPwd(pwd){
var pubKey = $('#pubKey').val();
if(!pwd || !pubKey || !SysConfig.encryptInfo){
return pwd;
}
var encrypt = new JSEncrypt();
encrypt.setPublicKey(pubKey);
return encrypt.encrypt(pwd);
}
核心的就兩行
encrypt.setPublicKey(pubKey); return encrypt.encrypt(pwd);這必定是RSA加密無疑了,繼續檢視原始碼,單獨的一個原始碼檔案,一共3300多行,刪減版如下
/*! JSEncrypt v2.3.1 | https://npmcdn.com/[email protected]/LICENSE.txt */
(function(a, b) {
if (typeof define === "function" && define.amd) {
define(["exports"], b)
} else {
if (typeof exports === "object" && typeof exports.nodeName !== "string") {
b(module.exports)
} else {
b(a)
}
}
}
)(this, function(ap) {
var bE;
var n = 244837814094590;
var aV = ((n & 16777215) == 15715070);
function bf(z, t, L) {
if (z != ) {
if ("number" == typeof z) {
this.fromNumber(z, t, L)
} else {
if (t == && "string" != typeof z) {
this.fromString(z, 256)
} else {
this.fromString(z, t)
}
}
}
}
function bm() {
return new bf()
}
function a7(bX, t, z, bW, bZ, bY) {
while (--bY >= 0) {
var L = t * this[bX++] + z[bW] + bZ;
bZ = Math.floor(L / 67108864);
z[bW++] = L & 67108863
}
return bZ
}
······刪減了3000行左右
a3.prototype.decrypt = function(t) {
try {
return this.getKey().decrypt(aW(t))
} catch (z) {
return false
}
}
;
a3.prototype.encrypt = function(t) {
try {
return ae(this.getKey().encrypt(t))
} catch (z) {
return false
}
}
;
a3.prototype.getKey = function(t) {
if (!this.key) {
this.key = new bx();
if (t && {}.toString.call(t) === "[object Function]") {
this.key.generateAsync(this.default_key_size, this.default_public_exponent, t);
return
}
this.key.generate(this.default_key_size, this.default_public_exponent)
}
return this.key
}
;
a3.prototype.getPrivateKey = function() {
return this.getKey().getPrivateKey()
}
;
a3.prototype.getPrivateKeyB64 = function() {
return this.getKey().getPrivateBaseKeyB64()
}
;
a3.prototype.getPublicKey = function() {
return this.getKey().getPublicKey()
}
;
a3.prototype.getPublicKeyB64 = function() {
return this.getKey().getPublicBaseKeyB64()
}
;
a3.version = "2.3.1";
ap.JSEncrypt = a3
});
JSEncrypt是前端使用的實現RSA加密的庫,看樣子應該比較標準,那就試試能不能改寫了,複製全部原始碼到node.js,會提示navigator、window未定義,這個問題很簡單,在檔案頭定義 var navigator = this; var window = this
然後在檔案尾部寫個呼叫程式試試
function test(pwd) {
var pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC7kw8r6tq43pwApYvkJ5laljaN9BZb21TAIfT/vexbobzH7Q8SUdP5uDPXEBKzOjx2L28y7Xs1d9v3tdPfKI2LR7PAzWBmDMn8riHrDDNpUpJnlAGUqJG9ooPn8j7YNpcxCa1iybOlc2kEhmJn5uwoanQq+CA6agNkqly2H4j6wIDAQAB";
var encrypt = new JSEncrypt();
encrypt.setPublicKey(pubKey);
return encrypt.encrypt(pwd);
}
是可以成功返回RSA加密結果的 ![在這裡插入圖片描述](https://mmbiz.qpic.cn/mmbiz_png/ibn1F3EPLriax7jlNZ5iaMkjlcsZEquY5aC5gdDCRW74jDPfuVNlpr7SYayxX6N55GjiaOibTTUoCRXETKjGJnSqPLg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1&retryload=1) 京東的post請求不是太難,引數也能在原始碼中找到,但是他的難度在發出post請求之前的一個get請求,這個get請求和驗證有關,和使用者名稱相關,簡單看了一下感覺有點複雜,留在第二篇講獲取authcode引數的其他引數是怎麼來的。