Protobuf 协议安全测试

栏目: 服务器 · 发布时间: 5年前

内容简介:1. Protobuf 是什么Protobuf 是 google 开源的一种平台无关、语言无关、可扩展且轻便高效的序列化数据结构的协议,可以用于网络通信和数据存储。

本文将介绍 Protobuf 协议在安卓 APP 中的应用,以及如何开展相关接口的安全测试。 文中用到的 vuls 漏洞应用代码及应用可以在https://github.com/AndroidAppSec/vuls/releases/tag/v4.1 下载。

前言

在对安卓 APP 的网络请求进行安全测试的时候,经常会遇到不同的数据传输协议,比如基于 XML 的、基于 JSON 的、甚至是基于二进制流的。本文将介绍一种常用的数据传输协议-- Protobuf 的安全测试方法

1. Protobuf 是什么  

Protobuf 是 google 开源的一种平台无关、语言无关、可扩展且轻便高效的序列化数据结构的协议,可以用于网络通信和数据存储。

其具有体积小、序列化和传输速度快、维护简单的特点,被越来越多的安卓 APP 使用。

其目前最新的版本为 proto3,相较于之前的版本支持更多的语言,语法也更为简洁。本文主要是以 proto3 为讨论对象。

2. Protobuf 语法  

Protobuf 数据结构文件 一般是以  .proto 结尾的文本文件。 拿官方文档中的例子来简单介绍一下。 以下是一个定义搜索请求消息的案例:

syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

文件的第一行指定了协议版本,如果不定义则默认为 proto2。这必须是文件的第一个非空的非注释行。

message 定义了 SearchRequest 消息,并指定了三个字段(以分号分割)。每一个字段中指定了字段数据类型、字段名称和字段编号。

更多内容请查看官方文档(https://developers.google.com/protocol-buffers/docs/proto3)。

3. 在 Android Studio 中使用 Protobuf

3.1 搭建开发环境

  • 在 Project/build.gradle 中加入 protobuf 插件

classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.6'

Protobuf 协议安全测试

  • 在 app/build.gradle 中加入如下配置,头部加上:

apply plugin: 'com.google.protobuf'

Protobuf 协议安全测试

  • android{ } 中加入

sourceSets { 
    main { 
        // 定义 java 文件目录 
        java { 
            srcDir 'src/main/java' 
        } 
        // 定义proto文件目录 
        proto { 
            srcDir 'src/main/proto' 
        } 
    } 
}

Protobuf 协议安全测试

  • android{ } 同级中加入

protobuf { 
    //配置protoc编译器 
    protoc { 
        artifact = 'com.google.protobuf:protoc:3.5.1' 
    } 
    //这里配置生成目录,编译后会在build的目录下生成对应的java文件 
    generateProtoTasks { 
        all().each { task -> 
            task.builtins { 
                remove java 
            } 
            task.builtins { 
                java {} 
            } 
        } 
    } 
}

Protobuf 协议安全测试

  • dependencies 中加入 protobuf 相关依赖

implementation 'com.google.protobuf:protobuf-java:3.6.1'
implementation 'com.google.protobuf:protoc:3.6.1'

Protobuf 协议安全测试

  • 安装 Protobuf Support 插件

Protobuf 协议安全测试

插件安装完成后需重启 Android Studio。

3.2 编写 proto 文件

这里我们打算用 protobuf 来实现登录的功能。

在 src/main 下建立 proto 文件夹,建立 LoginRequest.proto 文件,内容如下:

syntax = "proto3"; 
import public "Message.proto";

//登录请求结构体
message LoginRequest {
string username = 1;
string password = 2;
}

//登录响应结构体
message LoginResponse {
int32 code = 1;
Message msg = 2;
}

Message.proto 文件,内容如下:

syntax = "proto3"; 

// 返回消息体
message Message {
int32 id = 2;
string content = 1;
}

3.3 生成对应的 Java 文件

Sync Project 或者  Build-->Clean Project,会在 \app\build\generated\source\proto 中生成对应的 Java 文件。

Protobuf 协议安全测试

4. 编写测试应用

4.1 编写安卓客户端 登录功能代码

将生成的 Java 文件拷贝到 src 目录下:

Protobuf 协议安全测试

登录功能的主要代码如下:

public void login(View view){ 
    username = ((EditText) findViewById(R.id.et_ac_username)).getText().toString(); 
    password = ((EditText) findViewById(R.id.et_ac_password)).getText().toString(); 
    String url = "http://192.168.8.233/pblogin"; 
    final LoginRequestOuterClass.LoginRequest loginRequest = LoginRequestOuterClass.LoginRequest .newBuilder() .setUsername(username) .setPassword(password) .build(); 
    OkHttpClient okHttpClient = new OkHttpClient.Builder().build(); 
    RequestBody requestBody = RequestBody.create( MediaType.parse("application/pb"), loginRequest.toByteArray()); 
    Request request = new Request.Builder().url(url).post(requestBody).build(); 
    Call call = okHttpClient.newCall(request); 
    call.enqueue(new Callback() { 
        @Override 
        public void onFailure(Call call, IOException e) { 
        e.printStackTrace(); 
        runOnUiThread(new Runnable() { 
            @Override 
            public void run() { 
                Toast.makeText(ProtoActivity.this, "请求失败", Toast.LENGTH_LONG).show(); 
            } 
        }); 
    } 
        @Override 
        public void onResponse(Call call, Response response) throws IOException { 
            ResponseBody body = response.body(); 
            LoginRequestOuterClass.LoginResponse loginResponse = LoginRequestOuterClass.LoginResponse.parseFrom(body.bytes()); 
            final int code = loginResponse.getCode(); 
            MessageOuterClass.Message responseMsg = loginResponse.getMsg(); 
            final int id = responseMsg.getId(); 
            final String content = responseMsg.getContent(); 
            runOnUiThread(new Runnable() { 
                @Override 
                public void run() { 
                    if (id == 1){ 
                        Toast.makeText(ProtoActivity.this, content, Toast.LENGTH_LONG).show(); 
                    }else { 
                        Toast.makeText(ProtoActivity.this, content + code, Toast.LENGTH_LONG).show(); 
                    }
                } 
            }); 
        } 
    }); 
}

4.2 编写服务端代码

服务端使用 Springboot 框架,在 pom 文件中加入 protobuf 依赖:

<dependency> 
    <groupId>com.google.protobuf</groupId> 
    <artifactId>protobuf-java</artifactId> 
    <version>3.6.1</version> 
</dependency>

Controller 逻辑代码如下:

@RequestMapping("/pblogin") 
public void login(HttpServletRequest request, HttpServletResponse response) throws IOException { 
    request.setCharacterEncoding("utf-8"); 
    response.setCharacterEncoding("utf-8"); 
    LoginRequestOuterClass.LoginRequest loginRequest = LoginRequestOuterClass.LoginRequest .parseFrom(request.getInputStream()); 
    String username = loginRequest.getUsername(); 
    String password = loginRequest.getPassword(); 
    LoginRequestOuterClass.LoginResponse.Builder builder = LoginRequestOuterClass.LoginResponse.newBuilder(); 
    MessageOuterClass.Message.Builder messageBuilder = MessageOuterClass.Message.newBuilder(); 
    if ("admin".equals(username) && "12345".equals(password)){ 
        builder.setCode(200); 
        messageBuilder.setId(1); 
        messageBuilder.setContent("登录成功!"); 
        builder.setMsg(messageBuilder.build()); 
    }else { 
        builder.setCode(200); 
        messageBuilder.setId(-1); 
        messageBuilder.setContent("用户名或密码错误!"); 
        builder.setMsg(messageBuilder.build()); 
    } 
    builder.build().writeTo(response.getOutputStream()); 
}

原生应用是指开发的安卓应用,H5 是指通过 WebView 加载的 web 应用。很多情况下原

5. 抓包测试

5.1 启动服务端

执行命令 java -jar server-1.1.jar

5.2 配置手机代理为 burp

5.3 登录

Protobuf 协议安全测试

5.4 burp 抓包请求如下

Protobuf 协议安全测试

以 hex 方式查看一下,就知道 请求与普通的 http 请求还是不同的,是基于二进制序列化的。

Protobuf 协议安全测试

将请求发送到 repeter,然后修改参数,会报错,提示协议解析错误。

Protobuf 协议安全测试

6. BlackBox Protobuf Burp Extension

6.1 介绍

nccgroup 开源了一个 burp 插件专门用来做 protobuf 协议的安全测试,叫做 BlackBox,地址 https://github.com/nccgroup/blackboxprotobuf。

6.2 安装

  • 安装 Jpython

  • 依次运行命令

    git clone https://github.com/nccgroup/blackboxprotobuf

    cd blackboxprotobuf

git submodule update --init

  • 在 Burp 的 Extender 标签中安装插件

Protobuf 协议安全测试

  • 安装成功后会出现 “Protobuf Type Editor” 标签页

Protobuf 协议安全测试

6.3 使用

插件安装成功之后,burp 再抓取到 protobuf 协议数据时候,会自动添加 protobuf 标签,提供浏览和修改请求数据的功能 。

Protobuf 协议安全测试

Protobuf 协议安全测试

注:

  • BlackBox Protobuf 插件是通过 HTTP 请求头的 Content-Type 来判断数据是否为 protobuf 协议的。也就是说如果要插件去自动分析 protobuf 协议,需要将对应的  Content-Type 值 加入到 BlackBox Protobuf 插件的分析列表中。可以在  blackboxprotobuf/blackboxprotobuf/burp/editor.py 中进行添加。

Protobuf 协议安全测试

  • BlackBox Protobuf 插件可以在 Proxy 和 Repeater 中使用,但是在 Intruder 中无效。

7. 逆向 Protobuf 协议格式

对于 Protobuf 协议来说,只要能获取到一个数据结构体中的字段信息,就可以去生成相应的数据。字段信息包括: 字段数据类型、字段名称和字段编号。

使用 Jadx 打开 vuls 应用,找到对应的代码如下:

Protobuf 协议安全测试

上面的红框中,可以获取到字段 password(string类型)和 username(string类型)。

Protobuf 协议安全测试

上面的红框中,可以获取到字段 password 编码为 2,username编码为 1。

这样就可以还原出 LoginRequest 的请求结构体

//登录请求结构体 
message LoginRequest { 
    string username = 1; 
    string password = 2; 
} 

之后,就可以按照前面讲的自行生成对应的 java 类,然后编写程序进行安全测试。

8. 参考

https://github.com/huangdali/Android_ProtoBuf_Demo

https://developers.google.com/protocol-buffers/docs/overview

https://www.jianshu.com/p/2265f56805fa

https://developers.google.com/protocol-buffers/docs/proto3

https://github.com/nccgroup/blackboxprotobuf

https://www.kaifaxueyuan.com/basic/protobuf3.html

https://blog.csdn.net/kpioneer123/article/details/51491739

- End -


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

马云如是说

马云如是说

朱甫 / 中国经济出版社 / 2008-1-1 / 39.80元

任何一个企业家的成功,都需要一种特立独行的精神。换尔言之,他一定是不断地否定别人的反对意见,坚持自己独特的观点,才能够真正走向大成功。在中国企业家群像里,马云就是这样一个特立独行的人。 目录 *永不放弃——马云论创业精神 *天下没有难做的生意——马云论经营理念 *B2B时代——马云论电子商务 *网络只是一个工具——马云论互联网与网络公司 *太多钱会坏事——马云论......一起来看看 《马云如是说》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具