HTTP抓包实战

HTTP:超文本传输协议

  允许将HTTP文档从Web服务器传送到客户端的浏览器。HTTP请求报文分为3部分。第一部分叫做起始行(Request line)。第二部分叫首部(Request Header)。第三部分叫主题(Body)。

  Response一样,响应行(Response line),首部,主体。

  Fiddle本质是一个代理服务器,代理地址127.0.0.1,端口;8888

GET  /dongye95/home?wvr=5  HTTP/1.1

HTTP/1.1  200 OK

代理服务器

  1. 共享网络
  2. 提高访问速度,大部分代理服务器有缓冲功能
  3. 突破访问限制
  4. 隐藏身份

 

Web通信安全

1.浏览器和Web服务器之间的内容应该只有浏览器和Web服务器能够看到通信的真正内容。

2.HTTP请求的内容和HTTP请求的响应不会被第三方篡改。

Web服务器与每个客户端使用不同的对称加密算法。

 

HTTPS = HTTP + TLS 安全传输层协议或 SSL(Secure Sockets Layer 安全套接层)

 

HTTPS firefox 证书

包括IE、Chrome 和safari在内的大部分应用都使用Windows证书库来验证证书。firefox浏览器是自己维护证书列表,所以需要单独安装fiddle证书。

Tunnel to

  HTTP Tunnel(也叫HTTP隧道,HTTP穿梭)是这样一种技术。它用HTTP协议在要通信的 client 和 server 建立起一条 “Tunnel”。然后client 和server之间的通信都是在这条Tunnel的基础上实现的。简单来说,当Fiddle当做代理转发HTTPS请求的时候,就会产生“CONNECT Tunnels”。

  Fiddle可隐藏,Rules-》Hide CONNECTS

HTTP协议请求方法和状态码

HTTP 请求方法

GET 请求指定的页面信息并返回实体主体
HEAD 类似于GET请求,只不过返回的响应中没有具体的内容,用于获取报头
POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中,post请求可能会导致新的资源的建立和/或对已有资源的修改
PUT 从客户端向服务端传送的数据取代指定文档的内容
DELETE 请求服务器删除指定的页面
OPTIONS 询问支持的方法,用来查询针对请求 URI 指定的资源支持的方法
TRACE 追踪路径,让 Web 服务器端将之前的请求通信环回给客户端的方法
CONNECT 要求用隧道协议连接代理,要求在与代理服务器通信时建立隧道,实现用隧道协议进行 TCP通信。

 

 

 

 

 

 

 

GET

  用于获取资源,常用于向服务器查询某些信息。打开网页一般都是用GET方法,因为要以Web服务器获取信息。

参数

  浏览器也可以在GET方法中把数据传给服务器,数据放在URL的问号(?)后面,叫查询字符串,也叫做Query String。查询字符串以“名=值”这样的形式出现,多个之间用“&”隔开

POST

  通常用来把表单中填好的数据发送给服务器

 

GET和POST区别

  1. GET提交的数据会放在URL之后。POST放在Body中。
  2. GET提交的数据大小是有限制的(URL长度有限制)。POST没有限制。
  3. GET方式提交数据会带来安全问题,比如用户名和密码出现在URL中。页面被缓存或其他人访问这台机器,可从历史记录中获得该用户的账号和密码。

 

HTTP/1.1 状态码

状态码 已定义范围 分类
1XX 100 - 101 信息提示表示请求已被成功接收,继续处理
2XX 200 - 206 成功表示请求已被成功接收、理解、接收
3XX 300 - 302 重定向,要完成请求,必须进行更进一步的处理
4XX 400 - 415 客户端错误,请求有语法错误或请求无法实现
5XX 500 - 505 服务器错误,服务器未能实现合法的请求

 

常见的状态码

名称 释义
200 OK:服务器成功处理了请求(这个是我们见到最多的)
301/302 Moved Permanently(重定向):请求的URL已移走。Response中应该包含一个Location URL,说明资源现在所处的位置
304 Not Modified(未修改):客户的缓存资源是最新的,需要客户端使用缓存
404 Not Found:未找到资源
401 禁止访问
501 Internal Server Error:服务器遇到一个错误,使其无法对请求提供服务

 

200(OK)

  表示该请求被成功地完成,所请求的资源成功地发送回客户端。

204(No Content,没有内容

  返回的HTTP响应中只有一些Header和一个状态行,没有实体的主体内容(没有响应Body)

204 状态码作用如下:

  1. 在不获取资源的情况下了解资源的情况(比如判断其类型)、
  2. 通过查看HTTP响应中的状态码看某个对象是否存在
  3. 通过常看Header测试资源是否被修改

206(Partial Content,部分内容)

  表示服务器已经成功处理了部分GET请求(只有发送GET方法的HTTP请求,Web服务器才可能返回206)

  1. FlashGet、迅雷或者HTTP下载工具都是使用206状态码来实现断点续传
  2. 将一个大文档分解为多个下载段同时下载,比如在线看视频。

http://tv.sohu.com/20121011/n354681393.shtml

301(Moved Permanently)

  表示请求的网页已经永久性地转移到另一个地址

如下情况需要用到301:

  1. 防止用户输错域名。
  2. 网站更换域名。比如www.360buy.com改为www.jd.com
  3. 有多个权重不错的域名,需要把所有的权重都传递到新域名上,这就需要301重定向了。如果不设置301,多个域名绑定在一个主机头上,会被搜索引擎认为是两个相同的站点,不利于网站的排名。绑定的域名越多,内容重复度也就越高,排名越低。

302(Found)

  当我们访问一个URL的时候,服务器要我们访问另一个资源,这回收浏览器会继续发一个HTTP,请求访问新的资源。

  比如为登陆状态下,直接访问需要登陆才能访问的页面,会被服务器返回302,跳转到登陆页面。

 

301和302区别

  1. 301表示旧地址的资源已经被永久的移除了(这个资源不可访问了),搜索引擎会把权重算到新地址。
  2. 302表示旧地址的资源还在(仍然可以访问),这个重定向只是临时地从旧地址跳转到新地址,搜索引擎会把权重算到旧地址。

304(Not Modified)

  304状态码代表上次的文档已经被缓存了,还可以继续使用

如果不想使用本地缓存,用【Ctrl + F5】强制刷新

400(Bad Request)

  表示客户端请求有语法错误

401(Unauthorized)

  状态码401是指未授权错误,有些网页采用的是HTTP基本认证(Basic Authentication),需要在HTTP请求中带上 Authentication Header,否则服务器会返回状态码401

403(Forbidden)

  表示Web客户端发送的请求被Web服务器拒绝了。如果想说明原因,可以在body中说明,但是这个状态码通常表示服务器不想说明拒绝原因

404(Not Found)

  资源不存在。本来就不存在,或者被删了,或者被墙了。

500(Internal Server Error)

  服务器内部错误。比如代码错误,数据库连接语句出错,空指针等。

503(Server Unavailable)

  服务器暂不可用。由于服务器维护或者过载,服务器当前无法处理请求;这个状况是临时的,并且将在一段时间以后恢复。

HTTP协议Header介绍

  Header翻译成中文,叫“首部”或者“头域”。

  Header语法格式是:“key:value”,一行一个Header

Cache:缓存相关。如果本地有“已缓存的”副本,就可以从本地存储设备而不是从原始服务器中提取这个文档。
Accept:表示浏览器客户端可以接受的媒体类型。

Accept:text/html,*/*;q=0.8 代表浏览器可以处理所有的类型。一般浏览器客户端给Web服务器发送的都是这个。

Accept-Encoding:跟压缩有关。Accept-Encoding: gzip, deflate, br   

Accept-Language:浏览器声明自己接受的语言。

User-Agent:浏览器用来告诉服务器,客户端使用的操作系统及版本、CPU类型、浏览器及版本,浏览器渲染引擎、浏览器语言、浏览器插件等。

Referer:用来让服务器判断来源页面,即用户是从哪个页面来的。网站通常用其来统计用户来源,看用户是从搜索页面来的,还是从其他网站链接来的,或是从书签等访问的,以便合理定义网站。

Referer有时也被用作防盗链,即下载时判断来源地址是不是在网站域名之内,否则就不能下载或显示。

Connection:从HTTP/1.1起,系统默认都开启了Connection:Keep-Alive,保持连接特性

HTTP协议是基于TCP协议的。当一个网页完全打开后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭;如果客户端再次访问这个服务器上的网页,将会连续使用这一条已经建立的连接。

Keep-Alive不会永久保持连接,它有一个保持时间。

Host:这个Header是必需的,它的作用是指定被请求的主机和端口号。

Web网页抓包和Fiddler修改包

打开一个网页,浏览器需要发送很多个请求。

  1. 在浏览器输入http://www.cnblogs.com
  2. 浏览器会发送第一个HTTP请求去获取页面布局的HTML,这个请求叫做“父请求”。然后服务器把HTTP响应发回给浏览器。
  3. 浏览器会分析HTTP响应中的HTML,然后发现HTML中引用了其他文件:比如图片,CSS,JS,JSON。浏览器会自动再次发送很多HTTP请求,去获取图片,CSS文件或者JS文件。这些HTTP请求叫做“子请求”。
  4. 当所有自请求的响应都返回后,浏览器会把1个父请求加上多个子请求渲染出来。这样就形成了一个页面。

 

用Fiddler选择子请求

先找到父请求,鼠标右键选择Select -> Child Requests

用Fiddler选择父请求

先找到子请求,鼠标右键选择Select -> Parent Requests

用Fiddler选择相同请求

选择一个请求,鼠标右键选择Select -> Duplicate Requests

 

简单性能测试

  1. 子请求出现了404或者500之类的错误,会严重影响整个网页的加载速度。
  2. 子请求的响应速度慢也会影响网页加载的速度。

可以清楚看到每个HTTP请求的响应时间

修改HTTP请求单个断点:bpu www.baidu.com。取消:bpu

修改HTTP响应单个断点:bpafter www.baidu.com。取消 bpafter

HTTP协议中的缓存

HTTP中具有缓存功能的是浏览器缓存和代理服务器缓存。

HTTP缓存是指当Web请求抵达缓存时,如果本地有“已缓存的”副本,就可以从本地存储设备而不是从原始服务器中提取这个文档。

缓存优点

  • 减少了冗余的数据传输,节省了传输时间
  • 减少了服务器的负担,大大提高了网站性能
  • 加快了客户端加载网页的速度

Web服务器通过以下2种方式来判断浏览器缓存是否最新

  1. 浏览器把缓存文件的最后修改时间通过Header“If-Modified-Since”告诉Web浏览器
  2. 浏览器把缓存文件的ETag通过Header“If-None-Match”告诉服务器

通过最后修改时间来判断缓存新鲜度

浏览器可以通过缓存文件的修改时间来判断缓存的新鲜度,具体的步骤如下:

  1. 如果浏览器客户端想请求一个文档,它首先检查本地缓存,发现存在这个文档的缓存,获取缓存中文档的最后修改时间,通过“If-Modified-Since”发送HTTP请求给Web服务器。
  2. Web服务器收到HTTP请求,将服务器的文档修改时间(Last-Modified)跟HTTP请求Header中的If-Modified-Since相比较。如果时间是一样的,说明缓存还是最新的。Web服务器将发送状态码304(Not Modified)给浏览器客户端,告诉客户端直接使用缓存里的版本。

HTTP请求中跟缓存相关的Header

名称 释义
Cache-Control:max-age=0 以秒为单位
If-Modified-Since:Mon,19 Nov 2012 08:38:01 GMT 缓存文件的最后修改时间
If-None-Match:"0693f67a67cc1:0" 缓存文件的ETag
Cache-Control:no-cache 不使用缓存
Pragma:no-cache 不使用缓存

 

HTTP响应中跟缓存相关的Header

名称 释义

Cache-Control:public

响应被缓存,并且在多用户间共享
Cache-Control:private 响应只能作为私有缓存,不能再用户之间共享
Cache-Control:no-cache 提醒浏览器要从服务器提取文档进行验证
Cache-Control:no-store 绝对禁止缓存(用于机密、敏感文件)
Cache-control:max-age=60 60s之后缓存过期(相对时间)

Date:Mon,19 Nov 2012 08:39:00 GMT

当前响应发送的时间
Expires:Mon,19 Nov 2012 08:40:01 GMT 缓存过期的时间(绝对时间)
Last-Modified:Mon,19 Nov 2012 08:38:01 GMT 服务器端文件的最后修改时间

ETag:"20b1add7ec1sd1:0"

服务器端文件的ETag值

 

如果同时存在cache-control和Expires怎么办?浏览器总是优先使用cache-control。

ETag

是Entity Tag(实体标签)的缩写,是根据实体内容生成的一段hash字符串(类似于MD5或者SHA1之后的结果)

使用ETag主要是为了解决一些Last-Modified无法解决的问题。

  1. 某些服务器不能精确得到文件的最后修改时间,这样就无法通过最后修改时间来判断文件是否更新了。
  2. 某些文件的修改非常频繁,在以秒为单位以下的时间内进行修改,而Last-Modified只能精确到秒
  3. 一些文件的最后修改时间改变了,但是内容并非改变,我们不希望客户端认为这个文件修改了。

使用【Ctrl + F5】可以强制刷新浏览器,可以让浏览器不使用缓存。

Pragma:no-cache的作用和“Cache-Control:no-cache”一模一样,都是不使用缓存。Pragma:no-cache是HTTP1.0中定义的,所以为了兼容HTTP1.0会同时使用Pragma:no-cache和Cache-Control:no-cache

HTTP协议压缩和URL Encode

HTTP采用通用的压缩算法,比如用gzip来压缩HTML、JavaScript、CSS文件,能大大减少网络传输的数据量,提高了用户显示网页的速度。当然,这同时也会增加一点点服务器的开销。

HTTP压缩的过程

  1. 浏览器发送HTTP请求给Web服务器,请求中的Header能Accept-Encoding:gzip,deflate(告诉服务器,浏览器支持gzip压缩)
  2. Web服务器接到HTTP请求后,生成原始的HTTP响应,其中有原始的 Content-TypeContent-Length
  3. Web服务器通过gzip来对HTTP响应进行编码,编码后Header中有 Content-Type 和 Content-Length(压缩后的大小),并且增加了Content-Encoding:gzip,然后把HTTP响应发送给浏览器。
  4. 浏览器接到HTTP响应后,根据Content-Encoding:gzip来对HTTP响应进行解码,获取到原始HTTP响应后显示出网页。

内容编码类型:

Content-Encoding header 就是用这些标准化的代号来说明编码时使用的算法

  1. gzip 表明实体采用 GNU zip 编码
  2. compress 表明实体采用 UNIX的文件压缩程序
  3. deflate 表明实体是用 zlib 的格式压缩的
  4. identity 表明没有对实体进行编码;当没有 Contetn-Encoding header 时,就默认为这种情况。

gzip、compress以及deflate编码都是无损压缩算法,用于减少传输报文的大小,不会导致信息损失。其中 gzip 通常效率最高,使用最为广泛。

gzip是如何压缩的

简单来说,gzip压缩实在一个文本文件中找出类似的字符串,并临时替换它们,从而使整个文件变小。这种形式的压缩对Web来说非常适合,因为HTML和CSS文件通常包含大量重复的字符串,例如空格、标签等。也正是因为这样,gzip对JPEG这类文件压缩效果不好。

HTTP内容编码和HTTP压缩的区别

用其他编码方式把内容搅乱或者加密,以此来防止未被授权的第三方开到文档的内容。所以,我们说HTTP压缩其实就是HTTP内容编码的一种。

URL Encode介绍

URL只能用英文字母、数字或者某些标点符号,不能使用其他文字和符号。

URL Encode(URL编码)就是把所有非英文字母、数字字符都替换成百分号(%)后加两位十六进制数。

比如在搜狗搜索里输入中文,点击查找

中文对应为%E4%B8%AD%E6%96%87

在Fiddler中可以使用TextWizard工具来进行转换

Fiddler使用技巧

1.【Ctrl + X】清空列表

2.Fiddler异常退出后无法上网,重新启动Fiddler然后再关闭。

3.Fiddler中查询对话,【Ctrl + F】就可以了。

4.Fiddler中保存抓到的包

  先选中session,然后右键 -> Save -> Selected Sessions。保存后的文件后缀名是.saz。文件会保存完整的HTTP请求和HTTP响应

  双击.saz文件,或者单机Fiddler菜单栏中的File -> Load Archive,就能打开.saz文件。

Fiddler常用快捷键

快捷键 用途
Ctrl + X 删除所有的Session
Ctrl + A 选择所有的Session
ESC 不选择任何的Session
Ctrl + I 反选Session
Delete 删除选择的Session
Shift + Delete 删除未选择的Session
R 重放选择的Session(可以重放多个Session)
Shift + R 多次重放选择的Session(随后会提示你输入,重放几次)
U

无条件的重放选择的Session(不会发送If-Modified-Since 和 If-None-Match-Headers)

Shift + U

无条件的重放选择的Session(随后会提示你输入,重放几次)
P 选择“当前Session”的“父Session”(这个功能取决于Referer Header)
C 选择“当前Session”的“子Session”
D 选择“重复的Session”(有相同的URL和相同的method)
BackSpace或鼠标上的“Back” 选择“上次选择的Session”
Insert  

Ctrl + 1

Ctrl + 2

Ctrl + 3

Ctrl + 4

Ctrl + 5

Ctrl + 6

用粗体和颜色标记选择的Session
M 给选择的Session添加注释

 

Fiddler插件

Fiddler插件下载地址:www.telerik.com/fiddler/add-ons

比较会话的不同:Windiff

格式化JS代码:JavaScript Formatter

图片缩略图:Gallery

Fiddler的Script用法

Fiddler Script是一个可以自动修改HTTP请求和HTTP响应的脚本文件,使你不用手动地去下“断点”来修改。

Fiddler Script的本质其实是用JScript.NET语言写的一个脚本文件CustomRules.js,其语法类似于C#。

Fiddler Script Editor

或者

CustomRules.js中的主要方法

static function OnBeforeRequest(oSession:Session)

OnBeforeRequest函数在每次请求之前调用。在这个方法中修改Request的内容,我们用的最多

static function OnBeforeResponse(oSession:Session)

OnBeforeResponse函数在每次响应之前调用,在这个方法中修改Response的内容。

static function OnExexAction(sParams:String[])

这个方法中包含Fiddler命令。命令是在Fiddler界面中左下方的QuickExec中执行的。

Fiddler定制菜单

Rules -> User-Agents菜单中好像没有Iphone-4S safari,我们现在可以定制一个。上网查询user-Agents,添加代码:

RulesStringValue(23,"Iphone 4S safari","Mozilla/5.0(iPhone;U;CPU iPhone OS 4_0 like Mac OS X;en-us)AppleWebKit/532.9(KHTML,like Gecko) Version/4.0.5 Mobile/8A293Safari/6531.22.7")

重启Fiddler就行

修改Session在Fiddler的显示样式

把以下脚本放在OnBeforeRequest(oSession:Session)方法下,并且单机“Save script”,这样所有的cnblogs会话都会显示为红色

if (oSession.HostnameIs("www.cnblogs.com")) {
  oSession["ui-color"] = "red"
}

修改HTTP请求

如果要修改HTTP请求,代码应该放在OnBeforeRequest(oSession:Session)方法下面。

我们可以修改HTTP请求中的任何数据,如HOST、Header、Cookie等

修改HTTP请求中的Cookie

if(oSession.uriContains("cnblogs.com")
{
    //1.删除所有的cookie
    oSession.oRequest.headers.Remove("Cookie");
    
    //2.新建cookie
    oSession.oRequest.headers.Add("Cookie","username=testname;testpassword=P@ssword1");

    //修改Cookie,不能删除或者编辑单独的一个Cookie,需要替换Cookie字符串
    var oldCookie = oSession.oRequest["Cookie"];
    oldCookie = oldCookie.Replace("cookieName=","ignoreme=")
    oSession.oRequest["Cookie"] = oldCookie;

    //4.全新的Cookie
    var newCookie = "your cookie String";
    oSession.oRequest["Cookie"] = newCookie;  
}

 

替换HTTP请求的Host地址

我们最初发送给A站点的HTTP请求,都被Fiddler转发到B站点,而在浏览器中毫无感觉。测试或者debug过程中经常会有这种需求。

例如用 www.sina.com 代替 www.baidu.com

if (oSession.HostnameIs("www.sina.com"))
{
    oSession.hostname = "www.baidu.com";
}

修改HTTP请求中的Header

if (oSession.uriContains("cnblogs.com"))
{
    // 添加Header
    oSession.oRequest.headers.Add("headerName1","headerValue1");

    // 删除Header
oSession.oRequest.headers.Remove("headerName2");

    // 修改Header
oSession.oRequest["Referer"] = "www.baidu.com/TestReferer";
}

修改HTTP请求中发的Body

方法一:先把Body的字符串读取出来,修改后再塞回去。

static function OnBeforeRequest(oSession:Session)
{
    if (oSession.uriContains("http://www.cnblogs.com/TankXiao/"))
    {
        oSession.utilDecodeRequest();
        // 获取Request中的body字符串
        var strBody=oSession.GetRequestBodyAsString();
        // 用正则表达式或者 replace 方法修改string
        strBody=strBody.replace("1111","2222");
        // 弹个对话框检查下修改后的body
        FiddlerObject.alert(strBody);
        // 将修改后的body,重新写会Request中
       oSession.utilSeRequestBody(strBody);
    }
}

 第二种方法:也可以采用非常简单地方法,即直接替换body中的数据

if (oSession.uriContains("cnblogs.com"))
{
    oSession.utilReplaceInRequest("1111","2222");
}

修改HTTP响应

在Script中修改HTTP响应的方法,代码应该放在OnBefroeResponse(oSession:Session)方法下面。

修改HTTP响应的方法和修改HTTP请求的方法差不多。

实例:使用如下代码,修改博客园网页中的数据

if (oSession.uriContains("cnblogs.com"))
{
    oSession.utiReplaceInResponse("小坦克","大坦克 肖佳");  
}

打开浏览器,输入 www.cnblogs.com/tankxiao/

读写txt文件

先引用命名空间

import System。IO;
    // Read
    var txtPath = "c:\\tank.txt"
    var allNumbers = File.ReadAllLines(txtPath);
    var exist = 0;
    for(var i = 0; i<allNumbers.length;i++)
    {
        FiddlerObject.alert(allNumbers[i]);
    }

    // write
    var txtPath = "c:\\tank.txt"
    var txtWrite = File.AppendText(textPath);
    txtWriteLine("www.cnblogs.com/tankxiao");
    txtWrite.Close();

使用正则表达式

先引用命名空间

import System.Text.RegularExpressions;

var resBody = "<String>tankxiao.cnblogs.com</string>";
var r = new Regex("<string>(.*?)</string>");
var mc = r.Match(resBody);
FiddlerObject.alert(mc.Groups[1].Value);

保存Session

var sazFile = "c:\\aff\\"+number;
var sessionList : Session[] = [oSession];
Utilities.WriteSessionArchive(sazFile,sessionList,null,true)

读取Session,并且使用Fiddler来发送

var sazFile="c:\\aff\\"+number;
var sessionList : Session[] = Utilities.ReadSessionArchive(sazFile,true);
FiddlerApplication.oProxy.SendRequest(sessionList[0].oRequest.headers,sessionList[0].requestBodyBytes,null);

深入理解Cookie机制

HTTP协议是无状态的

对于浏览器的每一次请求,服务器都会独立处理。不与之前或之后的请求发生关联。即使同一个浏览器发送了3个请求,服务器也会独立处理这3个请求,服务器并不知道这3个请求是来自同一个浏览器。

服务器需要识别浏览器请求,就必须弄清楚浏览器的请求状态。既然HTTP协议是无状态的,那就让服务器和浏览器共同维护一个状态,这就是会话机制。

会话机制

浏览器第一次请求服务器时,服务器创建一个会话,并将会话的id作为响应的一部分发送给浏览器。

浏览器存储会话id,并在后续第二次和第三次请求中带上会话id。服务器取得请求中的会话id就知道是不是同一个用户了。

Cookie机制

服务器在内存中保存会话对象。浏览器可以使用Cookie机制保存会话id。

Cookie机制是一种会话机制。Cookie是浏览器用来存储少量数据的一种机制,数据以“key=value”形式存储,浏览器发送HTTP请求时,自动附带cookie信息。

Cookie是什么

Cookie是一小段文本信息,伴随着用户请求和页面在浏览器和Web服务器之间传递。

Cookie是一种HTTP Header,以“key=value”的形式组成,比如ip_country=CN

两个Cookie之间用分号隔开,比如ip_country=CN;mbox=check#true#1499311989

浏览器把Cookie通过HTTP请求中的Header,比如“Cookie:ip_country=CN”发送给Web服务器。Web服务器通过HTTP响应中的Header,比如“Set-Cookie:ip_country=CN”,把Cookie发送给浏览器。

Cookie的作用

Cookie最主要的作用是用来做用户认证,还可以用于保存用户的一些其他信息。

Cookie也可以用于互联网精确广告定向技术,比如用户浏览了某些商品,就可以用Cookie将其记录下来。

Cookie的属性

从Fiddler的抓包中,我们可以看到Web服务器返回了下面这一段数据给浏览器。

Set-Cookie:cookie_user_token=C5CBD6FBDJO5HGH324OV452;Expires=Thu,06-Jul-2017 09:17:46 GMT;Path=/;HttpOnly

Expires属性:Expires的值是一个时间,代表过期时间。过了这个时间,该Cookie就失效了。如果不指定Expire time,表示关闭浏览器/页面的时候,此Cookie就应该被浏览器删除了。

Path属性:表示Cookie所属的路径,asp.net默认为“/”,就是根目录。在同一个服务器上的目录如下:/test/、/test/cd/、/test/dd/。现假设一个Cookie1的path为/test/,Cookie2的path为/test/cd/,那么test下的所有页面都可以访问到Cookie1,而/test/cd/的子页面不能访问Cookie2。

HttpOnly属性:这是个关于安全方面的属性,将一个Cookie设置为HttpOnly后,通过JavaScript脚本将无法读取到Cookie信息,这能有效地防止黑客用XSS发起攻击。一般来说,跟登陆相关的Cookie必须设置为HttpOnly。

Cookie的分类

会话Cooike:临时地Cookie,它记录了用户访问站点时的设置和偏好;关闭浏览器,会话Cookie就被删除了

持久Cookie:存储在硬盘上,不管浏览器退出或者计算机重启,持久cookie都继续存在,持久Cookie有过期时间。

网站自动登录的原理

在登录页面输入用户名、密码,选择保存密码单机登录(这时候,其实在你的机器上已保存好了登录的Cookie),下次访问的时候。

  1. 用户打开IE浏览器,在地址栏输入www.cnblogs.com
  2. IE首先会在硬盘中查找关于cnblogs.comde Cookie,然后把Cookie放到HTTP Request中,再把Request发给Web服务器。
  3. Web服务器返回博客园首页,这时你会看到自己已经登录了。

Fiddler实现Cookie劫持攻击

通常有两种方法可以截获他人的Cookie

  1. 通过跨站脚本攻击(XSS)获取他人的Cookie。
  2. 想办法获取别人电脑上保存的Cookie文件。

找到登录的Cookie

  首先,我们需要使用 Fiddler 找到跟登录相关的 Cookie,具体的操作步骤如下。

打开豆瓣网 www.douban.com,用账号和密码登录。

启动Fiddler,在豆瓣网中单击右上角的用户名,在菜单栏中单机“账号管理”,就跳转到了这个页面:https://www.douban.com/accounts/。

在Fiddler中选择https://www.douban.com/accounts/这个Session,然后用鼠标右键选择Replay -> Reissue and Edit。在Raw选项卡下,找到一个名叫dbcl2的Cookie,比如我这里的是:dbcl2=“163572032:csUO41kxRDg”;删除这个 dbcl2 的Cookie,然后单机“Run to Completion”放行。

我们可以发现跳转到了登录页面。这说明dbcl2这个Cookie是跟登录相关的,将其删除后就处于未登录状态,Web服务器会返回302状态码,会自动重定向到登录界面。

网站退出的作用

网站退出是明确地告诉服务器立即删除服务器端的Session对象,这样客户端登录的Cookie就失效了。如果用户登录某个网站,然后离开的时候直接关闭浏览器,那么登录的Cookie还在,存在被冒用的风险。保险的办法是单击退出而不是直接关闭浏览器。

HTTP基本认证

  HTTP协议是无状态的,浏览器和Web服务器之间可以通过Cookie来识别身份。一些桌面应用程序(比如新浪桌面客户端)跟Web服务器之间是如何识别身份呢?

  HTTP协议中还有两种认证方式,分别是基本认证摘要认证。认证就是客户端要给服务器出示一些自己的身份证明,来证明自己是谁,一旦服务器知道了客户端的身份,就可以判定客户端可以进行访问了。通常是通过提供用户名和密码来进行认证的。

什么是HTTP基本认证

  一些网站和Web服务使用的是HTTP基本认证。有些桌面应用程序也通过HTTP协议跟Web服务器交互,桌面应用程序一般不会使用Cookie,而是把“用户名+冒号+密码”用Base64编码放在HTTP请求中的 Header Authorization 中发送给服务器,这种方式叫HTTP基本认证(Basic Authentication)

  在基本认证中,Web服务器可以拒绝一个事物,要求客户端提供有效地用户名和密码。服务器会返回401状态码来初始化认证质询,并用WWW-Authenticate响应首部指定要访问的安全域。浏览器收到质询时,会打开一个对话框,请求用户输入用户名和密码,然后将用户名和密码用Base64编码,再用 Authorization 请求首部发送给服务器。

在Fiddler中可以在Inspectors中的Auth选项卡中查看实际用户名和密码。

HTTP基本认证的缺点

把“用户名+冒号+密码”用Base64编码,可逆,所以不能用HTTP在网络上传输,一定要用HTTPS传输,因为HTTPS是加密的,稍微安全一点。

  1. HTTP协议是无状态的,同一个客户端对服务器的每个请求都要求认证。
  2. 基本认证会通过网络发送用户名和密码,这些用户名和密码以Base64编码。Base64编码是一种可逆编码,容易被第三方拦截。
  3. 使用基本认证登录后,除非关闭浏览器或者清楚历史记录,否则将无法登出。
  4. 无法防止重放攻击。即使基本认证的密码是经过加密传输的,第三方仍然可以捕获被修改过的用户名和密码,并将修改过的用户名和密码反复多次地重放给原始服务器,以获得对服务器的访问权,基本认证没有什么措施可以防止这些重放攻击。

摘要认证

摘要认证是针对基本认证存在的诸多问题而进行改良的方案。摘要认证是另外一种HTTP认证协议,它试图修复基本认证的严重缺陷,进行如下改进。

  1. 通过传递用户名、密码等计算出来的摘要来解决以明文方式在网络上发送密码的问题。
  2. 通过服务器产生随机数 nonce 的方式防止恶意用户捕获并重放认证的握手过程。
  3. 通过客户端产生随机数 cnonce 的方式支持客户端对服务器的认证。
  4. 通过对内容也加入摘要计算的方式,可以有选择地防止对报文内容的篡改。

Fiddler发送HTTP请求

Fiddler可以使用重放功能或者Fiddler Composer来发送HTTP请求。

Fiddler Composer发送HTTP请求

Fiddler有个功能组件叫Composer,可以用来发送HTTP请求。Fiddler的作者把HTTP Request发送器取名为Composer,中文意思是乐曲的创造者,很有诗意。

Composer发送Get请求

Composer的编辑模式

Composer有两种编辑模式

  1. Parsed模式。这个模式比较常用,把HTTP请求分为3个部分:请求起始行,请求Header和请求Body。通过该模式,创建一个HTTP请求变得很容易。
  2. Raw模式。该模式需要一行一行地写一个HTTP请求。

Composer发送Post请求

禅道的演示网站 http://demo.zendao.net,用户名是demo,密码是123456。手动登录抓包如下:

用Fiddler发送一个登录的Post请求

Composer编辑之前捕获的HTTP请求

  在Web会话列表中,可以将捕获到的HTTP请求拖拽到Composer中,编辑后再发送出去。

Fiddler重新发送HTTP请求

  Fiddler可以将捕获的HTTP请求重新发送出去。Fiddler工具栏上有一个Replay按钮,单击该按钮可以向Web服务器重新发送选中的HTTP请求。当选中多个Session,并且按下Replay按钮后,Fiddler会用多线程同时发送请求。此功能可以用来做并发性能测试。

Replay菜单

  按下Shift键的同时单击该按钮,会弹出提示框,要求指定每个请求被重新发送的次数。

  按下Ctrl键的同时单击该按钮,在HTTP请求中不会包含IF-Modified-Since和If-None-Match。

  在会话列表中,选中一个或者多个Session,右键菜单我们可以看到一个Replay菜单。

Reissue Requests 重新发送请求,和菜单栏上Replay按钮是一样的功能
Reissue Unconditionally 无条件反复发送选中的请求
Reissue and Edit 把选中的请求以原来的形式重新发送,在每个新的Session中设置断点,在请求发送给服务器之前,可以修改请求
Reissue and Verify 重新发送请求,检查响应,如果响应和上一个请求一样,就会变成绿色
Reissue Sequentially 选中多个Session会按顺序一个一个重新发送请求,是单线程模式
Reissue from Composer 在Composer中编辑该请求 
Revisit in IE 在IE浏览器中用Get方法访问这个请求 

 

简单地性能测试

  在Web Sessions列表中,选中一个或者多个Session,然后按下Shift键的同时单击“Replay”按钮,会弹出提示框,要求指定每个请求被重新发送的次数。Fiddler会用多线程同时发送该请求,相当于模拟了很多用户同时访问该请求。

先编辑再发送

  在Web Sessions列表中,选中一个Session,单击鼠标右键选择Replay - Reissue and Edit。该功能可以把一个HTTP请求重新发送出去,并且拦截住,将其进行编辑,然后再发出去。

安全测试之重放攻击

  重放攻击(Replay Attacks)又称重播攻击、回放攻击。

  攻击者发送一个目的主机已接收过的包,特别是在认证的过程中,用于认证用户身份所接收的包,来达到欺骗系统的目的。该包主要用于身份认证过程,破坏认证的安全性。

重放攻击是怎么发生的

  重放攻击是指黑客通过抓包的方式,得到客户端的请求数据及请求连接,重复地向服务器发送请求的行为。

重放攻击的危害

  比如APP中有一个“下单”的操作,当你单击购买按钮时,APP向服务器发送购买的请求。而这时黑客对你的请求进行了抓包,得到了你的传输数据,黑客把数据再往服务器提交一次。这就导致了你可能只想购买一个产品,结果由于黑客重放攻击,你就购买了多次。

  很多网站的投票或者点赞功能也要防止重放。黑客会对投票或者点赞进行抓包,然后重复发送来进行刷票。

重放攻击的解决方案

  在HTTP请求中添加时间戳(stamp)数字签名(sign),可以防止重放攻击。

  数字签名是为了确保请求的有效性。因为签名是经过加密的,只有客户端和服务器知道加密方式及Key,第三方模拟不了。

  时间戳是为了确保请求的时效性。我们将上一次请求的时间戳进行存储。

Fiddler实现弱网测试

  网速慢和网络中断的情况,我们称之为弱网。

  使用Fiddler能让弱网测试变得非常简单,Fiddler是通过延迟发送或接收数据的时间来模拟限速的。

什么是弱网

  验证在弱网的情况下软件的处理机制,从而避免因用户体验不友好造成用户的流失。弱网测试属于健壮性测试。在弱网测试条件下,要测试产品的运行状态、处理机制、提示信息,以及网络恢复后的重连等。

弱网环境带来的问题

  1、操作时间慢。用户在地铁里操作手机APP,由于网络慢,页面加载不出来。原因可能是API在网络慢的情况下性能很差。用户在公交车上用手机APP看新闻,当公交车进入隧道的时候,网络变得很慢,APP上的新闻一直没法加载出来。我们需要测试每个API消耗的时间,这个指标可以衡量APP性能的好坏。

  2、用户体验不好。一个安卓手机用户使用一款看小说的APP在地铁里看小说,当地铁进入隧道的时候,手机信号中断了。用户单击翻页,想看下一页的时候,因为网络中断,APP的界面卡死并且闪退。原因是APP不稳定,没有处理好网络中断的情况。

  3、非正常情况下,出现Bug的可能性会增加。如一个电商的手机APP有秒杀优惠券的功能。一些APP用户在乘坐电梯的时候,使用APP来秒杀优惠券。单击秒杀优惠券的按钮后,APP响应缓慢。于是,用户重复单击秒杀优惠券按钮。这就造成了几乎同一时间,同一个用户有多个HTTP请求发送服务器,形成了并发,结果用户抢到了多张优惠券。

弱网测试的目的

  弱网测试的目的是让APP在任何网络下都能表现自如,让开发人员能够预知APP在较差网络环境下的表现,提前发现问题,进行有针对性的优化

弱网的场景

  1、网络慢或者延迟,导致加载时间长。

  2、网络中断,Web服务器返回500等状态码。

  3、网络超时,HTTP请求发出去后,很久都没有响应。

Fiddler模拟网络延迟

  1、启动Fiddler,选择Rules - Performances - Simulate Modem Speeds

  2、打开浏览器,访问网站。

精确控制网速

可参考:https://www.jianshu.com/p/b9e349b8f411

 

  1、启动Fiddler,选择Rules - Performances - Simulate Modem Speeds

  2、在FiddlerScript中找到如下一段代码

        if (m_SimulateModem) {
            // Delay sends by 300ms per KB uploaded.  每上传1KB数据,延时0.3秒
            oSession["request-trickle-delay"] = "300"; 
            // Delay receives by 150ms per KB downloaded.  每下载1KB数据,延时0.15秒
            oSession["response-trickle-delay"] = "150"; 
        }

  改动数值,保存Script即可。

  3、保存完之后,原本已经勾选的Simulate Modem Speeds会被取消勾选:再次选中 Rules - Performances - Simulate Modem Speeds

  4、再次打开浏览器,访问网页

如果你习惯用kbps 去算的话,那么我们的算法就是 1KB/下载速度 = 需要delay的时间(毫秒),比如50KBps 需要delay20毫秒来接收数据。

request-trickle-delay中的值代表每KB的数据被上传时会被延时多少毫秒;response-trickle-delay则对应下载时每KB的数据会被延时多少毫秒。
比如你要模拟上传速度100KBps的网络,那上传延迟就是1KB/100KBps=0.01s=10ms,就改成10。

比如默认设置下上传延时为300ms下载延时为150ms,可以推算出大致的模拟带宽为:
上传带宽 = 1KB/300ms = (1 * 8/1000) /0.300 ≈ 0.027Mbps
下载带宽 = 1KB/150ms = (1 * 8/1000) /0.150 ≈ 0.053Mbps
(1MB = 1024 KB ≈ 1000 KB 这里为了运算简便就用了1000的倍数,忽略误差)

 

方法二,下面的脚本实现了一个随机延时量设置,使得网络带宽不是恒定为一个低速的值,而是会在一定范围内随机抖动:

if (m_SimulateModem) {
    // Delay sends by 300ms per KB uploaded.
    oSession["request-trickle-delay"] = ""+randInt(1,50);
    // Delay receives by 150ms per KB downloaded.
    oSession["response-trickle-delay"] = ""+randInt(1,50);
}

方法三:

点击fiddlerScript 在代码里找到onBeforeRequest,这里定义了在发送请求前做什么。加入如下代码可以实现延迟:

oSession["request-trickle-delay"]="3000";  //请求阶段延迟3秒
oSession["response-trickle-delay"]="3000";  //响应阶段延迟3秒

Fiddler模拟网络中断

  用Fiddler可以下断点,伪造HTTP响应。移动端发出的HTTP请求根本没有到达服务器,而是被Fiddler直接返回了一个伪造的HTTP响应。

  具体做法是用Fiddler拦截住移动端发出来的HTTP请求,然后在“Choose Response”选中需要返回的状态码并返回给移动客户端。

或者可以在桌面新建一个txt文档:

HTTP/1.1 500 Internal Server Error
Date: Fri, 11 Aug 2019 07:25:35 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Vary: Accept-Encoding

this is 500 internal Server Error by Fiddler! tank

Fiddler模拟网络超时

  利用Fiddler下断点的功能拦截移动客户端发出的HTTP请求,这样就相当于网络超时了,然后再检查客户端有没有重发或者超时的机制。

 

posted @ 2019-05-06 13:56  dongye95  阅读(5925)  评论(0编辑  收藏  举报