使用Wireshark與Burp Suite分析HTTPS協議
目錄
1.虛擬機器伺服器搭建網站,本機訪問用Burp Suite抓包獲取頭資訊。
2.Wireshark和Burp Suite處理HTTPS的過程與技術實現過程原理
-
目的
瞭解HTTPS是如何加密,SSL加密過程。
-
內容
1.虛擬機器伺服器搭建網站,本機訪問用Burp Suite抓包獲取頭資訊。
2.描述Wireshark和Burp Suite處理HTTPS的過程和兩者的技術實現過程原理。
3.在QT中編寫HTTP程式並執行。
-
器材(裝置、元器件)
Wireshark、Burp Suite、IIS搭建網站的虛擬機器windows2003系統
-
步驟
1.虛擬機器伺服器搭建網站,本機訪問用Burp Suite抓包獲取頭資訊。
①在虛擬機器中搭建了網站,在本機中用火狐瀏覽器訪問IP並用Burp Suite抓包。
②關閉抓包後,網站可訪問
2.Wireshark和Burp Suite處理HTTPS的過程與技術實現過程原理
(1)Wireshark
原理:
HTTPS(Hypertext TransferProtocol over Secure Socket Layer,基於SSL的HTTP協議),埠443,需要向CA申請證書,通過SSL握手建立安全通道,利用協商金鑰對資料進行對稱加密通訊。
SSL協議棧位置介於TCP和應用層之間,分為SSL記錄協議層和SSL握手協議層。
SSL握手:
1、 初始化階段。客戶端建立隨機數,傳送ClientHello 將隨機數連同自己支援的協議版本、加密演算法和壓縮演算法傳送給伺服器。伺服器回覆ServerHello將自己生成的隨機數連同選擇的協議版本、加密演算法和壓縮演算法給客戶端。
2、 認證階段。伺服器傳送ServerHello的同時可能將包含自己公鑰的證書傳送給客戶端(Certificate),並請求客戶端的證書(Certificate Request)。
3、 金鑰協商階段。客戶端驗證證書,如果收到Certificate Request則傳送包含自己公鑰的證書,同時對此前所有握手訊息進行雜湊運算,並使用加密演算法進行加密傳送給伺服器。同時,建立隨機數pre-master-secret並使用伺服器公鑰進行加密傳送。伺服器收到這個ClientKeyExchange之後解密得到pre-master-secret。伺服器和客戶端利用1階段的隨機數,能夠計算得出master-secret。
4、 握手終止。伺服器和客戶端分別通過ChangeCipherSpec訊息告知伺候使用master-secret對連線進行加密和解密,並向對方傳送終止訊息(Finished)。
抓包分析:
使用wireshark過濾ssl流量,可以看到有幾個明顯的ssl會話建立包,例如client hello,server hello等;
①藍色的就是我們客戶端向伺服器傳送hello ,即瀏覽器向伺服器請求一個安全的網頁。
然後雙擊這個Client Hello看下傳輸的內容:
②伺服器就把它的證書和公匙發回來,同時向服務端傳送ACK報文以便服務端確認資料是否無誤。
server hello包裡能看到服務端選擇的加密演算法;
伺服器傳送ServerHello的同時可能將包含自己公鑰的證書傳送給客戶端(Certificate);
③客戶端驗證證書,如果收到Certificate Request則傳送包含自己公鑰的證書,同時對此前所有握手訊息進行雜湊運算,並使用加密演算法進行加密傳送給伺服器;
④伺服器端傳送change_cipher_spec和finished訊息。到這裡握手結束。
(2)Burp Suite
原理:
BurpSuite的基本思路是偽裝成目標https伺服器,讓瀏覽器(client)相信BurpSuite就是目標站點。
為了達成目標,BurpSuite必須:(1)生成一對公私鑰,並將公鑰和目標域名繫結並封裝為證書;(2)讓瀏覽器相信此證書,即通過證書驗證。所以, BurpSuite需要在作業系統新增一個根證書,這個根證書可以讓瀏覽器信任所有BurpSuite頒發的證書。具體流程如下:
之後,BurpSuite擁有了兩套對稱金鑰,一套用於與client互動,另外一套與server互動,而在BurpSuite處可以獲得https明文。
抓包分析:
①開啟Burp Suite,連線百度:
②在Target中只檢視baidu
③過濾顯示:
④
3.在QT中編寫HTTP程式並執行。
在pro檔案中配置:
LIBS=-lpcap -lnet -lnids
程式碼
(C語言,源自《網路資料與協議分析》)
#include "nids.h"
#include "pcap.h"
#include "libnet.h"
char ascii_string[10000];
char *char_to_ascii(char ch)
/* 此函式的功能主要用於把協議資料進行顯示 */
{
char *string;
ascii_string[0] = 0;
string = ascii_string;
if (isgraph(ch))
/* 可列印字元 */
{
*string++ = ch;
}
else if (ch == ' ')
/* 空格 */
{
*string++ = ch;
}
else if (ch == '\n' || ch == '\r')
/* 回車和換行 */
{
*string++ = ch;
}
else
/* 其它字元以點"."表示 */
{
*string++ = '.';
}
*string = 0;
return ascii_string;
}
void parse_client_data(char content[],int number)
{
char temp[1024];
char str1[1024];
char str2[1024];
char str3[1024];
int i,j,k;
char entity_content[1024];
if(content[0]!='H' && content[1]!='T' && content[2]!='T' && content[3]!='P')
{
printf("實體內容為(續):\n");
for(i=0;i<number;i++)
{
printf("%s",char_to_ascii(content[i]));
}
printf("\n");
}
else
{
for(i=0;i<strlen(content);i++)
{
if(content[i]!='\n')
{
k++;
continue;
}
for(j=0;j<k;j++)
{
temp[j]=content[j+i-k];
}
temp[j]='\0';
if(strstr(temp,"HTTP"))
{
printf("狀態行為:");
printf("%s\n",temp);
sscanf(temp,"%s%s",str1,str2);
printf("HTTP協議為:%s\n",str1);
printf("狀態程式碼為:%s\n",str2);
}
if(strstr(temp,"Date"))
{
printf("當前的時間為(Date):%s\n",temp+strlen("Date:"));
printf("%s\n",temp);
}
if(strstr(temp,"Server"))
{
printf("伺服器為(Server):%s\n",temp+strlen("Server:"));
printf("%s\n",temp);
}
if(strstr(temp,"Cache-Control"))
{
printf("快取機制為(Cache-Control):%s\n",temp+strlen("Cache-control:"));
printf("%s",temp);
}
if(strstr(temp,"Expires"))
{
printf("資源期限為(Expires):%s\n",temp+strlen("Expires:"));
printf("%s",temp);
}
if(strstr(temp,"Last-Modified"))
{
printf("最後一次修改的時間為(Last-Modifid):%s\n",temp+strlen("Last-Modifid:"));
printf("%s",temp);
}
if(strstr(temp,"ETag"))
{
printf("ETag為(ETag):%s\n",temp+strlen("ETag:"));
printf("%s",temp);
}
if(strstr(temp,"Accept-Ranges"))
{
printf("Accept-Ranges(Accept-Ranges):%s\n",temp+strlen("Accept-Ranges:"));
printf("%s",temp);
}
if(strstr(temp,"Content-Length"))
{
printf("內容長度為(Content-Length):%s\n",temp+strlen("Content-Length:"));
printf("%s",temp);
}
if(strstr(temp,"Connection"))
{
printf("連線狀態為(Connection):%s\n",temp+strlen("Connection:"));
printf("%s",temp);
}
if(strstr(temp,"Content-Type"))
{
printf("內容型別為(Content-Type):%s\n",temp+strlen("Content-Type:"));
printf("%s",temp);
}
if((content[i]=='\n') && (content[i+1]='\r'))
{
if(i+3==strlen(content))
{
printf("無實體內容\n");
break;
}
for(j=0;j<number-i-3;j++)
{
entity_content[j]=content[i+3+j];
}
entity_content[j]='\0';
printf("實體內容為:\n");
for(i=0;j<j;i++)
{
printf("%s",char_to_ascii(entity_content[i]));
}
printf("\n");
break;
}
k=0;
}
}
}
void parse_server_data(char content[],int number)
{
char temp[1024];
char str1[1024];
char str2[1024];
char str3[1024];
int i,j,k;
char entity_content[1024];
for(i=0;i<strlen(content);i++)
{
if(content[i]!='\n')
{
k++;
continue;
}
for(j=0;j<k;j++)
{
temp[j]=content[j+i-k];
}
temp[j]='\0';
if(strstr(temp,"GET"))
{
printf("請求行為:");
printf("%s\n",temp);
sscanf(temp,"%s%s%s",str1,str2,str3);
printf("使用的命令為:%s\n",str1);
printf("獲得的資源為:%s\n",str2);
printf("HTTP協議型別為:%s\n",str3);
}
if(temp,"Accept:")
{
printf("接收的檔案包括(Accept):%s",temp+strlen("Accept:"));
printf("%s\n",temp);
}
if(temp,"Referer:")
{
printf("轉移地址為(Referer):%s",temp+strlen("Referer:"));
printf("%s\n",temp);
}
if(temp,"Accept-Language:")
{
printf("使用的語言為(Accept-Language):%s",temp+strlen("Accept-Language:"));
printf("%s\n",temp);
}
if(temp,"Accept-Encoding:")
{
printf("接收的編碼方式為(Accept-Encoding):%s",temp+strlen("Accept-Encoding:"));
printf("%s\n",temp);
}
if(temp,"If-Modified-Since:")
{
printf("上次修改的時間為(If-Modified-Since):%s",temp+strlen("If-Modified-Since:"));
printf("%s\n",temp);
}
if(temp,"If-None-Match:")
{
printf("If-None-Match為(If-Modified-Since):%s",temp+strlen("If-None-Match:"));
printf("%s\n",temp);
}
if(temp,"User-Agent:")
{
printf("使用者的瀏覽器資訊為(User-Agent):%s",temp+strlen("User-Agent:"));
printf("%s\n",temp);
}
if(temp,"Host:")
{
printf("訪問的主機為(Host):%s",temp+strlen("Host:"));
printf("%s\n",temp);
}
if(temp,"Connection:")
{
printf("連線狀態為(Connection):%s",temp+strlen("Connection:"));
printf("%s\n",temp);
}
if(temp,"Cookie:")
{
printf("Cookie為(Cookie):%s",temp+strlen("Cookie:"));
printf("%s\n",temp);
}
if((content[i]=='\n') && (content[i+1]='\r') && (content[i+2=='\n']))
{
if(i+3==strlen(content))
{
printf("無實體內容\n");
break;
}
for(j=0;j<strlen(content);j++)
{
entity_content[j]=content[i+3+j];
}
entity_content[j]='\0';
printf("實體內容為:\n");
printf("%s",entity_content);
printf("\n");
break;
}
k=0;
}
}
void http_protocol_callback(struct tcp_stream *tcp_http_connection,void **param)
{
char address_content[1024];
char content[65535];
char content_urgent[65535];
struct tuple4 ip_and_port=tcp_http_connection->addr;
strcpy(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.saddr))));
sprintf(address_content+strlen(address_content),":%i",ip_and_port.source);
strcat(address_content,"<----->");
strcat(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.daddr))));
sprintf(address_content+strlen(address_content),"%i:",ip_and_port.dest);
strcat(address_content,"\n");
if(tcp_http_connection->nids_state==NIDS_JUST_EST)
{
if(tcp_http_connection->addr.dest!=80)
{
return;
}
tcp_http_connection->client.collect++;
tcp_http_connection->server.collect++;
printf("\n\n\n\==============================\n");
printf("%s建立連線...\n",address_content);
return;
}
if(tcp_http_connection->nids_state==NIDS_CLOSE)
{
printf("-------------------------------\n");
printf("%s連線正常關閉...\n",address_content);
return;
}
if(tcp_http_connection->nids_state==NIDS_RESET)
{
printf("--------------------------------\n");
printf("%s連線被RST關閉...\n",address_content);
return;
}
if(tcp_http_connection->nids_state==NIDS_DATA)
{
struct half_stream *hlf;
if(tcp_http_connection->client.count_new)
{
hlf=&tcp_http_connection->client;
strcpy(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.saddr))));
sprintf(address_content+strlen(address_content),":%i",ip_and_port.source);
strcat(address_content,"<-----");
strcat(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.daddr))));
sprintf(address_content+strlen(address_content),"%i:",ip_and_port.dest);
strcat(address_content,"\n");
printf("\n");
printf("%s",address_content);
printf("瀏覽器接收資料...\n");
printf("\n");
memcpy(content,hlf->data,hlf->count_new);
content[hlf->count_new]='\0';
parse_client_data(content,hlf->count_new);
}
else
{
hlf=&tcp_http_connection->server;
strcpy(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.saddr))));
sprintf(address_content+strlen(address_content),":%i",ip_and_port.source);
strcat(address_content,"<-----");
strcat(address_content,inet_ntoa(*((struct in_addr*)&(ip_and_port.daddr))));
sprintf(address_content+strlen(address_content),"%i:",ip_and_port.dest);
strcat(address_content,"\n");
printf("\n");
printf("%s",address_content);
printf("伺服器接收資料...\n");
printf("\n");
memcpy(content,hlf->data,hlf->count_new);
content[hlf->count_new]='\0';
parse_server_data(content,hlf->count_new);
}
}
return;
}
int main()
{
//close xiaoyanhe
struct nids_chksum_ctl temp;
temp.netaddr = 0;
temp.mask = 0;
temp.action = 1;
nids_register_chksum_ctl(&temp,1);
if(!nids_init())
{
printf("出現錯誤:%s\n",nids_errbuf);
exit(1);
}
nids_register_tcp(http_protocol_callback);
nids_run();
return 0;
}