一、简介

Flask是由python实现的一个web微框架,让我们可以使用Python语言快速实现一个网站或Web服务

二、目录结构

flask-demo/
  ├ run.py           # 应用启动程序
  ├ config.py        # 环境配置
  ├ requirements.txt # 列出应用程序依赖的所有Python包
  ├ tests/           # 测试代码包
  │   ├ __init__.py 
  │   └ test_*.py    # 测试用例
  └ myapp/
      ├ admin/       # 蓝图目录
      ├ static/
      │   ├ css/     # css文件目录
      │   ├ img/     # 图片文件目录
      │   └ js/      # js文件目录
      ├ templates/   # 模板文件目录
      ├ __init__.py    
      ├ forms.py     # 存放所有表单,如果多,将其变为一个包
      ├ models.py    # 存放所有数据模型,如果多,将其变为一个包
      └ views.py     # 存放所有视图函数,如果多,将其变为一个包

三、示例

from flask import Flask  #引入Flask类

app = Flask(__name__)  #为这个类创建一个实例,当前模块的`__name__`为`main`

@app.route('/') #用route()这个修饰器定义了一个路由,告诉flask如何访问该函数
def index():
    return 'Hello World'

if __name__ == '__main__':
    app.debug = True # 设置调试模式,生产模式的时候要关掉debug
    app.run() #最后用run()函数使这个应用在服务器上运行起来

1、什么是路由(route)

https://blog.csdn.net/weixin_39862716/article/details/111791304

(1) 我的理解

简单来说路由就是一个映射器,利用一个给定的参数来映射到对应的指定路径或者执行函数等等

例如上面的示例,我们在浏览器中输入 http://localhost:5000/

浏览器中就会显示Hello World

(2) 动态路由

from flask import Flask

app1 = Flask('first_flask_demo')

@app1.route('/user/') # 指定了格式

def demo1(username): # username是用户从地址上的输入

	return 'Welcome %s' % username

if __name__ == '__main__':

	app1.run(debug=True, host='0.0.0.0', port=8080)

#运行后在浏览器中输入地址 http://localhost:8080/user/alex,可以看到输出为 Welcome alex

四、函数

1、urllib.unquote()

https://www.cnblogs.com/dplearning/p/5834938.html

用来处理提交的url,并解码

s = "url=%2F&email=imtesting%40tempmail.com&password=hereispassword"
print urllib.unquote(s)

 >>> url=/&email=imtesting@tempmail.com&password=hereispassword

2、os.urandom()

https://www.pynote.net/archives/2215

os.urandom函数用来获取一个指定长度的随机bytes对象,python的这个函数实际上是在读取OS操作系统提供的随机源。

>>> os.urandom(1)
b'\x03'
>>> os.urandom(2)
b'\t['
>>> os.urandom(3)
b'\xdb\x8a\x7f'
>>> os.urandom(4)
b'Q\xeal\xf4'
>>> len(os.urandom(4))
4

3.request.cookies.get(“action”) 和 request.args.get(“param”, “”)

(1)args只获取地址栏中参数 ,不分get请求方式还是post请求方式

这里应该是指定了获取param的值

(2)cookies 就是获取cookie中action的值

image

五、CTF原题

https://buuoj.cn/challenges#[De1CTF%202019]SSRF%20Me

1、源码

对现在的我来说有点多,一部分一部分的了解

image

image-20211230200954735

可以看到,这个路由输出了源码

image-20211230201242334

其他两个路由

image-20211230202224471

image-20211230202240058

2、解析

(1)大体思路

进入/De1ta 传参,先通过waf(),再进入task.Exec()

task.Exec()中需要绕过checkSign()中的getSign()

getSign()中我们需要知道它的secret_key

继续看task.Exec(),它的 if 判断是个 in,而不是==,那就比较好绕过了

只需要action包含read就行了

还有最后一个路由,/geneSign,在这个路由中,我们就可以获得我们想要的secret_key

geneSign()中的字符串,action中的scan是固定死的,但是param是可控的

由于getSign()geneSion()一样,其中param是放在前面的:param+action

那么我们构造paramflag.txtread

param+action=flag.txtreadscan

/geneSign中传入 param=flag.txt

获得flag.txtreadscansecret_key=912a422c93150ba5df01396d193022ce

在路由/De1ta中传入 param=flag.txt action=flag.txt secret_key=912a422c93150ba5df01396d193022ce

image-20211230214658133

六、总结

1、简要的了解了一下Flask框架的构造和一些基本语法

2、这道CTF题并不算难,主要还是为了熟悉Flask框架

3、记录这道题的目的,还是为了能够更加熟悉Python的一些函数以及语法

为后面写Python的脚本打下一些基础