前置知识

本题框架是flask框架,正好python面向对象和flask框架没怎么学,借着这个好好学一下

这里我直接听mooc上北京大学陈斌老师的内容,因为讲的比较清楚,直接把他的ppt拿过来,看看就懂了

解题思路

直接给源码,得知是python,flask框架。审就完事了

代码审计

#! /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)

代码量不是很长,大概意思是创建了一个Task类,定义了若干个函数,利用时再剖析,三个路由

  1. geneSign路由:

    其调用了getSign函数,返回了经md5处理的值

  2. De1ta路由:

    通过get方法传入param的值,在cookie中传入action和sign的值,将param通过waf函数。再用传入的参数构造一个Task类,执行Exec函数。

    首先看waf函数,禁了gopher协议和file协议,这么打ssrf打不了了。

    再看exec函数,大概就是先判断成功登陆,登陆成功后,读经过scan扫描的param,那么思路就出来了,如果我们传入param的值为flag.txt,并且令action里面有scan和read这两个参数,即可读取内容

  3. /路由:

    根目录路由,指定了访问根目录时,会读整个源码,并定义了一些基础函数

大概思路明确了。

保证checkSign函数返回真

保证 getSign(self.action, self.param) == self.sign

即经过hashlib.md5(secert_key + param + action).hexdigest()处理

需要知道这三个字符串连接后的md5值,但是纵观源码并没有哪里有secert_key

方法一 字符串拼接

我们又发现很有意思的一点,确认action的值时,使用的是in,并非是等于号,也就是说只要read在action里即可。

因为使用的是连接符号加号(+),那么传入这两个值时

md5(secert_key + 'flag.txt' + 'readscan')

md5(secert_key + 'flag.txtread' + 'scan')

其实是相同的字符串md5(secert_keyflag.txtreadscan),经md5处理当然也相同

我们先令/geneSign?param=flag.txtread。在此页面下我们可以获得md5(secert_key + 'flag.txtread' + 'scan') 的值

再访问/De1ta路由,在其中传入cookie值和get请求即可获得对应的flag

方法二 哈希长度扩展攻击

需要使用工具HashPump

原理见此篇

github源码

git clone https://github.com/bwall/HashPump.git

$ apt-get install g++ libssl-dev

$ cd HashPump

$ make

$ make install

首先在kali机下安装,这里我的kali机没换国内源。。。先换国内源,然后如果有问题的话aptitude降级安装

一步一步敲命令,完成后

使用方法:

使用方法:

Input Signature 为md5(salt+message)的值

Input Data 为message内容

Input Key Length 为salt+message长度

Input Data to Add 为自定义添加

(因为代码中告诉了secert_key为16位,这里的sat看成16位的secert_key+8位的flag.txt即24位)

算出最后的值同样放在cookie中即可(\x记得换成%,即url形式)

CVE-2019-9948

Python 2.x到2.7.16中的urllib支持local_file

local_file允许远程攻击者绕过保护机制

exp

这里是使用的 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 的错误

总结思路

  • 踏实的代码审计功底
  • MD5扩展攻击
  • 搜索cve,拿poc打

知识点

  • python代码审计
  • md5扩展攻击

刷题[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

    原帖地址 : https://xz.aliyun.com/t/5927 De1CTF 2019 的一个题目总结 题目描述 直接查看页面源代码可以看到正确格式的代码 #! /usr/bin/env py ...

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

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

  4. BUUCTF | [De1CTF 2019]SSRF Me

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

  5. 刷题[GWCTF 2019]mypassword

    解题思路 打开网站,登陆框.注册一个用户后再登陆 看样子是注入了,在feedback.php中发现注释 <!-- if(is_array($feedback)){ echo "< ...

  6. 刷题[GWCTF 2019]你的名字

    解题思路 打开发现需要输入名字,猜测会有sql注入漏洞,测试一下发现单引号被过滤了,再fuzs下看看过滤了哪些 长度为1518和1519的都有过滤,测试一下,感觉不是sql注入了.那还有什么呢,考虑了 ...

  7. 刷题[RCTF 2019]Nextphp

    前置知识 一些关于php7.4版本需知: 1.FFI扩展:ffi.cdef 其中还有这样一段话 如果ffi.cdef没有第二个参数,会在全局查找,第一个参数所声明的符号.意思就是其在不传入第二个参数时 ...

  8. 刷题[SUCTF 2019]CheckIn

    解题思路 打开网页发现只是简单做了一个上传界面,朴实无华 上传一个php文件,发现非法后缀. 上传一个.htaccess文件,发现,爆出很重要的信息 exif_imagetype函数通过检测文件头来检 ...

  9. 刷题[RoarCTF 2019]Easy Java

    前置知识 WEB-INF/web.xml泄露 java web工程目录结构 Servlet访问URL映射配置 由于客户端是通过URL地址访问Web服务器中的资源,所以Servlet程序若想被外界访问, ...

随机推荐

  1. dcoker 小应用(一)

    docker 创建Ubuntu系统 1.创建Dockerfile #ubuntu:14.04 image FROM ubuntu:14.04 MAINTAINER XXX, xxx@xxx.com R ...

  2. Java程序员值得拥有的TreeMap指南

    先看再点赞,给自己一点思考的时间,微信搜索[沉默王二]关注这个有颜值却假装靠才华苟且的程序员.本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题 ...

  3. shell 三剑客之 sed

    sed 在shell 编程里也很常用,功能强大! 同grep一样,sed提供两种方式: 方式一:stdout | sed [option] "pattern command" 从文 ...

  4. C# 根据出生年月 计算天数/计算X岁X月X天字符串

    public class TimeTool { //根据出生年月计算 整数天 private static int GetAgeByBirthdate(DateTime birthdate) { Da ...

  5. .Net 单元测试框架xUnit使用

    使用前需要导入下面的NuGet包:(不然可能会导致测试代码无法运行) .net版本 .net core3.1 Moq这个包只有需要Mock的时候才需要导入(不清楚Mock的话可以留言或自行百度) 开始 ...

  6. css学习入门-第一个css程序

    1.css的优势: --内容与表现分离 --网页结构统一,可以实现复用 --样式丰富 2.css的3种导入方式 2.1行内样式 <h1 style="color: red"& ...

  7. docker run <image-id>和 docker start <container-id>

  8. 这应该是最适合国内用户的K3s HA方案

    前 言 在面向生产环境的实践中,高可用是我们无法避免的问题,K3s本身也历经多个版本的迭代,HA方案也进行了不断优化,形成了目前的比较稳定的HA方案. 目前官方提供两种HA方案: 嵌入式DB的高可用( ...

  9. vue中饼状图的使用

    图形构建子组件 <template> <div> <div id="myChart" :style="echartStyle"&g ...

  10. oracle数据库备份 -九五小庞

    oracle数据库备份