0x00 介绍
SQL注入是一种攻击手段,通过将恶意SQL代码插入到应用程序的查询中,攻击者可以操控数据库执行未经授权的操作,如获取敏感数据或修改数据。SQL注入通常发生在应用程序的输入点,如表单字段、URL参数、HTTP头部等。
0x01 注入函数
mysql_query()
mysql_query()是旧版PHP中用于执行SQL查询的函数。它已经在PHP 7.0中被移除,建议使用mysqli或PDO。
mysqli_query()
mysqli_query()用于执行SQL查询。虽然比mysql_query()更安全,但仍需小心处理用户输入。
mysqli_real_escape_string()
mysqli_real_escape_string()用于对用户输入进行转义,以防止SQL注入。
PDO::query()
PDO::query()用于执行SQL查询,但在没有使用参数绑定的情况下,也可能导致SQL注入。
PDO::exec()
PDO::exec()用于执行SQL语句,如INSERT、UPDATE、DELETE等,但也可能导致SQL注入。
mysqli_stmt_execute()
mysqli_stmt_execute()用于执行预处理语句。如果不正确使用,也可能存在问题。
mysqli_prepare()
mysqli_prepare()用于准备SQL查询,以便后续绑定参数执行
PDO::prepare()
PDO::prepare()用于准备SQL查询。它是防止SQL注入的有效手段,但需确保正确使用
0x02 示例
经典SQL注入(In-Band SQL Injection)
// 不安全的代码
$user_id = $_GET['user_id'];
$query = "SELECT * FROM users WHERE id = $user_id";
$result = mysqli_query($conn, $query);
?user_id=1' OR 1=1;--
联合查询注入(Union-Based Injection):
// 不安全的代码
$search = $_GET['search'];
$query = "SELECT * FROM products WHERE name LIKE '%$search%'";
$result = mysqli_query($conn, $query);
?search=Product%20Name' UNION SELECT null, username, password FROM users;--
盲注(Blind SQL Injection)
布尔值盲注(Boolean-Based Blind Injection):
// 不安全的代码
$username = $_GET['username'];
$query = "SELECT * FROM users WHERE username = '$username'";
$result = mysqli_query($conn, $query);
?username=admin' AND 1=1;--
基于时间的盲注(Time-Based Blind Injection):
// 不安全的代码
$username = $_GET['username'];
$query = "SELECT * FROM users WHERE username = '$username'";
$result = mysqli_query($conn, $query);
?username=admin' OR IF(1=1, SLEEP(5), 0);--
基于内容的盲注(Content-Based Blind Injection)
存储型SQL注入(Stored SQL Injection)
// 不安全的代码
$comment = $_POST['comment'];
$query = "INSERT INTO comments (content) VALUES ('$comment')";
mysqli_query($conn, $query);
?comment=<script>alert('XSS')</script>
第二阶注入(Second-Order Injection)
// 不安全的代码
$email = $_POST['email'];
$query = "INSERT INTO users (email) VALUES ('$email')";
mysqli_query($conn, $query);
// 另一个地方
$user_id = $_GET['user_id'];
$query = "SELECT * FROM users WHERE id = $user_id";
$result = mysqli_query($conn, $query);
?email=' OR 1=1;-- // 用户注册时注入恶意代码
基于合成的盲注(Inferential Blind Injection)
// 不安全的代码
$username = $_GET['username'];
$query = "SELECT * FROM users WHERE username = '$username'";
$result = mysqli_query($conn, $query);
?username=admin' AND LENGTH(password) = 5;--
基于错误的注入(Error-Based Injection)
// 不安全的代码
$user_id = $_GET['user_id'];
$query = "SELECT * FROM users WHERE id = $user_id";
$result = mysqli_query($conn, $query);
?user_id=1' AND 1=CONVERT(int, (SELECT @@version));--
注入型跨站脚本(SQL Injection-Based XSS)
// 不安全的代码
$comment = $_POST['comment'];
$query = "INSERT INTO comments (content) VALUES ('$comment')";
mysqli_query($conn, $query);
// 渲染评论内容
$query = "SELECT * FROM comments";
$result = mysqli_query($conn, $query);
?comment=<script>alert('XSS')</script>
基于反射的注入(Reflected SQL Injection)
// 不安全的代码
$search = $_GET['search'];
$query = "SELECT * FROM products WHERE name LIKE '%$search%'";
$result = mysqli_query($conn, $query);
?search=' UNION SELECT null, username, password FROM users;--
改写注入(Rewrite Injection)
// 不安全的代码
$id = $_GET['id'];
$query = "CALL GetUserDetails($id)";
$result = mysqli_query($conn, $query);
?id=1; DROP TABLE users;--
利用存储过程注入(Stored Procedure Injection)
// 不安全的代码
$id = $_GET['id'];
$query = "CALL GetUserDetails($id)";
$result = mysqli_query($conn, $query);
?id=1; DROP TABLE users;--
0x03 实例
1、
$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>';
}
这个代码中没有过滤任何字符串
使用普通传参即可攻击成功
修改代码
$user=$_GET['name'];
$password=$_GET['password'];
$conn=mysqli_connect('127.0.0.1','test','123456','test');
// 使用白名单进行输入用户名和密码验证
$whitepattern="/^[a-zd]*$/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>';
}
2、
找到位置
跟踪参数
为了确认能不能控制SQL语句,可以把这个语句打印出来
原语句
id=1) and extractvalue(1,concat(0x7e,database()))#
url编码后
d=1)%20and%20extractvalue(1%2Cconcat(0x7e%2Cdatabase()))%23
原文始发于微信公众号(Pik安全实验室):[代码审计] php 数据库注入
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论