环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客
一、MySQL UPDATE语句复习:
- UPDATE语句用于修改表中的数据,基本形式为:
UPDATE 表名称 SET 列名称=新值 WHERE 更新条件;
- 语法结构示例:UPDATE 【表名】SET 字段1=新值1, 字段2=新值2 [WHERE 条件];
Update语句练习:
要修改security数据库中users表的admin字段的值为000000,可以使用以下UPDATE语句:
UPDATE users SET admin='000000' WHERE <更新条件>;
请确保将<更新条件>
替换为适合您情况的实际条件,以确保只有符合条件的行会被更新。如果要更新整个表中的所有行,可以省略WHERE子句
二、update 注入代码分析
靶场的17关(Less-17)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Less-17 Update Query- Error based - String</title>
</head>
<body bgcolor="#000000">
<div style=" margin-top:20px;color:#FFF; font-size:24px; text-align:center"><font color="#FFFF00"> [PASSWORD RESET] </br></font> <font color="#FF0000"> Dhakkan </font><br></div>
<div align="center" style="margin:20px 0px 0px 520px;border:20px; background-color:#0CF; text-align:center; width:400px; height:150px;">
<div style="padding-top:10px; font-size:15px;">
<!--Form to post the contents -->
<form action="" name="form1" method="post">
<div style="margin-top:15px; height:30px;">User Name :
<input type="text" name="uname" value=""/> </div>
<div> New Password :
<input type="text" name="passwd" value=""/></div></br>
<div style=" margin-top:9px;margin-left:90px;"><input type="submit" name="submit" value="Submit" /></div>
</form>
</div>
</div>
<div style=" margin-top:10px;color:#FFF; font-size:23px; text-align:center">
<font size="6" color="#FFFF00">
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
function check_input($value)
{
if(!empty($value))
{
// truncation (see comments)
$value = substr($value,0,15);
}
// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
// Quote if not a number
if (!ctype_digit($value))
{
$value = "'" . mysql_real_escape_string($value) . "'";
}
else
{
$value = intval($value);
}
return $value;
}
// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
//making sure uname is not injectable
$uname=check_input($_POST['uname']);
$passwd=$_POST['passwd'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname."\n");
fwrite($fp,'New Password:'.$passwd."\n");
fclose($fp);
// connectivity
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
//echo $row;
if($row)
{
//echo '<font color= "#0000ff">';
$row1 = $row['username'];
//echo 'Your Login name:'. $row1;
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
mysql_query($update);
echo "<br>";
if (mysql_error())
{
echo '<font color= "#FFFF00" font size = 3 >';
print_r(mysql_error());
echo "</br></br>";
echo "</font>";
}
else
{
echo '<font color= "#FFFF00" font size = 3 >';
//echo " You password has been successfully updated " ;
echo "<br>";
echo "</font>";
}
echo '<img src="../images/flag1.jpg" />';
//echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font size="4.5" color="#FFFF00">';
//echo "Bug off you Silly Dumb hacker";
echo "</br>";
echo '<img src="../images/slap1.jpg" />';
echo "</font>";
}
}
?>
</font>
</div>
</body>
</html>
这段源代码存在SQL注入问题,特别是在处理UPDATE
查询时。让我们逐步分析代码中的关键部分,以了解为什么会存在这个安全漏洞。
1. 用户输入处理:
$uname=check_input($_POST['uname']);
这行代码调用了check_input
函数来处理用户输入的用户名(uname
)。check_input
函数的目的是清理输入数据,以防止SQL注入攻击。它对输入值执行以下操作:
- 如果输入非空,截断到前15个字符。
- 如果启用了魔术引号(magic quotes),则去除转义的斜杠。
- 如果值不是数字,将其用单引号包围,并通过
mysql_real_escape_string
进行转义,以避免SQL注入攻击。 - 如果值是数字,通过
intval
转换为整数。
2. SQL查询构建:
$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
这行代码构建了一个SQL查询,用于查找与输入的用户名匹配的用户。由于uname
已经通过check_input
函数进行了处理,理论上应该是安全的。然而,问题出现在后面的更新密码部分。
3. 密码更新操作:
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'"; mysql_query($update);
这里构建了一个UPDATE
SQL查询,用于更新用户密码。但是,请注意,新密码($passwd
)没有经过任何清理或转义处理,直接插入到SQL查询中。这意味着如果$passwd
包含SQL语句的一部分,例如单引号('
),它可以终止密码字符串,并允许攻击者注入额外的SQL命令。
例如,假设攻击者在“New Password”字段中输入以下内容:
', email = 'attacker@example.com
这将导致$update
变量包含如下SQL语句:
UPDATE users SET password = '', email = 'attacker@example.com' WHERE username='victim'
这就修改了目标用户的电子邮件地址,展示了如何通过未经处理的用户输入来操纵SQL查询,这是典型的SQL注入攻击。
解决方案:
为了防止SQL注入,所有用户提供的数据都必须适当地清理和转义,特别是在构建SQL查询时。可以使用参数化查询(预处理语句)来安全地处理用户输入。此外,应避免使用mysql_*
函数,因为它们已经被弃用并在PHP 7.0中被移除。改用mysqli
或PDO
可以提供更好的安全性和功能。
三、手动注入演示
在密码的输入框输入
1' and extractvalue(1,concat(0x7e,database(),0x7e))#
注入语句解释:
基于原始的SQL更新语句:
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
如果攻击者在密码($passwd
)字段中插入了注入代码:
1' and extractvalue(1,concat(0x7e,database(),0x7e))#
这段注入代码的目的是尝试通过引发一个错误来泄露当前数据库的名称。下面是如何将这段代码插入到原始语句中,并解释其工作原理:
插入注入代码
假设攻击者控制的$passwd
变量的值被设置为注入代码,那么当这个值被插入到原始的SQL语句中时,最终执行的SQL语句将变为:
UPDATE users SET password = '1' and extractvalue(1,concat(0x7e,database(),0x7e))#' WHERE username='$row1';
这里,注入的代码试图通过以下方式操作:
-
1'
:首先,数字1
后跟一个单引号'
用来结束原始的password
值字符串,使得接下来的部分被视为SQL代码而不是字符串值。 -
and
:逻辑运算符and
用于确保只有当前面的条件(这里是1
)为真时,后面的extractvalue
函数才会被执行。在这种情况下,1
总是为真,因此可以确保执行注入的代码。 -
extractvalue(1,concat(0x7e,database(),0x7e))
:这是关键部分,extractvalue
是一个XML函数,用于从XML文档中提取信息。这里,它被滥用来生成一个错误消息,因为第一个参数1
并不是有效的XML文档。concat(0x7e,database(),0x7e)
函数调用将数据库名与~
字符连接起来,database()
函数返回当前数据库的名称。目的是让错误消息中包含数据库名称,从而泄露这一信息。 -
#
:井号#
开始了注释,意味着这个符号之后的所有内容(原始语句的剩余部分)都会被MySQL忽略。这样可以防止语法错误和原始SQL语句的其他部分干扰注入代码的执行。
通过这种方式,攻击者试图利用extractvalue
函数引发的错误消息来间接获取数据库名称。如果数据库配置为向用户显示详细的错误信息,那么这个错误可能会包含由concat(0x7e,database(),0x7e)
生成的值,即当前数据库的名称,被~
符号包围。
四、sqlmap 进行自动注入演示
SQLMap 工具我使用kali中自带的
使用bp对靶场进行抓包
# 格式:
sqlmap -r 文件名称 -p 参数名 --dbs --batch
# 示例:(我的数据包文件是存放在kali的桌面所以这里就是 /home/kali/桌面/test.txt)
sqlmap -r /home/kali/桌面/test.txt -p passwd --dbs --batch
-r /home/kali/桌面/test.txt
指定了一个请求文件,这个文件应该包含了一个HTTP请求,可能是从浏览器或者其他抓包工具中导出的。这个请求会被sqlmap用来测试SQL注入。-p passwd
指示sqlmap针对HTTP请求中的passwd
参数进行测试。这意味着passwd
参数可能存在SQL注入漏洞,需要被检测。--dbs
告诉sqlmap在发现SQL注入漏洞后尝试列出数据库的名称。--batch
表明sqlmap将以批处理模式运行,这意味着它会自动选择默认选项而不会提示用户输入