SQL注入

为什么会存在SQL注入

通俗来讲,sql作为一种解释型语言,在运行时是由一个运行时组件解释语言代码并执行其中包含的指令的语言。基于这种执行方式,产生了一系列叫做代码注入(code injection)的漏洞 。它的数据其实是由程序员编写的代码和用户提交的数据共同组成的。程序员在web开发时,没有过滤敏感字符,绑定变量,导致攻击者可以通过sql灵活多变的语法,构造精心巧妙的语句,不择手段,达成目的,或者通过系统报错,返回对自己有用的信息。

经常我们在面试中会遇到"sql中#和$的区别",都会提到注入问题:
(1)#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是id,则解析成的sql为order by "id"。
(2)$将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是id,则解析成的sql为order by id。
(3)#方式在很大程度上能够防止sql注入。
(4)$方式无法防止sql注入。

SQL注入演示

以PHP+MySQL为例,以一个Web网站中最基本的用户系统来做实例演示。
1.创建一个名为demo的数据库:

CREATE DATABASE  `demo` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

2.创建一个名为user的数据表,并插入1条演示数据:

CREATE TABLE  `demo`.`user` (
`uid` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT  '用户uid',
`username` VARCHAR( 20 ) NOT NULL COMMENT  '用户名',
`password` VARCHAR( 32 ) NOT NULL COMMENT  '用户密码'
) ENGINE = INNODB;
INSERT INTO `demo`.`user` (`uid`, `username`, `password`) VALUES ('1', 'plhwin', MD5('123456'));

实例一

传入username参数,在页面打印出这个user的详细信息,编写 userinfo.php 程序代码:

<?php
header('Content-type:text/html; charset=UTF-8');
$username = isset($_GET['username']) ? $_GET['username'] : '';
$userinfo = array();
if($username){
    //使用mysqli驱动连接demo数据库
    $mysqli = new mysqli("localhost", "root", "root", 'demo');
    $sql = "SELECT uid,username FROM user WHERE username='{$username}'";
    //mysqli multi_query 支持执行多条MySQL语句
    $query = $mysqli->multi_query($sql);
    if($query){
        do {
            $result = $mysqli->store_result();
            while($row = $result->fetch_assoc()){
                $userinfo[] = $row;
            }
            if(!$mysqli->more_results()){
                break;
            }
        } while ($mysqli->next_result());
    }
}
echo '<pre>',print_r($userinfo, 1),'</pre>';

上面这个程序要实现的功能是根据浏览器传入的用户名参数,在页面上打印出这个用户的详细信息,采用了mysqli的驱动,以便能使用到 multi_query 方法来支持同时执行多条SQL语句,这样能更好的说明SQL注入攻击的危害性。

假设我们可以通过 http://localhost/test/userinfo.php?username=plhwin这个URL来访问到具体某个会员的详情,正常情况下,如果浏览器里传入的username是合法的,那么SQL语句会执行:

SELECT uid,username FROM user WHERE username='plhwin'

如果在浏览器里把传入的username参数变为 "plhwin';SHOW TABLES-- hack",也就是当URL变为http://localhost/test/userinfo.php?username=plhwin';SHOW TABLES-- hack的时候,此时我们程序实际执行的SQL语句变成了:

SELECT uid,username FROM user WHERE username='plhwin';SHOW TABLES-- hack'

--会注释后面的内容
此时可以在浏览器里看到页面的输出,数据库的user表,此时将参数换成plhwin';DROP TABLE user-- hack,那将产生灾难性的严重结果。

Array
(
    [0] => Array
        (
            [uid] => 1
            [username] => plhwin
        )
    [1] => Array
        (
            [Tables_in_demo] => user
        )
)

SQL注入攻击的总体思路

1.寻找到SQL注入的位置

2.判断服务器类型和后台数据库类型

3.针对不通的服务器和数据库特点进行SQL注入攻击

主要讲一下如何寻找SQL注入点
寻找注入点常用的方法就是通过 不断调整参数来测试服务器的响应,进而暴露出与数据库结构有关的问题。传入SQL语句可控参数分为两类

  • 数字类型,参数不用被引号括起来,如?id=1
  • 其他类型,参数要被引号扩起来,如?name="phone"

数字类型

构造测试 预期结果 变种
' 触发错误,返回数据库错误
1+1 返回原来相同的结果 3-1
1+0 返回原来相同的结果
1 or 1=1 永真条件,返回所有记录 1) or (1=1
1 or 1=2 空条件,返回原来相同的结果 1) or (1=2
1 and 1=2 永假条件,不返回记录 1) and (1=2

其他类型

构造测试 预期结果 变种
col 3 is right-aligned $1600
col 2 is centered $12
zebra stripes are neat $1
a' 触发错误,返回数据库错误
a' or '1'='1 永真条件,返回所有记录 a') or ('1'=1
a' or '1'='2 空条件,返回原来相同结果 a') or ('1'=2
a' and '1'='2 永假条件,不返回记录 a') and ('1'='2

常见基本的方法有如下几种:
1.加引号法,通过在浏览器地址栏中的页面链接地址后面增加一个单引号,进而测试服务器的响应,来判断是否存在注入点。
2.“1=1和1=2”法

后续待补充

如何预防SQL注入

1. PreparedStatement预编译语句(简单最有效)

采用预编译语句集,它内置了处理SQL注入的能力,不同的程序语言,都分别有使用预编译语句的方法。
使用好处:

(1).代码的可读性和可维护性.
(2).PreparedStatement尽最大可能提高性能.
(3).最重要的一点是极大地提高了安全性.

还是以php为例:

<?php
header('Content-type:text/html; charset=UTF-8');
$username = isset($_GET['username']) ? $_GET['username'] : '';
$userinfo = array();
if($username){
    //使用mysqli驱动连接demo数据库
    $mysqli = new mysqli("localhost", "root", "root", 'demo');
    //使用问号替代变量位置
    $sql = "SELECT uid,username FROM user WHERE username=?";
    $stmt = $mysqli->prepare($sql);
    //绑定变量
    $stmt->bind_param("s", $username);
    $stmt->execute();
    $stmt->bind_result($uid, $username);
    while ($stmt->fetch()) {
        $row = array();
        $row['uid'] = $uid;
        $row['username'] = $username;
        $userinfo[] = $row;
    }
}
echo '<pre>',print_r($userinfo, 1),'</pre>';

我们程序里并没有使用addslashes函数,但是浏览器里运行 http://localhost/test/userinfo2.php?username=plhwin' AND 1=1-- hack 里得不到任何结果,说明SQL漏洞在这个程序里并不存在。实际上,绑定变量使用预编译语句是预防SQL注入的最佳方式,使用预编译的SQL语句语义不会发生改变,在SQL语句中,变量用问号?表示,黑客即使本事再大,也无法改变SQL语句的结构,像上面例子中,username变量传递的 plhwin' AND 1=1-- hack 参数,也只会当作username字符串来解释查询,从根本上杜绝了SQL注入。

2.用正则表达式过滤传入的参数

如关键字过滤:

reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"  + "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
3.字符串过滤
4.js代码预防注入(后台仍然需要预防)
5.不要随意开启生产环境中Webserver的错误显示,同时不要信任任何用户输入的数据,对请求服务器的数据需要进行一定的规则和格式校验。

附sql注入系列专题:sql注入专题
同时推荐testfire.net来模拟漏洞攻击:demo.testfire.net


看不到我 / \ 看不到我~~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容