安全矩阵

 找回密码
 立即注册
搜索
查看: 4586|回复: 0

Web安全:SQL注入漏洞

[复制链接]

991

主题

1063

帖子

4315

积分

论坛元老

Rank: 8Rank: 8

积分
4315
发表于 2020-10-26 08:42:12 | 显示全部楼层 |阅读模式
原文链接:Web安全:SQL注入漏洞

SQL注入漏洞指攻击者通过构建特殊的输入作为参数传入Web应用。这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所需要的操作。其主要原因是程序没有细致地过滤用户输入的数据,导致攻击数据植入程序被当作代码执行。


我们通过SQL注入漏洞,可以得到目标站点的敏感数据(如数据库中的账号和密码、目标站点的绝对路径等)。然后,若条件允许,我们可以通过sqlmap交互式写shell,得到目标站点的shell。得到shell之后,可以下载目标站点的代码。此时,我们可以对目标站点的代码进行审计,判断是否有数据库连接敏感信息,是否有旁站,是否有权限进入旁站等。

我们现在已经知道SQL注入漏洞的原理了,接下来介绍MySQL的SQL注入。在此提醒下大家,别把SQL注入的对象弄错了,是MySQL(数据库)的SQL注入,而非网上流传的脚本注入,如PHP注入。要知道,SQL注入的本质是针对数据库而非脚本语言的。首先,在PHP中,两个单引号闭合的信息是字符串,两个双引号闭合的信息最终也是字符串。只是,程序会搜索双引号闭合的信息中是否有可执行的运算,如有,就执行运算,如没有,就不执行运算;而对于单引号,则不会去搜索,默认闭合的信息中全部都是不可执行的字符串。其实,双引号只比单引号多执行了一个搜索算法而已。这样看来,被单引号闭合的信息的执行效率还是要比双引号要高一些。所以,我建议大家用单引号闭合那些纯粹的字符串,用双引号闭合那些存在可执行运算的字符串。这是一个PHP编程的好习惯,例如以下代码。

$user = addslashes($_GET['a']);
$sql = "select host,user,password from user where user='$user'";
$res = mysql_query($sql);
$row = mysql_fetch_array($res);
var_dump($row);

事实上,在这段代码中,我们可以将$sql变量看作用双引号闭合的且存在可执行运算的字符串。当PHP的Lex或者Yacc解析到第一个双引号时,就会去找第二个双引号,两个双引号都找到之后,自然就明白了,原来这些信息都是被这对双引号闭合的。因此,继续按照双引号闭合的规则解析。规则为,搜索可执行运算,有则计算处理,没有则不计算处理;然后,将总的处理结果作为纯粹的字符串返回$sql变量中。

接下来介绍SQL注入分类,一般将SQL注入分为3类:数字型SQL注入、字符型SQL注入及搜索型SQL注入。在此,我们从另一个角度来深入了解SQL注入的本质并读懂SQL注入真正的内涵。例如,大家分析以下这段PHP代码有没有MySQL的SQL注入(DB是MySQL)。

$user = addslashes($_GET['a']);
$sql = "select host,user,password from user where user='$user'";
$res = mysql_query($sql);
$row = mysql_fetch_array($res);
var_dump($row);

看到这段代码,我们应该想到的是magic_quotes_gpc是否开启(没开启就只是利用addslashes函数在此转义,开启了这里就是双重转义);此处有没有MySQL的宽字节注入(考虑PHP与MySQL的代码是否一致);单引号与双引号在此处的含义。SQL注入测试文件sql_inject.php,其代码如下。

<?php
//连接数据库
$conn = mysql_connect('127.0.0.1','root','root');
mysql_select_db('mysql',$conn);
//$user = addslashes($_GET['a']);
$user = $_GET['a'];
$sql = "select host,user,password from user where user='$user'"; echo $sql;
echo '<br />';
$res = mysql_query($sql);
$row = mysql_fetch_array($res);
var_dump($row);
?>

开启浏览器,输入http://localhost:81/sql_inject.php?a=123' or '1'='1,Web服务器返回如下信息。

select host,user,password from user where user='123' or '1'='1'
array(6) { [0]=> string(9) "localhost" ["host"]=> string(9)
"localhost" [1]=> string(4) "root" ["user"]=> string(4) "root"
[2]=> string(41) "*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B"
["password"]=> string(41) "*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B" }

显示注入已经成功了,暴出了root。

host | user | password
localhost | root | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
127.0.0.1 | root | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B

其实,当我们输入123' or '1'='1并提交请求的时候,$sql变量的值也随着变成select host,user,password from user where user='123' or '1'='1'。这段语句就是SQL语句,由MySQL解析执行。其实您会发现,这段SQL语句执行后,已经把user表里所有用户的信息都查询出来了。我们来分析一下为什么会这样。问题就出在where条件语句中,即user='123' or '1'='1'。这句话的意思就是,只要user表中的user字段满足其值等于123或者'1'='1'的这个条件,就执行前面的select查询。大家仔细想想,这里的运算是不是有问题,运算结果是不是永远都返回为true。

我们可以先来了解下运算的优先级,其口诀为,先算术,后关系,再逻辑。其含义为,在逻辑表达式中,混有算术运算,要先进行算术(加减乘除)运算,再进行关系(大小比较)运算,最后进行逻辑(或、且、非)运算,得到真假(true或 false)结果。所以,在select host,user,password from user where user='123' or'1'='1'中,先进行算术运算,若无算术运算,则看关系运算,'1'='1' 就是关系运算。由于这两者相等,所以,这句关系运算结果返回true。此时,SQL语句就变成了select host,user,password from user where user='123' or true,我们继续进行关系运算,user='123'吗?user肯定不等于123,其实user=root,看看数据库就明白了。所以,这句关系运算的代码执行后返回false。此时,SQL语句又变成了select host,user,password from user where false or true, where条件语句里面就只有“false or true”这个条件了。这是什么运算?这已经是逻辑运算了,真或假运算的结果是真还是假,这里就不解释了。执行效果如图1所示。

图1  执行SQL语句(1)

最后,来解释下这句SQL语句:select host,user,password from user where false or true。这句SQL语句中的false or true部分的执行结果是true。此时,这句SQL语句就变成了select host,user,password from user where true,where语句后面的条件始终是true。也就是说,条件始终都是真。我们的SQL语句执行的充分非必要事件就是where语句后面的条件恒为真。那么此时,执行select查询就是必然的事情了。这里可以列举C语言里面的一个循环语句来说明问题,它们如出一辙:where (true){//do something…},大家觉得它与此是不是一个道理呢?这样大家应该明白SQL注入的本质了吧?只要能构造出语法正确的SQL语句,注入不是难事。还有一点,需要明白3种运算的优先级关系。执行效果如图2所示。

图2  执行SQL语句(2)

例1:如果某站id参数存在数字型SQL注入漏洞,攻击者就能在浏览器(借助插件HackBar)中构造并提交攻击测试语句。然后发送至服务器,攻击测试语句为id=1) UNION ALL SELECT CONCAT(user()),NULL,NULL,NULL,NULL,NULL…。接下来,服务器返回敏感信息至浏览器,即数据库用户信息,信息为root@*.*.219.248,如图3所示。

图3  数字型SQL注入之敏感信息泄露

例2:如果某站fromCity参数存在字符型SQL注入漏洞,攻击者就能在浏览器(借助插件HackBar)中构造并提交攻击测试语句,然后发送至服务器。攻击测试语句为fromCity=6F9619FF-8A86-D011-B42D-00004FC964FF' UNION ALL SELECT user--?。接下来,服务器返回敏感信息至浏览器,即数据库用户名信息。数据库用户名信息为swwl,而且Web物理地址也泄露了,Web物理地址:F:\项目\,如图4所示。

图4  字符型SQL注入之敏感信息泄露

例3:如果某站doccatid参数存在搜索型SQL注入漏洞,攻击者就能在浏览器的搜索框中构造并提交攻击测试语句,然后发送至服务器。攻击测试语句为doccatid=(case when 1 like 1 then 1249014520765 end)。接下来,服务器将全部文章返回至浏览器,如图5所示。

图5  搜索型SQL注入敏感信息泄露

可以看到,这里存在搜索型SQL注入。此时,攻击者使用Python编写EXP。通过EXP,攻击者可以查询出敏感信息(如当前数据库的用户等)。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 11:44 , Processed in 0.012857 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表