某OA登陆数据包字段加密问题

Last updated on 2 months ago

在某次测试,遇到一OA页面存在验证码复用,本想可以直接水个洞交差了,但密码字段是加密,没法直接水洞,故做个笔记。

0x01 INFO

上图来自官网测试环境

如图,js加密函数调用为:desEncrypt(document.forms[0].newPassWord.value)

i

而且调用加密函数时,会发起一个ajax请求,同时服务端返回一串js代码。

分析发现加密函数:desEncrypt()定义在:[security.js]文件中:

把[security.js]保存,格式化一下。

Look look发现,该js文件中定义了 aes/des加密调用过程:

进行加密前,先向 [https://demo.xxx.com/resource/js/session.jsp] 发起请求,服务端返回包含当前SessionId的js,并将SessionId作为安全秘钥进行aes/des加密运算。

继续look发现,修改密码页面返回的数字有识别度:1为验证错误,2为原密码错误

0x02 刨析

​ 服务器后端会先校验验证码是否正确,然后再校验原密码正确性,正确后再进行下一步-修改密码,由于验证可复用(只要前端页面不刷新,验证码就不会失效),因此可以重复发起请求去验证原密码:当返数字非1、非2时则可能是原密码校验成功。

关于密码字段加密,可通过调用desEncrypt()进行加密。

0x03 准备

1、phantomJS
2、jsEncrypter - jsEncrypter_des.js;
3、保存标站点的【 security.js、base64.js、aes.js】;

4、拦截登录请求包,Ctrl+R,放掉当前拦截的数据包,重复发送,复制返回内容。

5、新建getSessionId()方法,写入返回的 SessionId值(每次变更后都需要修改):

注释引入文件以及ajax请求部分代码,新增内容:

1
2
str = getSessionId()
return str

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// filename: security.js

// Com_RegisterFile("security.js");
// Com_IncludeFile("aes.js");
// Com_IncludeFile("base64.js");

var SECURITYKEY = {
toHexString: function(str) {
var temp = "";
for (i = 0; i < str.length; i++) {
temp += str.charCodeAt(i).toString(16)
}
return temp
},
_2: function() {
// $.ajax({
// async: false,
// dataType: "script",
// url: Com_Parameter.ResPath + "js/session.jsp?_=" + new Date().getTime()
// });
// var str = "";


// if (window.getSessionId) {
// str = getSessionId()
// }
str = getSessionId()
return str
},
supportEncodings: function() {
return ["aes", "des"]
},
get: function(encodeType) {
var str = SECURITYKEY._2();
if (encodeType == null || encodeType == 'aes') {
if (str.length < 32) {
str += "abcdefghijklmnopqrstuvwxyz1234567890"
}
str = str.toUpperCase();
var key = {};
key.key = str.substring(0, 16);
key.iv = str.substring(16, 32);
key.security = "\u4435\u5320\u4d35"
} else {
if (str.length < 16) {
str += "abcdefghijklmnopqrstuvwxyz"
}
str = str.toUpperCase();
var key = {};
key.key = SECURITYKEY.toHexString(str.substring(0, 8));
key.iv = SECURITYKEY.toHexString(str.substring(8, 16));
key.security = "\u4445\u5320\u4d45"
}
return key
},
getCookie: function(c_name) {
if (document.cookie.length > 0) {
var cookies = document.cookie.split(";");
for (i = 0; i < cookies.length; i++) {
var xc = cookies[i];
var cn = xc.substring(0, xc.indexOf("=")).toUpperCase();
cn = cn.replace(/^\s*/, "").replace(/\s*$/, "");
if (cn == c_name) {
return unescape(xc.substring(xc.indexOf("=") + 1, xc.length))
}
}
}
return ""
}
};

function base64Convert() {
return "\u4241\u5345\u3634{" + Base64.encode(arguments[0]) + "}"
}

function _0(xForm) {
if (xForm == null) {
xForm = document.forms[0]
}
if (xForm != null) {
if (xForm.encoding == "multipart/form-data") {
return true
}
}
return false
}

function _1(str, xForm, isX) {
if (_0(xForm)) {
return str
} else {
var val = str;
if (str != null && str.length > 0) str = base64Convert(str);
if (val != str) {
if (isX == true) {
val = "\u4645\u5810\u4d40" + str
} else {
val = "\u4649\u5820\u4d45" + str
}
}
return val
}
}

function desEncrypt(value, xForm, type) {
if (_0(xForm)) {
return value
} else {
var keyObj = {};
if (type == null || "aes" == type.toLowerCase()) {
keyObj = SECURITYKEY.get();
value = CryptoJS.AES.encrypt(value, CryptoJS.enc.Utf8.parse(keyObj.key), {
iv: CryptoJS.enc.Utf8.parse(keyObj.iv)
}).toString()
} else {
keyObj = SECURITYKEY.get('des');
value = CryptoJS.DES.encrypt(value, CryptoJS.enc.Hex.parse(keyObj.key), {
iv: CryptoJS.enc.Hex.parse(keyObj.iv)
})
}
return keyObj.security + value
}
}

function base64Encode(str, xForm) {
return _1(str, xForm)
}

function base64Encodex(str, xForm) {
return _1(str, xForm, true)
}

function getSessionId(){
return "53AD650E8542F6E2723515913D104FC2"
}

6、burpsuite 加载 jsEncrypter 插件,编辑脚本 jsEncrypter_des.js:

运行phantomJS 测试可用性(使用gitbash,避免乱码显示不完整)

1
phantomJS jsEncrypter_des.js

加密后的密码有特殊字符,无法全部直接填充使用,把git bash中输入内容保存为txt,去除【特殊字符】和【==】再导入即可。

0x04 验证

it’s great!


某OA登陆数据包字段加密问题
https://guosec.online/posts/8fc8f9f9.html
Posted on
August 28, 2021
Updated on
November 14, 2023
Licensed under
本博客所有文章除特别声明外,均采用  协议,转载请注明出处!