您的位置:首页 > 产品设计 > UI/UE

Burpsuite中protobuf数据流的解析

2016-02-16 09:59 483 查看
Author:没羽@阿里移动安全

0x00 前言

对于protobuf over-HTTP的数据交互方式Burpsuite不能正确的解析其中的数据结构,需要Burpsuite扩展才能解析,笔者使用mwielgoszewski的burp-protobuf-decoder【1】扩展实践了protobuf数据流的解析,供有需要的同学学习交流。笔者实践使用的环境: burpsuite+python2.7+protobuf2.5.0。

0x01 安装burp-protobuf-decoder扩展

burp-protobuf-decoder【1】扩展是基于protobuf库(2.5.x版本)开发的burpsuite python扩展,可用于解析、篡改 request/response中protobuf数据流。从https://github.com/mwielgoszewski/burp-protobuf-decoder下载该扩展源码,然后解压。

该扩展是基于protobuf和jython实现的。先下载protobuf 2.5.0【2】源码进行编译,编译方法请参考其README.txt文件。需求在burpsuite的Extender中配置Jython【3】的路径:



Burpsuite中添加扩展:

在Burpsuite的Extender窗口中点击“Add”按钮,弹出的“Load Burp Extension”窗口中选择如下信息:



然后Next,当看到如下信息时表示扩展加载成功:



Tips:

加载扩展时提示
“Error calling protoc: Cannot run program "protoc" (in directory "******"): error=2, No such file or directory”
错误

解决办法:修改protoburp.py中调用protoc命令的路径,有多处,如:

process = subprocess.Popen(['protoc', '--version']
'protoc'
改为
'/home/name/protobuf/src/protoc'


加载扩展碰到
cannot import name symbol_database
错误

可能是你使用的protoc与扩展所使用protobuf python库版本不一致原因,一种解决办法是下载protobuf 2.5.0源码编译后,修改protoburp.py中对应的路径,再加载扩展。

扩展加载成功了,但不能解析protobuf数据流

该扩展通过判断头部“content-type”是否为“
'application/x-protobuf'
”来决定是否解析数据,你可以修改protoburp.py中的isEnabled()方法让其工作。

0x02 protobuf简介

protobuf是Google开源的一个跨平台的结构化数据存储格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

protobuf通过定义“.proto”文件来描述数据的结构。.proto文件中用 “Message”来表示所需要序列化的数据的格式。Message由Field组成,Field类似Java或C++中成员变量,通常一个Field的定义包含修饰符、类型、名称和ID。下面看一个简单的.proto文件的例子:

使用下面的python代码生成二进制数据流:

序列化后的二进制数据流如下:



有关Protobuf的语法网上已有很多文章了,你可以网上搜索或参考其官网【4】说明。

2.1Varint编码

Protobuf的二进制使用Varint编码。Varint 是一种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。

Varint 中的每个 byte 的最高位 bit 有特殊的含义,如果该位为 1,表示后续的 byte 也是该数字的一部分,如果该位为 0,则结束。其他的 7 个 bit 都用来表示数字。因此小于 128 的数字都可以用一个 byte 表示。大于 128 的数字,比如 300,会用两个字节来表示:1010 1100 0000 0010。

下图演示了protobuf如何解析两个 bytes。注意到最终计算前将两个 byte 的位置相互交换过一次,这是因为protobuf 字节序采用 little-endian 的方式。



(图片来自网络)

2.2数值类型

Protobuf经序列化后以二进制数据流形式存储,这个数据流是一系列key-Value对。Key用来标识具体的Field,在解包的时候,Protobuf根据 Key 就可以知道相应的 Value 应该对应于消息中的哪一个 Field。

Key 的定义如下:

(field_number << 3) | wire_type


Key由两部分组成。第一部分是 field_number,比如消息 tutorial .Person中 field name 的 field_number 为 1。第二部分为 wire_type。表示 Value 的传输类型。Wire Type 可能的类型如下表所示:

TypeMeaningUsed For
Varintint32, int64, uint32, uint64, sint32, sint64, bool, enum
164-bitfixed64, sfixed64, double
2Length-delimistring, bytes, embedded messages, packed repeated fields
3Start groupGroups (deprecated)
4End groupGroups (deprecated)
532-bitfixed32, sfixed32, float
以数据流:08 96 01为例分析计算key-value的值:

最后得到的结构化数据为:

1:150


其中1表示为
field_num
,150为value。

2.3手动反序列化



以上面例子中序列化后的二进制数据流进行反序列化分析:

读取7个字符“Vincent”;

读取10个字符“Vincent@test.com”;

读取11个字符“15011111111”;

最后得到的结构化数据为:

2.4使用protoc反序列化

实现操作经常碰到较复杂、较长的流数据,手动分析确实麻烦,好在protoc加“
decode_raw
”参数可以解流数据,我实现了一个python脚本供使用:

使用
python decode.py <proto.bin>
即可反序列化,其中proto.bin为protobuf二进制数据流文件。得到结构化的数据后我们可以逐步分析,猜测每个Field的名称,辅助协议、数据结构等逆向分析。

0x03 burpsuite+protobuf实战

用webpy模拟protobuf over-HTTP的web app。

服务端
overHttp_server.py
内容如下:

客户端
overHttp_client.py
内容如下:

3.1proto文件逆向分析

启动服务端:
python overHttp_server.py <ip>:8080


客户端请求:
python overHttp_client.py


此时burp中已解析出protobuf数据,如下图:



但是这个结构的可读性还是比较差,我们可以通过逆向分析逐步猜测字段名称、类型,然后再解析,方便实现协议的逆向、安全测试等。

对这个结构我们可以还原成以下proto文件:

然后使用右键的“Load .proto”加载该文件:



再看解析结果:



3.2数据篡改

打开request拦截:



运行
python overHttp_client.py
发送请求。拦截到request后,把
sub1_field2
改为999。



“Forward”后看request数据,已被篡改:



0x04 参考

【1】https://github.com/mwielgoszewski/burp-protobuf-decoder
【2】https://github.com/google/protobuf/tree/v2.5.0
【3】https://wiki.python.org/jython/InstallationInstructions
【4】https://developers.google.com/protocol-buffers/docs/proto
【5】https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/
【6】https://developers.google.com/protocol-buffers/docs/overview
【7】http://www.tssci-security.com/archives/2013/05/30/decoding-and-tampering-protobuf-serialized-messages-in-burp/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: