在 Linux 上保护 USB 闪存驱动器

信息安全 linux USB驱动器
2021-08-20 20:04:47

我们有一个带有 USB 端口的工业系统(在 linux 上运行)。我们的 USB 端口仅用于复制某些数据。除此之外,我们不希望 USB 驱动器包含任何其他可执行文件或脚本等。因为最终用户可能会将蠕虫/病毒复制到 USB 设备并连接到系统。有什么方法可以避免这种情况?我知道,如果它使用 noexec 选项安装,则用户无法执行文件。增强 USB 设备安全性的方法有哪些? 更新:系统在没有 KDE/GNOME 之类的 GUI 的情况下运行。

2个回答

我将从锁定 BIOS 开始,这样该设备就不能用于启动系统。

然后,我将禁用 USB 设备的自动挂载。此时,您需要限制用户与 U 盘“子系统”的交互。例如,这种数据复制通常需要转储日志或获取的数据,因此您可以将其归结为(在大多数情况下):

  • 挂载 USB 设备
  • 验证它是否有效并且有足够的空间
  • 在一系列可能的文件中选择要复制的数据(例如 datalog.001、20130402-dump.csv、/var/local/data... 中的任何内容)
  • 复制上述文件
  • (可选)重新读取并检查他们的 MD5/SHA 哈希值
  • (可选)删除/旋转原件以释放设备空间
  • 卸载 USB 设备

该过程仅允许在“选择数据”中进行交互,并且该交互仅限于多个复选框选择。有一些实用程序(zenity、kdialog 或用于 curses 系统的对话框)允许您立即构建一个“锁定”界面:这是一个改编的示例

#!/bin/bash
n=0
for file in $(ls /tmp); do
    n=$[n+1]
    echo "$file $n off" >> /tmp/output.txt
done
dialog --checklist "Items to copy:" 20 60 20 \
    $(cat /tmp/output.txt) 2>/tmp/output2.txt

for i in $(cat /tmp/output2.txt); do
    cp $i /mnt/usbkey/
done
rm /tmp/output*

现在,用户只能在系统已经启动时插入 USB 密钥,而当他这样做时,什么也没有发生;当他选择“数据转储”功能时,他的选择是有限的。

您不需要它,但要注意可能通过嵌入文件名中的 shell 元字符进行的攻击。始终使用 ls (或等效项)获取文件名并过滤它们。

注意:正如 Gilles 所注意到的,上面的例子是有缺陷的:dialog只支持没有空格的名称。对于更健壮的实现,您应该使用 bash 脚本以外的其他东西,可能是带有Urwid的 Python,或者根据现有接口,使用 CGI 或 Web 模块。

更新

不幸的是,在 bashwithdialog中可以做的最好的事情是删除有问题的文件(那些带有 $、空格、单引号、双引号的文件......)。一个更好的(如果缺少的话)脚本是这样的。忽略任何不遵守其命名约定的文件;它可能对某人仍然有用(例如复制日志。除非您现在要关闭data-九月.log)。

#!/bin/bash

DIRTOCOPY="/tmp"

clean() {
        rm -f .tmp.dir .tmp.out .tmp.cpy
}

clean

n=0

ls "$DIRTOCOPY" > .tmp.dir

while read file ; do
    if ( echo "$file" | grep "^[A-Za-z0-9._~^-]*\$" > /dev/null ); then
        n=$[n+1]
        echo "$file $n off" >> .tmp.out
    fi
done < .tmp.dir
rm -f .tmp.dir

dialog --checklist "Items to copy:" 20 60 20 \
    $(cat .tmp.out) 2>.tmp.cpy

cat .tmp.cpy
exit

for file in $( cat .tmp.cpy ); do
    echo cp "$file" /mnt/usbkey/
done

clean

Python

为了做得更好,我们必须使用不那么脆弱的结构。如上所述,这可以在 Python 中使用urwid库来完成(apt-get install python-urwid我被告知在 Ubuntu 上。否则,安装很简单)。这只不过是我编写的修改后的教程——但它甚至适用于阻塞dialog或复制不正确的文件:

/tmp/tests/file with spaces.txt
/tmp/tests/file "quoted, but only once.txt
/tmp/tests/file "quoted twice", that's right!.txt
/tmp/tests/ceci n'est pas une |.txt

唯一的问题是 UTF8 文件的名称可能被破坏:我有一个名为“Chissà”的文件?在 Linux EXT3 中,虽然它在复制到 Linux 或 NTFS 时保持不变,但它变成了“Chiss????” (是的,四个问号)在 FAT USB 密钥上。但我相信这是文件系统的限制,而不是脚本。

#!/usr/bin/python

import urwid
from os import listdir
from os.path import isfile, join
from shutil import copyfile

directory = '/tmp'
destination = '/mnt/usbkey'

choices = [ file for file in listdir(directory) if isfile(join(directory,file)) ]

tocopy = [ ]

def menu(title, choices):
    body = [urwid.Text(title), urwid.Divider()]
    for c in choices:
        box     = urwid.CheckBox(c, False, False, toggle, c)
        body.append(urwid.AttrMap(box, None, focus_map='reversed'))

    ende = urwid.Button('-- COPY --')
    urwid.connect_signal(ende, 'click', item_chosen)
    body.append(urwid.AttrMap(ende, None, focus_map='reversed'))

    return urwid.ListBox(urwid.SimpleFocusListWalker(body))

def toggle(button, state, file):
    if state:
        tocopy.append(file)
    else:
        tocopy.remove(file)

def item_chosen(button):
    response = urwid.Text([u'Proceed with copy?\n'])
    done = urwid.Button(u'Proceed')
    fine = urwid.Button(u'Cancel')
    urwid.connect_signal(done, 'click', copy_files)
    urwid.connect_signal(fine, 'click', exit_program)
    main.original_widget = urwid.Filler(urwid.Pile([response,
        urwid.AttrMap(done, None, focus_map='reversed'),
        urwid.AttrMap(fine, None, focus_map='reversed') ]))

def exit_program(button):
    raise urwid.ExitMainLoop()

def copy_files(button):
    for file in tocopy:
        src = join(directory, file)
        dst = join(destination, file)
        copyfile(src, dst)
    raise urwid.ExitMainLoop()

main = urwid.Padding(menu(u'File to be copied to USB', choices), left=2, right=2)
top = urwid.Overlay(main, urwid.SolidFill(u'\N{MEDIUM SHADE}'),
    align='center', width=('relative', 60),
    valign='middle', height=('relative', 60),
    min_width=20, min_height=9)
urwid.MainLoop(top, palette=[('reversed', 'standout', '')]).run()

开放 USB 端口的风险远超您的预期。我推荐的是 BIOS 保护运行工业服务的服务器。通过密码保护您的 BIOS,您可以限制未经授权的用户从 USB 设备启动并未经授权访问您的服务器资源。您可以进一步安装ClamAV等防病毒软件来扫描 USB 设备中的恶意软件。