整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

「JS 逆向百例」HN某服务网登录逆向,验证码形同虚

「JS 逆向百例」HN某服务网登录逆向,验证码形同虚设

本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!

逆向目标

  • 目标:某政务服务网登录接口
  • 主页:aHR0cHM6Ly9sb2dpbi5obnp3ZncuZ292LmNuL3RhY3MtdWMvbG9naW4vaW5kZXg=
  • 接口:aHR0cHM6Ly9sb2dpbi5obnp3ZncuZ292LmNuL3RhY3MtdWMvbmF0dXJhbE1hbi9sb2dpbk5v
  • 逆向参数:Form Data:loginNo、loginPwd、code、requestUUIDRequest Headers:token

抓包分析

本次逆向目标来源于某位粉丝的求助:

随便输入账号密码点击登陆,抓包发现接口的 Request Headers 有个加密参数 token,Form Data 里 loginNo、loginPwd、code、requestUUID 都是经过加密处理了的,loginNo 和 loginPwd 应该就是用户名密码了,由于登录前需要过一下滑动验证码,因此可以猜测另外两个参数与验证码有关,不过仅从抓包来看,另外两个参数类似于 uuid 的格式,不太像验证码的参数。

另外可以注意到登陆前,有两次 csrfSave 和一次 verCode 的请求,正常请求成功就会返回一个 JSON,里面有个 data 参数,后面应该是会用到的。

参数逆向

Form Data

先看 Form Data,搜索任意一个参数,比如 loginNo,很容易在 login.js 里找到加密的地方,用户名和密码都经过了 encrypt 这个函数进行加密,backUrl 这个值,是利用 localStorage 属性,从浏览器储存的键值对的数据里取的,为空也不影响。

跟进 encrypt,可以看到用到了 JSEncrypt,标准的 RSA 加密:

再看看 loginCode,直接搜索这个值,可以看到是 verCode 这个请求返回的:

然后再看看 requestUUID,其值就是个 UUID,直接在当前文件(login.js)里搜索,可以看到定义的地方,有个 uploadUUID() 方法,就是在设置 UUID 的值,方法里面是向一个 uploadIdentifier 的接口发送了 post 请求:

这里注意,如果你直接全局搜索 UUID 的话,还可以在 common.js 里搜索到一个方法,经过测试,直接使用这个方法生成一个 uuid 也是可以请求通过的,这网站可能不严谨,不会严格检测这个值。

Request Headers

Form Data 解决了,再来看看 Request Headers 里的 token 参数,由于它存在于请求头里,所以我们可以通过 Hook 的方式来查找其生成的地方:

(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 之类的关键字,很容易在 common.js 里找到,当我们点击登陆,会有一个 csrfSave 的请求,返回的 data 值,经过 encrypt 方法加密后就是登陆请求头的 token 了。

这个 token 参数在很多请求中都会用到,生成方法是一样的,都是拿 csrfSave 请求返回的 data 经过 RSA 加密后得到的:

另外注意一点的就是,以上所有涉及到网络请求的,Cookie 都需要一个 SESSION 值,这个可以在首次访问页面获取到:

登陆流程

这里我们理一下登陆的流程:

  1. 访问首页拿 Cookie 中的 SESSION 值;
  2. 访问 csrfSave,拿到一个 data 值,经过 RSA 加密得到 token,携带 token 访问 uploadIdentifier,拿到 uuid;
  3. 访问 csrfSave,拿到一个 data 值,经过 RSA 加密得到 token,携带 token 访问 verCode,拿到 code;
  4. 访问 csrfSave,拿到一个 data 值,经过 RSA 加密得到 token,携带 token、uuid、code 和加密后的账号密码,访问 loginNo 登录。

这里第2步,也可以直接用 Python 或者 JS 生成一个 uuid,网站校验不严格,也可以通过,另外可以看出这个滑块是假的,通过代码可以无视滑块进行登录。

完整代码

GitHub 关注 K 哥爬虫,持续分享爬虫相关代码!欢迎 star !https://github.com/kgepachong/

以下只演示部分关键代码,不能直接运行! 完整代码仓库地址:https://github.com/kgepachong/crawler/

JavaScript 加密代码

/*==================================# @Time    : 2022-01-11
# @Author  : 微信公众号:K哥爬虫
# @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;
}

// 测试样例
// console.log(encrypt("15555555555"))

Python 登录代码

个登录界面可能有一点点。。。[黑线]

源码放着了,要自己拿去吧[奸笑]


<!DOCTYPE html>

<html>

<head>

<title>Login Page</title>

<style>

body {

background-color: #000;

color: #fff;

text-align: center;

padding-top: 100px;

font-family: 'Courier New', Courier, monospace;

}


h1 {

font-size: 50px;

margin-bottom: 30px;

color: #ff0000;

text-shadow: 0 0 10px #ff0000;

}


table {

margin: 0 auto;

width: 400px;

}


th,

td {

padding: 10px;

}


input[type="text"],

input[type="date"] {

width: 300px;

padding: 5px;

border-radius: 5px;

border: 1px solid #ff0000;

background-color: #000;

color: #ff0000;

}


input[type="submit"] {

margin-top: 20px;

padding: 10px;

background-color: #ff0000;

color: #fff;

border: none;

border-radius: 5px;

cursor: pointer;

transition: background-color 0.3s ease;

animation: pulseEffect 1s infinite;

}


input[type="submit"]:hover {

background-color: #ff6666;

animation: none;

}


.success-message {

margin-top: 30px;

display: none;

animation: fadeInEffect 2s;

}


.checkbox-option {

margin-top: 20px;

animation: slideInEffect 2s;

}


.contact-info {

margin-top: 40px;

animation: bounceEffect 1.5s infinite;

}


/* Animations */

@keyframes pulseEffect {

0% {

transform: scale(1);

}


50% {

transform: scale(1.2);

}


100% {

transform: scale(1);

}

}


@keyframes fadeInEffect {

from {

opacity: 0;

}

to {

opacity: 1;

}

}


@keyframes slideInEffect {

from {

transform: translateX(-100%);

}

to {

transform: translateX(0);

}

}


@keyframes bounceEffect {

0%,

100% {

transform: scale(1);

}

50% {

transform: scale(1.2);

}

}

</style>

<script>

window.onload=function () {

document.querySelector('form').addEventListener('submit', function (event) {

event.preventDefault();

var successMessage=document.getElementById('successMessage');

successMessage.style.display='block';

successMessage.style.animation='fadeInEffect 2s forwards';


var submitButton=document.getElementById('submitButton');

submitButton.disabled=true;

});


document.getElementById('closeButton').addEventListener('click', function () {

var successMessage=document.getElementById('successMessage');

successMessage.style.display='none';

});

}

</script>

</head>

<body>

<h1>死亡协议</h1>

<form>

<table>

<tr>

<th>受害者姓名</th>

<td><input type="text"></td>

</tr>

<tr>

<th>身份证号码</th>

<td><input type="text"></td>

</tr>

<tr>

<th>iphone</th>

<td><input type="text"></td>

</tr>

<tr>

<th>邮箱</th>

<td><input type="text"></td>

</tr>

<tr>

<th>预定日期</th>

<td><input type="date"></td>

</tr>

</table>

<input id="submitButton" type="submit" value="签署协议">

</form>

<div id="successMessage" class="success-message">

<p>最近自杀人数较多,可能会延期</p>

<button id="closeButton">关闭</button>

</div>

<div class="checkbox-option">

<input type="checkbox" id="agreementCheckbox">

<label for="agreementCheckbox">我同意所有要求</label>

</div>

<div class="contact-info">

<p>客服:LHTZ173@163.com</p>

</div>

</body>

家好,今天分享的是仿京东登录页面的简单实现方法(结构与样式),首先我们依旧是先看下效果图

下面是HTML结构

下面是CSS样式

PS:本人也是小白一枚,自学没几天,疏漏之处在所难免,请多担待!