举个例子:
如果有一家公司要开年终晚会,并且请来了一个对公司一无所知的主持人。
主持人已经准备好了演进稿子,但是主持人并不知道上台表演的节目名称,需要请公司的同事来填写一下。
可是这位同事故意将节目名称写错了,结果主持人就直接将节目名称报出来了 ,这样就弄得整场晚会很尴尬。
其实故意写错填空内容,就和SQL注入是同一个道理,SQL注入其实也就是在搜索框中使用恶意SQL查询来实现攻击目的。
另外一个例子:
假设你用自己的用户名和密码登录了一个付费网站,网站服务器需要查询一下你是不是VIP用户。
服务器通常都是会向数据库进行查询的,因为服务器把用户数据都放在数据库里面了,要向数据库进行增加、删除、修改和查询这些操作,就需要用到SQL语言了。
但问题是如果黑客没有正常输入数据,而是把数据转换成代码,使得服务器向数据库的正常查询变成了不正常的代码执行,那么黑客就可以执行自己想要的操作了。
报错与注释
SQL的语法很像正常的英语,比如说这里有一个保存在数据库的用户名密码表格。
username | password |
admin | 1234 |
ichi | 123456 |
en | 321 |
abs | asb123 |
unioln | un123456789 |
如果我们要选取表格中的所有内容,就可以用SELECT * FROM,如果我们要选取指定的用户名和密码,就可以在后面加上WHERE,并且附上条件。
假设用户输入了用户名和密码后,服务器就会把输入的用户名和密码这两条数据,加在WHERE语句里面。
看起来是一个正常操作,但是服务器如果没有过滤用户输入的数据,比方说黑客在用户名最后加上一个单引号
SELECT * FROM allUsers WHERE username = 'admin'' AND password = '1234'
那当SQL执行这条语句的时候,会把一对引号里面的视为字符数据,而不是操作符,但是因为这里的引号不成对,因此这条SQL语句是会报错的。
如果此时服务器傻傻地把SQL报错的信息直接返回给用户,那么黑客就知道具体是什么原因导致报错了,SQL注入攻击的门就这样被打开了。
大家可能觉得报错没什么,但是如果我们在单引号后面再加上–,事情就不一样了
SELECT * FROM allUsers WHERE username = 'admin' -- AND password = '1234'
在大部分数据库中,系统遇到了这两条横线就会认为,从–开始到这一行结束都是注释,注释是不会被视为代码进行执行的,相当于只会执行前面部分的SQL语句。
如果黑客知道用户名,即使不知道密码也可以进行账号的登录了。
那如果黑客连正确的用户名信息都没有,怎么办呢?
也没关系,因为SQL语句在遇到WHERE关键词的时候,会判断条件是真还是假。
这种事情在计算机中就有意思了,因为如果一个条件为真,另一个条件为假,再用OR来把这两个条件拼接起来,那么得到的就是真!
SELECT * FROM allUsers WHERE username = 'admin'' OR 1=1 -- AND password = '1234'
也就是说,黑客只需要再增加一个为真的条件就行了。
UNION
在SQL里要合并两个表格的内容,常见的就是用UNION操作符来连接两个SELETE语句。
但是UNION是可以有离谱操作的,比如在MySQL里,UNION SELETE的后面不需要指定表格名字,直接在SELECT后面用NULL来代替列名。
SELECT * FROM UNION SELECT NULL,NULL
NULL是一个特殊的值,表示没有值,这个操作看似没什么意义,因为就直接把两个NULL合并在表格里一起进行展示。
但是UNION的操作必须保证合并两边的列数要一致的,一般是不知道表格是有多少列的。
但是没关系,黑客可以一直在后面加上NULL来测试,最后多少个NULL是返回成功的结果,就证明这个表格有多少列了。
当然还有其他方法可以获取表格的列数,但是如果现在黑客用其他方法知道了另一个表格的信息。
那就可以把表格的列名放在NULL的位置,并且指定选取的表格名。
如果熟悉UNION的同学就知道这条语句不一定可行,因为UNION除了要保证列数一致以外,还要保证数据类型要相似的,数字和字符就不是相似类型了。
如果ID值刚好是数字,UserName此时是字符,这样是无法进行合并的。
因此实际上黑客在确定好列数以后,还会进行数据类型的判断,比如逐列进行测试就行了。
现在黑客就可以把所有的东西都放在一起。
首先在可以注入的地方,用单引号强行终止数据内容,并且加上注释关键词使得后面的语句失效。
这样SQL语句就不会报错,黑客就可以在这里注入UNION语句了。
如果要获取账号密码,那么账号密码信息就这样被合并到一起了,并且展示在页面里面。
但是并不是每个网站都会把数据库的内容展示在页面里,也不是每个网站都会返回数据库的错误信息。
不过这还是难不倒黑客,比方说现在大部分网站都会使用Cookie,这样服务器就能根据不同Cookie来识别不同用户,从而展示不同的网页内容。
也就是说通常会在数据库里保存不同用户的Cookie,用户登录网页的时候就会在HTTP请求里面加上Cookie这个HTTP首部。
相应的也会生成服务器向数据库的查询语句,比方说SELECT、FROM,此时黑客就可以使用前面说到的方法,在这里修改Cookie的值。
强行加上一个单引号来结束字符数据,并且注释掉后面的SQL语句,如果此时返回的还是原来的页面,就证明是可以被注入的。
带外通道
但是如果网站服务器不返回内容到页面,也没有页面来判断查询是否成功,千万不要以为网站就安全了。
只要黑客可以向网站服务器发送正常的请求,并且服务器会向数据库进行沟通,就可能会产生漏洞。
比如向MySQL系统注入LOAD_FILE()函数,如果给这个函数提供域名,那么就会触发DNS查询。
也就是查询域名的IP地址,这个时候虽然服务器不返回内容给黑客,但是服务器还是会进行SQL查询。
此时如果黑客做了手脚,把要查询的管理员密码和域名进行拼接,相当于直接把管理员密码发给了黑客。
因为黑客的服务器是自己控制的,因此黑客可以查看DNS查询的内容,此时就可以把管理员密码给提取出来。