如何将YubiKey武器化
几年前,我有一枚受安全漏洞影响的YubiKey,Yubico免费寄给我一枚全新的YubiKey作为修复。由于收到新设备后不再使用旧的YubiKey进行认证,我决定尝试将其改造成类似USB Rubber Ducky的设备——一种模拟键盘的USB设备,插入后会向计算机发送一系列预编程的按键。
结果证明这是可行的。尽管标准版YubiKey并非理想的USB丢弃攻击工具,但它便于日常携带,通常比U盘更不显眼,并且多次在没有其他工具的情况下,帮我临时突破了信息亭的限制shell。
本文将介绍我如何识别美式键盘布局下标准YubiKey可生成的所有按键,并利用这些按键构建有效载荷。
第一步:下载YubiKey个性化工具
YubiKey在其网站上提供了一个名为YubiKey个性化工具(YPT)的程序,可用于在Linux、Windows或Mac上自定义YubiKey的不同功能。本文使用Linux版本,但Windows和Mac版本的操作类似。
第二步:使用静态密码编程YubiKey
在默认配置下,YubiKey每次使用时都会输入一个唯一的认证令牌,且该令牌每次都会变化。但YubiKey也可以被编程为输入用户定义的静态密码。由于YubiKey像普通键盘一样向计算机输入数据,我想知道除了标准字母、数字和符号外,它是否还能按下更有趣的键,如CTRL、ALT或Windows键。为了测试这一点,我启动了YPT,并从顶部栏选择了“静态密码”选项。然后在“静态密码”页面上,点击了标有“扫描码”的按钮。
为了理解工作原理,我首先用非常简单的静态密码“abcdef”编程YubiKey。在“静态密码”窗口中选择了以下选项:
- 配置槽:配置槽1
- 键盘:美式键盘
- 密码:abcdef
我注意到,当我在密码字段中输入密码时,十六进制值开始显示在右侧的扫描码字段中。我记下了这一点,并决定在编程静态密码后,下一步应该是识别每个我想输入的键的十六进制值。这样,我或许能够编程无法在密码字段中输入的按键——如CTRL和ALT。
以下截图显示了我上面概述的所有设置以及输入密码生成的扫描码:
接下来,我点击“写入配置”将静态密码写入YubiKey。第一次操作时,弹出一个对话框,要求我确认是否要覆盖YubiKey上槽1的当前配置。我勾选了“不再显示此消息”框,并点击“是”将更改写入设备。
警告:如果您正在使用自己的YubiKey操作,请确保它不是当前用于认证的设备。将新配置写入YubiKey将擦除所选配置槽中存储的设置,您必须重新编程YubiKey并在使用的服务中重新注册才能再次用于多因素认证。如果您只使用YubiKey上的一个配置槽进行认证,可能可以安全地覆盖另一个槽。但如果不确定,最好先从使用的任何服务中注销YubiKey,或使用不同的YubiKey。
写入更改后,我打开文本编辑器并按下了YubiKey上的硬件按钮。YubiKey按预期在屏幕上键入了密码“abcdef”。
第三步:识别YubiKey的十六进制键码
既然已经确认可以让YubiKey输入一系列预定义键,下一步是弄清楚是否可以通过在YPT中指定十六进制“扫描码”来让它按下更有趣的键。为了将扫描码映射到相应的按键,我从非常低技术的方法开始:在YPT的密码字段中输入字母“a”到“z”,并观察扫描码字段中的结果。这导致十六进制值04到1D出现在扫描码字段中。
我对键盘上所有其他可打印键以及每个键的大写版本重复了这一过程。我记下了所有收集到的十六进制值以及尚未与键盘上键匹配的值范围。将所有能够解码的字符组织成表格后,我注意到了一个模式:扫描码似乎从中间分开,小写字符全部位于00-7F之间,而大写或“键+Shift”版本位于80-FF之间的相同位置。这在下表中可以更清楚地看到。
键 | 扫描码 | 键(Shift) | 扫描码 |
---|---|---|---|
a | 04 | A | 84 |
b | 05 | B | 85 |
… | … | … | … |
z | 1D | Z | 9D |
现在剩下的就是识别每个未知范围中十六进制值生成的按键。由于在YPT的扫描码字段中输入十六进制值不会显示任何输出,并且我预计未知范围中的许多按键是不会生成任何可打印输出的键(例如CTRL键),我需要一种方法来捕获YubiKey生成的原始按键。为此,我决定使用Linux工具xinput和我的xinput-keylog-decoder脚本来解码输出。
如果您不熟悉xinput,它是一个命令行工具,通常包含在许多Linux发行版的图形桌面环境中。它也常在系统被入侵时被滥用作键盘记录器,我创建xinput-keylog-decoder工具正是为了这个目的。
由于YubiKey本质上是一个键盘,我开始捕获其按键的第一件事是识别它在xinput中的ID号。我通过运行不带任何参数的xinput命令检查了这一点,并确定其ID为16,如下输出所示:
|
|
默认情况下,xinput-keylog-decoder附带的示例脚本记录系统上所有连接的键盘的输入,但知道YubiKey的ID让我在解析输出时能够针对该设备。
接下来,我打开了三个终端窗口,并运行命令来记录和分析YubiKey生成的按键。每个命令的目的如下截图所示:
-
顶部终端:停止任何当前运行的xinput进程,启动新的xinput进程,并启动无限循环以从键盘读取输入。这是我在YubiKey向系统键入键时保持选中的终端窗口。这样,它键入的任何内容都不会干扰其他终端窗口。
1
./stop-logging.sh >0; rm *txt; ./start-logging.sh; while true; do read; sleep 0.1; done
-
中间终端:每秒在屏幕上显示test-output.16.txt的原始输出。test-output.16.txt是自动保存键盘ID 16的按键的文件。显示xinput输出的原始键码让我在xinput-keylog-decoder.py无法解码第三个终端窗口中的按键时获得更多信息。
1
watch -n 1 tail test-output.16.txt
-
底部终端:每秒解码键记录文件并将其显示为人类可读的文本。
1
watch -n 1 ./xinput-keylog-decoder.py test-output.16.txt
最后,在将十六进制扫描码编程到YubiKey中时,我首先将它们放在两个已知字符之间——通常是“a”(扫描码04)和“b”(扫描码05)。这样我可以确认目标按键前后确实按下了键,并且可以识别按键是否对这些其他键产生了任何影响。以下是以扫描码“2A”为目标的过程示例。
在第一张截图中,您可以看到未识别的扫描码“2A”夹在“a”和“b”的扫描码之间。您可能还会注意到密码字段中“a”和“b”之间的明显空白。
在下一张截图中,我选择了顶部终端并按下了YubiKey上的按钮。乍一看,似乎只按下了“b”键,而“a”被省略了。然而,在检查中间窗口后,您可以看到三个键依次被按下和释放。在第三个窗口中,中间窗口的键码被解码为人类可读的格式,很明显按下的键是“a”、退格键和“b”。这解释了为什么“a”没有出现在第一个窗口中,并将目标扫描码“2A”识别为退格键。
以这种方式识别键后,接下来我所做的只是按CTRL+C停止顶部窗口中的运行循环,再次运行命令(以清除日志并重新启动记录器),然后重复上述过程。对每个未识别的十六进制值重复这些步骤后,我确认了每个可能扫描码生成的按键,并将它们收集在下表中。
扫描码 | 键 | 描述 |
---|---|---|
2A | Backspace | 退格键 |
2B | Tab | 制表键 |
… | … | … |
E5 | Menu | 菜单键(右键单击) |
在解码扫描码时,我还观察到YubiKey在某些按键序列末尾会自动按下Enter键。在某些情况下,我能够通过以扫描码“00”终止序列来防止这种行为,但它并不总是有效。为了演示,这里有一张YubiKey被配置为键入字母“a”到“z”的截图,以及按下YubiKey按钮后的输出截图。请注意,“z”键(扫描码“1D”)是编程到YubiKey中的最后一个键,但YubiKey在字符串末尾还是按下了Enter键。这与之前示例中解码退格键代码时观察到的行为不同,那时没有按下Enter键。
按键序列的长度和YubiKey的输出速度(可在YPT的设置屏幕中配置)似乎都会影响这种行为。在我的测试中,额外的Enter键没有出现在长度小于23个键且以标准输出字符速率键入的序列中。然而,将字符速率减慢60毫秒会导致在短至一个按键的序列上自动按下Enter键。如果您不希望YubiKey在末尾自动按下Enter键,在创建有效载荷时请注意这一点。
第四步:创建有用的有效载荷
将所有扫描码与它们按下的键匹配后,我现在准备好开始构建有效载荷。不幸的是,我测试的扫描码都没有按下我希望能找到的CTRL、ALT或Windows键;因此,虽然它可以用于输入长的一行命令,但它并不理想作为完全自动化的命令注入工具或像Rubber Ducky或Teensy那样的USB丢弃攻击工具。
尽管YubiKey不会按下CTRL、ALT或Windows键,它仍然可以访问其他几个可能有趣的键,包括:
- Shift(通过使用“Shift + 无效果”扫描码之一)
- 功能键(F1-F12)
- 菜单键(相当于鼠标右键单击)
- Escape
- Shift键与所有已识别键的组合
尽管这些键可能不是向目标系统注入可执行有效载荷的首选,但一个它们极其有用的场景是尝试突破计算机信息亭的限制shell。
由于完全保护信息亭软件的困难,信息亭制造商通常从键盘上物理移除键,从指向设备上移除右键单击按钮,或完全移除这两个设备而支持触摸屏。但信息亭上的USB端口通常仍然暴露,以便技术人员可以连接自己的键盘进行故障排除。在这种情况下,携带自己键盘的攻击者(或在这种情况下是YubiKey)只需将键盘插入信息亭,并使用许多众所周知的方法之一突破限制shell并控制计算机。
从信息亭的限制shell中逃脱的第一步通常是打开一个新的应用程序窗口——无论是对话框、新浏览器窗口还是其他任何东西。这通常是键盘最有帮助的一步,因为攻击的其余部分通常可以用最少的指向设备输入完成。下表描述了YubiKey可以注入以尝试执行第一步的按键。
按键 | 对计算机信息亭的影响 |
---|---|
Escape | 退出当前窗口 |
按Shift五次 | 打开Windows的粘滞键对话框 |
F1 | 在许多应用程序和操作系统中打开帮助对话框 |
F6 | 选择Web浏览器地址栏 |
F10, Down Arrow | 在许多应用程序中打开应用程序菜单 |
F10, Down Arrow, “n” | 在Chrome、Firefox和Windows资源管理器中打开新窗口 |
F10, Down Arrow, “p” | 在许多应用程序中打开打印对话框 |
F11 | 退出全屏模式。可能显示Web浏览器的地址栏 |
F12, Esc | 打开Web开发人员工具并选择JavaScript控制台 |
Shift + F10 | 鼠标右键单击。打开快捷菜单 |
Shift + Menu | Shift + 右键单击。在Windows资源管理器中打开带有运行命令提示符或PowerShell扩展选项的快捷菜单 |
其他功能键(F1-F12) | 在许多应用程序中的额外功能。一些信息亭软件中的隐藏功能/菜单 |
Print Screen | 在一些系统上打开截图对话框 |
考虑到这些功能,我创建了以下三个有效载荷,将我的YubiKey用作信息亭突破设备。
YubiKey有效载荷
有效载荷1 – 简单功能键和粘滞键测试
- 扫描码:522c3a3b3c3d3e3f404142434445e6e6e6e6e6e652
- 输出字符速率:标准
- 执行的按键:
- 激活粘滞键对话框中的超链接(如果存在):上箭头,空格键
- 按下每个功能键:F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12
- 通过按Shift五次打开粘滞键对话框,再加一次以确保安全:Shift, Shift, Shift, Shift, Shift, Shift
- 选择粘滞键对话框中的超链接,并尝试阻止Enter键关闭窗口(如果按下):上箭头
有效载荷2 – 浏览器热键和粘滞键
- 扫描码:3f2a06b3a83f4dca06b3283c443e3b3d40ab2c29e5115128454142435113113ae6e6e6e6e652
- 输出字符速率:减慢60毫秒
- 执行的按键:
- 在新浏览器窗口中打开“c:”:F6, Backspace, 键入“c:”, Shift+Enter
- 打开“c:”(Chrome):F6, End, Shift+Home, “c:”, Enter
- 按下功能键:F3, F11, F5, F2, F4
- 尝试F7并在对话框出现时关闭它:F7, Shift+Tab, Space, Esc
- 打开新浏览器窗口:Shift+Menu, n, Down, Enter
- 尝试F12/Web开发人员控制台:F12
- 尝试F8和F9:F8, F9
- 打开打印对话框或新浏览器:F10, Down, p, n
- 尝试F1/帮助:F1
- 打开粘滞键对话框:Shift, Shift, Shift, Shift, Shift
- 阻止Enter键关闭粘滞键对话框:Up
有效载荷3 – Shift+右键单击
- 扫描码:e5
- 输出字符速率:标准
- 执行的按键:Shift+Menu键
第一个有效载荷非常简单:它按下上箭头、空格键、每个功能键(F1-F12),然后按Shift键六次,然后再按一次上箭头。这个有效载荷的目的是测试每个功能键,看它是否提供访问信息亭上额外功能的方式,然后重复按Shift键打开粘滞键对话框。一旦粘滞键对话框打开,可以第二次按下YubiKey上的按钮,上箭头和空格键按键将打开对话框中的超链接,导航到Windows的轻松访问设置。这是我为YubiKey创建的第一个有效载荷,它在现场多个平台上突破限制shell非常成功。
第二个有效载荷试图通过调整功能键的使用以反映它们在常见Web浏览器中的功能来改进第一个有效载荷。例如,按F7然后立即尝试F8没有意义,因为在大多数浏览器中按F7会导致提示出现,有效地在浏览器上下文中阻止F8被按下。每个功能键仍然被按下,连同粘滞键序列,与第一个有效载荷一样。包括额外的键以尝试自动选择菜单选项并提供浏览器跨兼容性。这个有效载荷是我在写本文时组装的新有效载荷,因此尚未在现场使用。在实验室环境中它工作得很好——尤其是在运行多次时。
最后,第三个有效载荷只按下Shift加菜单键。这实际上与按住Shift键并用鼠标右键单击相同。它让我能够向信息亭添加右键鼠标按钮,以便在获得初始立足点后可以在不同事物上右键单击。如果可以在资源管理器窗口内右键单击,它还提供了到PowerShell或命令提示符的快速快捷方式。我通常将这个有效载荷保存在YubiKey的槽2中,其他有效载荷之一在槽1中。
结论
尽管YubiKey是一款出色的双因素认证设备,但它肯定缺少一些使其成为理想USB HID攻击工具的功能,并且还有其他产品已经做得更好。YubiKey作为攻击工具的主要优势可能是它看起来像YubiKey。在不允许U盘的高安全环境中,可能可以走私YubiKey;在近距离社会工程场景中,说服员工打开公共互联网信息亭的机柜以便您“认证”到您的电子邮件账户可能比插入某些无法识别的设备更容易。
在我看来,这是实验YubiKey的主要收获。