WebScarab关键源码分析(3)

OWASP的WebScarab简介 WebScarab是由开放式Web应用安全项目(OWASP)组开发。OWASP是免费的,它为建立安全的Web应用提供了指导和建议。   WebScarab是一个用来分析使用HTTP和HTTPS协议的应用程序框架。WebScarab可以记录它检测到的会话内容(请求和应答),并允许使用者可以通过多种形式来查看记录。可以用它来调试程序中较难处理的bug,也可以帮助安全专家发现潜在的程序漏洞。 1 阅读详情

今天读的比较多,就多写点吧。

一个Http代理要实现的功能不外乎就四句话,保存客户端发过来的http请求,将请求发给服务器端,搜集返回结果,并发给客户端,如果用webscarab的数据结构来描述这个过程的话也就:

 

客户socket的输入流----->> request对象 ------->>>response对象------->>>客户socket输出流

如果把这三个箭头当做3个过程,过程1个过程3在前面的博文中已经详细说明(不外乎就是request的read方法和response的write方法,等等,不应该是过程0和过程2吗?好吧我编程中毒了已经),而第二个过程(你要非要说第一个也行)就是一开始说的URLFetcher的功能。

URLFetcher实现HttpClient接口,该接口就一个方法:

Response fetchResponse(Request request)

也就是把request转换成response。

下面我们仔细研究URLFetcher这个类。

研究一个类最本质的是回答以下三个问题:

1、这个类是做什么的?他代表一种什么样的实体?代表一种什么样的逻辑?具有着一种什么样的能力?提供一种什么样的服务?当然这几句话 本质上都是一样的。

2、我们要如何做才能正确的使用这个类?如何实例化?如何传入数据?调用的方法是否有顺序要求?

3、它是怎么实现它的功能的。

第一个第二问题从黑盒的角度出发,第三个问题从白盒的角度出发。下面就回答这3个问题。

1、URLFetcher代表一种能力,一种根据Resquest对象获得Response对象的能力。

2、直接调用fetchResponse方法即可,但可以有选择性的去设置代理服务器地址、连接超时时间等。

3、fetchResponse方法代码较长,将一段一段的进行描述。

首先,是一些检查初始化以及检查运行中用到的各变量合法性的代码,以及一些Http协议相关验证头部分的代码,我不是很懂http的Authentication头一些知识,所以这些代码我很遗憾的不能给出确切的说明。

 if (_response != null) {
            _response.flushContentStream(); // flush the content stream, just in case it wasn't read
            _response = null;
        }
        if (request == null) {
            _logger.severe("Asked to fetch a null request");
            return null;
        }
        HttpUrl url = request.getURL();
        if (url == null) {
            _logger.severe("Asked to fetch a request with a null URL");
            return null;
        }
        
        // if the previous auth method was not "Basic", force a new connection
        if (_authCreds != null && !_authCreds.startsWith("Basic"))
            _lastRequestTime = 0;
        if (_proxyAuthCreds != null && !_proxyAuthCreds.startsWith("Basic")) 
            _lastRequestTime = 0;
        
        // Get any provided credentials from the request
        _authCreds = request.getHeader("Authorization");
        
        String keyFingerprint = request.getHeader("X-SSLClientCertificate");
        request.deleteHeader("X-SSLClientCertificate");
        if (keyFingerprint == null && _keyFingerprint == null) {
            // no problem
        } else if (keyFingerprint != null && _keyFingerprint != null && keyFingerprint.equals(_keyFingerprint)) {
            // no problem
        } else {
            // force a new connection, and change the fingerprint
            _keyFingerprint = keyFingerprint;
            _lastRequestTime = 0;
        }
        
        String status;
        
        String oldProxyAuthHeader = null;
        if (_proxyAuthCreds == null && _authenticator!= null && useProxy(url))
            _proxyAuthCreds = _authenticator.getProxyCredentials(url.toString().startsWith("https") ? _httpsProxy : _httpProxy, null);
        String proxyAuthHeader = constructAuthenticationHeader(null, _proxyAuthCreds);
        
        String oldAuthHeader = null;
        if (_authCreds == null && _authenticator!= null)
            _authCreds = _authenticator.getCredentials(url, null);
        String authHeader = constructAuthenticationHeader(null, _authCreds);


其次是一个很长的do----while循环

int tries = 0;
        do {
            // make sure that we have a "clean" request each time through
            request.deleteHeader("Authorization");
            request.deleteHeader("Proxy-Authorization");
            ......
            tries ++;
        } while (tries < 3 && ((status.equals("401") && authHeader != null) || (status.equals("407") && proxyAuthHeader != null)));
       


中间省略号省略了很多代码。可以看到当且仅当尝试次数小于3并且响应码为401或407且有相应验证头的话才会重新进入循环,否则循环体只执行一次。

其次是一段发送请求的代码:

  // make sure that we have a "clean" request each time through
            request.deleteHeader("Authorization");
            request.deleteHeader("Proxy-Authorization");
            
            _response = null;
            connect(url);
            if (_response != null) { // there was an error opening the socket
                return _response;
            }
            
            if (authHeader != null) {
                request.setHeader("Authorization", authHeader);
                if (authHeader.startsWith("NTLM") || authHeader.startsWith("Negotiate")) {
                    if (request.getVersion().equals("HTTP/1.0")) {
                        // we have to explicitly tell the server to keep the connection alive for 1.0
                        request.setHeader("Connection", "Keep-Alive");
                    } else {
                        request.deleteHeader("Connection");
                    }
                }
            }
            // depending on whether we are connected directly to the server, or via a proxy
            if (_direct) {
                request.writeDirect(_out);
            } else {
                if (proxyAuthHeader != null) {
                    request.setHeader("Proxy-Authorization", proxyAuthHeader);
                    if (proxyAuthHeader.startsWith("NTLM") || proxyAuthHeader.startsWith("Negotiate")) {
                        if (request.getVersion().equals("HTTP/1.0")) {
                            // we have to explicitly tell the server to keep the connection alive for 1.0
                            request.setHeader("Connection", "Keep-Alive");
                        } else {
                            request.deleteHeader("Connection");
                        }
                    }
                }
                request.write(_out);
            }
            _out.flush();
            _logger.finest("Request : \n" + request.toString());

首先清除各种认证头(不用怕丢失信息,相关认证信息已在函数开头那段代码中保存起来了),然后设置返回的结果为空,接着尝试进行socket链接到目的url,url是哪来的呢?从request里面提取出来的。

如果连接成功后,该类的成员变量_in和_out会设置成该socket的输入流和输出流。

连接上之后再判断一下response对象是否为空,如果不为空则表示该方法被重入了,再其它线程或许调用了这个方法,为了防止重入出错,则函数直接返回。

之后根据_direct变量判断是否将http请求发送到代理服务器,这个变量的值是通过比较url和当前对象代理设置来决定的,代码不再赘述。

如果直接发送到http服务器,则直接写到socket的输出流,否则加上proxy的认证头(如果有的话)再发送到输出流。

至此发送过程结束。

接下来是接收过程。

do {
                _response.read(_in);
                status = _response.getStatus();
            } while (status.equals("100"));
            
            {
                StringBuffer buff = new StringBuffer();
                buff.append(_response.getStatusLine()).append("\n");
                NamedValue[] headers = _response.getHeaders();
                if (headers != null)
                    for (int i=0; i< headers.length; i++)
                        buff.append(headers[i].getName()).append(": ").append(headers[i].getValue()).append("\n");
                _logger.finest("Response:\n" + buff.toString());
            }
            
            if (status.equals("407")) {
                _response.flushContentStream();
                oldProxyAuthHeader = proxyAuthHeader;
                String[] challenges = _response.getHeaders("Proxy-Authenticate");
                if (_proxyAuthCreds == null && _authenticator != null) {
                    _proxyAuthCreds = _authenticator.getProxyCredentials(_httpProxy, challenges);
                }
                proxyAuthHeader = constructAuthenticationHeader(challenges, _proxyAuthCreds);
                if (proxyAuthHeader != null && oldProxyAuthHeader != null && oldProxyAuthHeader.equals(proxyAuthHeader)) {
                    _logger.info("No possible authentication");
                    proxyAuthHeader = null;
                }
            }
            
            if (status.equals("401")) {
                _response.flushContentStream();
                oldAuthHeader = authHeader;
                String[] challenges = _response.getHeaders("WWW-Authenticate");
                if (_authCreds == null && _authenticator != null)
                    _authCreds = _authenticator.getCredentials(url, challenges);
                _logger.finer("Auth creds are " + _authCreds);
                authHeader = constructAuthenticationHeader(challenges, _authCreds);
                _logger.finer("Auth header is " + authHeader);
                if (authHeader != null && oldAuthHeader != null && oldAuthHeader.equals(authHeader)) {
                    _logger.info("No possible authentication");
                    authHeader = null;
                }
            }
            
            // if the request method is HEAD, we get no contents, EVEN though there
            // may be a Content-Length header.
            if (request.getMethod().equals("HEAD")) _response.setNoBody();
            
            _logger.info(request.getURL() +" : " + _response.getStatusLine());
            
            String connection = _response.getHeader("Proxy-Connection");
            if (connection != null && "close".equalsIgnoreCase(connection)) {
                _in = null;
                _out = null;
                // do NOT close the socket itself, since the message body has not yet been read!
            } else {
                connection = _response.getHeader("Connection");
                String version = request.getVersion();
                if (version.equals("HTTP/1.0") && "Keep-alive".equalsIgnoreCase(connection)) {
                    _lastRequestTime = System.currentTimeMillis();
                } else if (version.equals("HTTP/1.1") && (connection == null || !connection.equalsIgnoreCase("Close"))) {
                    _lastRequestTime = System.currentTimeMillis();
                } else {
                    _logger.info("Closing connection!");
                    _in = null;
                    _out = null;
                    // do NOT close the socket itself, since the message body has not yet been read!
                }
            }


首先是一个do-while循环,尝试从输入流里得到服务器返回的信息,并独到response对象中。值得注意的是,如果返回码是100(100代表continue,感觉实际用的不多),则继续读,否则这个循环体只执行一次。

其次新建一个buffer,将第一行状态行(就是http 200 ok)之类的,以及剩下的http响应头读到buffer里,随后输出。这个StringBuffer并没有在之后使用,或许只是起到输出log的作用????

值得注意的是此时的response的状态,根据第一篇日志里所说,read只读取头,并没有读取实际内容的状态,所以此时输入流_in的位置是指向内容位第一个字节,换句话说真正的内容还在操作系统协议栈里,并没有flush出来。


 

 (待续)

 

 

web安全测试---WebScarab工具介绍(中间攻击,可以修改请求参数) 1.1Webscarab 【功能】 WebScarab是一个用来分析使用HTTP和HTTPS协议的应用程序框架。其原理很简单,WebScarab可以记录它检测到的会话内容(请求和应答),并允许使用者可以通过多种形式来查看记录。WebScarab的设计目的是让使用者可以掌握某种基于HTTP(S)程序的运作过程;可以用它来调试程序中较难处理的bug,也可以帮助安全专家发现潜在的程序漏洞... 阅读详情

相关推荐

webScarab 源码

WebScarab的HTTP代理提供了预期的功能(包括HTTPS拦截,不过和PAROS一样有认证报警)。WebScarab也提供了一些花哨的功能,比如SSL客户认证支持,十六进制或URL编码参数的解码,内置的会话ID分析和一键式“完成该会话”以增加效率等。就基本功能而言,WebScarab和PAROS差不多,但WebScarab为更懂技术的用户提供了更多的功能,并提供了对隐藏的底层更多的访问。但是,由于PAROS更简单,我们仍推荐学者在开始时使用它。

Webscarab关键源码分析(1)

最近写一个android上的东西,要用到http代理的一些东西,包括封装解析各种http request和response以及多连接并发管理各种麻烦的东西。虽然自己也能写,但感觉是在重复的发明轮子,不如拿一些现成的东西来用,而且更快更成熟。所以选择了Webscareb,打算把里面的http协议栈相关的东西裁减出来供自己使用,这就避免不了源码的阅读。 但在网上搜了搜发现没有什么和这方面有关的资料,

锐之锋芒 1403

webScarab源码

webScarab工具及源码 一款代理软件或许没有其它的工具能和OWASP的WebScarab如此丰富的功能相媲美了,如果非要列举一些有用的模块的话,那么他们包括HTTP代理,网络爬行、网络蜘蛛,会话ID分析,自动脚本接口,模糊测试工具,对所有流行的WEB格式的编码/解码,WEB服务描述语言和SOAP解析器等。WebScarab基于General Public License(GNU)版本协议。和Paros 一样是用JAVA编写的,因此安装它需要JRE.

Arxml文件可视化:当汽车软件架构遇见交互式设计工具

本文探讨了Arxml文件在汽车电子系统开发中的可视化技术,结合AUTOSAR架构标准,介绍了如何利用现代Web技术构建交互式设计工具。通过三维组件关系图、动态数据流展示和版本对比等功能,显著提升开发效率和架构评审质量,适用于MBD和ASPICE开发流程。

weixin_29050271的博客 428

计算机网络(国家电网)

1.局域网中NOS(网络操作系统)提供的通信服务有工作站与工作站之间的对等通信,工作站与服务器之间的通信2.ISP:Internet服务商应用层 APDU(应用层协议数据单元)表示层 PPDU(表示层协议数据单元)会话层 SPDU(会话层协议数据单元)传输层 segment(报文段)网络层 packet (数据包)数据链路层 frame(数据帧)物理层 bit (比特)4.

qq_31715647的博客 3185

WebScarab入门指南

WebScarab具有大量的功能,因而可能会让新用户有一种无从下手之感。为求简单起见,拦截和修改浏览器和HTTP/S服务器的请求和响应可以作为初学者很好的入门课,因为这无需学习太多的内容就可以完成。首先,我们假定您能够自由访问因特网,也就是说,您并非位于一个代理之后。为简单起见,我们还假定您使用的浏览器是Internet Explorer。 图7上面是WebScarab启动后的截图,其中有几个主要的区域需要介绍一下。首先要介绍的是工具栏,从这里可以访问各个插件,摘要窗口(主视图)和消息窗口。摘要窗口分成两个

clangke的专栏 4562

避坑指南:Unity新版InputSystem在移动端的5个常见问题及解决方案

本文针对Unity新版InputSystem在移动端开发中的常见问题,提供了5个关键解决方案,包括虚拟摇杆灵敏度调节、多点触控冲突处理、按钮反馈延迟优化、手势识别与陀螺仪数据融合以及Android/iOS平台差异处理。这些实战经验帮助开发者高效解决触控适配难题,提升移动游戏体验。

soda5的博客 405

WebScarab关键源码分析(3)(续)

接上篇。 接下来是两个if,如果接收到的是401或者407返回码(其含义分别为需验证和代理服务器需验证),则重新调整验证信息,并在下一个while里继续请求内容。 再一个是判断如果request使用的是head方法,则setNobody(),因为head方法是不可能有内容部分的,调用setnobody后未读取的输入流_in将不会再尝试读取。 接着判断connect域的内容,如果是不是keep

锐之锋芒 832

[零基础]用docker搭建Hadoop集群

[零基础]用docker搭建Hadoop集群,每一步都有详细的解释!

weixin_56114243的博客 2万+

【免费】最新区块链钱包和私钥的助记词碰撞器,bybit使用python开发

【免费】最新助记词钱包碰撞器,全链全网络,一周左右就有,稳定高效。

weixin_48529185的博客 1万+

WebScarab关键源码分析(4)

在上一篇博文里我们分析了URLFetcher的一些行为以及相关方法,顺着这个思路走,接着我们遇到的问题是: 谁使用了URLFetcher?它是如何使用URLFetcher的? 这就又牵扯到了两个关键的类:HTTPClientFactory和FetchQueue。 首先从HTTPClientFactory说起,从名字我们也可以大概看出,这是一个工厂模式,这个工厂可以产生HTTPClient对象

锐之锋芒 1269

【2026年华为暑期实习(AI)-4月8日-第一题- 选择题】(题目+思路+Java&C++&Python解析+在线测试)

答案与解析 1. 相关系数问题 答案:C. 完全负线性相关 解析:相关系数ρ=-1表示X和Y之间存在完全负线性相关关系,所有数据点都严格落在一条斜率为负的直线上。 2. 矩阵秩问题 答案:B. Σ的对角线上非零奇异值的个数 解析:矩阵A的秩等于其奇异值矩阵Σ中非零奇异值的个数,因为U和V都是正交矩阵,不改变矩阵的秩。 3. 条件概率问题 答案:B. 0.5 解析:根据全概率公式和贝叶斯公式计算,P(B)=0.5×0.4+0.3×0.6=0.38,P(A|B)=(0.5×0.4)/0.38≈0.526,最接近

m0_73659489的博客 287

WebScarab关键源码分析(5)

接上篇分析FetcherQueue,这个大概是最麻烦的方法了,通过这个方法实现线程池进而实现异步操作,并将resquest和httpclient对象结合起来,同时还维护请求队列,并负责调用上层传下来的ConversationHandler方法。 首先从构造函数说起: public FetcherQueue(String name, ConversationHandler handler

锐之锋芒 1119

【Python爬虫教程】第3篇-解决使用reqeusts遇到的ProxyError异常

Python request代理错误提示“HTTPSConnectionPool, Cannot connect to proxy, no such file or directory”

分享技术,记录思考和感悟 1508

[nlp] 自然语言理解基准 ATIS Snips

ATIS 4k 21 Intents(not include UNK) 120 SlotsSNIPS 13k 7 Intents(not include UNK) 72 SlotsATIS Benchmark (Intent Detection) | Papers With CodeSNIPS Benchmark (Intent Detection) | Papers With Code

心宝的博客 748

Webscarab关键源码分析(2)

接上篇说Request对象和Response对象 Request代表一个请求,首先给出一个http请求头: GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1 Host: net.tutsplus.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US;

锐之锋芒 1071

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

WebScarab产生OutOfMemory问题的解决办法

使用WebScarab做代理,截取HTTP数据包,IE代理设置“工具”—》“Internet选项”—》“连接”—》“局域网设置”—》“代理服务器”,选中“为LAN使用代理连接服务器”,其他选项一概不选中,代理地址为“127.0.0.1 ”,端口号为“8008 ”。 启动WebScarab程序,使用IE访问网页时,WebScarab报错,提示为:Expection in ...

weixin_33858336的博客 263

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Web安全测试-WebScarab工具

1.1 Webscarab1.1.1 工具安装1.1.2 功能原理1.1.3 工具使用1.1.34 使用心得 转载自web安全测试—WebScarab工具介绍(中间攻击,可以修改请求参数) 1.1 Webscarab 【功能】 WebScarab是一个用来分析使用HTTP和HTTPS协议的应用程序框架。其原理很简单,WebScarab可以记录它检测到的会话内容(请求和应答),并允许使用者可以通过多种形式来查看记录。WebScarab.

风间琉璃zero 4089

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

certificate unknown(46) - 中间证书问题排查

因为腾讯云的网站备案迟迟没有批下来,因此使用了朋友在阿里云的域名yk,我则申请了一台阿里云服务器,并将域名解析映射至该服务器。SSL证书则是在腾讯云上申请的,使用了Apache文件夹中的文件,放置在cowboy的priv/ssl目录下,1_root_bundle为根证书,2_yk.crt为网站证书,3_yk.key为密钥。一切布置妥当后,在PC的chrome、android的chrome、...

weixin_34303897的博客 5839

谷歌浏览器偶发“失败 - 证书有误”报错,SSL层 Certificate Unknown (46)错误

问题描述: 谷歌浏览器 <a>标签下载静态文件 偶发出现 失败 - 证书有误情况。SSL层Certificate Unknown (46)错误。 环境: https协议,nginx/1.15.12,谷歌浏览器版本73.0.3683.86 火狐验证,没有这个问题。 解决过程: 出现报错后,点击谷歌浏览器报错详情。跳转下面url。 https://support.goog...

万事屋 1万+

Web安全测试-WebScarab工具介绍

 1.1  Webscarab 【功能】 WebScarab是一个用来分析使用HTTP和HTTPS协议的应用程序框架。其原理很简单,WebScarab可以记录它检测到的会话内容(请求和应答),并允许使用者可以通过多种形式来查看记录。WebScarab的设计目的是让使用者可以掌握某种基于HTTP(S)程序的运作过程;可以用它来调试程序中较难处理的bug,也可以帮助安全专家发现潜在的程序漏洞。...

iteye_5347的博客 1150

java 证书错误_java – SSL证书错误:certificate_unknown

我想创建推送通知服务器,并在服务器中安装SSL证书和.p12文件时,我们面临以下错误:我想知道ssl证书有什么问题,因为我收到certificate_unknown错误.main, RECV TLSv1 ALERT: fatal, certificate_unknownmain, called closeSocket()main, handling exception: javax.net.ss...

weixin_28771631的博客 5173
上一篇: Webscarab关键源码分析(2)
下一篇: WebScarab关键源码分析(3)(续)
ROger__Wong
博客等级 码龄14年 250粉丝 78原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值