技术标签: c string byte 服务器 exchange ssl
摘要
通过对SSL握手协议的分析,得知在SSL双向认证握手过程中,客户端需要出示客户端证书以供服务器验证,利用sniffer技术截获网络通信过程中的TCP/IP数据包,通过对TCP/IP数据包的解析,获得客户端证书公钥。
关键字:sniffer,SSL 握手协议,TCP/IP, 证书公钥
相关工具:
Ethereal:网络抓包工具,Ethereal是免费的网络协议检测程序,支持Unix,Windows。让您经由程序抓取运行的网站的相关资讯,包括每一封包流向及其内容、资讯。可依操作系统语系看出,方便查看、监控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=
证书DN:CN=ARAAuditOfficer,OU=pmi,O=jit,L=cc,ST=jilin,C=CN
结论:利用JPCAP截获网络通信过程中的TCP/IP数据包,通过对TCP/IP数据包的解析,可以获得客户端证书公钥。
注:
1.测试时服务器和客户端必须在两台主机上运行,否则通讯不出网卡,无法截获通讯数据
2.目前测试仅在TOMCAT,IIS服务上运行,没有在其他服务上测试过
3.该测试目前仅能结果TOMCAT服务上的SSL通讯的客户端证书公钥,无法截获IIS服务上SSL通讯的客户端证书公钥,IIS服务上如何截获还在进一步钻研中。
MySQL第七章(更高阶用法部分与上面内容重叠)apt-get安装MySQL-server和MySQL-client启动服务:sudo service start mysqlCREATE USER ‘username’@‘host’ IDENTIFIED BY ‘password’;如果想让用户从任意地方连接可以把host改成%查看当前版本:SELECT VERSION(), CURRE...
这个是因为链接器在给定路径上搜索不到对应的头文件,而大多数的Qt相关的头文件都集中在一个include文件夹里:我电脑上的路径是:C:\Qt\Qt5.9.7\5.9.7\msvc2017_64\include然后我们在项目设置里: 注意,这边要加上\*,因为include里的文件才是我们想要的: 我们可以看到qDebug其实是一个函数的宏,我们会发现,这个函数是返回了一个QDebug类: 我们继续跟踪这个类: 发现这个类里面有一个内部类为Stream,大概作用应该是对接到C++的标准流上面,在上面做一些处理
有个需求:一有数据就显示列表提示,让用户选择是哪个数据。由于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 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
命令行方式1、命令执行命令可以进入命令行模式./sqlline.py node-1:21810: jdbc:phoenix:node-1>然后执行相关的命令退出命令:!quit2、常用命令命令开头需要一个感叹号,使用help可以打印出所有命令0: jdbc:phoenix:node-1> help!all Execute the specified SQL aga
上一篇写的是上传单张图片并预览,因为需求不一样,也顺便百度了一下上传多张图片并预览的,整理了一个demo,存一下,留着用。不兼容IE。实现效果:上传多张图片并预览; #divUL div{ float: left; } //多张 document.get
Ninja具体干了什么
大型分布式网站架构设计与实践在大型网站架构的演变过程中,集中式的架构设计出于对系统的可扩展性,可维护性,成本等多方面因素的考虑,逐渐被放弃。分布式架构的核心思想是采用大量廉价的PC Server ,构建一个低成本,高可用,高可扩展,高吞吐的集群系统,以支撑海量用户的访问和数据存储,理论上具备无限的扩展能力。分布式系统的设计,是一门复杂的学问,它设计通讯协议,远程调用,服务治理,系统安全
前置知识:IO流 – 字节流和字符流的区别和使用,分别实现文本的复制引言:生活中的每个人都在进行网络通信(只要你不是八九十岁的老大爷老大妈,甚至有的老大妈大爷比年轻人玩的还 6)。我们每天用的 QQ、微信 、and so on …实际上都是网络通信。网络编程:上图展现的就是一个简单的网络通信, 计算机 A 通过协议和传输到网络,网络再通过协议传输给另一个计算机。那什么是协议呢?协议:为了让网络中不同计算机之间能够相互通信而建立的规则、约定、约定。常见的协议有:TCP协议:面向连接的、可靠的
官方下载地址(不推荐)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
最近在分析Linux模块加载过程的时候。发现模块加载过程和链接过程有点点相似,都需要做重定向、解决符号引用问题。而这些操作都和elf文件格式有着莫大的联系,所以在出模块加载过程分析的文档之前,先分析一下elf文件。elf全称executable and linkable format,是一种可执行文件、目标文件和库使用的文件的格式。替代了早年的a.out文件格式。linux不仅将elf用于用户...
在工作中,由于本地启动了多个nginx进程,突然有一天改变了某一个nginx的配置,需要重启,在资源管理器中总是无法杀掉nginx进程以上问题,用下面的命令,在命令行中执行即可把所有的nginx进程杀掉taskkill /im nginx.exe /f...