SQL注入原理:
注释符号:#,-- (有个空格)
把后面的SQL语句注释掉,也就是后面的SQL语句不执行。
select id,email from member where username='$admin';//原语句
传入admin=xx' or 1=1#
select id,email from member where username='xx' or 1=1#';//拼接后的语句
'闭合,select id,email from member where username='xx'能够执行,or:左右两边正确一个就可以,1=1一定是正确的,就可以查询所有的信息。在遍历id,email表时会发现里面每一个条件,每一个数据都满足1=1这个条件。
注释后的语句:select id,email from member where username='xx' or 1=1;
通过引号闭合前面的数据,通过#注释了后面的语句,达到拼接了一个SQL语句,将程序员原来的SQL语句做了一个拼接,拼接成另外一个SQL语句来数据库执行,来到数据库里面拿到自己想拿到的东西。
不是说#把后面的都注释了吗,那么为什么后面还会有;,因为你的这个SQL语句去到MySQL服务端就会自认为在后面帮你加;执行。
这些就是SQL注入的原理。
SQL注入攻击漏洞的原因,是由于程序员在编写web程序时,没有对客户端(比如浏览器)提交的参数进行严格的过滤和判断,用户可以修改参数或数据并传递至服务端,导致服务端拼接了伪造的SQL查询语句,服务端连接数据库,并将伪造的SQL语句发送给数据库执行,数据库将SQL语句的执行结果返回给了服务端,服务端又将结果返回给客户端,从而获取到敏感信息,甚至执行危险的代码或系统命令。简单来说就是:注入产生的原因是服务端接受客户端相关参数未经处理直接带入数据库查询操作。
如何查找注入点位置:
一句话简单概括就是:前端页面上所有提交数据的地方,不管是登录,注册,留言板,评论区,分页等等地方,只要是提交数据给后台,后台拿着该数据和数据库交互了,那么这个地方就可能存在注入点。
注释符号
如果是get请求,也就是我们在浏览器中输入的url,解释执行的时候,url中的#号是用来指导浏览器动作的,对服务端无用,会报错。而-- (有空格)在传输过程中同样会被忽略,所以可以用--+来代替,+会被解释为空格。
当然也可以使用--%20,#可以为%23.
如果是post请求,则可以直接用#来进行闭合,常见的就是表单注入,如我们在后台登录框中进行注入。
如果--后面不加空格,--直接和系统自动生成的单引号连接在了一起,会被认为是一个关键词,无法注释掉系统自动生成的单引号。
SQL注入分类
主要分为以下俩类:数字型,字符型(还有其他特殊的)
数字型
数字型注入的时候,是不需要考虑单、双引号闭合问题的,因为SQL语句中的数字是不需要用引号括起来的,如:
字符型
需要考虑单双引号闭合问题。
报错注入:
简单原理:拼接后的SQL语句是错误的,数据库查询报错,报错信息直接返回服务端。
背景条件:后台没有屏蔽报错信息,在语法发生错误时会输出到前端,并且错误信息里面可能会包含库名,表名等相关信息。
基于报错的信息获取(三个常用的用来报错的函数)
updatexml()函数是MySQL对xml文档数据进行查询和修改的XPATH函数;
语法:
UPDATEXML(XML_document, XPath_expression, New_value)
参数:
- XML_document:要更新的 XML 文档。
- XPath_expression:一个 XPath 表达式,用于指定要更新的元素或属性。
- New_value:要更新为的新值。
返回值:
更新后的 XML 文档。
extractvalue()函数也是MySQL对xml文档数据进行查询和修改的XPATH函数;
语法:
EXTRACTVALUE(XML_document, XPath_expression)
参数:
- XML_document:要从中提取值的 XML 文档。
- XPath_expression:一个 XPath 表达式,用于指定要提取的值。
返回值:
一个字符串,包含从 XML 文档中提取的值。
floor()函数,MySQL中用来取整的函数。
等等,还有其他很多种函数。
实战测试:
x' and updatexml(1,concat(0x7e,(select xx),0x7e),3)# x这个字母是随便写的,什么都可以,0x7e是16进制,表示一个~符号。那么为什么不直接写~呢?因为~为字符串,如果直接写需要用引号引起来,如果用单引号,可能会和我们的单引号闭合起冲突,所以只能用双引号,比较麻烦,并且如果别人后台对引号做了限制的话,还会注入失败。
简单做一个ctfhub技能树的报错注入:
报错注入:
构造payloud:?id=1 and updatexml(1,concat(0x7e,(select database()),0x7e),3)
爆出数据库sqli
接着爆表名。构造payloud:?id=1 and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema = 'sqli'),0x7e),3)
可以看到有news和flag。读取flag,构造payloud:
?id=1 and updatexml(1,concat(0x7e,(select group_concat(flag) from flag),0x7e),3)
在MySQL的5.1版本及以上,MySQL数据库中会存在一个叫做information_schema的默认数据库,这个库里面记录着MySQL管理的数据库的名称,表名,列名(也叫字段名)
concat拼接的数据不能有多行,可以加limit多次爆数据。
堆叠注入
从名词的含义应该就可以看到是一堆SQL语句(多条)一起执行,而在真实的运用中也是这样的,我们知道在MySQL中,主要是在命令行中,每一条语句结尾加;表示语句结束。所有是不是可以多局一起使用。
原理:
在SQL中,;表示语句结束,结束一个语句后会执行下一个语句,就有了堆叠注入。而union联合注入也是将两条语句合并在一起,但它是有限的,只能执行查询语句。而堆叠注入可以执行的是任意语句。比如增删查改,非常的危险。
但也有限制,堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到API或数据库引擎不支持的限制,当然了权限不足也可以解释为什么攻击者无法修改数据或调用一些程序。