草庐IT

【网络安全】记一次数据包解签名实战

H_00c8 2023-03-28 原文

声明:系统为授权测试,本文所提供的信息学习研究或自查使用,切勿用于非法用途,由于传播,利用此文所提供的信息而造成的任何直接或间接的后果和损失,均由使用者本人负责,本文作者不承担任何责任。

前言

来了一个测试项目,启动burp开始日常操作后,很快就发现事情不太对劲,应用系统使用数据包签名用于数据防篡改,本文主要介绍寻找签名算法和实现自动化签名的过程。

找签名算法

观察http请求包后发现发现有sign字段,应该是对请求内容做了签名防篡改,签名破解不了,也就没法开始后面的业务测试。

image.png

从burp里找到该接口对应的html页面,在浏览器访问该页面,打开F12源代码里进行搜索,根据经验尝试对请求里的sign、reqno这几个参数进行反查,最终确定到这一段可疑代码。

image.png

代码是看不懂滴,能调就调,530行下断点,刷新下网页,可以看到,c是由http body、reqNo、reqTime组成,t是一段字符串,m不知道是个什么函数。

i=m()(c+t)
"sign":i
image.png

先试试hash算法,命中了md5。

image.png

【相关技术资料】
1、网络安全学习路线
2、电子书籍(白帽子)
3、安全大厂内部视频
4、100份src文档
5、常见安全面试题
6、ctf大赛经典题目解析
7、全套工具包
8、应急响应笔记

自动化签名

现在已知了sign的计算方法,但如果不能实现自动改签名的话,会给后面手动测试和工具扫描带来很大的麻烦,现在有两条路:

1、写burp插件

2、代理脚本

3、xray插件?

第1种:通用性可能不行,需要能兼容我burp里各种插件,还要能用于后面的漏扫工具,况且我也不会jvav。

第2种:最终找到了mitmproxy这个工具,能自定义python脚本,可以满足站在burp背后工作的需求。

image.png

开始写mitm的py脚本。

#!/usr/bin/python
# coding: UTF-8
# author: DF2L
# https://docs.mitmproxy.org/stable/api/events.html
# https://www.jianshu.com/p/036e5057f0b9 常见接口

from mitmproxy import ctx, http
import hashlib
import json

def md5(str):
 m5 = hashlib.md5()
 m5.update(str.encode('utf-8'))
 return m5.hexdigest()

def chenchen(a, b, c, d):
 plaintext = "reqData={http_body}&reqN0={reqno}&reqTime={reqtime}{SecretKey}".format(http_body=a, reqno=b, reqtime=c, SecretKey=d)
 Sign = md5(plaintext)
 return Sign, plaintext

class Modify:

 def request(self, flow):
  if flow.request.method == "POST" and flow.request.host == "www.example.com":
   try:
    #http_body = flow.request.raw_content.decode('utf-8')   # byte => str
    http_body = flow.request.get_text()         # 获取json,dict类型
    #http_body = json.dumps(http_body, sort_keys=False, separators=(',', ':'))    # dict格式转字符串,去空格,按key排序
    reqno = flow.request.headers["reqno"]
    reqtime = flow.request.headers["reqtime"]
    SecretKey = 'abcdefgabcdefgabcdefg'
    ori_sign = flow.request.headers["sign"]
    self.new_sign, self.plaintext = chenchen(http_body, reqno, reqtime, SecretKey)

    if http_body != '{}':
     flow.request.headers["sign"] = self.new_sign
     ctx.log.info('\n接口地址:{}\n更新签名:{} => {}\n签名内容:{}\n'.format(flow.request.path, ori_sign, self.new_sign, self.plaintext))
    else:
     ctx.log.info('无参数无需改签')
   except KeyError as e:
    ctx.log.info('数据包无签名')
'''
请求字段:flow.request
 host字段:flow.request.host
 url字段:flow.request.url
 path字段:flow.request.path
 cookie字段:flow.request.cookies
 body字段:flow.request.urlencoded_form、.get_text()、.raw_content
 整个请求包:flow.request.data
'''
 def response(self, flow):
  if '渠道验签异常' in flow.response.get_text():
   ctx.log.error('\n签名异常:\nurl => {}\n异常信息 => {}\n'.format(flow.request.path, flow.response.get_text()))
'''
响应字段:flow.response
响应body json:flow.response.get_text()
'''

addons = [
    Modify()        # 加载类
]
image.png

mitmdump启动,good! (看起来很顺利,其实调了一年 - -。)

mitmdump.exe -p 7788 -s .\X-sign2.py --flow-detail 0
image.png

插曲

后面刚准备套娃上xray,结果命令行异常弹刀怀疑人生。

image.png

回到burp查看这些异常的接口,手动算和程序算的值确实不一样,猜想某些特定接口是不是用了不同的secret。通过对比验签成功和失败的数据包后,发现了一个可疑的请求头Appkey,验签成功的是100301,而失败的都是100101,所以两套验签应该没跑了。

用同样的方法开始调试找签名内容,发现格式是一样的,只是拼接的字符串不一样。

image.png

验证正确,后面发现直接改Appkey,强制请求去第一套网关验签也是可行的。。。。

image.png

ok,再改改mitmdump脚本,另外由于服务端会校验时间戳是否过期,但不向上校验,所以直接把时间戳拉满写死,便于后面重放复现。

image.png

开始套娃:App => Burp => xray => mitmdump => Server

burp:User options -> Upstream Proxy Servers -> 指向xray

xray:

# 启动监听
.\xray_windows_amd64.exe webscan --listen 127.0.0.1:7777 --html-output report-__datetime__.html
# config.yaml 配置代理
http: 
    proxy: "http://127.0.0.1:7788"

mitmdump:

# 启动监听
mitmdump.exe -p 7788 -s .\X-sign.py --flow-detail 0

套完之后,可以看到已经成功跑起来!

image.png

总结

这次的破解签名算法还是比较顺利的,简单回顾下过程:

1、找签名算法。

2、用py实现一个demo。

3、寻找自动化工具mitmdump,调试脚本。

4、处理异常,完善脚本。

5、串联xray,over。

数据包签名做防御机制还是很大程度的提升了攻击成本,当然没有绝对的安全,而企业能做的就是不断提高防御水平,缩小暴露风险面,从而提高攻击者的攻击成本。

有关【网络安全】记一次数据包解签名实战的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  3. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  4. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  5. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  6. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  7. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

  8. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  9. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  10. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

随机推荐