[XDCTF 2015]filemanager

2024-01-02 07:28
文章标签 2015 filemanager xdctf

本文主要是介绍[XDCTF 2015]filemanager,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

[XDCTF 2015]filemanager

我们打开题目,大概看了下存在文件上传功能,并且可以执行重命名和删除文件的操作

在这里插入图片描述

扫描目录发现有源码泄露

在这里插入图片描述

我们逐一分析

upload.php

<?php
require_once "common.inc.php";if ($_FILES) {$file = $_FILES["upfile"];if ($file["error"] == UPLOAD_ERR_OK) {$name = basename($file["name"]);$path_parts = pathinfo($name);if (!in_array($path_parts["extension"], array("gif", "jpg", "png", "zip", "txt"))) {exit("error extension");}$path_parts["extension"] = "." . $path_parts["extension"];$name = $path_parts["filename"] . $path_parts["extension"];// $path_parts["filename"] = $db->quote($path_parts["filename"]);// Fix$path_parts['filename'] = addslashes($path_parts['filename']);$sql = "select * from `file` where `filename`='{$path_parts['filename']}' and `extension`='{$path_parts['extension']}'";$fetch = $db->query($sql);if ($fetch->num_rows > 0) {exit("file is exists");}if (move_uploaded_file($file["tmp_name"], UPLOAD_DIR . $name)) {$sql = "insert into `file` ( `filename`, `view`, `extension`) values( '{$path_parts['filename']}', 0, '{$path_parts['extension']}')";$re = $db->query($sql);if (!$re) {print_r($db->error);exit;}$url = "/" . UPLOAD_DIR . $name;echo "Your file is upload, url:<a href=\"{$url}\" target='_blank'>{$url}</a><br/><a href=\"/\">go back</a>";} else {exit("upload error");}} else {print_r(error_get_last());exit;}
}

首先检查上传文件的文件拓展名是否在白名单中,然后使用addslashes()函数对文件名进行转义处理,进行sql语句查询,如果不存在。那么上传文件到/uploads/文件名,执行insert命令将文件名和拓展名插入该数据表file中

接着看common.inc.php

<?php
$DATABASE = array("host" => "127.0.0.1","username" => "root","password" => "ayshbdfuybwayfgby","dbname" => "xdctf",
);$db = new mysqli($DATABASE['host'], $DATABASE['username'], $DATABASE['password'], $DATABASE['dbname']);
$req = array();foreach (array($_GET, $_POST, $_COOKIE) as $global_var) {foreach ($global_var as $key => $value) {is_string($value) && $req[$key] = addslashes($value);}
}define("UPLOAD_DIR", "upload/");function redirect($location) {header("Location: {$location}");exit;
}

告诉我们数据库的信息,然后用foreach嵌套循环$_GET, $_POST, $_COOKIE参数是否为字符串,如果是则进行转义处理

然后看rename.php

<?php
require_once "common.inc.php";if (isset($req['oldname']) && isset($req['newname'])) {$result = $db->query("select * from `file` where `filename`='{$req['oldname']}'");if ($result->num_rows > 0) {$result = $result->fetch_assoc();} else {exit("old file doesn't exists!");}if ($result) {$req['newname'] = basename($req['newname']);$re = $db->query("update `file` set `filename`='{$req['newname']}', `oldname`='{$result['filename']}' where `fid`={$result['fid']}");if (!$re) {print_r($db->error);exit;}$oldname = UPLOAD_DIR . $result["filename"] . $result["extension"];$newname = UPLOAD_DIR . $req["newname"] . $result["extension"];if (file_exists($oldname)) {rename($oldname, $newname);}$url = "/" . $newname;echo "Your file is rename, url:<a href=\"{$url}\" target='_blank'>{$url}</a><br/><a href=\"/\">go back</a>";}
}
?>

如果请求中存在oldname和newname参数,那么连接数据库进行查询旧文件名是否存在,如果查到那么用update命令去更新该文件名,然后定义newname为/upload/新文件名.拓展名,echo新的文件上传路径

delete.php

<?php
require_once "common.inc.php";if(isset($req['filename'])) {$result = $db->query("select * from `file` where `filename`='{$req['filename']}'");if ($result->num_rows>0){$result = $result->fetch_assoc();}$filename = UPLOAD_DIR . $result["filename"] . $result["extension"];if ($result && file_exists($filename)) {$db->query('delete from `file` where `fid`=' . $result["fid"]);unlink($filename);redirect("/");}
}
?>

就是查询文件是否存在,如果存在则执行delete命令删除文件

既然题目存在文件上传功能,那么我们的思路肯定就是如何传马,但是由于上传时有白名单,那么我们就无法解析php后缀的文件。

我们是否可以尝试将jpg后缀改为php后缀呢,我们重点看向rename.php的这段代码

if ($result) {$req['newname'] = basename($req['newname']);$re = $db->query("update `file` set `filename`='{$req['newname']}', `oldname`='{$result['filename']}' where `fid`={$result['fid']}");if (!$re) {print_r($db->error);exit;}$oldname = UPLOAD_DIR . $result["filename"] . $result["extension"];$newname = UPLOAD_DIR . $req["newname"] . $result["extension"];if (file_exists($oldname)) {rename($oldname, $newname);}$url = "/" . $newname;echo "Your file is rename, url:<a href=\"{$url}\" target='_blank'>{$url}</a><br/><a href=\"/\">go back</a>";}

update命令涉及到参数newname以及从数据库中查找参数oldname值,而后面进行rename()的时候是文件名(不包括拓展名),并且后面拼接路径是从数据库中查找拓展名,那么是不是可以文件名为1.php,然后拓展名为空即可实现getshell

我们可以本地测试下如何利用update语句让拓展名为空

上传', extension=",filename='1.jpg.jpg后,存储在数据库中

在这里插入图片描述

如果我们更新文件名为1.jpg(也就是对文件名', extension='',filename='1.jpg),并且让extension为空

那么我们更新的时候拼接进去的是

update uploadfile set filename='1.jpg', oldname='', extension='',filename='1.jpg';

至于为什么选择在oldname注入,是因为文件上传的时候虽然做了转义但是文件名并不会发生改变,然后在rename的时候oldname是从数据库中找到,而我们在newname注入的话,会发生转义导致文件路径包含\

在这里插入图片描述

因此成功设置extension为空

在这里插入图片描述

然后我们要将文件名1.jpg修改为1.php,这里就需要绕过file_exists()

因为虽然找得到1.jpg的文件名,但是没有拓展名使得判断为错

if (file_exists($oldname)) {rename($oldname, $newname);}

解决办法就是再上传一个1.jpg的文件,和前面提到还是一样,这里的$oldname是从数据库中得到的,也就是说文件名1.jpg拼接上空拓展名就等于文件名1拼接上拓展名.jpg,这样就能查询到存在使其为真

回到题目,我们先上传', extension='',filename='1.jpg.jpg(别忘了是两个jpg)

在这里插入图片描述

然后oldname填', extension='',filename='1.jpg

在这里插入图片描述

这样经过拼接就可以实现让extension为空,然后上传最关键一步1.jpg

然后rename为1.php

在这里插入图片描述

得到flag

在这里插入图片描述

这篇关于[XDCTF 2015]filemanager的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/561720

相关文章

CF Bayan 2015 Contest Warm Up B.(dfs+暴力)

B. Strongly Connected City time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/475/probl

CF Bayan 2015 Contest Warm Up A.(模拟+预处理)

A. Bayan Bus time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/475/problem/A The fi

2015年校赛总结

题目名为“校赛总结”,其实更想换成“Rainbow为什么五题滚粗?!”。作为今年校赛大二没拆的两个队伍之一,结果打成这样,没脸见人了,总结起来就是我认为自己今天SB了。主要有以下几点: 1.我今天状态的确不好,最后卡的那道B题跟去年在农大校赛上遇见的那题类似,在最后那段时间我已经有思路了,可是由于当时不敢写。等到最后15分钟才开始敲,加上我用很麻烦的Dijstra那种方法,调试起来好多细节要处理

百度之星 2015 复赛 1001 (数长方形)

数长方形    Accepts: 595    Submissions: 1225  Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description 小度熊喜欢玩木棒。一天他在玩木棒的时候,发现一些木棒会形成长方形

百度之星 2015 初赛(1) 1002 找连续数

找连续数      Accepts: 401      Submissions: 1911  Time Limit: 2000/1000 MS (Java/Others)      Memory Limit: 32768/32768 K (Java/Others) Problem Description 小度熊拿到了一个无序的数组,对于这个数组,小度熊想知道是

2015多校联合训练第三场Work(hdu5326)

题意: a是b的上司,b是c的上司,则a是c的上司,问构成一个树种,有多人是 k个人的上司 思路: 先找出root,然后dfs一下就行 #include <bits/stdc++.h>#define LL long longusing namespace std;const int MAXN = 1e6;int f[105];int n, k;int mp[101][101];

2015年多校联合训练第三场RGCDQ(hdu5317)

题意: f(i)代表i数中有的素数的种数,给出区间[l,r],求区间内max(gcd(f(i))), 由于i最大是1e6,2*3*5*7*11*13*17>1e6,故最多不超过7种素数, 先打表打出1e6内的素数种数表,然后用sum[i][j]代表1-i个数中,还有j个素数的个数,最后用sum[r][j] - sum[l-1][j]求出区间内含有j个素数的数的个数,暴力找出1,2,3,4,5

2015多校联合训练第一场Tricks Device(hdu5294)

题意:给一个无向图,给起点s,终点t,求最少拆掉几条边使得s到不了t,最多拆几条边使得s能到t 思路: 先跑一边最短路,记录最短路中最短的边数,总边数-最短边数就是第二个答案 第一个答案就是在最短路里面求最小割,也就是求最大流,然后根据最短路在建个新图,权为1,跑一边网络流 模板题,以后就用这套模板了 #include <iostream>#include <cstdio>#incl

2015多校联合训练第一场Assignment(hdu5289)三种解法

题目大意:给出一个数列,问其中存在多少连续子序列,子序列的最大值-最小值< k 这题有三种解法: 1:单调队列,时间复杂度O(n) 2:RMQ+二分,时间复杂度O(nlogn) 3:RMQ+贪心,时间复杂度O(nlogn) 一:RMQ+二分 RMQ维护最大值,最小值,枚举左端点i,二分找出最远的符合的右端点j,答案就是ans += j - i+1;(手推一下就知道) 比如1 2 3

2015年多校联合训练第一场OO’s Sequence(hdu5288)

题意:给定一个长度为n的序列,规定f(l,r)是对于l,r范围内的某个数字a[i],都不能找到一个对应的j使得a[i]%a[j]=0,那么l,r内有多少个i,f(l,r)就是几。问所有f(l,r)的总和是多少。 公式中给出的区间,也就是所有存在的区间。 思路:直接枚举每一个数字,对于这个数字,如果这个数字是合法的i,那么向左能扩展的最大长度是多少,向右能扩展的最大长度是多少,那么i为合法的情况