牛魔的这道题没给我做死了差点
进入题目就是一个登录界面,这里用SQL注入是不行的,我们正常的注册登录之后就进来了一个传文件的地方,我们一路上看URL处和抓包的情况来看,有以下几个目录:
login.php index.php download.php regist.php login.php
我们尝试了之后发现只有图片能够上传,然后试了其他方法也没什么用
但是我们点下载之后会看见这里有个filename,就联想到如果这里的filename是可控的,那么我是不是可以通过控制这个参数来实现对其他东西的下载呢

试了一下发现我们想要下载的东西都不在当前目录,我们必须要上两层目录才可以下载也就是../../index.php
index.php:
<?php
session_start();
if (!isset($_SESSION[‘login’])) {
header(“Location: login.php”);
die();
}
?>
<script src="static/js/jquery.min.js"></script>
<script src="static/js/bootstrap.bundle.min.js"></script>
<script src="static/js/toast.js"></script>
<script src="static/js/panel.js"></script>
<input type=”file” id=”fileInput” **class**=”hidden”>
<?php
include “class.php”;
$a = new FileList($_SESSION[‘sandbox’]);
$a->Name();
$a->Size();
?>
Class.php
<?php
error_reporting(0);
$dbaddr = “127.0.0.1”;
$dbuser = “root”;
$dbpass = “root”;
$dbname = “dropbox”;
$db = new mysqli($dbaddr, $dbuser, $dbpass, $dbname);
class User {
public $db;
public function __construct() {
global $db;
$this->db = $db;
}
public function user_exist($username) {
$stmt = $this->db->prepare(“SELECT username FROM users WHERE username = ? LIMIT 1;”);
$stmt->bind_param(“s”, $username);
$stmt->execute();
$stmt->store_result();
$count = $stmt->num_rows;
if ($count === 0) {
return false;
}
return true;
}
public function add_user($username, $password) {
if ($this->user_exist($username)) {
return false;
}
$password = sha1($password . “SiAchGHmFx”);
$stmt = $this->db->prepare(“INSERT INTO users (id, username, password) VALUES (NULL, ?, ?);”);
$stmt->bind_param(“ss”, $username, $password);
$stmt->execute();
return true;
}
public function verify_user($username, $password) {
if (!$this->user_exist($username)) {
return false;
}
$password = sha1($password . “SiAchGHmFx”);
$stmt = $this->db->prepare(“SELECT password FROM users WHERE username = ?;”);
$stmt->bind_param(“s”, $username);
$stmt->execute();
$stmt->bind_result($expect);
$stmt->fetch();
if (isset($expect) && $expect === $password) {
return true;
}
return false;
}
public function __destruct() {
$this->db->close();
}
}
class FileList {
private $files;
private $results;
private $funcs;
public function __construct($path) {
$this->files = array();
$this->results = array();
$this->funcs = array();
$filenames = scandir($path);
$key = array_search(“.”, $filenames);
unset($filenames[$key]);
$key = array_search(“..”, $filenames);
unset($filenames[$key]);
foreach ($filenames as $filename) {
$file = new File();
$file->open($path . $filename);
array_push($this->files, $file);
$this->results[$file->name()] = array();
}
}
public function __call($func, $args) {
array_push($this->funcs, $func);
foreach ($this->files as $file) {
$this->results[$file->name()][$func] = $file->$func();
}
}
public function __destruct() {
$table = ‘
| ‘ . htmlentities($func) . ‘ | ‘;Opt | ‘;
|---|---|
| ‘ . htmlentities($value) . ‘ | ‘;下载 / 删除 | ‘;‘ . $value . ‘ | ‘; // 把flag内容拼进去
1 |
|
我们上面说到了会有foreach,所以这里的files就必须还是数组,而里面必须是new File,这是因为:

看似是$file调用name,但是$file的值是$files遍历后传的,也就是这里要求files有name()所以要这么干
而后就是运行了,在运行之前必须把phar.readonly给改成off,默认关闭的
我这里是拿的kali做的,我觉得自己还是搞复杂了,后面在优化吧:
kali自带php环境,输入php –ini
Loaded这个就是

然后用nano改

control+w搜索,control加o保存,control加x退出
改了在创一个去跑我们的脚本:

然后告诉我失败了,只能用个临时的方法了:

ls -l之后是这样就OK了
然后脚本写好了,我就直接在下载的时候抓包然后给filename改了,其实不行,看了网上的wp
我们的dowload.php会卡目录
. ini_set() 函数
- 作用:PHP 内置函数,用于动态修改 php.ini 配置文件中的配置项(只对当前脚本生效,脚本执行完就失效,不会改物理的 php.ini 文件)。
- 参数格式:
ini_set(配置项名称, 配置值)。 - 对比:如果直接改 php.ini 里的
open_basedir,会对所有 PHP 脚本生效;用ini_set()只影响当前脚本,灵活性更高。
"open_basedir"(配置项名称)
- 中文含义:“基于目录的开放限制”,是 PHP 的核心安全配置项。
- 作用:限制 PHP 脚本的文件操作(比如
fopen()、file_get_contents()、unlink()等)只能在指定的目录及其子目录下进行。 - 安全意义:防止恶意脚本访问 / 篡改服务器上的敏感文件(比如
/etc/passwd、其他网站的源码文件等),是 PHP 防护的重要手段。
getcwd() . ":/etc:/tmp"(配置值)
这是open_basedir的具体限制规则,拆解:
(1) getcwd() 函数
- 全称:get current working directory(获取当前工作目录)。
- 作用:返回 PHP 脚本当前执行的目录路径(比如脚本放在
/var/www/html,就返回这个路径)。 - 示例:如果脚本在
/home/user/project下运行,getcwd()就返回/home/user/project。
(2) 分隔符 :(Linux/Mac)/ ;(Windows)
open_basedir支持指定多个目录,不同系统用不同分隔符:- Linux/Mac/Unix:用冒号
:分隔多个目录; - Windows:用分号
;分隔(比如getcwd() . ";C:\Windows\Temp")。
- Linux/Mac/Unix:用冒号
(3) :/etc:/tmp
拼接后整体含义:允许 PHP 脚本访问的目录包括:
getcwd()返回的当前脚本目录;/etc目录(Linux 系统的系统配置目录);/tmp目录(Linux 系统的临时文件目录)。
实际效果示例
假设你的脚本运行目录是/var/www/html,这行代码执行后:
✅ 允许的操作:
读取
/var/www/html/test.txt(当前目录);读取
/etc/nginx/nginx.conf(/etc 目录下的文件);写入
/tmp/temp_file.txt(/tmp 目录下的文件)。❌ 禁止的操作:
读取
/root/password.txt(不在指定目录);写入
/var/www/other_site/config.php(不在指定目录);操作这些目录外的文件时,PHP 会抛出
Warning: file_exists(): open_basedir restriction in effect警告,且操作失败。

delete.php没有限制,还有unlink
.因此我们只需要上传我们生成的phar.jpg文件,并在delete时抓包,将filename参数改为phar://phar.jpg/test.txt即可.
这里把文件从kali里面弄出来也卡了,第一次不熟,先进入phar.phar的目录
然后:ip a

得到地址后有内置的python跑:
!
然后直接浏览器访问对应ip/文件下载就可以了
最后control+c退出
这里对php版本还有要求,所以这里我flag出不来,总之就是这么个东西



