【BUUCTF】[GXYCTF2019]BabysqliV3.01

进入题目页面如下

是一个登陆界面,尝试万能密码登录

当输入带有符号的用户名时,提示用户不存在,那尝试

弱口令密码

用户名:admin

密码:password

可以,登陆上去了,页面如下

难道是文件上传?

上传了一句话木马的文件并没有显示上传成功及文件路径,上传带有木马的图片转化成了文本且显示太大了

应该换个思路

发现URL里有传参?file=upload

想要获取源码,猜测需要构造伪协议

构造伪协议

1、home.php

php 复制代码
http//:a6e52924-fe4f-43a7-8bec-59cf51b383c6.node5.buuoj.cn:81/home.php?file=php://filter/convert.base64-encode/resource=home

2、upload.php

php 复制代码
http//:a6e52924-fe4f-43a7-8bec-59cf51b383c6.node5.buuoj.cn:81/home.php?file=php://filter/convert.base64-encode/resource=upload

伪协议知识点

在 Web 安全测试和开发过程中,有时候需要利用伪协议来获取目标文件的源码

PHP 环境下的伪协议利用

1. php://filter 伪协议
  • 原理php://filter 伪协议允许你在读取文件内容之前对其进行过滤,例如进行 base64 编码,这样可以绕过一些文件包含的限制,并且避免直接执行文件中的代码。
  • 假设存在一个文件包含漏洞,目标代码如下
php 复制代码
<?php
$file = $_GET['file'];
include($file);
?>

可以构造如下 URL 来获取目标文件的源码

复制代码
http://example.com/index.php?file=php://filter/read=convert.base64-encode/resource=target_file.php
  • 解释
    • php://filter 是伪协议的名称。
    • read=convert.base64-encode 表示对读取的文件内容进行 base64 编码。
    • resource=target_file.php 指定要读取的目标文件。

获取到 base64 编码后的内容后,在本地进行解码即可得到目标文件的源码。

2. data://text/plain 伪协议

这里 PD9waHAgc3lzdGVtKCJscyAiKTs/Pg==<?php system("ls ");?> 的 base64 编码。

  • 解释
    • data://text/plain 是伪协议名称。
    • ;base64 表示后面的数据是经过 base64 编码的。
    • 编码后的数据就是要执行或包含的内容。

Java 环境下的伪协议利用

1. jar: 伪协议
  • 原理jar: 伪协议可以用来访问 JAR 文件中的资源。在一些存在文件包含或资源加载漏洞的 Java 应用中,可以利用该伪协议来获取 JAR 文件中的源码。

  • 假设存在一个 Java 应用,通过 URLClassLoader 加载外部资源,攻击者可以构造如下 URL:

    jar:file:/path/to/your.jar!/com/example/YourClass.class

  • 解释

    • jar: 是伪协议名称。
    • file:/path/to/your.jar 指定 JAR 文件的路径。
    • !/com/example/YourClass.class 指定 JAR 文件中要访问的具体类文件。

利用伪协议获得home.php和upload.php的源码

访问后得到的页面如下

需要对以上base64编码解码,可以使用下面这个在线工具

base64解码 base64编码 在线base64解码/编码工具 iP138在线工具

按以上方法获得home.php和upload.php的源码

1、home.php源码

php 复制代码
<?php
session_start();
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /> <title>Home</title>";
error_reporting(0);
if(isset($_SESSION['user'])){
	if(isset($_GET['file'])){
		if(preg_match("/.?f.?l.?a.?g.?/i", $_GET['file'])){
			die("hacker!");
		}
		else{
			if(preg_match("/home$/i", $_GET['file']) or preg_match("/upload$/i", $_GET['file'])){
				$file = $_GET['file'].".php";
			}
			else{
				$file = $_GET['file'].".fxxkyou!";
			}
			echo "当前引用的是 ".$file;
			require $file;
		}
		
	}
	else{
		die("no permission!");
	}
}
?>

2、upload.php源码

php 复制代码
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
 
<form action="" method="post" enctype="multipart/form-data">
	上传文件
	<input type="file" name="file" />
	<input type="submit" name="submit" value="上传" />
</form>
 
<?php
error_reporting(0);
class Uploader{
	public $Filename;
	public $cmd;
	public $token;
	
 
	function __construct(){
		$sandbox = getcwd()."/uploads/".md5($_SESSION['user'])."/";
		$ext = ".txt";
		@mkdir($sandbox, 0777, true);
		if(isset($_GET['name']) and !preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i", $_GET['name'])){
			$this->Filename = $_GET['name'];
		}
		else{
			$this->Filename = $sandbox.$_SESSION['user'].$ext;
		}
 
		$this->cmd = "echo '<br><br>Master, I want to study rizhan!<br><br>';";
		$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{
			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 $sandbox.$this->Filename.$ext;
		return $this->Filename;
	}
 
	function __destruct(){
		if($this->token != $_SESSION['user']){
			$this->cmd = "die('check token falied!');";
		}
		eval($this->cmd);
	}
}
 
if(isset($_FILES['file'])) {
	$uploader = new Uploader();
	$uploader->upload($_FILES["file"]);
	if(@file_get_contents($uploader)){
		echo "下面是你上传的文件:<br>".$uploader."<br>";
		echo file_get_contents($uploader);
	}
}
 
?>
 

代码审计

类 Uploader:

构造函数 __construct:

生成一个沙盒目录,路径为当前工作目录下的 uploads 文件夹,以用户会话中的 user 值的 MD5 哈希命名。

_GET\['name'\] 存在且不包含特定的危险字符串(如 data://、filter://、php:// 或 .),则将其赋值给 Filename;否则,使用沙盒目录和用户会话中的 user 值加上 .txt 扩展名作为文件名。

初始化 cmd 为一个提示信息,token 为用户会话中的 user 值。

方法 upload:

Filename 包含非字母数字字符,将 cmd 设置为输出非法文件名的错误信息。

若上传文件大小超过 1024 字节,将 $cmd 设置为输出文件过大的错误信息。

若以上条件都不满足,将 $cmd 设置为使用 move_uploaded_file 函数将上传文件移动到指定位置的代码。

魔术方法 __toString:返回 $Filename 的值。

析构函数 __destruct:

检查 token 是否与用户会话中的 user 值相等,若不相等,将 cmd 设置为输出令牌检查失败的错误信息。

执行 $cmd 中的代码。

主程序逻辑:

若存在上传文件,创建 Uploader 对象并调用 upload 方法处理上传文件。

尝试读取上传文件的内容,若成功则输出文件路径和内容。

重点看以下代码

有file_get_contents($uploader)函数,这是一个读取文件的函数,猜测可以读取flag文件,通过修改Filename参数来读取flag信息

构造payload如下

php 复制代码
http://7273c8cf-da67-4fc9-b0e5-8a1691cef3f8.node5.buuoj.cn:81/home.php?file=upload&name=/var/www/html/flag.php

访问后,上传一个按照规定内的文件,最后利用burpsuite抓包,得到flag

相关推荐
BingoGo1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
cipher2 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
BingoGo2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack4 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理5 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
一次旅行5 天前
网络安全总结
安全·web安全