[GXYCTF2019]BabysqliV3.0
首先查看页面源码。发现提示
扫描目录,发现存在upload.php和home.php,经过测试发现没什么用。
尝试登录发现/search.php。
可以通过页面响应判断用户名为admin。
考虑此处是否有sql注入。
尝试之后未发现注入。
爆破出密码password。
登录后跳转至/home.php?file=upload
。感觉此处存在文件包含。
利用后获得源码
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 74
| <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); } }
?>
|
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!"); } } ?>
|
可以看到home.php对包含的文件名进行了限制,只允许包含以home或upload结尾的php文件。
而upload.php实现了文件上传的功能,其__construct()
构造函数对$_GET['name']
进行了限制,要求不能包含data:/\ | filter:// | php:// | .
,否则文件名将被赋值为txt文件,但没有对其他特殊字符进行限制,而后面的upload()
函数虽然对文件内容进行了限制,但直接将刚获取的文件名进行了语句拼接,并在__destruct()
析构函数中使用eval()
,进行命令执行,所以此处存在命令执行漏洞。
以下语句可闭合php语句实现phpinfo()。
1
| /upload.php?name=1');phpinfo();print('
|
最终通过system()
获取flag