buuctf 刷題記錄 [第二章 web進階]文件上傳
上傳,下面給了代碼
代碼審計
<?php
header("Content-Type:text/html; charset=utf-8");
// 每5分鍾會清除一次目錄下上傳的文件
require_once('pclzip.lib.php');
if(!$_FILES){
echo '
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>文件上傳章節練習題</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style type="text/css">
.login-box{
margin-top: 100px;
height: 500px;
border: 1px solid #000;
}
body{
background: white;
}
.btn1{
width: 200px;
}
.d1{
display: block;
height: 400px;
}
</style>
</head>
<body>
<div class="container">
<div class="login-box col-md-12">
<form class="form-horizontal" method="post" enctype="multipart/form-data" >
<h1>文件上傳章節練習題</h1>
<hr />
<div class="form-group">
<label class="col-sm-2 control-label">選擇文件:</label>
<div class="input-group col-sm-10">
<div >
<label for="">
<input type="file" name="file" />
</label>
</div>
</div>
</div>
<div class="col-sm-8 text-right">
<input type="submit" class="btn btn-success text-right btn1" />
</div>
</form>
</div>
</div>
</body>
</html>
';
show_source(__FILE__);
}else{
$file = $_FILES['file'];
if(!$file){
exit("請勿上傳空文件");
}
$name = $file['name'];
$dir = 'upload/';
$ext = strtolower(substr(strrchr($name, '.'), 1));
$path = $dir.$name;
function check_dir($dir){
$handle = opendir($dir);
while(($f = readdir($handle)) !== false){
if(!in_array($f, array('.', '..'))){
if(is_dir($dir.$f)){
check_dir($dir.$f.'/');
}else{
$ext = strtolower(substr(strrchr($f, '.'), 1));
if(!in_array($ext, array('jpg', 'gif', 'png'))){
unlink($dir.$f);
}
}
}
}
}
if(!is_dir($dir)){
mkdir($dir);
}
$temp_dir = $dir.md5(time(). rand(1000,9999));
if(!is_dir($temp_dir)){
mkdir($temp_dir);
}
if(in_array($ext, array('zip', 'jpg', 'gif', 'png'))){
if($ext == 'zip'){
$archive = new PclZip($file['tmp_name']);
foreach($archive->listContent() as $value){
$filename = $value["filename"];
if(preg_match('/\.php$/', $filename)){
exit("壓縮包內不允許含有php文件!");
}
}
if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {
check_dir($dir);
exit("解壓失敗");
}
check_dir($dir);
exit('上傳成功!');
}else{
move_uploaded_file($file['tmp_name'], $temp_dir.'/'.$file['name']);
check_dir($dir);
exit('上傳成功!');
}
}else{
exit('僅允許上傳zip、jpg、gif、png文件!');
}
}
代碼分為3個功能
1.將上傳的文件保存在upload路徑下,同時檢查壓縮包內的文件名是否有帶有.或者..
的,並且檢查文件是否是jpg,gif,png
$dir = 'upload/';
$ext = strtolower(substr(strrchr($name, '.'), 1));
$path = $dir.$name;
function check_dir($dir){
$handle = opendir($dir);
while(($f = readdir($handle)) !== false){
if(!in_array($f, array('.', '..'))){
if(is_dir($dir.$f)){
check_dir($dir.$f.'/');
}else{
$ext = strtolower(substr(strrchr($f, '.'), 1));
if(!in_array($ext, array('jpg', 'gif', 'png'))){
unlink($dir.$f);
直接上傳的'jpg', 'gif', 'png
文件是沒有這個待遇的,會被放入一個tmp路徑
2.tmp路徑
$temp_dir = $dir.md5(time(). rand(1000,9999));
if(!is_dir($temp_dir)){
mkdir($temp_dir);
move_uploaded_file($file['tmp_name'], $temp_dir.'/'.$file['name']);
check_dir($dir);
exit('上傳成功!');
tmp路徑是隨機的md5值,從1000到9999
3.文件解壓縮
if(in_array($ext, array('zip', 'jpg', 'gif', 'png'))){
if($ext == 'zip'){
$archive = new PclZip($file['tmp_name']);
foreach($archive->listContent() as $value){
$filename = $value["filename"];
if(preg_match('/\.php$/', $filename)){
exit("壓縮包內不允許含有php文件!");
apache漏洞
apache服務器,有文件解析漏洞,也就是可以上傳類似backdoor.php.notexist
這種文件,
如果遇到無法解析的后綴名會向前解析,也就是跳過notexist
后綴,直接解析php
后綴
用010editor改文件名
首先確定目錄穿越時候用的名字
比如需要到根目錄就是../../
然后計算好起的名字的長度
例如../../1.php.xxx
這個名字就是15位的
然后給這個還沒有壓縮的馬起個占15字符的名字,例如123456789123456
后綴無所謂,反正到時候都需要010editer改
然后zip壓縮一下
用010edirer改