某大学登陆流程分析
动手!
首先登录、抓包,查看所提交的参数,password
被加密并经过base64编码。
F12审查元素,查看登陆表单以及所绑定事件。
将password
和pwdDefaultEncryptSalt
传入_etd2
函数,pwdDefaultEncryptSalt
(下文中简称key)可在表单中获取。
function doLogin() {
var username = casLoginForm.find("#username");
var password = casLoginForm.find("#password");
if (!checkRequired(username, "usernameError")) {
username.focus();
return false;
}
if (!checkRequired(password, "passwordError")) {
password.focus();
return false;
}
var captchaResponse = casLoginForm.find("#captchaResponse");
if (!checkRequired(captchaResponse, "cpatchaError")) {
captchaResponse.focus();
return false;
}
_etd2(password.val(), casLoginForm.find("#pwdDefaultEncryptSalt").val());
}
将password
和key
传入encryptAES
,可知加密算法为AES。
function _etd2(_p0, _p1) {
try {
var _p2 = encryptAES(_p0, _p1);
$("#casLoginForm").find("#passwordEncrypt").val(_p2);
} catch (e) {
$("#casLoginForm").find("#passwordEncrypt").val(_p0);
}
}
_rds
函数为产生指定长度随机字符串,encryptAES
函数将64位的随机字符串拼接上password
作为第一个参数,key
和16位随机字符串作为后两个参数传入_gas
函数。
function encryptAES(data, _p1) {
if (!_p1) {
return data;
}
var encrypted = _gas(_rds(64) + data, _p1, _rds(16));
return encrypted;
}
var $_chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
var _chars_len = $_chars.length;
function _rds(len) {
var retStr = '';
for (i = 0; i < len; i++) {
retStr += $_chars.charAt(Math.floor(Math.random() * _chars_len));
}
return retStr;
}
可见,加密算法为AES,待加密字符为64位的随机数拼接上password
,密钥为key
,初始向量IV为16位随机字符串,CBC模式,填充方式为PKCS7。
function _gas(data, key0, iv0) {
key0 = key0.replace(/(^\s+)|(\s+$)/g, "");
var key = CryptoJS.enc.Utf8.parse(key0);
var iv = CryptoJS.enc.Utf8.parse(iv0);
var encrypted = CryptoJS.AES.encrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
base64编码
function() {
var u = CryptoJS
, p = u.lib.WordArray;
u.enc.Base64 = {
stringify: function(d) {
var l = d.words
, p = d.sigBytes
, t = this._map;
d.clamp();
d = [];
for (var r = 0; r < p; r += 3)
for (var w = (l[r >>> 2] >>> 24 - 8 * (r % 4) & 255) << 16 | (l[r + 1 >>> 2] >>> 24 - 8 * ((r + 1) % 4) & 255) << 8 | l[r + 2 >>> 2] >>> 24 - 8 * ((r + 2) % 4) & 255, v = 0; 4 > v && r + 0.75 * v < p; v++)
d.push(t.charAt(w >>> 6 * (3 - v) & 63));
if (l = t.charAt(64))
for (; d.length % 4; )
d.push(l);
return d.join("")
},
parse: function(d) {
var l = d.length
, s = this._map
, t = s.charAt(64);
t && (t = d.indexOf(t),
-1 != t && (l = t));
for (var t = [], r = 0, w = 0; w < l; w++)
if (w % 4) {
var v = s.indexOf(d.charAt(w - 1)) << 2 * (w % 4)
, b = s.indexOf(d.charAt(w)) >>> 6 - 2 * (w % 4);
t[r >>> 2] |= (v | b) << 24 - 8 * (r % 4);
r++
}
return p.create(t, r)
},
_map: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
}
}
登陆复现
解密验证,发现末尾为密码。(推荐工具:cyberchef)
CBC模式
可见,初始向量的不同只影响第一块的明文,所以初始向量可自定义。
复现代码
import base64
import random
import requests
import re
from Crypto.Cipher import AES
import json
#随机字符串产生
def getRandomN(N):
s = ''
for _ in range(N):
s += str(random.randint(0,9))
return s
#PKCS7填充
def pad(data):
bs = AES.block_size
data += (bs - len(data)%bs) * chr(bs - len(data)%bs)
return data
#加密函数
def encrypt(data,key,iv):
iv = iv.encode('utf-8')
cipher = AES.new(key.encode('utf-8'),AES.MODE_CBC,iv)
data = cipher.encrypt(pad(data).encode('utf-8'))
return data
#解密函数
def decrypt(data,key):
iv = '0000000000000000'.encode('utf-8')
cipher = AES.new(key,AES.MODE_CBC,iv)
data = cipher.decrypt(data)
return (data[64:])
#base64编码
def getPwd(data,key):
iv = getRandomN(16)
data = getRandomN(64) + data
return (base64.b64encode(encrypt(data,key,iv)).decode('utf-8'))
#登陆函数
def login(username,password):
url = 'https://xxx.edu.cn'
r = ses.get(url,headers=header)
text = r.text
l = re.findall(r'<input type=\"hidden\" .*?=\".*?\" value=\"(.*?)\"',text)
password = getPwd(password,l[5])
data = {
'username':username,
'password':password,
'lt':l[0],
'dllt':l[1],
'execution':l[2],
'_eventId':l[3],
'rmShown':l[4],
}
r = ses.post(url,data=data,allow_redirects=False)
header = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36',
}