这一章的学习,个人感觉比前面几章稍微有难度一些,虽然过程挺艰苦的,但还算是勉强做出来了吧:)
这一章节的内容,因为jython对python3的兼容性不乐观,所以我们将使用python2编写代码。
Jython是一种完整的语言,而不是一个Java翻译器或仅仅是一个Python编译器,它是一个Python语言在Java中的完全实现。Jython也有很多从CPython中继承的模块库。最有趣的事情是Jython不像CPython或其他任何高级语言,它提供了对其实现语言的一切存取。所以Jython不仅给你提供了Python的库,同时也提供了所有的Java类。这使其有一个巨大的资源库。
我个人理解就是python+java=jython
因为burp拓展需要jython环境,所以这里我们需要安装jython。
这里安装的步骤直接略过,百度有很多教程可以自行搜索。
启动burpsuite后,我们将设置jython的路径位置
设置完成后基本环境已经搭建好了。
burpsuite软件中有许多API文档,我们可以通过查看文档来增加我们对burpsuite的接口以及框架的了解。(虽说是了解,但都是英文我啥也看不懂啊:(
这里通过文档我们可以知道我们脚本中需要用到的类
IBurpExtender
:在编写Burp拓展时必须要使用的类,该类的作用是在Burp上正确注册,注册方法是使用registerExtenderCallbacks()
方法,传递callbacks参数
。
package burp;/** @(#)IBurpExtender.java** Copyright PortSwigger Ltd. All rights reserved.** This code may be used to extend the functionality of Burp Suite Free Edition* and Burp Suite Professional, provided that this usage does not violate the* license terms for those products.*/
/*** All extensions must implement this interface.** Implementations must be called BurpExtender, in the package burp, must be* declared public, and must provide a default (public, no-argument)* constructor.*/
public interface IBurpExtender
{/*** This method is invoked when the extension is loaded. It registers an* instance of the* IBurpExtenderCallbacks
interface, providing methods that may* be invoked by the extension to perform various actions.** @param callbacks An* IBurpExtenderCallbacks
object.*/void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks);
}
IIntruderPayloadGeneratorFactory
:拓展Burp中intruder
模块payload。使用时要在IBurpExtender
类中正确注册后,将对象使用registerIntruderPayloadGeneratorFactory()
方法在Intruder
模块中正确注册。使用getGeneratorName()
方法定义拓展工具名字,此方法需要成功返回一个字符串。使用createNewInstance()
方法接收攻击相关的参数attack,并要返回一个IIntruderPayloadGenerator
类型的对象。
package burp;/** @(#)IIntruderPayloadGeneratorFactory.java** Copyright PortSwigger Ltd. All rights reserved.** This code may be used to extend the functionality of Burp Suite Free Edition* and Burp Suite Professional, provided that this usage does not violate the* license terms for those products.*/
/*** Extensions can implement this interface and then call* IBurpExtenderCallbacks.registerIntruderPayloadGeneratorFactory()
* to register a factory for custom Intruder payloads.*/
public interface IIntruderPayloadGeneratorFactory
{/*** This method is used by Burp to obtain the name of the payload generator.* This will be displayed as an option within the Intruder UI when the user* selects to use extension-generated payloads.** @return The name of the payload generator.*/String getGeneratorName();/*** This method is used by Burp when the user starts an Intruder attack that* uses this payload generator.** @param attack An* IIntruderAttack
object that can be queried to obtain details* about the attack in which the payload generator will be used.* @return A new instance of* IIntruderPayloadGenerator
that will be used to generate* payloads for the attack.*/IIntruderPayloadGenerator createNewInstance(IIntruderAttack attack);
}
IIntruderPayloadGenerator
:此模块用来配置payload功能。hasMorePayloads()
方法来判定是否将修改后的请求发送会Burp Intruder
,返回True
则继续,返回False
则停止。getNextPayload()
方法获得下一个payload,使用时要将一个数组传递进去,该方法需要返回一个payload
。reset()
方法重置有效载荷生成器的状态。
package burp;/** @(#)IIntruderPayloadGenerator.java** Copyright PortSwigger Ltd. All rights reserved.** This code may be used to extend the functionality of Burp Suite Free Edition* and Burp Suite Professional, provided that this usage does not violate the* license terms for those products.*/
/*** This interface is used for custom Intruder payload generators. Extensions* that have registered an* IIntruderPayloadGeneratorFactory
must return a new instance of* this interface when required as part of a new Intruder attack.*/
public interface IIntruderPayloadGenerator
{/*** This method is used by Burp to determine whether the payload generator is* able to provide any further payloads.** @return Extensions should return* false
when all the available payloads have been used up,* otherwise* true
.*/boolean hasMorePayloads();/*** This method is used by Burp to obtain the value of the next payload.** @param baseValue The base value of the current payload position. This* value may be* null
if the concept of a base value is not applicable (e.g.* in a battering ram attack).* @return The next payload to use in the attack.*/byte[] getNextPayload(byte[] baseValue);/*** This method is used by Burp to reset the state of the payload generator* so that the next call to* getNextPayload()
returns the first payload again. This* method will be invoked when an attack uses the same payload generator for* more than one payload position, for example in a sniper attack.*/void reset();
}
在了解完上面这三个类后,我们可以开始编写我们的代码了(bhp_fuzzer.py),这里需要注意的是,千万不要在脚本里面写入中文注释,否则在导入拓展时会报出编码错误!!!
from burp import IBurpExtender
from burp import IIntruderPayloadGeneratorFactory
from burp import IIntruderPayloadGeneratorfrom java.util import List, ArrayListimport random# 定义BurpExtender类,并继承IBurpextender类与IIntruderPayloadGeneratorFactory类
class BurpExtender(IBurpExtender, IIntruderPayloadGeneratorFactory):# 传入callbacks参数在Burp中正确注册def registerExtenderCallbacks(self, callbacks):# 将传递过来的callbacks赋值到类中self._callbacks = callbacks# 将帮助信息传入到类中self._helpers = callbacks.getHelpers()# 将拓展在Burp Intruder模块中注册callbacks.registerIntruderPayloadGeneratorFactory(self)return# 使用return返回拓展名,并设置def getGeneratorName(self):return "BHP Payload Generator"# 接受attack参数,并返回IIntruderPayloadGenerator类。def createNewInstance(self, attack):return BHPFuzzer(self, attack)# 定义BHPfuzzer类,并继承IIntruderPayloadGenerator类
class BHPFuzzer(IIntruderPayloadGenerator):# 定义初始方法def __init__(self, extender, attack):self._extender = extenderself._helpers = extender._helpersself._attack = attackprint("BHP Fuzzer initialized")# 定义payload上限self.max_payloads = 1000# 记录payload数量self.num_iterations = 0return# 定义停止攻击条件def hasMorePayloads(self):print "hasMorePayload called."# 当记录的payload达到上限时停止if self.num_iterations == self.max_payloads:print("No more payloads.")return Falseelse:print("More payloads. Continuing.")return True# 返回payloaddef getNextPayload(self, current_payload):# convert into a string# 转换成字符串payload = "".join(chr(x) for x in current_payload)# call our simple mutator to fuzz the POST# 调用简单的变形器对POST请求进行模糊测试payload = self.mutate_payload(payload)# increase the number of fuzzing attempts# 记录payload次数self.num_iterations += 1return payload# 重置函数def reset(self):# 清零self.num_iterations = 0returndef mutate_payload(self, original_payload):# pick a simple mutator or even call an external script# like Radamsa does# 仅生成随机数,或者调用一个外部脚本picker = random.randint(1, 3)# select a random offset in the payload to mutate# 在载荷中选取一个随机的偏移变量去变形offset = random.randint(0, len(original_payload) - 1)payload = original_payload[:offset]# random offset insert a SQL injection attempt# 在随机便宜位置插入SQL注入尝试if picker == 1:payload += "'"# jam an XSS attempt in# 插入XSS尝试if picker == 2:payload += ""# repeat a chunk of the original payload a random number# 随机重复原始载荷if picker == 3:chunk_length = random.randint(len(payload[offset:]), len(payload) - 1)repeater = random.randint(1, 10)for i in range(repeater):payload += original_payload[offset:offset+chunk_length]# add the remaining bits of the payload# 添加载荷中剩余的字节payload += original_payload[offset:]return payload
程序编写完成后,我们将脚本导入Burp中。
导入成功
导入成功后,我们可以尝试运用:
首先抓取http://testphp.vulnweb.com
请求头,在输入框里输入任意字符,然后点击go使用brup抓取请求头
使用ctrl+i
将请求头发送到intruder
点击payloads
设置我们刚刚加入的拓展
开始攻击
略,由于本人对bing的API key实在时注册不上去,所以这一小节选择跳过,见谅。
敲写代码之前,我们可以先看下脚本需要用到的类:
IContextMenuFactory
:此模块用来拓展右键菜单功能首先使用registerContextMenuFactory()
方法注册菜单拓展,然后建立createMenuItem()
方法创建菜单,使用add()
函数,配合JmenuItem()
方法设置菜单信息,在此方法内定义actionPerformed
参数设置行动函数。
package burp;/** @(#)IContextMenuFactory.java** Copyright PortSwigger Ltd. All rights reserved.** This code may be used to extend the functionality of Burp Suite Free Edition* and Burp Suite Professional, provided that this usage does not violate the* license terms for those products.*/
import java.util.List;
import javax.swing.JMenuItem;/*** Extensions can implement this interface and then call* IBurpExtenderCallbacks.registerContextMenuFactory()
to register* a factory for custom context menu items.*/
public interface IContextMenuFactory
{/*** This method will be called by Burp when the user invokes a context menu* anywhere within Burp. The factory can then provide any custom context* menu items that should be displayed in the context menu, based on the* details of the menu invocation.** @param invocation An object that implements the* IMessageEditorTabFactory
interface, which the extension can* query to obtain details of the context menu invocation.* @return A list of custom menu items (which may include sub-menus,* checkbox menu items, etc.) that should be displayed. Extensions may* return* null
from this method, to indicate that no menu items are* required.*/List<JMenuItem> createMenuItems(IContextMenuInvocation invocation);
}
简单了解了Burp的各种API后&#xff0c;我们开始编写我们的代码&#xff1a;
# 导入相应的模块
from burp import IBurpExtender
from burp import IContextMenuFactoryfrom javax.swing import JMenuItem
from java.util import List, ArrayList
from java.net import URLimport re
from datetime import datetime
from HTMLParser import HTMLParserclass TagStripper(HTMLParser):def __init__(self):# 初始化函数HTMLParser.__init__(self)self.page_text &#61; []# 获得标签之间的字符串def handle_data(self, data):self.page_text.append(data)# 获得页面中的注释def handle_comment(self, data):self.handle_data(data)def strip(self, html):# 接受一个字符串类型的html内容&#xff0c;进行解析self.feed(html)# 返回最后的字符串&#xff0c;每个字符串以空格相隔return " ".join(self.page_text)class BurpExtender(IBurpExtender, IContextMenuFactory):def registerExtenderCallbacks(self, callbacks):self._callbacks &#61; callbacksself._helpers &#61; callbacks.getHelpers()self.context &#61; None# 使用set()函数防止重复self.hosts &#61; set()# 初始化字典集合&#xff0c;默认增加‘password’self.wordlist &#61; set([&#39;password&#39;])# 模块命名与注册callbacks.setExtensionName("BHP Wordlist")callbacks.registerContextMenuFactory(self)return# 创建菜单&#xff0c;返回菜单列表def createMenuItems(self, context_menu):self.context &#61; context_menumenu_list &#61; ArrayList()menu_list.add(JMenuItem("Create Wordlist", actionPerformed&#61;self.wordlist_menu))return menu_list# 行动函数def wordlist_menu(self, event):# 获取用户点击的详情信息http_traffic &#61; self.context.getSelectedMessages()for traffic in http_traffic:# 获得http服务对象http_service &#61; traffic.getHttpService()# 得到http中host属性host &#61; http_service.getHost()# 添加到集合中self.hosts.add(host)# 获取响应信息http_response &#61; traffic.getResponse()# 在响应信息存在的情况下使用自定义的get_words()函数获取页面信息生成字典if http_response:self.get_words(http_response)# 将最后的结果利用此函数回显出来self.display_wordlist()# 生成密码def get_words(self, http_response):# 将响应使用tostring函数转换为字符串&#xff0c;并使用split()函数以两个换行为条件分割一次# 这里是将响应头信息与响应体进行分割headers, body &#61; http_response.tostring().split(&#39;\r\n\r\n&#39;, 1)# 将响应头在不区分大小写的情况下找到指定字符串# find(str, beg, end&#61;)包含字符串返回相应索引&#xff0c;否则返回-1# 忽略下一个相应if headers.lower().find("content-type: text") &#61;&#61; -1:return# 实例化对象tag_stripper &#61; TagStripper()# 将body带入类进行解析page_text &#61; tag_stripper.strip(body)# 找到所有以字母开头后跟着两个及以上单词的字符串words &#61; re.findall("[a-zA-Z]\w{2,}", page_text)# 遍历加入集合for word in words:# 过滤超长字符串if len(word) <&#61; 12:self.wordlist.add(word.lower())# 将一些常见关键字与密码组合def mangle(self, word):year &#61; datetime.now().yearsuffixes &#61; ["", "1", "!", year]mangled &#61; []for password in (word, word.capitalize()):for suffix in suffixes:mangled.append("%s%s" % (password, suffix))return mangled# 遍历打印所有生成密码def display_wordlist(self):print "#!comment: BHP Wordlist for site(s) %s" % ", ".join(self.hosts)# sorted()函数&#xff0c;将列表里的所有元素进行排序for word in sorted(self.wordlist):for password in self.mangle(word):print passwordreturn
代码敲写完毕&#xff0c;开始运用以下我们的代码