CTF Web安全

fmkq的简化版'如此木大'详解(SSRF。python格式化字符串)

Posted on 2020-04-15,3 min read

首先是php的SSRF。

可以用进制绕过。
格式化字符串。用%1$s绕过
之后就是探测开放端口

得到5000端口有个应用

告诉我们flag在/fl4g/flag
使用方法是/query?path=

存在任意文件读取。读取源码进行分析
main.py

from flask import Flask, request
from file import File
from readfile import FileReader

app = Flask(__name__)

@app.route('/query')
def query():
    path = request.args.get('path')
    if not path:
        return '请输入路径'
    file = FileReader(File(path))
    return str(file)

@app.route('/')
def index():
    return 'Use /query?path= to query what you want. And what you want is at /fl4g/flag' 

if __name__ == '__main__':
    app.run(port=8890)

file.py

import os
import os.path

class File:
    "The file class"
    def __init__(self, path):
        self.path = path
        self.name = os.path.basename(self.path)
        self.dir = os.path.dirname(self.path)
    def listDir(self):
        return os.listdir(os.path.dirname(self.dir))

readfile.py

class FileReader:
    def __init__(self, file):
        self.file = file
    def __str__(self):
        if 'fl4g' in self.file.path:
            return 'nonono,it is a secret!!!'
        else:
            output = 'The file you read is:\n'
            filepath = (self.file.dir + '/{file.name}').format(file=self.file)
            output += filepath
            output += '\n\nThe content is:\n'
            try:
                f = open(filepath,'r')
                content = f.read()
                f.close()
            except:
                content = 'can\'t read'
            output += content
            output += '\n\nOther files under the same folder:\n'
            output += '\n'.join(self.file.listDir())
            return output.replace('\n','')

从main.py开始分析
接受path的值。然后传入File类中

File.path=path
File.name= os.path.basename(path)
File.dir=os.path.dirname(path)

再把File类当作参数。传入FileReader类中
判断。File.path不能有fl4g

filepath = (self.file.dir + '/{file.name}').format(file=self.file)
简化下就是
filepath = (File.dir + '/{File.name}').format(file=File)

当我们传入/etc/passwd时
File类各个属性值如下

path=/etc/passwd
name=passwd
dir=/etc

我们现在要绕过/f14g这个限制
这里可以利用format这个点

输入/fl4{file.name[3]}/flag
此时的属性如下

path=/fl4{file.name[3]}/flag
name=flag
dir=/fl4{file.name[3]}

进行format格式化时

'/fl4{file.name[3]}'+'/{file.name}'.format(file)

这个file是Fille类。所以format是调用File类的name的第四个字符
也就是g
然后file.name返回flag
就变成了

'/fl4g'+'/flag'

然后读取。成功绕过限制

下一篇: [FireshellCTF2020]Caas(C语言编译器)→