POST绕过滑动拼图验证,批量查询某成绩的试验

在越来越重视网络信息安全的今天,各类网上信息查询网站的设计也越来越先进,以往的数字验证码,滑动验证码都淘汰了,纷纷使用了滑动拼图验证码,如下图:

其原理是,在查询页面添加了一个隐藏input,用于提交滑动验证成功后返回的__RequestVerificationToken,如果输入和这个全部正确,就用json格式返回成绩,并用JQ填写在网页上供翻页查询。

校验的JS代码为:

<script>
function submitForm() {
var key1 = $.trim($(“#key1”).val());
var key2 = $.trim($(“#key2”).val());

if (key1 == “”) {
PopErr(“请输入 考生号 或 准考证号”);
return false;
}

if (key2 == “” || key2.length!=4) {
PopErr(“请输入身份证号后四位”);
return false;
}

if ($(“.code”).length == 1) {
var verifyCode = $(“.code”).val();
if (verifyCode == “”) {
PopErr(“请输入验证码”);
return false;
}

if (chkCode.toLowerCase() != verifyCode.toLowerCase()) {
PopErr(“验证码不正确”);
return false;
}
}

$(“.inquire”).attr(“disabled”, “disabled”);
$(“.inquire”).val(“正在查询…”);
return true;
}
var msg = “”;
if (msg != “”) {
PopErr(msg);
}
</script>

我们在用POST查询时,如果没有获取正确的验证token,是无法进行查询的。能否先在网页上手工滑动通过后,将token复制出来使用呢?下面是滑动成功后返回的token:

jQuery111004234991525023184_1557704440595({state: 0, msg: “正确”, data: 42, token: “D70B58D7CF5EA40F79B0C16DA74C5656″})
data:42
msg:”正确”
state:0
token:
“D70B58D7CF5EA40F79B0C16DA74C5656”

经测试,这个token是“一次性钥匙”,第一次查询是可用的,能够查询到成绩,第二次使用就失效了。

能否绕过呢?我记得2018年中旬时,这网站过滤不严格,这参数是可以不提供的,所以能绕过它进行查询,现在测试发现已修补了漏洞,POST提示验证码错误了:

function loginNCEE(token) {

var key1 = $(“#key1”).val();
var key2 = $(“#key2”).val();
var NECaptchaValidate = $(“input[name=’NECaptchaValidate’]”).val();

$.ajax({
url: Host + “/temptotal?rnd=” + Math.random() + “&StudentNo=” + key1 + “&SFZH4W=” + key2 + “&NECaptchaValidate=” + NECaptchaValidate,
method: ‘Post’,
dataType: “json”,
success: function (data) {
if (data.success == “0”) {
PopErr(data.msg);
captchaIns.refresh();
resetQuery();

} else {
var expiresDate = new Date();
expiresDate.setTime(expiresDate.getTime() + (5 * 60 * 1000));// 过期时间5分钟
$.cookie(‘user’, JSON.stringify(data.score), { expires: expiresDate });
$.cookie(‘smallscore’, JSON.stringify(data.scores), { expires: expiresDate });
$.cookie(‘luqu’, JSON.stringify(data.luqu), { expires: expiresDate });
window.location.href = “/nceeresult”;
}
}, error: function (e) {
consoleErr(e);
resetQuery();
}
});
}

function loginCHKNCEE(token) {
var key1 = $(“#key1”).val();
var key2 = $(“#key2”).val();

$.ajax({
url: Host + “/temptotalCHK?rnd=” + Math.random() + “&StudentNo=” + key1 + “&SFZH4W=” + key2,
method: ‘Post’,
dataType: “json”,
success: function (data) {
if (data.success == “0”) {
PopErr(“输入信息有误,请重新输入!”);
resetQuery();

} else {
var expiresDate = new Date();
expiresDate.setTime(expiresDate.getTime() + (5 * 60 * 1000));// 过期时间5分钟
$.cookie(‘user’, JSON.stringify(data.score), { expires: expiresDate });
window.location.href = “/nceechkresult”;
}
}, error: function (e) {
consoleErr(e);
resetQuery();
}
});
}

接下来,我们研究一下token是怎么生成的,如何获取。

用抓包软件,分析下数据,token是用GET方式提交获取的:

Request URL:http://171.34.169.85/api/checkcode

callback:jQuery111004234991525023184_1557704440595

data:N4IgkgJiBcIIwA4BsBWADAZgwJhAGhAAcB7ASwDsAXGAFgwMtIFsBTAZ0IENyZsMakBCJ0osANqTbVYcPHBQoA7IrQ01ORQgA+2OQuWr12AJw0t9eUpVq6GNNi009Vw7bgOUzgzayItir2t1DS0EQNcsfi1jcJ9+BzhZS29glGMtd1jgxRQMi30g2wQEp2TCrGM0DM8yiIxjbThBWp8aNCQMgJb1GjgzOBjuuhpsB2w0LOG7HSSCiLp0vkn+AR1SudaUM2wajZ6kMea94ZUdLuP+TR0wof5kHUGLlDgqu2WFdIxZlx8lXJxlkh2uZ8j91AcHPxAdMMLswXRFFEMEd4RhFEgOmjlgg+uYbhcEDRFOZHqjjLDHBNbqZcr1lsZno5vikFkg4I5dNSkMS6PSEBhHOsycZ2TQ4Sy2kgBQJJm0EDzxYUBApBbLFMZ0ryhjQEGhFCAAL5AA
type:0
_:1557704440597

我们将为些数据模拟GET再提交一下,提示参数有错误:

再找到验证码生成的JS:http://gkcfyzm.jxedu.gov.cn/drag.js

var url = “http://171.34.169.85/api/”;
var Id = “”;
$.getScript(“http://171.34.169.85/res/lz-string.min.js”);
/*
* drag 1.1
* date 2017-02-10
* 获取滑块验证码
* JavaScript工具推荐:
* http://tool.lu/js
*/
(function ($) {
var __imgx = 0, //图片宽度
__imgy = 0, //图片高度
__spec = “”,//图片尺寸
__executename,//校验通过后执行的函数名
__codediv,//验证码区域的div
__type = 0;//验证码类型
/******************************************************
* 参数一 验证码图片规格 “300*300”, “300*200”, “200*100”
* 参数二 校验通过时执行的函数名
* 参数三 0为滑块验证码、1为中文点选验证码。默认为0
* 绑定的div width与图片宽一致 height为图片高加34像素
******************************************************/
$.fn.slide = function (imgspec, exename, type) {
//校验参数
if (typeof imgspec === ‘undefined’) {
imgspec = “300*300”;
}
else if (typeof imgspec !== “string”) {
imgspec = “300*300”;
}
if (typeof exename === ‘undefined’) {
exename = “”;
}
else if (typeof exename !== “string”) {
exename = “”;
}
if (typeof type === ‘undefined’) {
type = 0;
}
else if (typeof type !== “number”) {
type = 0;
}
else if (type < 0 || type > 1) {
throw ‘验证码类型参数错误’;
}
var div = this;
__codediv = div.attr(“id”);
__spec = imgspec;
__executename = exename;
__type = type;
if (__codediv === undefined) {
throw div.selector + ‘ does not exist’;
}
__init();
};
//载入
function __init() {
if (__spec === “”)
__spec = “300*300”;
var _spec = __spec.split(‘*’);
__imgx = _spec[0];
__imgy = _spec[1];
$(“#” + __codediv).css(“width”, __imgx);
$(“#” + __codediv).css(“height”, parseInt(__imgy) + 34);
CreadeCodeDiv();
if (__type == 0) {
$(‘#drag’).drag(__executename, __spec, __imgx, __imgy, __codediv);
}
else {
$(‘#drag’).clickPic(__executename, __spec, __imgx, __imgy, __codediv);
}
}
//绘制验证码结构
function CreadeCodeDiv() {
var __codeDIV = document.getElementById(__codediv);
__codeDIV.innerHTML = ”;
var __codeHTML = “<div class=’_pic’ style=’width:” + __imgx + “px;height:” + __imgy + “px;background-color:#e8e8e8;’>”;
//正在载入提示文字
__codeHTML += “<div class=’vcode-hints’style=’width:” + __imgx + “px;line-height:” + (__imgy / 100) * 7 + “;’>\u6b63\u5728\u8f7d\u5165…</div>”;
for (var i = 0; i < 20; i++) {
//20张小图组成完整的验证码图片
__codeHTML += “<div id=’bb” + i + “‘class=’cut_bg’></div>”;
}
__codeHTML += ‘<a href=”javascript:void(0);” title=”\u70b9\u51fb\u5237\u65b0\u9a8c\u8bc1\u7801″‘
+ ‘class=”refesh_bg”></a><input type=”hidden” id=”token” name=”token” />’;
if (__type == 0) {
__codeHTML += “<div id=’xy_img’class=’xy_img_bord’></div>”;
}
__codeHTML += “</div><div id = ‘drag’></div > “;
__codeDIV.innerHTML = __codeHTML;
$(“.refesh_bg”).click(function () { __init(); });
}
})(jQuery);
/*
*
* date 2017-02-10
* 滑块验证码校验
*/
(function ($) {
$.fn.drag = function (executename, __spec, imgx, imgy, __codediv) {
var x, drag = this, isMove = false;
//添加背景,文字,滑块
var html = ‘<div class=”drag_bg”></div><div class=”drag_text” onselectstart=”return false;”‘
+ ‘unselectable=”on”>\u62d6\u52a8\u56fe\u7247\u9a8c\u8bc1</div>’
+ ‘<div class=”handler handler_bg”></div>’;
this.append(html);
$(“#drag .drag_text”).css(“width”, imgx);
$(“.refesh_bg”).css(“left”, imgx – 20);
var handler = drag.find(‘.handler’),
drag_bg = drag.find(‘.drag_bg’),
text = drag.find(‘.drag_text’),
maxWidth = imgx – 40, // drag.width() – handler.width(); //能滑动的最大间距
t1 = new Date(), //开始滑动时间
t2 = new Date(); //结束滑动时间

getVerificationCode(__spec, 0, function (result) {
Id = result[‘Id’];
if (result[‘state’] === -1) {
return;
}
var errcode = result[‘errcode’];
if (errcode !== 0) {
document.getElementById(__codediv).innerHTML =
“<span style=’color:red’>\u9a8c\u8bc1\u7801\u83b7\u53d6\u5931\u8d25\u002c”
+ result[‘errmsg’] + “</span>”;
}
var yvalue = result[‘y’], small = result[‘small’], array = result[‘array’], normal = result[‘normal’];
imgx = result[‘imgx’];
imgy = result[‘imgy’];
$(“.cut_bg”).css(“background-image”, “url(” + normal + “)”);
$(“#xy_img”).css(“background-image”, “url(” + small + “)”);
$(“#xy_img”).css(“top”, yvalue);
$(“#drag”).css(“width”, imgx);
$(“#drag .drag_text”).css(“width”, imgx);
$(“.cut_bg”).css(“width”, imgx / 10);
$(“.cut_bg”).css(“height”, imgy / 2);
$(“.refesh_bg”).show();
$(“.refesh_bg”).css(“left”, imgx – 20);
$(“.refesh_bg”).css(“top”, imgy – 20);
var bgarray = array.split(‘,’);
//还原图片
var _cutX = imgx / 10;
var _cutY = imgy / 2;
for (var i = 0; i < bgarray.length; i++) {
var num = indexOf(bgarray, i.toString()); //第i张图相对于混淆图片的位置为num
var x = 0, y = 0;
//还原前偏移
y = i > 9 ? -_cutY : 0;
x = i > 9 ? (i – 10) * -_cutX : i * -_cutX;
//当前y轴偏移量
if (num > 9 && i < 10) y = y – _cutY;
if (i > 9 && num < 10) y = y + _cutY;
//当前x轴偏移量
x = x + (num – i) * -_cutX;
//显示第i张图片
$(“#bb” + i).css(“background-position”, x + “px ” + y + “px”);
}
//完成,移除提示
$(“.vcode-hints”).remove();
});

var $xy_img = $(“#xy_img”);
var arrayDate = new Array();//鼠标/手指移动轨迹
/*
*鼠标/手指在上下文移动时,
*移动距离大于0小于最大间距
*滑块x轴位置等于鼠标移动距离
*绑定document防止鼠标/手指
*离开滑块时监听停止
*/
handler.mousedown(function (e) {
dragstart(e.pageX);
});//鼠标按下
$(document).mousemove(function (e) {
dragmoving(e.pageX);
});//移动鼠标
$(document).mouseup(function (e) {
dragmovend(e.pageX);
});//松开鼠标
handler.mouseout(function (e) { });//鼠标移出元素
handler.on(“touchstart”, function (e) {
dragstart(e.originalEvent.touches[0].pageX);
//阻止页面的滑动默认事件
document.addEventListener(“touchmove”, defaultEvent, false);
});//手指按下
$(document).on(“touchmove”, function (e) {
dragmoving(e.originalEvent.touches[0].pageX);
});//手指移动
$(document).on(“touchend”, function (e) {
dragmovend(e.originalEvent.changedTouches[0].pageX);
//阻止页面的滑动默认事件
document.removeEventListener(“touchmove”, defaultEvent, false);
});//手指松开
//鼠标/手指开始滑动
function dragstart(thisx) {
//if (thisx >= maxWidth) {
// return;
//}
$xy_img.show();
isMove = true;
x = thisx – parseInt(handler.css(‘left’), 10);
t1 = new Date();
}
//鼠标/手指移动过程
function dragmoving(thisx) {
var _x = thisx – x;
if (isMove) {
if (_x > 0 && _x <= maxWidth) {
$xy_img.css({ ‘left’: _x });
$(“.refesh_bg”).hide();
handler.css({ ‘left’: _x });
drag_bg.css({ ‘width’: _x });
arrayDate.push([_x, new Date().getTime()]);
}
else if (_x > maxWidth) { //鼠标指针移动距离达到最大时清空事件
}
}
}
//鼠标/手指移动结束
function dragmovend(thisx) {
if (!isMove) {//没有滑动过程 直接返回
return;
}
isMove = false;
if (isNaN(x) || x === undefined) {
return;
}
var _x = Math.round(thisx – x);//取整
if (_x < 10) {
$(“.refesh_bg”).show();
$xy_img.css({ ‘left’: 0 });
handler.css({ ‘left’: 0 });
drag_bg.css({ ‘width’: 0 });
return;
}
t2 = new Date();

var data = LZString.compressToEncodedURIComponent(JSON.stringify({
Id: Id,
point: _x,
timespan: t2 – t1,
datelist: (arrayDate.join(“|”))
}));

checkVerificationCode(data, 0, function (result) {
if (result[‘state’] === 0) {//成功
//抖动效果
for (var i = 1; 4 >= i; i++) {
$xy_img.animate({ left: _x – (40 – 10 * i) }, 50);
$xy_img.animate({ left: _x + 2 * (40 – 10 * i) }, 50, function () {
$xy_img.css({ ‘left’: result[‘data’] });
});
}
handler.css({ ‘left’: maxWidth });
drag_bg.css({ ‘width’: maxWidth });
$xy_img.removeClass(‘xy_img_bord’);
$xy_img.css(“border”, “1px solid rgb(255,255,255)”);
$(“#drag a”).remove();
dragOk();
var token = result[‘token’];//用于后台验证
$(“#token”).val(token);
} else {//失败
$(“.refesh_bg”).show();
$xy_img.css({ ‘left’: 0 });
handler.css({ ‘left’: 0 });
drag_bg.css({ ‘width’: 0 });
//if (result[‘msg’] > 4) {
//超过最大错误次数限制 刷新验证码
$(“#” + __codediv).slide(imgx + “*” + imgy, executename);
// }
// else {
// }
}
});
}
//取消事件的默认动作
//防止一些Android浏览器页面跟随滑动的情况
function defaultEvent(e) {
e.preventDefault();
}
//清空事件
function dragOk() {
handler.removeClass(‘handler_bg’).addClass(‘handler_ok_bg’);
text.text(‘\u9a8c\u8bc1\u901a\u8fc7’);
drag.css({ ‘color’: ‘#fff’ });
handler.unbind(‘mousedown’);
handler.unbind(‘touchstart’);
handler.unbind(‘touchmove’);
handler.unbind(‘touchend’);
$(document).unbind(‘mousemove’);
$(document).unbind(‘mouseup’);
$(“.refesh_bg”).hide();
if (executename !== ”)
window[executename]();
}
};
})(jQuery);

/*
*
* date 2018-07-06
* 图片点选验证码校验
*/
(function ($) {
$.fn.clickPic = function (executename, __spec, imgx, imgy, __codediv) {
var count = 1, index = 0, array = [],
t1 = new Date(), //开始点击时间
t2 = new Date(); //结束点击时间
//添加背景,文字
var html = ‘<div class=”drag_bg”></div><div class=”drag_text” onselectstart=”return false;”‘
+ ‘unselectable=”on”></div>’;
this.append(html);
$(“#drag .drag_text”).css(“width”, imgx);
$(“.refesh_bg”).css(“left”, imgx – 25);

getVerificationCode(__spec, 1, function (result) {
Id = result[‘Id’];
if (result[‘state’] === -1) {
return;
}
var errcode = result[‘errcode’];
if (errcode !== 0) {
document.getElementById(__codediv).innerHTML =
“<span style=’color:red’>\u9a8c\u8bc1\u7801\u83b7\u53d6\u5931\u8d25\u002c”
+ result[‘errmsg’] + “</span>”;
}
count = result[‘count’];
var array = result[‘array’], normal = result[‘normal’];
imgx = result[‘imgx’];
imgy = result[‘imgy’];
$(“.cut_bg”).css(“background-image”, “url(” + normal + “)”);
$(“#drag”).css(“width”, imgx);
$(“#drag .drag_text”).css(“width”, imgx);
$(“#drag .drag_text”).html(“按次序点选:” + result[‘chars’]);
$(“.cut_bg”).css(“width”, imgx / 10);
$(“.cut_bg”).css(“height”, imgy / 2);
$(“.refesh_bg”).show();
$(“.refesh_bg”).css(“left”, imgx – 20);
$(“.refesh_bg”).css(“top”, imgy – 20);
var bgarray = array.split(‘,’);
//还原图片
var _cutX = imgx / 10;
var _cutY = imgy / 2;
for (var i = 0; i < bgarray.length; i++) {
var num = indexOf(bgarray, i.toString()); //第i张图相对于混淆图片的位置为num
var x = 0, y = 0;
//还原前偏移
y = i > 9 ? -_cutY : 0;
x = i > 9 ? (i – 10) * -_cutX : i * -_cutX;
//当前y轴偏移量
if (num > 9 && i < 10) y = y – _cutY;
if (i > 9 && num < 10) y = y + _cutY;
//当前x轴偏移量
x = x + (num – i) * -_cutX;
//显示第i张图片
$(“#bb” + i).css(“background-position”, x + “px ” + y + “px”);
}
//完成,移除提示
$(“.vcode-hints”).remove();
});

$(“#” + __codediv).find(“._pic”).on(“click”, function (e) {
if (index == 0) {
t1 = new Date();
}
index++;
var x = e.pageX – $(“#” + __codediv).offset().left;
var y = e.pageY – $(“#” + __codediv).offset().top;
$(“#” + __codediv).find(“._pic”).append(“<div class=’pic-wz _point” + index + “‘ style=’top:” + (y – 13) + “px;left:” + (x – 13) + “px’>” + index + “</div>”);
array.push({ css: “_point” + index, p: [x, y], t: new Date() });
$(“.pic-wz”).click(function () {
event.stopPropagation();
var obj = array.pop();
if ($(this).hasClass(obj.css)) {
$(this).remove();
index–;
}
else {
array.push(obj);
}
});
if (index == count) {
$(“#” + __codediv).find(“._pic”).unbind(“click”);
$(“.pic-wz”).unbind(“click”);
t2 = new Date();
var str = JSON.stringify({
Id: Id,
point: array.map(function (item, index, input) {
return item.p;
}),
timespan: t2 – t1,
datelist: array.map(function (item, index, input) {
return item.t;
})
});
var data = LZString.compressToEncodedURIComponent(str);
checkVerificationCode(data, 1, function (result) {
if (result[‘state’] === 0) {//成功
$(“#drag .drag_text”).text(‘\u9a8c\u8bc1\u901a\u8fc7’);
$(“#drag .drag_bg”).css({ ‘width’: imgx – 40 });
$(“#drag”).css({ ‘color’: ‘#fff’ });
$(“#drag”).append(‘<div class=”handler handler_ok_bg” style=”left: 160px;”></div>’);
$(“.refesh_bg”).hide();
var token = result[‘token’];//用于后台验证
$(“#token”).val(token);
} else {//失败
$(“#drag .drag_text”).text(‘\u9a8c\u8bc1\u5931\u8d25\uff0c\u8bf7\u91cd\u8bd5’);
$(“.refesh_bg”).show();
$(“#drag .drag_bg”).css({ ‘width’: 0 });
//if (result[‘msg’] > 4) {
//超过最大错误次数限制 刷新验证码
$(“#” + __codediv).slide(imgx + “*” + imgy, executename, 1);
// }
// else {
// }
}
});
}
});
};
})(jQuery);

/*
*获取验证码
*/
function getVerificationCode(imgspec, type, successfun) {
jQuery.support.cors = true;
$.ajax({ //获取验证码
type: “GET”,
url: url + “getcode”,
dataType: “JSONP”,
async: true,
//crossDomain: true,
data: { spec: imgspec, type: type },
success: function (result) {
if (typeof successfun == “function”) {
successfun(result);
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
},
beforeSend: function () {
}
});
};

/*
*验证验证码
*/
function checkVerificationCode(data, type, successfun) {
$.ajax({ //校验
type: “GET”,
url: url + “checkcode”,
dataType: “JSONP”,
async: true,
data: { data: data, type: type },
success: function (result) {
if (typeof successfun == “function”) {
successfun(result);
}
},
beforeSend: function () {
}
});
};

/*
* 判断位置
*/
function indexOf(arr, str) {
if (arr && arr.indexOf) return arr.indexOf(str);
var len = arr.length;
for (var i = 0; i < len; i++) { if (arr[i] === str) return i; } return -1;
}

/*
*Map方法
*兼容IE8
*/
if (!Array.prototype.map) {
Array.prototype.map = function (callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(” this is null or not defined”);
}
var O = Object(this);
var len = O.length >>> 0;
if (typeof callback !== “function”) {
throw new TypeError(callback + ” is not a function”);
}
if (thisArg) {
T = thisArg;
}
A = new Array(len);
k = 0;
while (k < len) {
var kValue, mappedValue;
if (k in O) {
kValue = O[k];
mappedValue = callback.call(T, kValue, k, O);
A[k] = mappedValue;
}
k++;
}
return A;
};
}

分析后,得知

未经允许不得转载:教师文摘 » POST绕过滑动拼图验证,批量查询某成绩的试验

赞 (0)

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址