Chrome 外掛程式
#Chrome 外掛程式是向 Chrome 瀏覽器新增或修改功能的瀏覽器拓展程式。一般透過 JavaScript, HTML 以及 CSS 就可以寫 Chrome 插件了。市面上有許多非常優秀的 Chrome 插件擁有非常多的用戶。 Chrome 插件的編寫也比較簡單,基本上你熟悉一點前端知識,然後熟悉 Chrome 插件的 API,你就可以寫 Chrome 插件。
Chrome 外掛程式的安裝,如果你沒有發佈在 Chrome 商店的話(因為網路原因,可能沒辦法直接從商店下載),可以透過開發者模式安裝 Chrome 外掛程式。或者你也可以註冊 Chrome 外掛程式的開發者帳號(只要 5 美元,就可以發佈 20 個外掛程式)。
簡單介紹了一下 Chrome 插件的開發,咱們主要還是聊一下關於 Chrome 插件關於被動掃描器的方面的內容。對於 Chrome 插件,主要是透過插件的能力去獲取經過瀏覽器的流量,並將流量轉送給後端來處理。
Chrome 外掛程式關於網路流量的處理地 API 主要有兩個:chrome.devtools.network 以及 chrome.webRequest。但是前者使用的時候需要打開 Chrome 開發者工具,這個有點不太方面,所以選擇了後者,這也是對於被動流量獲取常見的方式。
Chrome 外掛程式中的 webrequest API 是以對應的事件驅動的,其中請求的生命週期圖如下,主要有7個事件。只需要監聽關鍵事件進行處理就可以滿足被動掃描器取得流量的需求了。
其實這些事件不難理解,基本上透過事件的名稱就可以知道事件的意義了,主要就是請求發送前,發送請求頭之前,發送請求頭等等事件。對於不同的事件,可以獲得的流量資料也是不盡相同的。
首先,考慮一下,對於被動掃描器來說,哪些流量資料是比較關心的。被動掃描器主要是透過收集業務的正常流量來進行測試,提高測試的效率,並能取得比主動掃描器更好的效果。那麼一般來說,被動掃描器最關心的就是請求的 URL 以及請求頭了,如果是 POST 請求,還需要請求體。對於掃描器來說,回應頭和回應體則沒那麼重要,其實可以透過回應狀態過濾一下,一般只需要能夠正常回應的請求頭以及請求體即可。
對於被動掃描器上述的需求,chrome.webrequest 中的 onBeforeRequest 以及 onSendHeaders 這兩個事件可以滿足需求。透過前者,可以取得請求體。透過後者則可以獲得請求頭。不過在使用onSendHeaders 的時候,有好幾點要注意:
相容問題
##從Chrome 79 開始,必須在opt_extraInfoSpec 中指定extraHeaders 才可以取得Origin 請求頭。從Chrome 72 開始,必須在opt_extraInfoSpec 中指定extraHeaders 才可以取得以下請求頭:Accept-Language
#Accept-Encoding
#Referer
Cookie
const headers = version >= 72 ? ["requestHeaders", "extraHeaders"] : ["requestHeaders"]; chrome.webRequest.onSendHeaders.addListener( beforeSendHeaderHandler, requestFilters, headers )
requestBody 的格式問題
可以透過 onBeforeRequest 事件來取得 POST 請求中的請求體。但有一點注意,chrome.webrequest 中把請求體進行了解析,所以你取得的不是原生的請求體。請求體位於requestBody 中的fromData,而formData 其實是有兩種形式,一種是鍵值對形式的字典,這種一般對於請求體類型為 multipart/form-data 或 application/x-www-form-urlencoded而言,一般即為 a=xxx&b=xxx&c=xxx 這種形式;另外一種則是原生的字節,這個官方的API 文件沒有直接提到,你需要自己手動解析資料。const postbody = decodeURIComponent(String.fromCharCode.apply(null, new Uint8Array(details.requestBody.raw[0].bytes)));
使用 RequestFilter 去過濾請求
如果你希望在事件中可以过滤特定的请求地址或者请求的资源类型,那么就可能需要使用到 RequestFilter 了。RequestFilter 里面有4个属性,比较重要的属性就是 urls 以及 types,通过这两个属性就可以过滤特定的请求 URL 以及资源类型。
但是注意一点是,RequestFilter 是在注册事件的时候配置的参数的,不可以后续直接修改。不过有一种方法是先移除监听事件,再添加新的事件。
if (!chrome.webRequest.onSendHeaders.hasListener(beforeSendHeaderHandler)) { chrome.webRequest.onSendHeaders.addListener( beforeSendHeaderHandler, requestFilters, headers ) }
Burp 插件篇
Burp 是渗透测试中不可缺少的工具之一,而 Burp 插件也让测试者如虎添翼,达到事半功倍的效果。同时,开发 Burp 插件也是为了弥补一些系统无法在 Chrome 中使用的场景来进一步地补充。
Burp 插件开发的资料网上不是特别的丰富,之前也写过一篇文章“如何写一个 Burp 插件”。其实开发 Burp 插件比较简单,只要遵守基本的规范,然后学习一下 API 的使用,基本就可以完成 Burp 插件的开发了。反倒是如果希望在 Burp 插件中开发 GUI 有点困难,因为使用 J**A 来写 GUI 比较麻烦,毕竟不能像 C# 那样,妥妥拽拽就搞定了,不过这也不是本文的重点。
其实在 Burp 中的 Extender 标签页中的 APIs 就可以看到提供的 API 接口。基本上每个函数都有参数说明的注释,不过其实学习 Burp 插件的最好的方法就是拿一个现成的插件代码看一下,就可以很好地理解这些 API 的作用了。
public interface IHttpListener{ /** * This method is invoked when an HTTP request is about to be issued, and * when an HTTP response has been received. * * @param toolFlag A flag indicating the Burp tool that issued the request. * Burp tool flags are defined in the * <code>IBurpExtenderCallbacks</code> interface. * @param messageIsRequest Flags whether the method is being invoked for a * request or response. * @param messageInfo Details of the request / response to be processed. * Extensions can call the setter methods on this object to update the * current message and so modify Burp's behavior. */ void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo); }
在这,以我开发的 Burp 插件 r-forwarder-burp 为例,使用 J**A 开发。在开发 Burp 插件需要注意几点。必须定义一个 BurpExtender 类,并且必须实现 IBurpExtender,如果还需要其他 API 可以实现多个其它接口,J**A 中的类是可以实现多个接口的。另外还需要重写父类中的 registerExtenderCallbacks 方法。同样,针对被动扫描器的需求,在 Burp 插件中我们最主要涉及的接口是 IHttpListener 接口。这个主要涉及到 HTTP
在 processHttpMessage 方法中,主要涉及到以上3个参数。toolFlag 主要指的是和请求相关的 Burp 工具,比如 Proxy 以及 Repeater。可以在 IBurpExtenderCallbacks 接口中看到相应的定义。
messageIsRequest 则表示是请求还是响应,而我们只关心请求部分。通过解析 messageInfo 则可以获取请求头以及请求体数据。
public Map<String, String> getHeaders(IHttpRequestResponse messageInfo) { Map<String, String> headers = new HashMap<>(); IRequestInfo analyzeRequest = helpers.analyzeRequest(messageInfo); List<String> h = analyzeRequest.getHeaders(); for (String h1: h) { if (h1.startsWith("GET") || h1.startsWith("POST")) { continue; } else { String[] header = h1.split(":", 2); headers.put(header[0], header[1].trim()); } } return headers; } private String getBody(IHttpRequestResponse messageInfo) { IRequestInfo requestInfo = helpers.analyzeRequest(messageInfo); int bodyOffset = requestInfo.getBodyOffset(); byte[] byteRequest = messageInfo.getRequest(); byte[] byteBody = Arrays.copyOfRange(byteRequest, bodyOffset, byteRequest.length); return new String(byteBody); }
上面是简单开发的内容方面的介绍,其它方面可以直接看源代码了解更多,尤其是 GUI 开发的部分。另外想说明的一点就是如何打 jar 包。通过 maven-assembly-plugin 插件可以很方便地打包,只需要配置如下,然后通过 mvn package 即可进行打包。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration></plugin>
另外注意如果使用了外部依赖的时候,需要配置 jar-with-dependencies,这样在打包的时候就可以把依赖的 jar 包一并打进去。最后,成品的 jar 包安装之后就可以使用了。
其实,我认为在 Burp 插件开发过程中最重要的部分就是调试了。通过调试可以快速提高开发效率。以 IDE IDEA 为例,只需要以下几步就可以进行插件开发地调试:
1.配置 debug 配置项,点击 IDE 右上角就可以新增配置项。
在终端中通过上述的配置项启动 burp 插件。
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar burpsuite_community_v2.1.0.jar
2.在 Burp 中通过上面的方式安装打包好的插件。
3.在 IDE 中相应的代码打上断点,并打开 debug 就可以进行调试了。
总结
以上就是在开发被动扫描器 Chrome 插件以及 Burp 插件遇到的一些坑,在这里和大家分享一下。其实被动扫描器开发,最重要的还是一些细节方面的考虑,可以将插件的功能做到更完美。
相关文章教程推荐:web服务器安全教程
以上是關於開發被動掃描器插件遇到的一些問題的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!