Podatności format string
Wykorzystają Państwo ciągi formatujące printf do odczytywania dowolnych obszarów pamięci i zapisywania pod dowolnymi adresami.
Podatności format string to bezpłatna lekcja Cyber Security Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Cyber Security Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Cyber Security Academy zawiera 4 lekcji w sumie.
Czym jest podatność format string
Podatność format string występuje, gdy dane użytkownika są przekazywane bezpośrednio jako argument określający łańcuch formatujący funkcji printf() lub podobnych funkcji. Atakujący może odczytywać pamięć, ujawniać adresy stosu i zapisywać dowolne wartości.
Podatny wzorzec
Wersja podatna i bezpieczna:
// VULNERABLE - user controls the format string:
printf(user_input);
fprintf(stderr, user_input);
// SAFE - user input is a data argument:
printf("%s", user_input);Odczytywanie pamięci za pomocą %x i %p
Specyfikatory formatu bez odpowiadających im argumentów odczytują wartości ze stosu:
# Input: %p.%p.%p.%p.%p
# Output: 0x7ffd12345678.0x400580.0x0.0x1.0x7f3a...
# Each %p prints the next value off the stack - leaking addresses!Obejście ASLR dzięki wyciekom format string
Stos często zawiera wskaźniki do libc, stosu i pliku binarnego. Ujawniając je za pomocą specyfikatorów %p lub %lx, atakujący może obliczyć adresy bazowe i obejść ASLR — nawet bez żadnej innej podatności.
Odczytywanie dowolnej pamięci za pomocą %s
%s traktuje wartość ze stosu jako wskaźnik i wypisuje łańcuch znajdujący się pod tym adresem. Umieszczając adres docelowy na właściwej pozycji stosu i używając dostępu do parametrów (%7$s), atakujący może odczytywać dowolne obszary pamięci.
# Direct parameter access:
printf("%7$s") # prints string at 7th stack parameter
# If 7th param is an address you control, reads that memoryZapisywanie pamięci za pomocą %n
%n zapisuje liczbę znaków wypisanych do tej pory pod adresem wskazywanym przez odpowiadający mu argument. Pozwala to zapisywać kontrolowane wartości pod dowolnymi adresami — potencjalnie nadpisując wskaźniki funkcji lub adresy powrotu.
Praktyczna technika zapisu
Aby zapisać określoną wartość za pomocą %n:
- Należy kontrolować wskaźnik na stosie wskazujący adres docelowy
- Należy użyć
%Xc%N$n, aby zapisać X znaków, a następnie zapisać ich liczbę do N-tego parametru (adresu docelowego)
Narzędzia takie jak pwntools automatyzują tworzenie exploitów wykorzystujących format string.
Wykrywanie błędów format string
Testowanie pod kątem podatności format string:
# Test inputs:
%x.%x.%x
%p.%p.%p
%s%s%s
AAAA.%p.%p.%p.%p (looking for 0x41414141 in output)
# Automated testing with fuzzer:
python3 -c "print('%p.' * 20)" | ./vulnZabezpieczenie: naprawa kodu
Naprawa jest banalnie prosta: dane użytkownika należy zawsze przekazywać jako argument danych, nigdy jako łańcuch formatujący.
// WRONG:
printf(buffer);
// RIGHT:
printf("%s", buffer);
// Compiler warning:
// gcc -Wformat-security will flag thisFormat string w innych językach
Podatności format string występują w wielu językach:
- C:
printf(input) - Python: to nie to samo — jednak formatowanie za pomocą
%z danymi słownikowymi może ujawniać zmienne - Java:
String.format(input)— jest mniej niebezpieczne i nie umożliwia dostępu do pamięci
Przykłady z rzeczywistego świata
Błędy format string dotknęły między innymi:
- ProFTPD — umożliwiały zdalne wykonanie kodu za pośrednictwem poleceń FTP
- WU-FTPD — zdalny exploit umożliwiający uzyskanie uprawnień roota za pomocą format string
- Różne demony systemu Linux sprzed 2000 roku
Współczesne kompilatory i FORTIFY_SOURCE pomagają, ale nie eliminują całkowicie tej klasy podatności.
Szybki test: format string
Którego specyfikatora formatu można użyć do zapisu pod dowolnym adresem pamięci w ataku format string?
Podsumowanie lekcji
Podatności format string występują, gdy dane użytkownika są bezpośrednio używane jako łańcuch formatujący funkcji printf. %p/%x ujawnia pamięć stosu; %s odczytuje dane spod dowolnych adresów; %n zapisuje pod dowolnymi adresami. Naprawa wymaga jednego znaku: printf("%s", input). Należy włączyć -Wformat-security w opcjach kompilatora, aby wykrywać te błędy.
Często zadawane pytania
Czy lekcja „Podatności format string” jest bezpłatna?
Tak — pełny tekst „Podatności format string” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Cyber Security Academy, przejdź na CoddyKit PRO. Kurs Cyber Security Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Podatności format string”?
Wykorzystają Państwo ciągi formatujące printf do odczytywania dowolnych obszarów pamięci i zapisywania pod dowolnymi adresami. Ćwiczysz Cyber Security Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Cyber Security Academy?
Nie wymagamy żadnego doświadczenia. Cyber Security Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Podatności format string”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Cyber Security Academy?
Tak. Każda lekcja Cyber Security Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Przepełnienia bufora stosu
- Programowanie zorientowane na zwroty (ROP)
- Podatności format string
- Wykorzystanie sterty: use-after-free i heap spraying