2010-03-31 12 views
6
  • Chcę dodać dane do pliku w/tmp.
  • Jeśli plik nie istnieje, chcę go utworzyć
  • Nie obchodzi mnie, że ktoś inny jest właścicielem pliku. Dane nie są tajne.
  • Nie chcę, aby ktoś był w stanie ścigać się z wyścigiem, aby zapisać go w innym miejscu lub w innym pliku.

Jaki jest najlepszy sposób na zrobienie tego?Jak powinienem chronić się przed atakami z twardym łączem?

Oto moja myśl:

fd = open("/tmp/some-benchmark-data.txt", O_APPEND | O_CREAT | O_NOFOLLOW | O_WRONLY, 0644); 
fstat(fd, &st); 
if (st.st_nlink != 1) { 
    HARD LINK ATTACK! 
} 

Problem z tym: Ktoś może połączyć plik do jakiegoś pliku krótkotrwały kopalni, tak że /tmp/some-benchmark-data.txt jest taka sama jak/tmp/tmpfileXXXXXX, którego używa inny skrypt (i poprawnie otworzony przy użyciu O_EXCL i tak dalej). Moje dane porównawcze są następnie dołączane do tego pliku/tmp/tmpfileXXXXXX, , podczas gdy nadal jest używane.

Jeśli mój inny skrypt miałby otworzyć swój plik tymczasowy, usuń go, a następnie użyj go; wtedy zawartość tego pliku zostanie uszkodzona przez moje dane porównawcze. Ten inny skrypt musiałby następnie usunąć swój plik między open() i fstat() powyższego kodu.

Więc innymi słowy:

This script   Dr.Evil  My other script or program 
            open(fn2, O_EXCL | O_CREAT | O_RDWR) 
        link(fn1,fn2) 
open(fn1, ...) 
            unlink(fn2) 
fstat(..)=>link is 1 
write(...) 
close(...) 
            write(...) 
            seek(0, ...) 
            read(...) => (maybe) WRONG DATA! 

A zatem powyższe rozwiązanie nie działa. Prawdopodobnie istnieją inne ataki.

Jaka jest właściwa droga? Poza tym nie używasz katalogu do zapisu na świecie.

Edit: W celu ochrony przed takim skutkiem, że zło użytkownik tworzy plik z jego/jej własności i uprawnień, lub po prostu źle uprawnieniami (przez trudne łącząc swój plik, a następnie usunięcie oryginału lub hardlinking krótkotrwały plik) Mogę sprawdzić bity prawa własności i pozwolenia po sprawdzeniu nlink.

Nie będzie problemu z bezpieczeństwem, ale zapobiegnie również niespodziankom. Najgorszym przypadkiem jest to, że dostaję część moich własnych danych (z innego pliku) na początku pliku skopiowanego z innego mojego pliku.

Edycja 2: Myślę, że to prawie niemożliwe, aby chronić przed ktoś ciężko łącząc nazwę pliku, który jest otwarty, a następnie usunięty używane. Przykładem tego są pakery EXE, które czasem wykonują nawet usunięty plik poprzez/proc/pid/fd-num. Wyścigi z tym powodują niepowodzenie wykonania spakowanego programu. lsof mógłby prawdopodobnie znaleźć, gdyby ktoś inny miał otwarty i-węzeł, ale wydaje się, że jest to więcej kłopotu niż jest warte.

+0

To tylko atak przed utworzeniem pliku. Jeśli jestem standardowym użytkownikiem, mogę utworzyć łącze do dowolnego pliku (nawet jeśli nie mogę napisać do tego pliku) w dowolnym katalogu, w którym mogę pisać. Oznacza to, że mogę utworzyć plik o nazwie '/ tmp/foo', który jest twardy link '/ etc/passwd'. Teraz, gdy jego program zapisuje do '/ tmp/foo', to naprawdę pisze do'/etc/passwd'. Chce tego uniknąć, upewniając się, że to jego pierwsze ogniwo z stworzonym przez niego kastą. – Gabe

+0

@gabe: right. Dlatego sprawdzam st_nlink. Możesz utworzyć nowy link do plików innych osób, ale nie możesz ich usunąć (zmniejsz liczbę połączeń). – Thomas

+0

Dobra uwaga, Thomas. Jeśli mój komentarz wygląda zabawnie, to dlatego, że odpowiadam na inny komentarz, który został usunięty. – Gabe

Odpowiedz

2

Niezależnie od tego, co zrobisz, na ogół uzyskasz warunek wyścigowy, w którym ktoś inny utworzy łącze, a następnie usunie je, gdy wykona się wywołanie systemowe fstat().

Nie powiedziałeś dokładnie, co próbujesz zapobiec. Istnieją na pewno łatki na jądro, które uniemożliwiają tworzenie (twardych lub symbolicznych) linków do plików, które nie należą do twoich katalogów (lub lepkich katalogów).

Umieszczenie go w katalogu nieopisanym na świecie wydaje się słuszne.

SELinux, który wydaje się być standardowym ulepszonym linuxem bezpieczeństwa, może być w stanie skonfigurować politykę, aby zabronić użytkownikom robienia złych rzeczy, które łamią twoją aplikację.

Ogólnie, jeśli pracujesz jako root, nie twórz plików w/tmp. Inną możliwością jest użycie setfsuid() do ustawienia twojego systemu plików na innym, wtedy jeśli plik nie jest zapisywalny dla tego użytkownika, operacja po prostu się nie powiedzie.

+0

Pomyślałem o tym, ale jeśli utworzą link do pliku, który nie jest ich właścicielem, nie będą mogli usunąć tego linku. W katalogu o + t/tmp możesz tylko usuwać pliki (linki), które posiadasz. Więc nie będą mogli zmniejszyć st_nlink z powrotem do 1. – Thomas

+0

Tak, ale mogą być w stanie usunąć go z innego katalogu, w którym się znajduje, jeśli mają dostęp do zapisu. – MarkR

+0

Ale co oni wtedy wygrywają? Czy to nie to samo, co tworzenie pliku w/tmp na pierwszym miejscu, do którego należy dołączyć? – Thomas

1

Krótki, co po prostu pokazano, tylko inna rzecz Próbowałem skończyło się niemal równie Racey i droższe, ustanawiając inotify zegarki na/tmp przed do tworzenia pliku, który pozwala na łowienie przypadku hardlink w niektórych przypadkach.

Jednak nadal jest bardzo nieczytelny i nieefektywny, ponieważ konieczne jest również ukończenie pierwszego wyszukiwania w/tmp, przynajmniej do poziomu, w którym ma zostać utworzony plik.

Tam (według mojej wiedzy) nie ma "pewnego" sposobu na uniknięcie tego rodzaju wyścigu, poza używaniem katalogów zapisywalnych w słowie. Jakie są konsekwencje przechwytywania twojego urządzenia przez twardy link? Czy dostaną coś użytecznego, czy po prostu sprawią, że twoja aplikacja będzie wykazywać niezdefiniowane zachowanie?

+0

Same dane nie są tajne. To tylko dane porównawcze. "Funkcja X zajęła 2 sekundy". – Thomas

Powiązane problemy