Дано:
- Пользовательские ПК, под управлением linux (suse 11, mint 16);
- Пользователи работают удаленно с терминалами, куда пробрасываются USB накопители;
- Пользователи не имеют на персональных компьютерах никаких прав, кроме запуска rdesktop/freerdp.
Задачи:
- отслеживать факты подключения USB накопителей;
- отслеживать факты записи и изменения файлов на USB накопителях.
Необходимое отступление. Я не буду обсуждать моральные аспекты подобной слежки за сотрудниками. Есть корпоративные стандарты и требования корпоративной службы безопасности с которыми ознакомлены сотрудники.
1. Отслеживаем факт подключения USB устройства
Для выполнения данной задачи я использовал свойство udev, которое позволяет выполнять скрипт при наступлении какого-либо события. Создадим правило, которое будет отвечать за подключение и отключение usb устройств:
touch /etc/udev/rules.d/usb.rules
Содержимое файла usb.rules:
ACTION=="add", SUBSYSTEM=="block", ENV{ID_BUS}=="usb|mmc|memstick|ieee1394", RUN+="/bin/bash /etc/udev/usb_on.sh %E{ID_SERIAL_SHORT} %E{ID_MODEL} %E{ID_VENDOR}"
ACTION=="remove", SUBSYSTEM=="block", ENV{ID_BUS}=="usb|mmc|memstick|ieee1394", RUN+="/bin/bash /etc/udev/usb_off.sh %E{ID_SERIAL_SHORT} %E{ID_MODEL} %E{ID_VENDOR}"
Где:
- ACTION – отслеживаемое действие, add – подключение устройств, remove – отключение;
- ENV – перечень отслеживаемых устройств по типу;
- RUN – исполняемое действие. В данном случае, в зависимости от события, запускаются скрипты usb_on.sh и usb_off.sh.
Скриптам usb_on.sh и usb_off.sh udev передает следующие данные:
- %E{ID_SERIAL_SHORT} – серийный номер USB устройства;
- %E{ID_MODEL} – модель USB устройства;
- %E{ID_VENDOR} – производитель USB устройства.
Скрипт usb_on.sh:
/usr/bin/curl -d "host=$(hostname)&serial=$1&name=$2&vendor=$3&file=on&sub=true" --noproxy 10.0.40.16 http://10.0.40.16/usb/input.php
Скрипт usb_off.sh:
/usr/bin/curl -d "host=$(hostname)&serial=$1&name=$2&vendor=$3&file=off&sub=true" --noproxy 10.0.40.16 http://10.0.40.16/usb/input.php
Данные скрипты выполняют единственное действие – посылают http POST запрос по адресу 10.0.40.16/usb/input.php (директива noproxy 10.0.40.16 нужна для того, что бы запрос отсылался минуя прокси-сервер). В данном POST запросе передаются следующие переменные:
- host – имя компьютера результат выполнения команды hostname;
- serial — серийный номер USB устройства (%E{ID_SERIAL_SHORT})
- name — модель USB устройства (%E{ID_MODEL})
- vendor — производитель USB устройства (%E{ID_VENDOR})
- file – действие. on – подключение, off — отключение (file — название поля выбрано по той причине, что сюда же будет вноситься и информация о файлах, над которыми производились какие-либо действия)
- sub=true – имитация нажатия кнопки на веб-форме.
2.Сервер сбора информации
Как видно из запускаемых скриптов usb_on.sh и usb_off.sh – вся информация передается на php скрипт, который состоит из простой веб-формы и обработчика запроса.
<form action="" method="post" enctype="multipart/form-data">
<input type="submit" name="sub" value="Сохранить">
<input type="text" name="host" maxlength=255 size=100>
<input type="text" name="serial" maxlength=255 size=100>
<input type="text" name="name" maxlength=255 size=100>
<input type="text" name="vendor" maxlength=255 size=100>
<textarea id="file" name="file"></textarea>
</form>
Обработчик делает одно – складывает принятые данные в таблицу usb БД MySQL
mysql_query("INSERT INTO `usb`
(`id`, `date`, `host`, `ip`, `serial`, `name`, `vendor`, `file`) VALUES (NULL, '$time', '$_POST[host]', '$_SERVER[REMOTE_ADDR]', '$_POST[serial]', '$_POST[name]', '$_POST[vendor]', '$_POST[file]')");
Структура таблицы:
CREATE TABLE IF NOT EXISTS `usb` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` bigint(20) NOT NULL,
`ip` varchar(15) COLLATE utf8_bin NOT NULL,
`host` varchar(50) COLLATE utf8_bin NOT NULL,
`serial` varchar(100) COLLATE utf8_bin NOT NULL,
`name` varchar(100) COLLATE utf8_bin NOT NULL,
`vendor` varchar(100) COLLATE utf8_bin NOT NULL,
`file` text COLLATE utf8_bin,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;
3. Мониторинг операций с файлами
Для выполнения функции отслеживания операций, которые выполнялись на файлами на подключенном носителе был написан следующий скрипт:
touch /var/tmp/usb.check # обновляем время модификации файла
check=1
while [ $check ] # бесконечный цикл
do
if [ -f /var/tmp/usb.check ] # если существует файл
then
ACCESS='' # обнуляем переменные
CREATE=''
MODIFY=''
# Далее, ищем в папке /media файлы, значения времен создания, изменения, доступа которых больше, чем только что созданным файлом /var/tmp/usb.check
ACCESS=`find /media -anewer /var/tmp/usb.check -type f`
CREATE=`find /media -cnewer /var/tmp/usb.check -type f`
MODIFY=`find /media -newer /var/tmp/usb.check -type f`
if [ ! -z "$ACCESS" ]
then
ACCESS="access "$ACCESS
# Передача информации на сервер
/usr/bin/curl -d "host=$(hostname)&serial=$2&name=$3&vendor=$4&action=$ACCESS&sub=true" --noproxy 10.0.40.16 http://10.0.40.16/usb/input.php
fi
if [ ! -z "$CREATE" ]
then
CREATE="create "$CREATE
/usr/bin/curl -d "host=$(hostname)&serial=$2&name=$3&vendor=$4&action=$CREATE&sub=true" --noproxy 10.0.40.16 http://10.0.40.16/usb/input.php
fi
if [ ! -z "$MODIFY" ]
then
MODIFY="modify "$MODIFY
/usr/bin/curl -d "host=$(hostname)&serial=$2&name=$3&vendor=$4&file=$MODIFY&sub=true" --noproxy 10.0.40.16 http://10.0.40.16/usb/input.php
fi
fi
touch /var/tmp/usb.check # обновляем время
sleep 5 # пауза
done
Данный скрипт добавляется в автозапуск и работает в фоновом режиме.
Для получения выборки сохраненной информации написан php скрипт, выбирающий из БД записи за указанный период и по выбранным ПК. Пример вывод информации:
4. Распростренение по ПК
Т.к. ПК с сети расположено достаточно много, было решено сделать это в полу-автоматическом режиме. А именно: написан скрипт, который считывает из файла список ПК для распространения и передает на них необходимые файлы. Выполняется это с помощью утилит sshpass (для автоматического ввода пароля) и scp (копирование).
Для начала в /etc/ssh/ssh_config меняем директиву StrictHostKeyChecking:
StrictHostKeyChecking no
Делается это для того, что бы ssh ключи автоматически добавлялись в список доверенных.
Непосредственно сам скрипт распространения:
#!/bin/bash
while read line; do
array[$index]="$line"
index=$(($index+1))
done < hosts.conf
for ((a=0; a < ${#array[*]}; a++))
do
remote=`echo ${array[$a]} | awk '{ print $1 }'`
echo "$remote begin";
/usr/bin/sshpass -p "root_password" /usr/bin/scp /home/user/usb_mon/usb.rules admin@$remote:/etc/udev/rules.d/usb.rules
/usr/bin/sshpass -p "root_password" /usr/bin/scp /home/user/usb_mon/*.sh admin@$remote:/etc/udev/
/usr/bin/sshpass -p "root_password" /usr/bin/scp /home/user/usb_mon/boot.local admin@$remote:/etc/rc.d/boot.local
echo "$remote end";
done
Т.к. некоторые ПК могут быть выключенными, запуск скрипта выполняется с выводом всей информации в лог и последующим анализом:
./deploy.sh &> deploy.log &
PS. Планы на будущее
Что нужно доработать:
- безопасность передачи информации при POST запросе
- убрать логирование служебных файлов (например Thumbs.db)
- теневое копирование файлов, над которыми были произведены какие-либо действия.
Автор: ale_rudenko