服务器校验客户端证书分析及代码

curl调用微信退款No required SSL certificate was sent 在之前的博客中提到微信证书到期了,需要更换,但是当我更换完证书自信满满的时候,却出现了两个问题,记录一下。 阅读详情

当前app安全越来越受到重视,很多app采取了HTTPS的协议,但是一般app都不会对证书进行校验,一些app只是客户端对服务端证书进行了强校验,也就是通常呢,抓包的时候app提示无网络连接或者网络连接错误,这种情况就是app发现证书是伪造的,并不是服务器的证书,因此中断了通讯。这个时候可以通过逆向app,找到校验的代码,过掉即可,偷懒的话可以尝试justTustMe模块来过掉。今天我们的重点是如何在服务器强校验客户端证书的情况下,抓到数据包,相关内容在网上很少见,以下仅仅抛砖引玉做个简单的示范,不涉及高级逆向。

可能大家遇到过这种情况,在抓包的时候,

fiddler提示:服务器请求客户端证书。

相关访问返回内容为:

<html>

<head><title>400 No required SSL certificate was sent</title></head>

<body bgcolor="white">

<center><h1>400 Bad Request</h1></center>

<center>No required SSL certificate was sent</center>

<hr><center>nginx</center>

</body>

</html>

这种情况是由于客户端内置了客户端证书。常规条件下,客户端在与服务器进行通讯的时候,会将自己的证书发送给服务器,服务器校验证书的合法性,当我们采用fiddler代理的时候,默认使用的是fiddler的证书,当然对方服务器不认可fiddler的证书,所以会提示错误。

这种情况怎么办?

这儿我们以翼健康app为例进行说明。

使用的工具:

Fiddler,抓数据包

JEB,反编译app

安装好xposed的雷电模拟器

Eclipse,编写xposed模块

...

以上工具均可以百度到,所以这儿不放链接了。

 

首先,随便抓一条数据包:

可以看到,对于数据包的内容,我们是可以清楚的看到的,但是服务器返回错误。

 

我们直接解压app,在./assets目录下,发现客户端证书client.pfx

当我们进行双击安装证书的时候发现需要密码,这个时候没有办法,我们只能尝试逆向app。

 

我们在manifest文件中可以看到,app包名是com.gdhbgh.activity,入口是com.telecom.vhealth.ui.activities.WelcomeActivity,那么在逆向app的时候,要重点关注telecom下的http的相关类或者方法,这个是常规思路,证书操作肯定会和通讯类放在一起。

 

使用JEB逆向app,果然发现了有com.telecom.vhealth.http.utils.HttpUtils类。这儿给大家解释一下我为什么第一时间找到这个类,首先根据入口定位到了com.telecom.vhealth。App一般代码都是模块化,集成化。所以我们需要第一时间关注相关http包,在包里面我们重点关注工具类或者服务类。当然了,如果比较难找,我们也可以采取别的思路,比如直接搜索证书的名字,定位关键位置,或者搜索网页访问的地址,我们定位一下http访问的类,在进入到类里面看看是怎么样设置证书的等等,方法有很多,大家需要发挥一下,不要拘泥于一种方法。

言归正传,运气很好,在HttpUtils类里面我们发现了getSocketFactory获取连接工厂这个函数。不管是从方法名还是具体的代码,我们都基本确定关键函数就在这儿了。

摘录其中关键语句给出注释:

InputStream v3 = arg7.getAssets().open("client.pfx");  // 读入证书文件

KeyStore v4 = KeyStore.getInstance("PKCS12");  // Key存储器初始化

v4.load(v3, v0_1);  // Key存储器载入客户端证书文件,参数一为证书,参数二为密码

我们向上找找v0_1是从哪儿蹦出来的,发现关键语句:

char[] v0_1 = EncryptUtils.getHttpSign(arg7).toCharArray();

进入EncryptUtils类,发现是两个native函数,相关代码在so里面,

分析so还是比较麻烦的,直接省略分析so文件,我们使用xposed来hook这个参数。这儿呢,我选择hook了KeyStore的load的方法。原因呢,我个人认为容错性比较高,省的来回写代码。

相关xposed的入门教程请大家百度。Xposed还是很容易入门以及上手的。

贴出代码:

运行模块,成功拿到证书密码:vhealth2016

拿到密码,我们转到电脑端,首先双击client.pfx,将证书文件安装进电脑,然后本地在证书管理里面将证书导出为base64编码的cer证书文件或者百度证书转换工具,将pfx证书转换为pem文件,pem文件包含了公钥和私钥,我们手动提取出公钥数据新建一个cer文件就ok,觉得不够严谨可以使用openssl命令来转换。Cer文件是用于存储公钥证书的文件格式。

 

我们把生成的ClientCertificate.cer文件放入fiddler的文件目录下。然后重启fiddler,就可以发现成功抓包:

对于数据中的sign,我们也可以顺便分析一下:

以下是跟踪路径,自己分析就好,我列的代码可直接忽略:

((Map)v4).put("sign", HttpUtils.getHttpSign());

接下来:

public static String getHttpSign() {

        UnifiedUserInfo v1 = c.c();

        String v0 = "";

        if(v1 != null) {

            v0 = v1.getPhoneNumber();

        }



        return HttpUtils.getSign("|", new String[]{String.valueOf(System.currentTimeMillis()), v0});

}

接下来:

public static String getSign(String arg3, String[] arg4) {

        StringBuilder v1 = new StringBuilder();

        int v0;

        for(v0 = 0; v0 < arg4.length; ++v0) {

            v1.append(arg4[v0]);

            if(!TextUtils.isEmpty(((CharSequence)arg3)) && v0 < arg4.length - 1) {

                v1.append(arg3);

            }

        }



        return HttpUtils.encryptByPk(v1.toString());

}



最后定位到:

private static String encryptByPk(String arg5) {

        String v0_2;

        String v1 = null;

        try {

            Object v0_1 = new ObjectInputStream(YjkApplication.getContext().getAssets().open("public.ppk")).readObject();

            byte[] v2 = arg5.getBytes("utf-8");

            Cipher v3 = Cipher.getInstance("RSA/ECB/PKCS1Padding");

            v3.init(1, ((Key)v0_1));

            v0_2 = f.a(v3.doFinal(v2));

        }

        catch(Exception v0) {

            s.a(((Throwable)v0));

            v0_2 = v1;

        }



        return v0_2;

}

发现sign是采用了assets目录下的public.ppk文件作为公钥,RSA/ECB/PKCS1Padding为加密方式。我们顺便在xposed代码hook一下相关地方,瞅瞅加密前数据是什么,加密后的数据是什么,密钥是什么。

贴出完整xposed代码:

import java.io.InputStream;



import de.robv.android.xposed.IXposedHookLoadPackage;

import de.robv.android.xposed.XC_MethodHook;

import de.robv.android.xposed.XposedBridge;

import de.robv.android.xposed.XposedHelpers;

import de.robv.android.xposed.callbacks.XC_LoadPackage;



import java.security.Key;



public class Hook implements IXposedHookLoadPackage {



    private static String package_name = "com.gdhbgh.activity";



    //byte[]转16进制

    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

    public static String bytesToHex(byte[] bytes) {

        char[] hexChars = new char[bytes.length * 2];

        for ( int j = 0; j < bytes.length; j++ ) {

            int v = bytes[j] & 0xFF;

            hexChars[j * 2] = hexArray[v >>> 4];

            hexChars[j * 2 + 1] = hexArray[v & 0x0F];

        }

        return new String(hexChars);

    }

    

    @Override

    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {



        if (!loadPackageParam.packageName.equals(package_name)) {

         return;

        }

        XposedBridge.log(loadPackageParam.packageName +" -> load");

        

        //通过hook密钥加载函数来得到证书密钥

        final Class<?> clazz = XposedHelpers.findClass("java.security.KeyStore", loadPackageParam.classLoader);

        XposedHelpers.findAndHookMethod(clazz,"load", InputStream.class,char[].class,new XC_MethodHook(){

         @Override

         protected void beforeHookedMethod(MethodHookParam param) throws Throwable {

         if((char[])param.args[1]==null) return;

         String s = new String((char[])param.args[1]);

         if(s==null) return;

         XposedBridge.log("java.security.KeyStore.load param1: " + s);

            }

        });

        

        //hook加密方法瞅瞅加密前数据是个啥玩意儿

        XposedHelpers.findAndHookMethod("com.telecom.vhealth.http.utils.HttpUtils",loadPackageParam.classLoader,"encryptByPk", String.class,new XC_MethodHook(){

         @Override

         protected void beforeHookedMethod(MethodHookParam param) throws Throwable {

         XposedBridge.log("com.telecom.vhealth.http.utils.HttpUtils.encryptByPk param0:" + (String)param.args[0]);

            }

         @Override

         protected void afterHookedMethod(MethodHookParam param) throws Throwable {

         XposedBridge.log("com.telecom.vhealth.http.utils.HttpUtils.encryptByPk result: " + (String)param.getResult());

            }

        });

        

        //hook一下RSA的公钥数据

        XposedHelpers.findAndHookMethod("javax.crypto.Cipher",loadPackageParam.classLoader,"init", int.class,Key.class,new XC_MethodHook(){

         @Override

         protected void beforeHookedMethod(MethodHookParam param) throws Throwable {

         Key key1=(Key)param.args[1];

         byte[] keyBytes=key1.getEncoded();

         XposedBridge.log("javax.crypto.Cipher.init param1:" + bytesToHex(keyBytes));

            }

        });

        

        //hook一下加密前后的数据

        XposedHelpers.findAndHookMethod("javax.crypto.Cipher",loadPackageParam.classLoader,"doFinal", byte[].class,new XC_MethodHook(){

         @Override

         protected void beforeHookedMethod(MethodHookParam param) throws Throwable {

         byte[] data=(byte[])param.args[0];

         XposedBridge.log("javax.crypto.Cipher.doFinal param0:" + bytesToHex(data));

            }

         @Override

         protected void afterHookedMethod(MethodHookParam param) throws Throwable {

         byte[] data=(byte[])param.getResult();

         XposedBridge.log("javax.crypto.Cipher.doFinal result:" + bytesToHex(data));

            }

        });

        

    }

}

 

分析完毕!

完整的项目文件,样本文件,相关工具请大家自己动手完成。

HTTPS自签证书及Android客户端校验 HTTPS自签证书及Android客户端校验使用openssl生成自签证书生成自己的根证书生成服务端证书配置服务端证书到服务端在浏览器中打开效果Android客户端校验自签证书Android 中内置证书在系统中的位置 使用openssl生成自签证书 生成自己的根证书 生成CA私钥文件ca.key: openssl genrsa -out ca.key 1024 生成X.509证书签名请求文件ca... 阅读详情

相关推荐

Android WebView实现Https证书单向校验

本文主要讲解webview实现Https自制证书的校验。 我们使用Android的webview的时候会设置一个`WebViewClient`,而如果请求Https发生错误的时候,就会调用`WebViewClient`的`onReceivedSslError`方法

renzhongrui的博客 4559

Nginx配置客户端SSL双向认证

转自:https://www.cnblogs.com/qiumingcheng/p/13282145.html 对于 NGINX 的 HTTPS 配置,通常情况下我们只需要实现服务端认证就行,因为浏览器内置了一些受信任的证书颁发机构(CA),服务器端只需要拿到这些机构颁发的证书并配置好,浏览器会自己校验证书的可用性并通过 SSL 进行通讯加密。 但特殊情况下我们也需要对客户端进行验证,只有受信任的客户端才能使用服务接口,此时我们就需要启用双向认证来达到这个目的,只有当客户端请求带了可用的证书才能调通服.

yazhiye的专栏 5689

【Android逆向】okhttp 证书绑定流程 ssl pinning分析

本次通过代码实现了 https 证书绑定也就是 ssl pinning。分析了 okhttp 的证书校验逻辑,其中 startHandshake 是一个hook点。在这时刻往下就是app中的证书校验逻辑。文章后半部分给出了证书校验的绕过逻辑,总体来说在 app 端的证书校验,使用 hook手段绕过。服务端的证书校验,是把 app 端的证书导入抓包工具解决,其中app端的证书定位与证书密码获取也是通过hook进行定位。文章很难面面俱到,如果有更多想要交流的可以来深入探讨一下哈 lvdouzhou_。

tx123hy的博客 2035

记一次帮朋友处理nginx报错400 Bad Request No required SSL certificate was sent

nginx配置了双向认证,客户端也开启了https认证,但是证书并没有提供客户端的ssl证书,禁用了客户端的证书验证成功解决。还有一种更直接的解决方法,直接禁用client证书认证。

踏上征程 6348

【异常】客户端发起HTTPS请求报错,服务端返回400 Bad Request ,并且提示No required SSL certificate was sent

HTTP响应码400表示客户端发送了一个无效的请求。这可能是由于请求中缺少必需的参数或格式不正确等原因导致的。服务器无法处理此请求并返回400响应码。如果您正在编写Web应用程序,建议在处理请求时检查请求的有效性,并在必要时返回400响应码以指示客户端请求无效。

奶爸的编程之路,也就一周冷个三天 2万+

【异常】调用Spring Boot接口时提示错误400 Bad Request No required SSL certificate was sent

双向认证是指客户端和服务端互相验证对方身份的过程,确保通信双方的安全性。

奶爸的编程之路,也就一周冷个三天 6880

OPPO应用商城wifi代理检测

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Ma...

斯文这个禽兽 2403

Android RootTrustManager 证书校验简单分析

阅读本篇博文,博主假设你已经按顺序读过下面三篇文章。 Android okhttp https TrustManager简单总结 Android CertificateSource 简单说明 Android AndroidNSSP的简单说明 在Android AndroidNSSP的简单说明我们知道,Android在安装AndroidNSSP这个Provider的时候,初始化了系统证书管理器,以及RootTrustManager ,今天文章的主角就是这个RootTrustManager 。 从结构来看,该类

菜鸟博客 2156

android sleep_【Android】解密SSL双向验证

工具:1.JEB 2.逍遥模拟器 3.Frida 4.Xpose 5.JustTrustMe 6.Charles概述:试图分析某App协议,无法抓包,服务器会校验客户端的证书是否正确,不正确则会与我们断开连接思路:既然是双向验证,也就是说我们要从两个方面来解决,本地证书校验我们使用Xposed模块的JustTrustMe解决,提交给服务器的证书我们需要从包里面将证书找出来,然后挂在Charles上...

weixin_39745013的博客 190

自考计算机系统原理(第六章计算机系统概论)-13015

名词解释 I/O 硬件 I/O软件 用户空间I/O软件 内核空间I/O 软件 系统调用处理程序 系统调用服务例程 设备驱动程序 中断服务程序 系统级1/O函数 虚拟文件系统 文件描述符 文件元数据 流缓冲区 索引节点 目录文件 目录项 系统打开文件表 磁盘高速缓存 高速缓存 RAM I / O 控制方式 程序直接控制I/O 就绪状态 中断控制I/O 中断屏蔽字 多重中断 中断嵌套 DMA 方式 DMA 控制器 设备控制器 I/O端口 控制端口 数据端口 状态端口 I/O 地址空间 独立编址方式 统一编址方

qq_23872947的博客 1150

systemView的安装使用

systemView的安装使用

qq_33712422的博客 3969

双向证书校验 和单向证书校验分别是什么原理

双向证书校验 和单向证书校验分别是什么原理

sunminem的博客 2612

基于STM32的工业I/O模块硬件电路实现

深入解析基于STM32的工业I/O模块硬件电路实现,涵盖关键电路设计与信号处理,突出硬件电路稳定性和工业级可靠性,适合嵌入式开发者参考。

weixin_35835018的博客 454

一文带你快速掌握java http客户端的证书校验

一文带你快速掌握JAVA HTTP客户端的证书校验

weixin_45642975的博客 1362

【电击防护篇】电击防护技术详解:从人体效应到接地系统全解析

本文系统讲解了电击防护的关键知识,包括电流对人体的影响(如30mA是心室颤动阈值)、人体电阻特性(700Ω-6100Ω)以及电气接触防护措施。重点分析了TT、TN和IT三大接地系统的结构特点与应用场景,强调TN-S系统最安全,IT系统供电连续性最佳。详细介绍了漏电保护器(RCD)的工作原理与选型指南,建议人身防护选用30mA高灵敏度RCD。文章通过对比表总结三大系统的安全性、成本及适用场景,为电气安全设计提供实用参考。

2301_81299416的博客 1742

如何利用MATLAB建立Lotka-Volterra模型及其改进模型

今天我们要说的就是利用MATLAB对常微分方程进行数值求解的实例应用-Lotka-Volterra模型及其改进模型。20世纪40年代,Lotka(1925)和Volterra(1926)奠定了种间竞争关系的理论基础,他们提出的种间竞争方程对现代生态学理论的发展有着重大影响。

Nick的博客 2万+

HTTPS 的「秘钥交换 + 证书校验」全流程

步骤核心技术安全目标密钥交换ECDHE(临时密钥)前向保密证书校验X.509 证书链 + OCSP服务器身份认证会话密钥生成HKDF 密钥派生生成加密密钥握手完整性验证Finished 消息 HMAC防篡改📌部署建议优先启用 TLS 1.3(Nginx 配置使用 ECDSA 证书(比 RSA 更高效安全)开启 OCSP Stapling 加速证书吊销检查。

tschen的博客 5464

用Verilog搭出RISC-V架构单周期CPU

这是笔者学校暑期学期的必修课,难度并不高(仅追求及格的话),但相当耗时,对于在硬件设计方面完全不感冒的同学更是一场避不开的折磨,所以笔者想通过自己的成果和被折磨经验来帮助有此方面需求的同学,或是对于CPU设计有浓厚兴趣的人。

paticita的博客 1万+

iOS客户端校验https网络请求证书

其实iOS系统的网络请求都有校验,比如NSURLConnection、NSURLSession都有系统的自动校验。具体的校验可进行百度 我使用的是NSURLConnection进行的网络请求,NSURLConnection是代理回调的请求方式,其中有两个代理方法是用于进行校验证书的 另外我说一下我们的需求,我们要求使用指定的CA证书进行校验不能使用系统的校验,系统的校验可自行百度,他校验证

u011604049的博客 6095

【深度学习新浪潮】Token经济学深度解析:从AI“新智元”梗到产业核心,研究成果+标杆产品全拆解

在正式深入研究和产品分析前,必须先破除概念误区:行业内常说的Token经济学,并非单一概念,而是分为AI词元Token经济学和Web3通证Token经济学两大核心分支,二者底层逻辑、应用场景天差地别,也是大众最容易混淆的点。Token是AI时代的新大宗商品:黄仁勋将Token类比为工业时代的电力、石油,是AI时代的核心生产资料与基础计价单位,不再是单纯的技术单元,而是具备标准化、可计量、可交易、可分层的数字商品,其价值由算力消耗、推理效率、实际应用价值共同决定,而非虚拟炒作。Token五层定价模型。

专注:太空算力、AI infra、异构调度、大模型成本工程 685

YOLOv13改进目录一览 | 涉及卷积层、轻量化、注意力、损失函数、Backbone、SPPF、Neck、检测头等全方位改进

1️⃣ 已更新种不同的改进方案,专栏内的每篇文章皆,均可顺利运行。2️⃣ 订阅专栏即可进群获取以及从的各种答疑内容。3️⃣ 全新的YOLOv13改进专栏,,只为更好的满足论文发表的要求。专栏内容,专栏实时评分,全网最高,质量保证。🎫。。

Limiiiing的博客 9153

nginx 根证书 服务器证书,Nginx双向证书校验(服务器验证客户端证书)

1、创建Root CA私钥openssl genrsa -out root-ca.key 10242、创建Root CA证书请求openssl req -new -out root-ca.csr -key root-ca.key3、签发Root CA根证书openssl x509 -req -in root-ca.csr -out root-ca.crt -signkey root-ca.key ...

weixin_35730840的博客 4172

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Golang 服务器端对客户端的证书进行校验(双向证书校验)

服务器端对客户端的证书进行校验(双向证书校验),客户端访问服务器端,必须校验,如果跳过验证,客户端无法成功地建立与服务器之间的连接,也就是您在浏览器地址访问服务器api接口时,会同样象单向校验那样出现“Your connection is not secure”,即使您此时在浏览器页面上选择添加安全异常,也无法建立与服务器连接。

zhengzizhi的专栏 1万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

抓包之服务器校验客户端证书

挂上vpn,打开charles抓包可以看到没网络,但是可以抓到包,怀疑是服务器校验客户端证书了 这里推荐一下肉老师的文章 https://www.anquanke.com/post/id/197657 引用里面一张图 原本服务器校验的是app的证书,但是挂上charles,服务器校验的是charles的证书,一匹配发现不是app的证书,就返回网络失败,所以我们要将app中内置的证书导入到Charles中去。 这个操作通常需要完成两项内容: 1.找到证书文件 2.找到证书密码 首先找证书文件,直接对ap

公过水蚊的博客 2131

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

一文详解 HTTPS 与 TLS证书链校验

HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议,是一种通过计算机网络进行安全通信的传输协议。HTTPS利用SSL/TLS来加密数据包,经由HTTP进行通信。其设计的主要目的是,提供对网站服务器的身份认证、保护交换数据的隐私与完整性。SSL/TLS握手协商:用非对称加密的手段传递密钥,然后用密钥进行对称加密传递数据。

赶路人儿 1万+

flutter 中 ssl 双向证书校验

flutter 中 ssl 双向证书校验

唐僧的专栏 1631
上一篇: confirmSingleForQueue(确认队列中单个状态)
下一篇: 某直播APP逆向TCP协议分析
袁赛因不花
博客等级 码龄10年 82粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值