Uruchom niezaufany program C w piaskownicy w systemie Linux, który uniemożliwia mu otwieranie plików, rozwidlanie itp.?


110

Zastanawiałem się, czy istnieje sposób na uruchomienie niezaufanego programu w C w piaskownicy w systemie Linux. Coś, co uniemożliwiłoby programowi otwieranie plików lub połączeń sieciowych, forking, exec itp.?

Byłby to mały program, zadanie domowe, które jest przesyłane na serwer i wykonywane na nim testy jednostkowe. Program byłby więc krótkotrwały.


Czy to jest jak pojedynczy program C, który musisz uruchomić 1 raz przez 5 minut, czy coś, co musisz uruchamiać stale?
bwawok

Byłby to mały program, który jest ładowany i wykonywany jest na nim testy jednostkowe. Program byłby więc krótkotrwały.
Frank

Z jakiej dystrybucji korzysta system? Niektóre dystrybucje mają gotowe narzędzia do piaskownicy. Czy Twój system ma włączony model bezpieczeństwa, taki jak SELinux lub AppArmor?
thkala

Używam Fedory 13. Zajmuję się polityką SELinux Sandbox. Zastanawiam się, jakie są inne opcje.
Frank

Odpowiedzi:


47

Użyłem Systrace do piaskownicy niezaufanych programów zarówno w trybie interaktywnym, jak iw trybie automatycznym. Ma ptrace()backend oparty na systemie , który pozwala na użycie go w systemie Linux bez specjalnych uprawnień, a także znacznie szybszy i bardziej wydajny backend, który wymaga łatania jądra.

Możliwe jest również utworzenie piaskownicy w systemach uniksopodobnych przy użyciu chroot(1), chociaż nie jest to tak łatwe ani bezpieczne. Kontenery Linuksa i więzienia FreeBSD są lepszą alternatywą dla chroot. Inną alternatywą w Linuksie jest użycie struktury bezpieczeństwa, takiej jak SELinux lub AppArmor , którą proponuję dla systemów produkcyjnych.

Bylibyśmy w stanie pomóc Ci bardziej, gdybyś powiedział, co dokładnie chcesz zrobić.

EDYTOWAĆ:

Systrace będzie działał w twoim przypadku, ale myślę, że coś opartego na modelu bezpieczeństwa Linuksa, jak AppArmor lub SELinux, jest bardziej standardową, a zatem preferowaną alternatywą, w zależności od twojej dystrybucji.

EDYCJA 2:

Chociaż chroot(1)jest dostępny w większości (wszystkich?) Systemach typu Unix, ma sporo problemów:

  • Można go wyrwać. Jeśli zamierzasz faktycznie kompilować lub uruchamiać niezaufane programy w języku C w swoim systemie, jesteś szczególnie narażony na ten problem. A jeśli twoi uczniowie są podobni do moich, ktoś BĘDZIE próbował wydostać się z więzienia.

  • Musisz stworzyć pełną niezależną hierarchię systemu plików zawierającą wszystko, co jest niezbędne do wykonania zadania. Nie musisz mieć kompilatora w chroocie, ale wszystko, co jest wymagane do uruchomienia skompilowanych programów, powinno być dołączone. Chociaż istnieją narzędzia, które w tym pomagają, nadal nie jest to trywialne.

  • Musisz zachować chroot. Ponieważ jest niezależny, pliki chroot nie będą aktualizowane wraz z dystrybucją. Będziesz musiał albo regularnie odtwarzać chroot, albo dołączać do niego niezbędne narzędzia aktualizacyjne, co zasadniczo wymagałoby, aby była to pełnowartościowa dystrybucja Linuksa. Będziesz także musiał zsynchronizować dane systemowe i dane użytkownika (hasła, pliki wejściowe itp.) Z systemem hosta.

  • chroot()chroni tylko system plików. Nie zapobiega to otwieraniu gniazd sieciowych złośliwemu programowi ani pobieraniu wszystkich dostępnych zasobów przez źle napisany.

Problem wykorzystania zasobów jest powszechny wśród wszystkich alternatyw. Przydziały systemu plików zapobiegną zapełnieniu dysku przez programy. Prawidłowe ulimit( setrlimit()w C) ustawienia mogą chronić przed nadużyciem pamięci i wszelkimi bombami widelcowymi, a także położyć kres obciążeniom procesora. nice(1)może obniżyć priorytet tych programów, tak aby komputer bez problemu mógł być używany do dowolnych zadań uznanych za ważniejsze.


systrace działało dla mnie dla prostych programów, ale utknęło na czas nieokreślony, gdy GNU as (1) było uruchamiane przez GCC. Więc zrezygnowałem z tego. To nie naprawiony błąd w systrace: forum.soft32.com/linux/ ...
pkt

Czy istnieje sposób, aby zapewnić, że pamięć współdzielona, ​​kolejki wiadomości i semafory nie będą współużytkowane przez procesy w piaskownicy?
daveagp,

1
Łącze systrace jest zepsute.
Collin,

2
A co z Firejailem? Nie musisz już dłużej utrzymywać systemu plików przy jego użyciu.
m3nda,

18

Niedawno napisałem przegląd technik piaskownicy w Linuksie . Myślę, że najłatwiejszym podejściem byłoby użycie kontenerów Linuksa (lxc), jeśli nie masz nic przeciwko rozwidlaniu i tak dalej, co nie ma znaczenia w tym środowisku. Możesz nadać procesowi główny system plików tylko do odczytu, izolowane połączenie sieciowe pętli zwrotnej i nadal możesz go łatwo zabić i ustawić limity pamięci itp.

Seccomp będzie nieco trudny, ponieważ kod nie może nawet przydzielić pamięci.

Selinux to inna opcja, ale myślę, że może to wymagać więcej pracy niż kontener.


6

Możesz użyć Qemu do szybkiego testowania zadań. Poniższa procedura zajmuje mniej niż 5 sekund na moim 5-letnim laptopie.

Załóżmy, że uczeń musi opracować program, który pobiera niepodpisane liczby int, każdy w osobnym wierszu, aż nadejdzie wiersz z wartością „-1”. Program powinien następnie uśrednić wszystkie wartości int i wypisać „Średnia:% f”. Oto, jak możesz przetestować program całkowicie izolowany:

  1. Najpierw pobierz root.binz Jslinux, użyjemy tego jako przestrzeni użytkownika (ma kompilator C tcc):

    wget https://github.com/levskaya/jslinux-deobfuscated/raw/master/root.bin

  2. Chcemy wprowadzić zgłoszenie ucznia root.bin, więc skonfiguruj urządzenie pętli:

    sudo losetup /dev/loop0 root.bin

    (do tego też możesz użyć fuseext2, ale nie jest to zbyt stabilne. Jeśli się ustabilizuje, nie będziesz potrzebować do tego rootowania)

  3. Utwórz pusty katalog:

    mkdir mountpoint

  4. Mocowanie root.bin:

    sudo mount /dev/loop0 mountpoint

  5. Wprowadź zamontowany system plików:

    cd mountpoint.

  6. Napraw prawa:

    sudo chown -R `whoami` .

  7. mkdir -p etc/init.d
  8. vi etc/init.d:

    #!/bin/sh
    cd /root
    echo READY 2>&1 > /dev/ttyS0
    tcc assignment.c 2>&1 > /dev/ttyS0
    ./a.out 2>&1 > /dev/ttyS0
    
  9. chmod +x etc/init.d/rcS

  10. Skopiuj przesłanie do maszyny wirtualnej:

    cp ~/student_assignment.c root/assignment.c

  11. Wyjdź z głównego FS maszyny wirtualnej:

    cd ..

  12. sudo umount mountpoint
  13. Teraz obraz jest gotowy, wystarczy go uruchomić. Skompiluje się i uruchomi przesyłanie po uruchomieniu.
  14. mkfifo /tmp/guest_output
  15. Otwórz oddzielny terminal i zacznij nasłuchiwać wyjścia gościa:

    dd if=/tmp/guest_output bs=1

  16. W innym terminalu:

    qemu-system-i386 -kernel vmlinuz-3.5.0-27-generic -initrd root.bin -monitor stdio -nographic -serial pipe:/tmp/guestoutput (Właśnie użyłem tutaj jądra Ubuntu, ale wiele jąder będzie działać)

  17. Kiedy wyjście gościa pokazuje "GOTOWE", możesz wysłać klucze do maszyny wirtualnej z zachęty qemu. Na przykład, aby przetestować to przypisanie, możesz to zrobić

    (qemu) sendkey 1
    (qemu) sendkey 4
    (qemu) sendkey ret
    (qemu) sendkey 1
    (qemu) sendkey 0
    (qemu) sendkey ret
    (qemu) sendkey minus
    (qemu) sendkey 1
    (qemu) sendkey ret
    
  18. Teraz Average = 12.000000powinien pojawić się na potoku wyjściowym gościa. Jeśli tak się nie stanie, uczeń poniósł porażkę.

  19. Zamknij qemu: quit

Program, który przeszedł test, jest tutaj: https://stackoverflow.com/a/14424295/309483 . Po prostu użyj tcclib.hzamiast stdio.h.


5

Wypróbuj system Linux w trybie użytkownika . Ma około 1% narzut wydajności w przypadku zadań intensywnie wykorzystujących procesor, ale może być 6 razy wolniejszy w przypadku zadań intensywnie korzystających z operacji we / wy.


4

Firejail to jedno z najbardziej wszechstronnych narzędzi do tego - obsługuje seccomp, kontenery systemu plików, możliwości i nie tylko:

https://firejail.wordpress.com/features-3/


Ta odpowiedź jest doskonała, naprawdę zasługuje na więcej głosów, biorąc pod uwagę, że firejail jest aktywnie utrzymywany z doskonałą dokumentacją, obejmuje większość, jeśli nie wszystkie, inne odpowiedzi i jest zaprojektowany tak, aby był stosunkowo łatwy w użyciu.
Jeff Hykin

3

Uruchomienie go na maszynie wirtualnej powinno zapewnić wszystkie wymagane zabezpieczenia i ograniczenia.

QEMU dobrze by się do tego nadawało, a cała praca (pobieranie aplikacji, aktualizacja obrazu dysku, uruchamianie QEMU, uruchamianie aplikacji w nim i zapisywanie danych wyjściowych do późniejszego pobrania) mogłaby zostać utworzona za pomocą skryptów do automatycznych testów.


2
Nie wiem o OP, ale uruchomienie maszyny wirtualnej na program testowy byłoby w wielu przypadkach niedopuszczalne. W moim środowisku (jestem asystentem) może być nawet 200 studentów, którzy w ciągu 2 godzin przedstawi 10-12 programów. Żaden program nie działa dłużej niż 10 sekund czasu procesora, ale kiedy liczba zgłoszeń się nagromadzi, otrzymujemy czas realizacji 15 minut lub więcej. Wprowadzenie maszyny wirtualnej dla każdego programu spowodowałoby wydłużenie czasu procesora do 60 sekund lub więcej na program, a ja w ogóle nie chcę myśleć o czasach zwrotu. Może maszyna wirtualna na sesję, ale nie ma mowy, abyśmy mogli to zrobić dla programu ...
thkala

@thkala To dobra uwaga. Podoba mi się pomysł QEMU, ale uruchamianie maszyny wirtualnej dla każdego przesłania nie jest dobre.
Frank

W takim przypadku utrzymuj tę samą maszynę wirtualną działającą przez cały czas.
Laurent Parenteau

Czy mógłbyś coś zrobić, używając migawki maszyny wirtualnej, która jest w całości uruchomiona i gotowa do kompilowania i uruchamiania kodu? FYI, maszyny wirtualne niekoniecznie są odporne na piercing. Możesz także zbudować wersję sprzętową tego - mały system, który uruchamia obraz wznowienia z nośnika tylko do odczytu lub przez sieć i dostarcza dane wyjściowe przez sieć lub port szeregowy, a następnie jest ponownie uruchamiany na następny. Było kilka szybkich postępów w uruchamianiu, które uruchamiają Linuksa w kilka sekund.
Chris Stratton,

@thkala: Oznacza to, że jeśli uruchamiasz je seryjnie, potrzebujesz mniej niż 3 sekundy na każde zgłoszenie. Podejście, które opublikowałem, zajmuje prawdopodobnie około 3 sekund na nowoczesnej maszynie (seryjnie). Jeśli wykonasz zrównoleglenie (co równie dobrze możesz zrobić), byłoby to wystarczająco szybkie.
Janus Troelsen

3

Kiedy chodzi o sanboxing oparty na ptrace (strace) check-out:

" sydbox " sandbox i biblioteka programistyczna " pinktrace " (to C99, ale z tego co wiem, istnieją powiązania z Pythonem i Ruby).

Zebrane linki związane z tematem:

http://www.diigo.com/user/wierzowiecki/sydbox

(przepraszam, że nie są to bezpośrednie linki, ale nie ma jeszcze wystarczającej liczby punktów reputacji)



1

Ta biblioteka powinna dobrze służyć Twojemu celowi

http://sandbox.sourceforge.net

Powodzenia!


8
Nie wydaje się, aby było to aktywnie utrzymywane. Wydaje się również, że wymaga łatki na jądro Linuksa, co uczyniłoby ją w większości bezużyteczną, biorąc pod uwagę, że jej najnowsza wersja pochodzi z 2003 roku.
thkala


-1

ok dzięki wszystkim odpowiedziom, które bardzo mi pomogły. Ale nie zasugerowałbym żadnego z nich jako rozwiązania dla osoby, która zadała pierwotne pytanie. Wszystkie wymienione narzędzia wymagają wiele pracy, aby przetestować kod uczniów jako nauczyciel, korepetytor, prof. Najlepszym sposobem w tym przypadku byłoby moim zdaniem virtualbox. Ok, emuluje kompletny system x68 i nie ma nic wspólnego ze znaczeniem piaskownicy w ten sposób, ale jeśli wyobrażam sobie mojego nauczyciela programowania, byłoby to dla niego najlepsze. Tak więc „apt-get install virtualbox” w systemach opartych na Debianie, wszyscy inni udają się na http://virtualbox.org/ , utwórz maszynę wirtualną , dodaj iso, kliknij zainstaluj, poczekaj chwilę i miej szczęście. Będzie o wiele łatwiejsze w użyciu, jeśli chodzi o konfigurowanie systemu Linux w trybie użytkownika lub robienie ciężkich rzeczy ...

A jeśli obawiasz się, że twoi uczniowie cię zhakują, myślę, że masz problem z autorytetem i rozwiązanie tego groziłoby im, że pozwiesz ich żywe światło dzienne, jeśli możesz udowodnić tylko jeden kęs męskiego oprogramowania w pracy, którą wykonują ty...

Również jeśli jest klasa i 1% z niej jest tak dobre, jak on mógłby robić takie rzeczy, nie zanudzaj ich tak prostymi zadaniami i daj im jakieś duże, w których muszą kodować więcej. Uczenie się integracyjne jest najlepsze dla wszystkich, więc nie polegaj na starych, zakleszczonych strukturach ...

I oczywiście nigdy nie używaj tego samego komputera do ważnych rzeczy (takich jak pisanie zaświadczeń i egzaminów), których używasz do takich rzeczy, jak przeglądanie sieci i testowanie oprogramowania.

Używaj komputera offline do ważnych rzeczy i komputera online do wszystkich innych rzeczy.

Jednak dla każdego, kto nie jest paranoicznym nauczycielem (nie chcę nikogo urazić, jestem po prostu zdania, że ​​powinieneś nauczyć się podstaw o bezpieczeństwie i naszym społeczeństwie, zanim zaczniesz być nauczycielem programistów ...)

... gdzie byłem ... dla wszystkich innych:

szczęśliwego hakowania !!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.