前端验证漏洞
0.概述
前端验证漏洞是指主要采用JS作为前端数据验证媒介时进而产生的一种漏洞。
1.AJAX身份验证
Ajax定义: AJAX不是JavaScript的规范,它只是一个哥们“发明”的缩写:Asynchronous JavaScript and XML,意思就是用JavaScript执行异步网络请求,实现数据的交互(原用php交互)。
异步:指的是一次性发送多个数据再进行校验。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AJax传参与JQuery引用</title>
</head>
<script src="jquery-1.12.4.min.js"></script> <!--调用JQuery框架标志(黑盒测试中常见)-->
<body>
帐号:<input type="text" class="user">
密码:<input type="password" class="pass">
<button>用户登录</button>
<script>
$('button').click(function () {
$.ajax({
type:'post',
url:'ajax.php', //传递的目标
dataType:'json',
data:{
myUname:$('.user').val(),
myUpass:$('.pass').val()
},
success:function (res){
if(res.infoCode == 1){
alert('登录成功!');
}else {
alert('登录失败!');
}
}
})
});
</script>
</body>
</html>
后端验证代码:
<?php
//1.接受传参
$username = $_POST['myUname'];
$password = $_POST['myUpass'];
$success = array(
'msg'=>'ok',
'infoCode'=>0
); //设置字典的目录与默认对应值
//2.后端检验
if ($username=='Haige' && $password=='666'){
$success['infoCode'] = 1;
}else{
$success['infoCode'] = 0;
}
echo json_encode($success); //输出编码(方便在控制台中的Response中观察)
?>
后期的后端验证无非就是在后端验证代码中加入数据库连接,再将输入的账号密码与数据库中管理员的账号密码进行对应验证。(infoCode字段即为登录成功与否标志位)
在代码编写中容易犯传参大小写忽略问题!
验证原理:
可能存在的漏洞–>未授权访问
success:function (res){
if(res.infoCode == 1){
alert('登录成功!');
}else {
alert('登录失败!');
}
}
由上面的代码分析可得前端仅仅只是验证了infoCode这个选项是否为1就赋予后台登录权限,因此可进行抓包修改工具将后台发送给前端的数据包进行修改,进而达到目的
总结: 功能越复杂并不是越安全,反之精简的功能的代码产生漏洞的概率可能会小些。
2.Ajax逻辑支付
1.前端设置好价格后端进行购买计算,再前端验证
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>购买设计1</title>
</head>
<script src="../jquery-1.12.4.min.js"></script>
<body>
<img src="../iphone.jpg" width="270" height="270" alt=""/><br>
价格:8888<br>
数量:<input type="text" class="num">
<button>购买</button>
<script>
$('button').click(function () {
$.ajax({
type:'POST',
url:'shop.php',
dataType:'json',
data:{
price:'8888',
number:$('.num').val() //获取类名中的数据 (.'类名').val()
},
success:function (res) {
if (res.code == 1){
alert('购买成功!');
}else {
alert('购买失败!');
}
}
});
});
</script>
</body>
由代码可知,此种方式容易产生的漏洞与前面Ajax越权登录相似,其验证原理也相似。依葫芦画瓢即可.
2.商品价格以前端设置价格为准,数据接收价格后运算
对应模型:1.后端数据发送到前端 2.前端接受数据进行接受并相关运算(通常采用数据库中的数据作为设置)
前端:
<?php
//从数据库中提取价格参数
$con = mysqli_connect("127.0.0.1","root","root","study");
if ($con -> connect_error){
echo "连接失败"."<br>";
}else{
echo "连接成功"."<br>";
}
//从数据库中提取数据作为设置的价格
$sql='select * from shop where id=1';
$result = mysqli_query($con,$sql);
while ($row = mysqli_fetch_row($result)){
$imgsrc = $row[2];
$price = $row[1];
}
echo "<img src='../iphone.jpg' width='270' height='270' alt=''/><br>";
echo "价格:$price<br>";
echo "数量:<input type='text' class='num'>";
echo "<button>购买</button>";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>购买设计2</title>
</head>
<script src="../jquery-1.12.4.min.js"></script>
<body>
<script>
$('button').click(function () {
$.ajax({
type:'POST',
url:'shop.php',
dataType:'json',
data:{
price:<?php echo $price?>, //这里传递的价格虽然是从数据库中获取但也是从前端传递
number:$('.num').val() //获取类名中的数据 (.'类名').val()
},
success:function (res) {
if (res.code == 1){
alert('购买成功!');
}else {
alert('购买失败!');
}
}
});
});
</script>
</body>
后端shop.php
<?php
header("Content-Type:text/html;charset=utf-8");
$success = array(
'msg'=>'ok',
'code'=>0
);
$price = $_POST['price'];
$num = $_POST['number'];
$m=$price*$num;
if($m<10000){
$success['code']=1;
}else{
$success['code']=0;
}
echo json_encode($success);
分析:
参数传递的参数虽然是从数据库中获取,但参数任然是通过Ajax传递的 Json格式,因此可通过抓包拦截进而造成一系列安全问题。此种情况虽然价格是从数据库提取,但任是通过前端传递验证
data:{
price:<?php echo $price?>, //这里传递的价格虽然是从数据库中获取但也是从前端传递
number:$('.num').val() //获取类名中的数据 (.'类名').val()
},
修改价格(零元购)可造成或是订购number(为0.01或是负数)可造成一系列逻辑支付的问题
3.问题规避
- 仅使用后端验证(即价格由后端从数据库中提取)
- 后端接受参数,并限制前端的部分传递参数,并对传递的参数进行加密
if ($num > 0 && filter_var($num,$num)) {
if (直接数据库中接受的价格 * $num < 10000) {
$success['code'] = 1;
} else {
$success['code'] = 0;
}
}
这样的化就会相对安全一点,总结就是尽量减少前后端数据交互,亦或是添加好交互时的过滤语句,避免数据在前后端交互过程中被修改*