liuxinyustu

PS:下章节我会就XSS/CSRF写一篇文章,还请各位关注

1.什么是SQL注入攻击?

百度百科:所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。

其实,我们可以简单的理解SQL注入为:未对用户输入进行过滤,导致用户的一些输入在程序执行时,当做SQL语句的一部分进行执行,从而针对一些敏感操作:OR 1=1 或者 WHERE 1=1 这种条件的加入,使得我们本身的SQL逻辑被跳过执行。

 

2.PHP通用SQL注入攻击方式

为了方便理解SQL注入攻击,现在模拟网站的用户登录操作,进行SQL注入攻击演示,附上以下示例:

登录界面如下:

我们的测试用户名及密码:admin/123456

①首先,我们使用正确的登录用户名及密码:

②我们通过SQL注入方式跳过密码验证登录:

 

通过两次登录的SQL语句,我们可以很清楚的看出差异

# step 1 SQL
 
SELECT * FROM users WHERE username = \'admin\' AND password = \'e10adc3949ba59abbe56e057f20f883e\'
 
# step 2 SQL
 
SELECT * FROM users WHERE username = \'admin\'#\' AND password = \'96e79218965eb72c92a549dd5a330112\'

其中第二步由于前台传入特殊字符单引号(\')及#,在数据库中#为语句注释部分,则后续SQL语句不会被执行,可直接跳过我们的密码验证逻辑。

同时,我们也可以通过下面方式跳过逻辑判定

SQL语句如下:

SELECT * FROM users WHERE username = \'admin\' OR 1=\'1\' AND password = \'96e79218965eb72c92a549dd5a330112\'

同样,我们使用此种方式可以达到跳过登录验证的目的

此类问题是未对用户输入的特殊字符进行过滤,如单引号(\'),双引号("),NULL等。PHP可以通过设置打开magic_quotes_gpc,自动针对特殊字符增加反斜线(\)的方式,对其进行转义,而避免被程序执行,当然,也可以利用以下方法针对未开启magic_quotes_gpc时,进行处理:

function addslashes_deep($value)
{
 
    if (empty($value))
    {
 
        return $value;
 
    }
    else
    {
 
        return is_array($value) ? array_map(\'addslashes_deep\', $value) : addslashes($value);
 
    }
 
}
 
 
 
if(!get_magic_quotes_gpc())
{
 
    $_POST = addslashes_deep($_POST);
 
    $_GET = addslashes_deep($_GET);
 
}

这样,上述经过处理的SQL语句如下:

SELECT * FROM users WHERE username = \'admin\\' OR 1=\\'1\' AND password = \'96e79218965eb72c92a549dd5a330112\'
就不会被解释执行了

 

③数字型SQL注入攻击

首先,我们将上面测试代码一部分改为如下:

$id = $_GET[\'id\'];
 
$sql = "SELECT * FROM users WHERE id=".$id;
 
$res = $db->query($sql)->fetch_all();
/test.php?id=1 UNION SELECT 1,username,password,4,5,6,password,8,9,10,11 FROM users

浏览器地址栏输入如上地址,后台显示SQL如下:

SELECT * FROM users WHERE id=1 UNION SELECT 1,username,password,4,5,6,password,8,9,10,11 FROM users

我们通过这里很容易利用UNION命令,查询出用户名和密码等敏感信息

当然,此类防御也相当简单,对于整数型数据,我们在获取时,需要对其进行转化如下:

$id = intval($_GET[\'id\'])
即可避免此类上述SQL注入

 

3.总结

通过以上两个示例,在PHP中,可以通过简单的三种方法来防御SQL注入:

①对用户的输入进行过滤处理后,在进行操作,如:addslashes()方法或者开启magic_quotes_gpc方法

②针对获取的数值型数据,进行二次转换,如intval(),floatval()

③所有需进行数据库查询的变量都使用单引号(\')包围,如下:

$sql = "SELECT * FROM users WHERE username=\'".$username."\'";

4.代码:

后台test.php

function pretty_print($array)
{
 
    echo \'<pre>\';
     
    print_r($array);
     
    echo \'</pre>\';
 
}
 
function addslashes_deep($value)
{
 
    if (empty($value))
    {
     
    return $value;
     
    }
    else
    {
     
    return is_array($value) ? array_map(\'addslashes_deep\', $value) : addslashes($value);
     
    }
 
}
 
 
 
if(!get_magic_quotes_gpc())
{
 
    $_POST = addslashes_deep($_POST);
     
    $_GET = addslashes_deep($_GET);
 
}
 
 
 
$db = mysqli_connect(\'127.0.0.1\',\'root\',\'root\',\'mysqli_test\');
 
 
 
$username = $_POST[\'username\'];
 
$password = $_POST[\'password\'];
 
 
 
$sql = "SELECT *".
 
" FROM users".
 
       " WHERE username = \'".$username.
 
"\' AND password = \'".md5($password)."\'";
 
 
$res = $db->query($sql)->fetch_row();
 
 
 
if(empty($res))
{
    echo \'登录失败,用户名或密码不正确!\';
}
else
{
 
    echo \'登录成功,欢迎您:\'.$res[1];
 
}

前台index.html

<!DOCTYPE html>
<html>
 <head>
 <title>表单提交测试</title>
 <meta charset="utf-8">
 </head>
 <body>
    <form method="post" action="test.php">
    用户名:<input type="text" name="username"><br/>
    密    码:<input type="text" name="password"><br/><br/>
    <button type="submit">提交</button>
    </form>
 </body>
</html>

资源参考:

百度百科:https://baike.baidu.com/item/sql%E6%B3%A8%E5%85%A5/150289?fr=aladdin

BLOG:https://www.cnblogs.com/joshua317/articles/3939718.html

分类:

技术点:

相关文章: