首页 > 其他分享 >ssrfme(flask代码审计)

ssrfme(flask代码审计)

时间:2022-10-31 14:44:20浏览次数:72  
标签:审计 ssrfme return flask self param sign result action

源码

#! /usr/bin/env python
# #encoding=utf-8
from flask import Flask
from flask import request
import socket
import hashlib
import urllib
import sys
import os
import json
reload(sys)
sys.setdefaultencoding('latin1')
 
app = Flask(__name__)
 
secert_key = os.urandom(16)
 
class Task:
    def __init__(self, action, param, sign, ip):
        self.action = action
        self.param = param
        self.sign = sign
        self.sandbox = md5(ip)
        if(not os.path.exists(self.sandbox)):
            os.mkdir(self.sandbox)
 
    def Exec(self):
        result = {}
        result['code'] = 500
        if (self.checkSign()):
            if "scan" in self.action:
                tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
                resp = scan(self.param)
                if (resp == "Connection Timeout"):
                    result['data'] = resp
                else:
                    print resp
                    tmpfile.write(resp)
                    tmpfile.close()
                result['code'] = 200
            if "read" in self.action:
                f = open("./%s/result.txt" % self.sandbox, 'r')
                result['code'] = 200
                result['data'] = f.read()
            if result['code'] == 500:
                result['data'] = "Action Error"
        else:
            result['code'] = 500
            result['msg'] = "Sign Error"
        return result
 
    def checkSign(self):
        if (getSign(self.action, self.param) == self.sign):
            return True
        else:
            return False
 
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))   #接收参数param
    action = "scan"
    return getSign(action, param)
 
@app.route('/De1ta',methods=['GET','POST'])
def challenge():
    action = urllib.unquote(request.cookies.get("action"))      #读取cookie值
    param = urllib.unquote(request.args.get("param", ""))       #读取GET值  
    sign = urllib.unquote(request.cookies.get("sign"))          #读取cookie值
    ip = request.remote_addr
    if(waf(param)):
        return "No Hacker!!!!"
    task = Task(action, param, sign, ip)        #实例化TASK
    return json.dumps(task.Exec())      #调用函数,以json格式输出
 
@app.route('/')
def index():
    return open("code.txt","r").read()
 
def scan(param):
    socket.setdefaulttimeout(1)
    try:
        return urllib.urlopen(param).read()[:50]
    except:
        return "Connection Timeout"
 
def getSign(action, param):
    return hashlib.md5(secert_key + param + action).hexdigest()     #把密钥与传入的param和action拼接经过md5加密后返回,注意运行代码后这里密钥是唯一的,因为没有再次生成新的,所以不用管secert_key。
 
def md5(content):
    return hashlib.md5(content).hexdigest()
 
def waf(param):
    check=param.strip().lower()     #删除首尾空格并且转换小写
    if check.startswith("gopher") or check.startswith("file"):      #字符串开头,把gopher和file协议禁用
        return True
    else:
        return False
if __name__ == '__main__':
    app.debug = False
    app.run(host='0.0.0.0',port=9999)

wp

flask框架,先找到三个路由

@app.route("/geneSign", methods=['GET', 'POST'])

输入/geneSign会执行下面的函数geneSign(),methods表示接收的方法是GET和POST,接收参数param,返回getSign()函数。

@app.route('/De1ta',methods=['GET','POST'])

输入/De1ta会执行下面的函数challenge(),methods表示接收的方法是GET和POST,获取GET的param和cookie的actionsign,waf()过滤函数,实例化Task并调用方法Exec(),返回对象的json格式。

@app.route('/')

返回源代码

首先看第二个路由,接收三个主要参数,并且waf()过滤了两个伪协议。接下来实例化类并调用Exec()函数。我们来看下Exec()。

if语句中调用了checkSign(),又调用了getSign(),

getSign():将刚开始生成的随机数与param和action拼接并生成md5返回。

如果getSign()的返回值与我们需要传入的cookie里的sign相等就返回true。

接下来有两个if语句

第一个,只需'scan'在action中,然后以写入方式打开result.txt,调用scan()读取param文件(param=flag.txt)的前50个字符,然后写入result.txt文件。

第二个,只需'read'在action中,然后读取result.txt内容返回作为result字典中data的值。

从代码中来看,如果未通过第二个if的read,则输出的resp如下(即未写入之前的result.txt,此时result字典里只有code的值)

因此我们也需要获取data里的内容,这里的两个if语句中都是使用了'in'来判断,而不是通过'='来判断,因此如果action=readscan或者scanread的话,两个if语句都会被执行。这样既可以将flag.txt写入results.txt,又能读取写入后的results.txt内容。

接下来我们回到checkSign()函数,要让它返回true我们就要得到sign的值,sign我们可以通过geneSign()来获取。由于这里的action已经是scan,而我们想要的是action='readscan'或者'action=scanread',因此需要想办法让action是我们想要的值。由于getSign()函数是使用拼接的方式(secert_key + param + action)进行md5加密,因此我们可以使 param=flag.txtread,那么此时返回的是 secert_key+'flag.txtread'+'scan'的md5加密的密文。当我们使用路由De1ta时,只需要让param='flag.txt',sign为geneSign()返回后的值,action='readscan',这样checkSign()就能够返回true,成功执行接下来的两个if语句写入后读取获得flag。

获取sign

添加Cookie到请求包,添加sign以及action,最后获取flag。

标签:审计,ssrfme,return,flask,self,param,sign,result,action
From: https://www.cnblogs.com/p0n9/p/16844204.html

相关文章

  • flask数据库迁移方法
     一、集成pythonshell为避免每次启动shell会话都要导入数据库实例和模型,我们可以使用app.shell_context_processer装饰器来创建并注册一个shell上下文处理器。app.py......
  • 效率倍升:逐浪HMS主题大师1.2-全渠道自动打包、快速传送、锁屏提取、资源审计,移动主题
    逐浪HMS主题大师1.2[更加快递|华为、小米、oppo、vivo以及字体上架打包都来啦]逐浪HMS主题大师介绍软件架构使用环境启动使用捐赠我们联系我们界面欣赏![在......
  • Flask初步认识
    1.Flask基本认识Flask本身相当于一个内核,其他几乎所有的功能都要用到扩展包(数据库Flask-SQLAlchemy),都需要用第三方的扩展来实现。比如可以用Flask扩展加入ORM、窗体验......
  • flask之wtforms
    简介WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证。安装:pip3installwtforms==2.3.3用户登录注册示例1.用户登录当用户登录时候,需要......
  • 运用索引快速删除aud$表6个月前的审计记录
    文档课题:运用索引快速删除aud$表6个月前的审计记录.应用场景:最近在生产库发现定时Job执行删除aud$表6个月前的记录需要1.5小时,该表大小30g,总记录数0.12billion.真是有点耗......
  • 重构 Flask 服务端项目对于 SQL 的配置使用和延迟的请求回调巧妙设计运用
    一.Flask-SQLAlchemySQLAlchemy的声明扩展是使用SQLAlchemy的最新方法,可以像Django一样在一个位置定义表和模型,然后在任何地方使用。fromsqlalchemyimportcreate_engi......
  • flask之flask_session
    flask-session-Flask中session处理机制(内置:将session保存在加密cookie中实现)-请求刚到来:获取随机字符串,存在则去"数据库"中获取原来的个人数据,否则创建一......
  • flask的自定义bootstrap模板
    由于​​flask-bootstrap​​​的​​base.html​​​模板提供功能有限(文件位置:​​/site-packages/flask_bootstrap/templates/bootstrap/base.html​​),比如我想在body中最......
  • [代码审计][ThinkPHP]Thinkphp3.2.3反序列化利用链分析
    文章目录​​Thinkphp3.2.3反序列化利用链分析​​​​分析​​​​利用链​​菜鸡在做CTF的时候想深入分析一下,也就产生了这篇文章Thinkphp3.2.3反序列化利用链分析分析首......
  • [Java代码审计]javacon WriteUp
    文章目录​​写在前面​​​​javacon​​写在前面在P神星球看到的,这里学习一下,文件在​​https://www.leavesongs.com/media/attachment/2018/11/23/challenge-0.0.1-SNAPS......