利用sniffer技术捕捉SSL通信时客户端证书公钥_如何从sniffer里面提取证书_gnn19820901的博客-程序员秘密

技术标签: c  string  byte  服务器  exchange  ssl  

摘要

         通过对SSL握手协议的分析,得知在SSL双向认证握手过程中,客户端需要出示客户端证书以供服务器验证,利用sniffer技术截获网络通信过程中的TCP/IP数据包,通过对TCP/IP数据包的解析,获得客户端证书公钥。

        

关键字:sniffer,SSL 握手协议,TCP/IP, 证书公钥

 

相关工具:

Ethereal网络抓包工具,Ethereal是免费的网络协议检测程序,支持UnixWindows。让您经由程序抓取运行的网站的相关资讯,包括每一封包流向及其内容、资讯。可依操作系统语系看出,方便查看、监控TCP session动态等等

Ethereal0.99.0下载地址:http://www.newhua.com/soft/3906.htm

 

JPCAP开源组件: JAVA语言虽然在TCP/UDP传输方面给予了良好的定义,但对于网络层以下的控制,却是无能为力的。JPCAP扩展包弥补了这一点。JPCAP实际上并非一个真正去实现对数据链路层的控制,而是一个中间件,JPCAP调用wincap/libpcap,而给JAVA语言提供一个公共 的接口,从而实现了平台无关性。在官方网站上声明,JPCAP支持FreeBSD 3.x, Linux RedHat 6.1, Fedora Core 4, Solaris, and Microsoft Windows 2000/XP等系统。

JPCAP下载地址:http://netresearch.ics.uci.edu/kfujii/jpcap/doc/download.html

 

SSL协议分析

参考文档:http://blog.chinaunix.net/u/6258/showart_156636.html

 

         SSL的握手协议包括如下几个步骤:

Ø         交换Hello信息,协商算法、交换随机数、检查会话重组

Ø         交换允许客户端和服务器端协商预主秘密的必要的密码参数

Ø         交换证书和密码信息,使得客户端和服务器端进行认证

Ø         从预主秘密和给定随机数产生主秘密

Ø         为记录层提供安全参数

Ø         允许客户端和服务器端检测实体是否计算出相同的安全参数,握手是否在没有攻击的情况下发生的

 

 

 

 

 

 

 

 

Client                                Server

      ClientHello                  -------->

                                           ServerHello

                                           Certificate*

                                           ServerKeyExchange*

                                           CertificateRequest*

                                 <--------    ServerHelloDone

      Certificate*

      ClientKeyExchange

      CertificateVerify*

      [ChangeCipherSpec]

      Finished                     -------->

                                           [ChangeCipherSpec]

                                  <--------   Finished

Application Data              <------->   Application Data

图一:完全握手的信息流程

*表示并不一定发送的可选的或者依情况而定的信息

 

红色部分为服务器为双向认证时,服务器会向客户端发送CertificateRequet请求,要求客户端出示证书,客户端接受到CertificateRequet请求后,弹出证书选择列表,用户选择客户端使用证书,点击确定后向服务器发送Certificate,我们所要截获的客户端出示的证书公钥包含在此请求中。

 

SSL记录层协议数据包结构定义如下:

       enum {

           change_cipher_spec(20), alert(21), handshake(22),

           application_data(23), (255)

} ContentType;

 

struct {

        uint8 major, minor;

} ProtocolVersion;

 

    struct {

           ContentType type;

           ProtocolVersion version;

           uint16 length;

           opaque fragment[TLSPlaintext.length];

} TLSPlaintext;

 

 

 

 

 

SSL握手协议数据包结构定义如下:

enum {

hello_request(0), client_hello(1), server_hello(2),

certificate(11), server_key_exchange (12),

certificate_request(13), server_hello_done(14),

certificate_verify(15), client_key_exchange(16),

finished(20), (255)

} HandshakeType;

 

struct {

HandshakeType msg_type;    /* handshake type */

uint24 length;               /* bytes in message */

select (HandshakeType) {

case hello_request:        HelloRequest;

case client_hello:         ClientHello;

case server_hello:         ServerHello;

case certificate:           Certificate;

case server_key_exchange:  ServerKeyExchange;

case certificate_request:    CertificateRequest;

case server_hello_done:    ServerHelloDone;

case certificate_verify:     CertificateVerify;

case client_key_exchange:  ClientKeyExchange;

case finished:            Finished;

} body;

} Handshake;

 

通过以上内容可分析出如下结论:

 

SSL通信时数据包数据部分

1.       第一位为协议标识位

2.       第二位为SSL协议主版本号

3.       第三为为SSL协议次版本号

4.       第四位和第五位为数据内容长度

5.       后边为具体的协议内容数据包

如果第一位为22则代表当前通信内容为握手协议(handshake(22)

6.       第六位为握手协议标识位

7.       第七位第八位第九位为数据内容长度

如果第六位为11则代表当前传输的为客户端证书内容(certificate(11)

8.       第十位第十一位第十二位为证书列表长度

9.       第十三位第十四位第十五位为第一张证书长度

10.   从第十六位开始后开始获取第一张证书,证书内容为从第十六位开始,长度为上一步计算得到的结果;

 

 

通过以下程序可以验证上边结论

 

package cn.com.jit.ums.test;

 

import java.io.IOException;

import cn.com.jit.ida.util.pki.PKIException;

import cn.com.jit.ida.util.pki.cert.X509Cert;

import cn.com.jit.ida.util.pki.encoders.Base64;

import jpcap.JpcapCaptor;

import jpcap.NetworkInterface;

import jpcap.PacketReceiver;

import jpcap.packet.Packet;

import jpcap.packet.TCPPacket;

 

public class SSLReceiver implements PacketReceiver {

    public int receivePost;

 

    public void receivePacket(Packet p) {

       // TODO Auto-generated method stub

       //判断是否时TCP数据包

       if (p instanceof TCPPacket) {

           TCPPacket tcp = (TCPPacket) p;

           //判断端口是否为监听端口

           if (tcp.src_port == receivePost || tcp.dst_port == receivePost) {

              //获取TCP数据包中数据

              byte[] bytes = tcp.data;

              //如果bytes中第一位为22 代表是 握手协议

              //并且第五位是 11 代表是客户端出示的证书

              //则获取客户端证书

              if (bytes != null && bytes.length > 6 && ((int) bytes[0]) == 22 && ((int) bytes[5]) == 11) {

                  StringBuffer buf = new StringBuffer();

                  //将数据转换为16进制处理

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

                     for (j = 0; j < 8 && i < bytes.length; j++, i++) {

                         String d = Integer

                                .toHexString((int) (bytes[i] & 0xff));

                         buf.append((d.length() == 1 ? "0" + d : d) + " ");

                         if (bytes[i] < 32 || bytes[i] > 126)

                            bytes[i] = 46;

                     }

                  }

                  System.out.println("数据包内容(16进制):"+buf);

                  //16进制字符串转换为16进制数组

                  String[] data = buf.toString().split(" ");

                  //取得 12 13 14 位数据 16进制转换为10进制 该值为证书长度

                  int certLength = Integer.parseInt(data[12] + data[13]

                         + data[14], 16);

                  //从第15位开始取,把证书内容提取出来

                  StringBuffer certString = new StringBuffer();

                  for (int i = 0; i < certLength; i++) {

                     certString.append(data[i + 15]);

                  }

                  //创建一个字节数据存储证书内容

                  byte[] cert=new byte[certLength];

                  //提取证书内容,16进制数据转换为字节数组

                  for(int i=0;i<certLength;i++){

                     String tempstr=certString.substring(i*2,i*2+2);

                     cert[i]=uniteBytes(tempstr);

                  }

                 

                  System.out.println("证书base64编码:"+new String(Base64.encode(cert)));

             

                  try {

                     X509Cert xcert = new X509Cert(cert);

                     System.out.println("证书DN"+xcert.getSubject());

                  } catch (PKIException e) {

                     // TODO Auto-generated catch block

                     e.printStackTrace();

                  }

              }

           }

       }

    }

 

    private static byte uniteBytes(String str) {

       byte[] bs = str.getBytes();

       byte src0 = bs[0];

       byte src1 = bs[1];

       byte _b0 = Byte.decode("0x" + new String(new byte[] { src0 }))

              .byteValue();

       _b0 = (byte) (_b0 << 4);

       byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 }))

              .byteValue();

       byte ret = (byte) (_b0 | _b1);

       return ret;

    }

 

    public int getReceivePost() {

       return receivePost;

    }

 

    public void setReceivePost(int receivePost) {

       this.receivePost = receivePost;

    }

 

    public static void main(String[] args) {      

       try {

           NetworkInterface[] devices = JpcapCaptor.getDeviceList();

           JpcapCaptor jpcap = JpcapCaptor.openDevice(devices[1], 2000, false, 20);

           SSLReceiver sslR=new SSLReceiver();

           //监听的SSL协议的端口号

           sslR.receivePost=443;

           jpcap.loopPacket(-1, sslR);

       } catch (IOException e) {

           // TODO Auto-generated catch block

           e.printStackTrace();

       }

 

    }

}

 

执行后,如果能成功截获客户端证书会在控制台输出

数据包内容(16进制):16 03 01 04 24 0b 00 03 14 00 03 11 00 03 0e 30 82 03 0a 30 82 02 73 a0 03 02 01 02 02 01 0c 30 0d 06 09 2a 86 48 86 f7 0d 01 01 04 05 00 30 57 31 0b 30 09 06 03 55 04 06 13 02 43 4e 31 0e 30 0c 06 03 55 04 08 13 05 6a 69 6c 69 6e 31 0b 30 09 06 03 55 04 07 13 02 63 63 31 0c 30 0a 06 03 55 04 0a 13 03 6a 69 74 31 0c 30 0a 06 03 55 04 0b 13 03 70 6d 69 31 0f 30 0d 06 03 55 04 03 13 06 4c 6f 6e 67 43 41 30 1e 17 0d 30 34 30 32 30 39 30 34 34 36 30 33 5a 17 0d 31 34 30 32 30 36 30 34 34 36 30 33 5a 30 60 31 0b 30 09 06 03 55 04 06 13 02 43 4e 31 0e 30 0c 06 03 55 04 08 13 05 6a 69 6c 69 6e 31 0b 30 09 06 03 55 04 07 13 02 63 63 31 0c 30 0a 06 03 55 04 0a 13 03 6a 69 74 31 0c 30 0a 06 03 55 04 0b 13 03 70 6d 69 31 18 30 16 06 03 55 04 03 13 0f 41 52 41 41 75 64 69 74 4f 66 66 69 63 65 72 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 e1 22 09 c5 25 de dd 9f 93 8b bf 9e e6 63 35 1f 15 2f 59 1c 94 4b 37 18 4f ee 3c e3 9d fc 9d 12 6d fa c3 cb 30 9b ea f9 9b 2d 9e 36 64 56 17 4c 47 c9 81 6d bb 23 59 21 e7 b6 dd a2 5b fb 57 e5 58 83 5c f5 a5 56 c6 9e 8d 19 87 e7 eb eb 16 b0 62 60 cf ae 44 d9 26 fb df 9d 49 ac 8f bb c1 c7 3f 07 88 5f fe 4c db 5b f4 6e 1f e8 52 3d 2a 5c 37 ee 46 11 c5 4e 38 17 aa 91 fa 2c 4a 86 5c 09 02 03 01 00 01 a3 81 dc 30 81 d9 30 09 06 03 55 1d 13 04 02 30 00 30 2c 06 09 60 86 48 01 86 f8 42 01 0d 04 1f 16 1d 4f 70 65 6e 53 53 4c 20 47 65 6e 65 72 61 74 65 64 20 43 65 72 74 69 66 69 63 61 74 65 30 1d 06 03 55 1d 0e 04 16 04 14 2d 5b c6 78 61 a7 ee ab 51 c1 1c 48 26 81 7b d7 71 39 d4 a7 30 7f 06 03 55 1d 23 04 78 30 76 80 14 eb 4c ce f4 f9 9e ed 09 c3 fa 22 d8 5c eb ec 30 d5 52 00 ee a1 5b a4 59 30 57 31 0b 30 09 06 03 55 04 06 13 02 43 4e 31 0e 30 0c 06 03 55 04 08 13 05 6a 69 6c 69 6e 31 0b 30 09 06 03 55 04 07 13 02 63 63 31 0c 30 0a 06 03 55 04 0a 13 03 6a 69 74 31 0c 30 0a 06 03 55 04 0b 13 03 70 6d 69 31 0f 30 0d 06 03 55 04 03 13 06 4c 6f 6e 67 43 41 82 01 00 30 0d 06 09 2a 86 48 86 f7 0d 01 01 04 05 00 03 81 81 00 84 c1 2c 8f 44 d4 60 53 2b 42 5f d2 73 b4 77 77 f1 b3 e5 94 ce a6 8b ec a0 0a de 15 3e 14 28 e4 a7 af d2 a7 a2 8a 08 d8 9e 70 1e 18 35 5f 6f f9 61 d8 f4 ca ea e9 ec cd 5c 13 8d 14 de 36 4c 8e 81 05 d8 95 f5 63 cd f1 9b de 0d e5 2e 82 4c 62 1c 30 89 a3 14 28 8f 51 20 76 0c d1 d4 a8 1c d2 6f c6 90 66 c4 c6 69 61 dd 07 6f 22 2c 14 8b 85 9f 6e 1e 6c 6e 4a 6b 05 23 3b a8 be cd b1 24 19 10 00 00 82 00 80 c2 fd 38 02 08 0c c9 7e da 61 c6 11 1b fa a7 8f 82 e9 98 83 3d 49 bb aa e8 68 63 39 d5 5c 0f e8 5a 7b bf 58 83 92 a6 11 2b ac ca 38 67 19 cf a0 8f 39 53 6a 97 64 8d b4 02 3e dc 96 10 1e 03 57 9a f3 56 82 59 f4 53 77 76 b9 0b f3 51 14 61 a9 b0 08 c7 65 b7 02 82 62 40 c5 19 e7 fd b4 90 04 a9 ab 86 5b b1 c0 31 2a 06 2f c4 9a be 55 f4 76 e8 f4 55 4a 31 cc 0f e6 91 d3 ef f5 d0 e3 32 8c 0f 00 00 82 00 80 30 30 99 95 15 05 ec 0f c9 37 2c 23 8d 50 f3 b1 fb 5d e9 9b f5 35 5d 22 94 67 57 d2 85 ef 2b 1f 7d 01 8c 81 60 d3 d4 ac 12 41 d7 a9 99 e3 5b 7f a2 ff a2 88 56 40 6d 3b c2 8c 59 59 3d 66 f4 ff 83 28 bd 08 f5 e4 a6 65 a4 8e 7b b0 75 60 e8 93 4a e7 a5 95 8c 7c a3 c2 d3 d0 88 c7 ce cb d1 31 2d f5 95 a7 fe 8a 6e 54 86 78 4a d6 eb 41 43 c0 83 d2 c6 50 1d 7a c6 3e db 69 b1 f0 c4 b8 ef 3d 14 03 01 00 01 01 16 03 01 00 20 72 2a a1 7a 2f 9a 45 05 5b 50 bd 22 75 63 c6 ec 54 98 61 81 b4 7f e2 3a c4 e6 d9 06 b5 20 8d a5

证书base64编码:MIIDCjCCAnOgAwIBAgIBDDANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEOMAwGA1UECBMFamlsaW4xCzAJBgNVBAcTAmNjMQwwCgYDVQQKEwNqaXQxDDAKBgNVBAsTA3BtaTEPMA0GA1UEAxMGTG9uZ0NBMB4XDTA0MDIwOTA0NDYwM1oXDTE0MDIwNjA0NDYwM1owYDELMAkGA1UEBhMCQ04xDjAMBgNVBAgTBWppbGluMQswCQYDVQQHEwJjYzEMMAoGA1UEChMDaml0MQwwCgYDVQQLEwNwbWkxGDAWBgNVBAMTD0FSQUF1ZGl0T2ZmaWNlcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4SIJxSXe3Z+Ti7+e5mM1HxUvWRyUSzcYT+484538nRJt+sPLMJvq+ZstnjZkVhdMR8mBbbsjWSHntt2iW/tX5ViDXPWlVsaejRmH5+vrFrBiYM+uRNkm+9+dSayPu8HHPweIX/5M21v0bh/oUj0qXDfuRhHFTjgXqpH6LEqGXAkCAwEAAaOB3DCB2TAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQULVvGeGGn7qtRwRxIJoF713E51KcwfwYDVR0jBHgwdoAU60zO9Pme7QnD+iLYXOvsMNVSAO6hW6RZMFcxCzAJBgNVBAYTAkNOMQ4wDAYDVQQIEwVqaWxpbjELMAkGA1UEBxMCY2MxDDAKBgNVBAoTA2ppdDEMMAoGA1UECxMDcG1pMQ8wDQYDVQQDEwZMb25nQ0GCAQAwDQYJKoZIhvcNAQEEBQADgYEAhMEsj0TUYFMrQl/Sc7R3d/Gz5ZTOpovsoAreFT4UKOSnr9KnoooI2J5wHhg1X2/5Ydj0yurp7M1cE40U3jZMjoEF2JX1Y83xm94N5S6CTGIcMImjFCiPUSB2DNHUqBzSb8aQZsTGaWHdB28iLBSLhZ9uHmxuSmsFIzuovs2xJBk=

证书DNCN=ARAAuditOfficer,OU=pmi,O=jit,L=cc,ST=jilin,C=CN

 

结论:利用JPCAP截获网络通信过程中的TCP/IP数据包,通过对TCP/IP数据包的解析,可以获得客户端证书公钥。

 

注:

1.测试时服务器和客户端必须在两台主机上运行,否则通讯不出网卡,无法截获通讯数据

2.目前测试仅在TOMCATIIS服务上运行,没有在其他服务上测试过

3.该测试目前仅能结果TOMCAT服务上的SSL通讯的客户端证书公钥,无法截获IIS服务上SSL通讯的客户端证书公钥,IIS服务上如何截获还在进一步钻研中。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/gnn19820901/article/details/4053761

智能推荐

MySQL (part2)_kaiyin_hzau的博客-程序员秘密

MySQL第七章(更高阶用法部分与上面内容重叠)apt-get安装MySQL-server和MySQL-client启动服务:sudo service start mysqlCREATE USER ‘username’@‘host’ IDENTIFIED BY ‘password’;如果想让用户从任意地方连接可以把host改成%查看当前版本:SELECT VERSION(), CURRE...

QT:debug日志—打不开头文件以及qDebug和Q_CLASSINFO的使用_无法打开源文件qdebug_刘欢明的博客-程序员秘密

这个是因为链接器在给定路径上搜索不到对应的头文件,而大多数的Qt相关的头文件都集中在一个include文件夹里:我电脑上的路径是:C:\Qt\Qt5.9.7\5.9.7\msvc2017_64\include然后我们在项目设置里: 注意,这边要加上\*,因为include里的文件才是我们想要的: 我们可以看到qDebug其实是一个函数的宏,我们会发现,这个函数是返回了一个QDebug类: 我们继续跟踪这个类: 发现这个类里面有一个内部类为Stream,大概作用应该是对接到C++的标准流上面,在上面做一些处理

(简单好用)popupWindow+listView实现下拉列表的功能_xiyangyang8110的博客-程序员秘密

有个需求:一有数据就显示列表提示,让用户选择是哪个数据。由于spinner定制性差,所以选择popupWindow+listView实现package com.blzt.test;import android.app.Activity;import android.graphics.drawable.BitmapDrawable;import android.os.Bundle;imp...

ValueError: fill value must be in categories._链巨人的博客-程序员秘密

执行下面代码时报错:ValueError: fill value must be in categoriesimport pandas as pd;import numpy as np;df = pd.DataFrame({'a':[1, 2, 3, 4], 'b':['d', 'e', 'f', None]}, dtype='category');print(df)df['b'].fillna

Phoenix实战(二)_Running_Tiger的博客-程序员秘密

命令行方式1、命令执行命令可以进入命令行模式./sqlline.py node-1:21810: jdbc:phoenix:node-1>然后执行相关的命令退出命令:!quit2、常用命令命令开头需要一个感叹号,使用help可以打印出所有命令0: jdbc:phoenix:node-1> help!all Execute the specified SQL aga

上传多张图片并预览_西风XF的博客-程序员秘密

上一篇写的是上传单张图片并预览,因为需求不一样,也顺便百度了一下上传多张图片并预览的,整理了一个demo,存一下,留着用。不兼容IE。实现效果:上传多张图片并预览; #divUL div{ float: left; } //多张 document.get

随便推点

大型分布式网站架构设计与实践《概述与大纲》_听说你在这里的博客-程序员秘密

大型分布式网站架构设计与实践在大型网站架构的演变过程中,集中式的架构设计出于对系统的可扩展性,可维护性,成本等多方面因素的考虑,逐渐被放弃。分布式架构的核心思想是采用大量廉价的PC Server ,构建一个低成本,高可用,高可扩展,高吞吐的集群系统,以支撑海量用户的访问和数据存储,理论上具备无限的扩展能力。分布式系统的设计,是一门复杂的学问,它设计通讯协议,远程调用,服务治理,系统安全

网络基础及TCP 协议 实现 Server/Client 简单通信 (socket 套接字)_潘小蓝的博客-程序员秘密

前置知识:IO流 – 字节流和字符流的区别和使用,分别实现文本的复制引言:生活中的每个人都在进行网络通信(只要你不是八九十岁的老大爷老大妈,甚至有的老大妈大爷比年轻人玩的还 6)。我们每天用的 QQ、微信 、and so on …实际上都是网络通信。网络编程:上图展现的就是一个简单的网络通信, 计算机 A 通过协议和传输到网络,网络再通过协议传输给另一个计算机。那什么是协议呢?协议:为了让网络中不同计算机之间能够相互通信而建立的规则、约定、约定。常见的协议有:TCP协议:面向连接的、可靠的

ubuntu镜像下载地址_以燃的博客-程序员秘密

官方下载地址(不推荐)https://www.ubuntu.com/download中科大源http://mirrors.ustc.edu.cn/ubuntu-releases/16.04/阿里云开源镜像站http://mirrors.aliyun.com/ubuntu-releases/16.04/兰州大学开源镜像站http://mirror.lzu.edu.cn/ubuntu-releases/16.04/北京理工大学开源http://mirror.bit.edu.cn/ubuntu-r

elf文件分析_查看elf文件中的大的静态变量_头像很酷的博客-程序员秘密

最近在分析Linux模块加载过程的时候。发现模块加载过程和链接过程有点点相似,都需要做重定向、解决符号引用问题。而这些操作都和elf文件格式有着莫大的联系,所以在出模块加载过程分析的文档之前,先分析一下elf文件。elf全称executable and linkable format,是一种可执行文件、目标文件和库使用的文件的格式。替代了早年的a.out文件格式。linux不仅将elf用于用户...

windows强制杀进程_windows 强杀进程_温润如风的博客-程序员秘密

在工作中,由于本地启动了多个nginx进程,突然有一天改变了某一个nginx的配置,需要重启,在资源管理器中总是无法杀掉nginx进程以上问题,用下面的命令,在命令行中执行即可把所有的nginx进程杀掉taskkill /im nginx.exe /f...

推荐文章

热门文章

相关标签