SQL 注入攻击解密

关注 Web 安全的同学都知道,历年来,SQL 注入一直是位于 OWASP TOP 10 榜首的安全威胁。无数的 Web 站点因为存在 SQL 注入漏洞而被入侵,导致网站被挂马,被篡改,挂广告;甚至导致黑客上传 Webshell 能够控制整台服务器。

本文将会具体介绍什么是 SQL 注入攻击,SQL 注入攻击简单演示,以及如何做好 SQL 注入攻击的防护。

SQL 注入攻击解密

一、什么是 SQL 注入

要讲清楚什么是 SQL 注入,那首先得说明什么是SQL。

SQL 的全称是 Structured Query Language,结构化查询语言。

用于对数据库进行增加、删除、修改、查询等操作的编程语言。

我们都知道,在动态网站的架构中,页面展示的内容并不是写在页面中,而是存储在数据库中,Web 服务通过动态语言来调用数据库中的数据,产生静态页面后再传递至客户端浏览器。

SQL 注入攻击解密

如图,我们要在网站上浏览某篇文章的详细内容,会经过这么几个步骤:

客户端想要浏览数据库中 ID 为 36 的文章详细内容,

于是通过点击 URL http://test.com/article.php?id=36,

向文章详细页面传递参数 id=36

1.文章的详细页面已经提前写好了SQL 查询句 select * from article where id=request(“id”) (该语句的意思是在 article 表中查询一条 id 值为变量 request(“id”)的记录)。该页面会把接收到的 id=36 的参数代入到上述语句中的变量,使数据库去查询 id 为 36 的文章信息。

2.数据库查询到 id 为 36 的文章信息后,把该信息传递至 Web 服务器的脚本引擎。

3.脚本引擎根据收到的数据库传来的文章内容,生成静态页面,发送给客户端浏览。

这个过程中有没有什么地方可能存在安全风险呢?假设用户提交 id 信息的时候,在 36 后面不怀好意的加入了几个文字,比如 and 1=2,这时会发生什么事情呢?

文章详细页面还是会照常把用户提交的信息 id=36 and 1=2 代入到 SQL 语句的变量中,那这时数据库执行的 SQL 语句就变成 select * from article where id=36 and 1=2,

查询 article 表中 id=36 并且 1=2 的记录。我们知道,1 永远不可能等于 2,所以你会发现数据库无法查询到任何记录,我们也会看不到任何文章内容。

这就是一次简单的 SQL 注入,所谓 SQL 注入,就是客户端向 Web 服务器恶意提交会干扰 SQL 查询的代码,而导致数据库执行一些非常危险的操作。当然,刚才的例子可能没有什么危害性。那我们换一个例子。

SQL 注入攻击解密

这是网上一度流传很广的图,非常形象的解释了什么是 SQL 注入攻击。图中车的号牌被车主用一张字条遮挡了,字条上写了一段不知道是啥的代码。这段代码具体是什么我们不用关心,你只用知道 DROP DATABASE 是删除数据库的意思就行了。对,就是我们俗称删库跑路的那个删库。然后我们来分析一下车主的这个行为有什么目的。

我们先解释一下交警电子眼的违章拍照是什么工作原理。首先,当一辆车发生违章后,电子眼会进行拍照,拍出违章车辆的号牌。然后通过 OCR 技术把照片中的车牌信息识别为文本,再通过后台的 SQL 语句把车牌号码插入到数据库中的违章信息表中。我们假设这个系统后台并没有对提交的车牌信息作出过滤,那么后台程序将会把车牌上删库的语句当做命令执行,就触发了删除数据库的操作,导致整个交警后台数据库全没了。

当然这只是一个段子,如果真有人这么做了而且引发后果了,估计就不止跑路这么简单了。 

二、SQL 注入攻击实例

现在大家应该已经能够理解 SQL 注入大概是怎么一回事了。那么我们来通过一次实例演示来看看 SQL 注入攻击在 Web 攻击中能做到什么事情。

SQL 注入攻击解密

如上图所示,首先我们要找到可能存在 SQL 注入攻击点的页面。根据刚才我们的分析,我们知道 SQL 注入一定是用户向服务器提交了恶意的 SQL 代码。图中的页面 URL 地址我们可以发现,页面地址后的 ?id=33 代表浏览器在向服务器提交参数 id=33,希望浏览 id=33 的文章内容。这种地址格式的页面就极有可能存在 SQL 注入漏洞,然后我们需要通过测试来确定这个页面到底是否存在注入点。

我们在该页面地址中提交的 id=36 的参数后加了一个不起眼的 ‘ 符号。提交时,发现页面报错了。但注意,这时报错不仅不是坏消息,反而是好消息。因为单引号是程序语言的关键符号,在代码中随意加入没有闭合的引号势必将破坏语言的正确结构而导致程序出错。这时页面报错恰好说明我们提交的 ’ 被服务器当做 SQL 语言的一部分执行了。如果网站做了相应过滤的话,反而是不会报错的。而且我们可以从报错信息中得知该网站使用的数据库是 MySQL,这也是一个非常重要的信息。

其实到这里我们基本可以断定该页面存在 SQL 注入漏洞了。但是标准的测试方法,还可以在 id=36 后加入 and 1=1 或者 and 1=2。如果 and 1=1 页面能正常返回数据,而 and 1=2 页面无法显示任何内容,才能彻底断定该页面存在 SQL 注入漏洞。

现在既然我们已经确认了该页面的注入点,那接下来就很简单了,直接使用 SQL 注入神器,大名鼎鼎的 SQLMAP 来自动化完成注入了

SQL 注入攻击解密

我们在该页面地址中提交的 id=36 的参数后加了一个不起眼的 ‘ 符号。提交时,发现页面报错了。但注意,这时报错不仅不是坏消息,反而是好消息。因为单引号是程序语言的关键符号,在代码中随意加入没有闭合的引号势必将破坏语言的正确结构而导致程序出错。这时页面报错恰好说明我们提交的 ’ 被服务器当做 SQL 语言的一部分执行了。如果网站做了相应过滤的话,反而是不会报错的。而且我们可以从报错信息中得知该网站使用的数据库是 MySQL,这也是一个非常重要的信息。

其实到这里我们基本可以断定该页面存在 SQL 注入漏洞了。但是标准的测试方法,还可以在 id=36 后加入 and 1=1 或者 and 1=2。如果 and 1=1 页面能正常返回数据,而 and 1=2 页面无法显示任何内容,才能彻底断定该页面存在 SQL 注入漏洞。

现在既然我们已经确认了该页面的注入点,那接下来就很简单了,直接使用 SQL 注入神器,大名鼎鼎的 SQLMAP 来自动化完成注入了

SQL 注入攻击解密

先跑出该服务器中所有的数据库名称,我们需要的是名为 cms 的数据库,接下来跑一下这个数据库中有哪些表

SQL 注入攻击解密

我们看到,跑出的表中,有个叫 cms_users 的表特别显眼,非常有可能网站的后台管理员用户密码就记录在这个表中,那么我们就继续跑一下这个表中有什么字段,看看到底是不是和我们的猜想一样

SQL 注入攻击解密

不出我们所料,表中分别有字段是 username 和 password,管理员信息表无疑了。接下来最后一步,把用户名和密码的内容跑出来。

SQL 注入攻击解密

大功告成。表中的 5 个管理员的用户名和密码全跑出来了。而且 SQLMAP 还贴心的帮我把 MD5 加密都已经破解出明文了。

通过上述演示我们可以发现,如果网站的某个页面存在 SQL 注入漏洞的话,可能造成的后果就是网站管理员账户密码被破解,而直接导致黑客拿下网站的控制权,后果不堪设想。

三、SQL 注入防护

最后,关于 SQL 注入的防护,我们大概可以分为有钱的防护方法和没钱的防护方法。

首先说说没钱的防护方法。既然没钱,那就只能靠技术了。程序开发这个行业有句至理名言,叫永远不要相信用户的输入。谁也不知道用户里有没有坏人,所以不要天真的指望用户会遵照你设想的规则来输入提交信息。那么防护方法就很简单了,在所有用户可以提交信息的页面做信息过滤,把所有会引发 SQL 查询的关键字符和符号过滤掉,不让用户提交就行了。常见的,比如单引号、双引号、斜杠、冒号、空格等。当然,写过滤规则得长点心,不然可能会导致用户正常提交的信息被系统给过滤掉了。

上面是没钱走技术流的方法,那如果技术差一点,或者懒得花精力去写什么过滤规则的话,也可以花钱去买 WAF (Web 应用防火墙)。WAF 会帮你检测用户向 Web 服务器提交的信息,如果发现有 SQL 注入的动作特征,就会自动帮你把这个信息给过滤,并且对该用户的 IP 地址做出阻断,来保护网站。

版权声明

文章来源:金信润天 作者:邓老师 

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论