Vorrei iniziare con il blocco del BIOS in modo che il dispositivo non possa essere utilizzato per avviare il sistema.
Quindi, disabiliterei l'automounting per i dispositivi USB. A questo punto, è necessario limitare l'interazione dell'utente con il "sottosistema" dell'unità USB. Ad esempio, questa copia di dati è solitamente necessaria per scaricare i registri oi dati acquisiti, pertanto è possibile ridurli (nella maggior parte dei casi) a:
- monta il dispositivo USB
- verifica che sia valido e abbia spazio sufficiente
- seleziona i dati che vuoi copiare tra una scelta di file possibili
(ad esempio datalog.001, 20130402-dump.csv, qualsiasi cosa in / var / local / data ...)
- copia i file
- (facoltativamente) rilegge e controlla i loro hash MD5 / SHA
- (facoltativo) elimina / ruota gli originali per liberare spazio sul dispositivo
- smonta il dispositivo USB
Il processo consente solo l'interazione nei "dati selezionati" e tale interazione è limitata a una scelta di caselle multiple. Ci sono programmi di utilità (zenity, kdialog, o dialog for curses systems) che ti permettono di costruire un'interfaccia "bloccata" in un batter d'occhio: questo è un esempio adattato
#!/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*
Ora, l'utente può solo utilmente inserire una chiave USB quando il sistema è già avviato, e quando lo fa, non succede nulla; quando sceglie la funzione "Data Dump", le sue scelte sono limitate.
Non dovresti averne bisogno, ma tieni conto dei possibili exploit attraverso i metacaratteri della shell incorporati nei nomi dei file. Ottieni sempre i nomi dei file con ls (o equivalente) e filtrali.
Nota : come notato da Gilles, l'esempio sopra riportato è imperfetto: dialog
supporterà solo nomi senza spazi. Per un'implementazione più solida, dovresti usare qualcos'altro che uno script bash, possibilmente Python con Urwid o, a seconda dell'interfaccia esistente, un CGI o modulo web.
Aggiornamento
Il meglio che si può fare in bash e con dialog
è, sfortunatamente, rimuovere i file problematici (quelli con $, spazio, virgoletta singola, doppia citazioni...). Una sceneggiatura migliore, se manca, è questa. ignora qualsiasi file che non aderisce alla sua convenzione di denominazione; può ancora essere utile a qualcuno (ad esempio per copiare i log. A meno che tu non stia chiudendo 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
Per fare meglio, dobbiamo impiegare un costrutto meno fragile. Come suggerito sopra, questo può essere fatto in Python usando la libreria urwid
( apt-get install python-urwid
su Ubuntu, mi viene detto, altrimenti l'installazione è semplice). Questo è poco più di un tutorial modificato che ho attivato, ma funziona anche con i file che possono essere soffocati per dialog
o copiati in modo errato:
/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
L'unica cosa è che i file UTF8 potrebbero avere i loro nomi storpiati: ho un file che si chiama "Chissà?" in Linux EXT3, e mentre rimane intatto quando copiato su Linux o NTFS, diventa "Chiss ????" (sì, quattro punti interrogativi) su una chiave USB FAT. Ma credo che questa sia una limitazione del filesystem, non dello script.
#!/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()