SQL注入原理及代码分析

VSole2021-10-20 07:49:11

1)前言

我们都知道,学安全,懂SQL注入是重中之重,因为即使是现在SQL注入漏洞依然存在,只是相对于之前现在挖SQL注入变的困难了。而且知识点比较多,所以在这里总结一下。通过构造有缺陷的代码,来理解常见的几种SQL注入。本文只是讲解几种注入原理,没有详细的利用过程。

如果想要了解Access的详细手工注入过程,可以看我的这篇文章

https://www.cnblogs.com/lxfweb/p/12643011.html

如果想要了解MySQL的详细手工注入过程,可以看我的这篇文章

https://www.cnblogs.com/lxfweb/p/12655316.html

如果想要了解SQL server的详细手工注入过程,可以看我的这篇文章

https://www.cnblogs.com/lxfweb/p/12675023.html

2)sql注入原理

SQL注入漏洞的产生需要满足两个条件

  1. 参数用户可控:前端传给后端的参数内容是用户可以控制的。
  2. 参数带入数据库查询:传入的参数拼接到SQL语句并带入数据库查询。
  3. 所以在实际环境中开发者要秉持“外部参数皆不可信原则”进行开发。

3)几种常见的sql注入攻击

3.1)union注入攻击

先看代码

$con=mysqli_connect("localhost","root","XFAICL1314","dvwa"); #连接数据库,我这里直接连接了dvwa的数据库
if(mysqli_connect_error())
{
    echo "连接失败:" .mysqli_connect_error();
}
$id=$_GET['id'];
$result=mysqli_query($con,"select * from users where `user_id`=".$id);
$row=mysqli_fetch_array($result);
echo $row['user'] . ":" . $row['password'];
echo "
";
?>

在union注入页面中,程序获取GET参数id,对用户传过来的id值没有进行过滤,直接拼接到SQL语句中,在数据库中查询id对应的内容,并将这一条查询结果中的user和password 输出到页面。进行union注入攻击前提是页面有回显。

然后就是注入的常规思路,判断类型,判断字段数,使用union查询相关数据。

3.2)布尔盲注攻击

先看代码

$con=mysqli_connect("localhost","root","XFAICL1314","dvwa");
if(mysqli_connect_error())
{
    echo "连接失败:" .mysqli_connect_error();
}
$id=$_GET['id'];
if(preg_match("/union|sleep|benchmark/i",$id)){
    exit("on");
}
$result=mysqli_query($con,"select * from users where `user_id`=".$id);
$row=mysqli_fetch_array($result);
if ($row) {
    exit("yes");
}
else{
    exit("no");
}
?>

在布尔盲注页面中,程序先获取GET参数id,通过preg_match()函数判断其中是否存在union sleep benchmark等危险字符。然后将参数id拼接到SQL语句,从数据库查询,如果有结果,返回yes,否则返回no。所以访问这个页面,代码根据查询结果返回只返回yes和no,不返回数据库中的任何结果,所以上一种的union注入在这里行不通。尝试利用布尔盲注。

布尔盲注是指构造SQL判断语句,通过查看页面的返回结果来推测哪些SQL判断是成立的。例如,我们可以判断数据库名的长度构造语句如下。

and length(database())>=1 #依次增加,查看返回结果

通过上面的语句我们可以猜到数据库名长度为4。

接着使用逐字符判断的方式获取数据库库名,数据库库名范围一般都是az,字母09。构造语句如下。

and substr(database(),1,1)=要猜解的字母(转换成16进制)

substr是截取的意思,构造语句的含义是,截取database()的值,从第一个开始,每次返回一个。这里要注意,要和limit语句区分开,limit从0开始排序,substr从1开始排序。因为我知道数据库的第一个字母是d,所以直接换成d,转换成16进制就是0x64。结果如下。

在真实环境中,自己手工的话,工作量有点大,可以借助burp的爆破功能爆破要猜解的字母。

同样,也可以利用substr()来猜解表名和字段。构造语句

and substr((select table_name from information_schema.tables where table_schema=库名 limit 0,1),1,1)=要猜解的字母(这里指表名)

用这样的方法,可以猜解出所有的表名和字段,手工会累死,可以借助burp或者sqlmap。

3.3)报错注入攻击

先看代码

$con=mysqli_connect("localhost","root","XFAICL1314","dvwa");
if (mysqli_connect_error())
{
    echo "连接失败:".mysqli_connect_error();
}
$id=$_GET['id'];
if($result=mysqli_query($con,"select *from users where `user_id`=".$id))
{
    echo "ok";
}else{
    echo mysqli_error($con);
}
?>

查看代码,在报错注入页面中,程序获取GET参数id后,将id拼接到SQL语句中查询,如果执行成功,就输出ok,如果出错,就通过echo mysqli_error($con)将错误信息输出到页面。我们可以利用这种错误回显,通过updatexml()、floor()等函数将我们要查询的内容显示到页面上。

例如,我们通过updatexml()获取user()的值,构造如下语句。

and updatexml(1,concat(0x7e,(select user()),0x7e),1) #0x7e是~16进制编码

发现查询出了user()的值

同样,我们也可以查询出database()的值

and updatexml(1,concat(0x7e,(select database()),0x7e),1) #0x7e是~16进制编码

查询出了数据库名

我们可以用这种方法查询出剩下的所有表名和字段,只需要构造相关的SQL语句就可以了。

3.4)时间盲注攻击

先看代码

$con=mysqli_connect("localhost","root","XFAICL1314","dvwa");
if (mysqli_connect_error())
{
    echo "连接失败:".mysqli_error();
}
$id=$_GET['id'];
if (preg_match("/union/i",$id)){
    exit("no");
}
$result=mysqli_query($con,"select * from users where `user_id`=".$id);
$row=mysqli_fetch_array($result);
if ($row){
    exit("yes");
}
else{
    exit("no");
}
?>

查看代码,在时间盲注页面中,程序获取GET参数id,通过preg_match()函数判断是否存在union危险字符,然后将id拼接到SQL语句中,并带入数据库查询。如果有结果返回yes,没有结果返回no。不返回数据库中的任何数据。

它与布尔盲注的不同在于,时间盲注是利用sleep()或benchmark()等函数让执行时间变长。一般和if(expr1,expr2,expr3)结合使用,这里的if语句的含义为如果expr1为真,则if()返回expr2,否则返回expr3。所以判断数据库的长度,咱们构造的语句如下

if (length(database())>3,sleep(5),1) #判断数据库长度,如果大于3,休眠5秒,否则查询1

由上面图片,我们通过时间可以判断出,数据库的长度为4。

得到长度后,通过substr()来查询数据库的第一个字母,这里和布尔盲注很类似,构造如下语句。

and if (substr(database(),1,1)=库的第一个字母,sleep(5),1)

依次进行猜解。依次类推,可以猜解出数据库完整的库名,表名,字段名和具体数据。手工的话依旧是一个浩大的工程,一般借助工具。

4)总结

今天对union注入、布尔盲注、报错注入、时间盲注的原理和代码进行了简单的分析。在第二篇文章中,会对堆叠注入、二次注入、宽字节注入、cookie注入等进行简单的分析。

sql注入数据库原理
本作品采用《CC 协议》,转载必须注明作者和本文链接
NoSQL,泛指非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库数据库管理系统的统称。NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。 分类
id=3';对应的sql:select * from table where id=3' 这时sql语句出错,程序无法正常从数据库中查询出数据,就会抛出异常; 加and 1=1 ,URL:xxx.xxx.xxx/xxx.php?id=1' order by 3# 没有报错,说明存在3列爆出数据库:?id=-1' union select 1,group_concat,3 from information_schema.schemata#爆出数据表:?id=1' and extractvalue--+(爆字段)?
数据库注入提权总结
2022-08-10 15:52:54
首先,不能直接将该函数注入子查询中,因为 Oracle 不支持堆叠查询 。其次,只有数据库管理员才能使用 DBMS_LOCK 包。在 Oracle PL/SQL 中有一种更好的办法,可以使用下面的指令以内联方式注入延迟:dbms_pipe.receive_messageDBMS_PIPE.RECEIVE_MESSAGE() 函数将为从 RDS 管道返回的数据等待 10 秒。
在渗透测试过程中遇到了MSSQL数据库,市面上也有一些文章,不过大多数讲述的都是如何快速利用注入漏洞getshell的,对于MSSQL数据库注入漏洞没有很详细地描述。在这里我查阅了很多资料,希望在渗透测试过程中遇到了MSSQL数据库能够相对友好地进行渗透测试,文章针对实战性教学,在概念描述方面有不懂的还请自行百度,谢谢大家~
id=1' order by 3# 没有报错,说明存在3列。id=-1' union select 1,group_concat,3 from 数据库名.数据表名--+拓展一些其他函数:system_user() 系统用户名。updatexml函数:细节问题:extractvalue()基本一样,改个关键字updatexml即可,与extractvalue有个很大的区别实在末尾注入加上,如:,而extractvalue函数末尾不加1(数值)?
基础介绍Microsoft SQL Server 是微软开发的关系型数据库管理系统。作为数据库服务器,它是一种软件产品,主要功能是根据其他软件应用程序的请求存储和检索数据,这些应用程序可以在同一台计算机上运行,也可以在网络上的另一台计算机上运行。SQL Server 默认开放的端口是 TCP 1433。判断数据库类型/*?数据库中独有的数据表,如果页面返回正常即可表示为?为便于管理数据库中的权限,SQL Server 提供了若干角色,这些角色是用于对其他主体进行分组的安全主体。
MSSQL注入和漏洞利用姿势总结
VSole
网络安全专家