Paweł Goleń, blog

Nie spodziewałem się, że mój poprzedni wpis zaowocuje tak dużą ilością komentarzy. Tak, pytanie o to, czy gra ma sens, jest nieco przewrotne. Odpowiedź na to pytanie zależy od tego, co uznamy za sensowność. Z grubsza (na dłuższą metę) mogą zajść trzy sytuacje:

  • gracze i organizator gry wychodzą na zero,
  • gracze są stratni,
  • organizator gry jest stratny,

W komentarzach utworzyły się dwie partie. Według części komentujących w grze wychodzi się “na zero”, według innych – organizator gry musi dopłacać do interesu (pojawia się też trzecia partia obstająca za trzecią możliwością – zarobkiem dla kasyna). I tutaj jest kolejna przewrotność: zgadywanka. Tu nie chodzi o zgadywanie, tylko o fakty.

Czytaj dalej...

Wyobraźmy sobie następującą grę. W skrzyni znajduje się 10 kul, z czego 1 może być czarna. Prawdopodobieństwo, że czarna kula znajduje się w skrzyni wynosi ½. Zadaniem gracza jest właściwe odgadnięcie, czy w skrzyni znajduje się czarna kula. Gracz może:

  • udzielić odpowiedzi natychmiast,
  • raz wylosować dowolną, z góry zadeklarowaną, liczbę kul,

Przystąpienie do gry kosztuje 50 PLN. Za prawidłową odpowiedź gracz otrzymuje 100 PLN, przy czym kwota jest pomniejszana o 5 PLN za każdą wylosowaną kulę.

Przykładowo: gracz przystępuje do gry, deklaruje wylosowanie 3 kul. Jedna z kul jest czarna, więc oczywiście odpowiada (prawidłowo), że w skrzyni znajduje się czarna kula. Otrzymuje 85 PLN (100 – 3 * 5 = 100 – 15 = 85 PLN).

Pytanie: czy ta gra ma sens?

Oryginał tego wpisu dostępny jest pod adresem Zgadywanka: czy to ma sens?

Autor: Paweł Goleń

Kontynuuje ten interesujący chyba tylko dla mnie temat odzyskiwania sekretu z jego kawałków. Korzystając z poprawionej wersji skryptu, postanowiłem przeprowadzić prosty eksperyment, który pozwoli z grubsza oszacować ilość próbek, które należy przechwycić, by ustalenie sekretu było możliwe. To tak z ciekawości jak będzie się to miało do liczby prób uwierzytelnienia, które malware musi podpatrzeć (wie, o które znaki system pyta!), by odgadnąć całe hasło. Pisałem na ten temat wiele razy, ostatnio (chyba) tutaj: Hasła maskowane. Znowu.

Czytaj dalej...

Jeszcze raz powrót do poprzedniego tematu. Przerobiłem swój skrypt na nieco mniej naiwną formę. Z ciekawości uruchomiłem go na jednym zestawie danych wejściowych, przy czym kolejność haseł była losowa. Wszystkich, poza pierwszym przypadkiem, który był brany bezpośrednio z poprzedniego wpisu. Nie można porównywać wprost czasów działania obu wersji skryptu (różne maszyny). Różnica pomiędzy poszczególnymi przypadkami w obrębie jednego zestawu haseł jest jednak bardzo widoczna:

['avSffipDyj', 'JaSyfapyb', 'aSyfipyi', 'avSfapDb', 'avSfpDy', 'ayfpji', 'JyffDb', 'vSfiyb', 'vaybj', 'ffpDb'] 0.411000013351 ['ffpDb', 'avSfapDb', 'vaybj', 'avSfpDy', 'JaSyfapyb', 'avSffipDyj', 'vSfiyb', 'aSyfipyi', 'JyffDb', 'ayfpji'] 1056.74699998 ['aSyfipyi', 'avSffipDyj', 'ffpDb', 'avSfpDy', 'vSfiyb', 'JaSyfapyb', 'avSfapDb', 'vaybj', 'JyffDb', 'ayfpji'] 38.4509999752 ['vSfiyb', 'avSfapDb', 'aSyfipyi', 'ffpDb', 'avSffipDyj', 'vaybj', 'avSfpDy', 'ayfpji', 'JyffDb', 'JaSyfapyb'] 174.740999937 ['avSffipDyj', 'JyffDb', 'ffpDb', 'JaSyfapyb', 'aSyfipyi', 'vSfiyb', 'ayfpji', 'vaybj', 'avSfapDb', 'avSfpDy'] 3.45799994469 ['avSfpDy', 'aSyfipyi', 'JaSyfapyb', 'ayfpji', 'avSfapDb', 'vaybj', 'JyffDb', 'avSffipDyj', 'ffpDb', 'vSfiyb'] 25.5379998684 ['avSfpDy', 'aSyfipyi', 'avSffipDyj', 'vaybj', 'JaSyfapyb', 'vSfiyb', 'ayfpji', 'ffpDb', 'avSfapDb', 'JyffDb'] 87.6420001984 ['JyffDb', 'avSfapDb', 'avSfpDy', 'avSffipDyj', 'vaybj', 'aSyfipyi', 'vSfiyb', 'ffpDb', 'JaSyfapyb', 'ayfpji'] 290.555999994 ['ayfpji', 'ffpDb', 'vaybj', 'avSfapDb', 'vSfiyb', 'aSyfipyi', 'avSffipDyj', 'avSfpDy', 'JaSyfapyb', 'JyffDb'] 734.882999897 ['aSyfipyi', 'vSfiyb', 'avSffipDyj', 'avSfpDy', 'JaSyfapyb', 'ffpDb', 'vaybj', 'avSfapDb', 'ayfpji', 'JyffDb'] 84.8340001106 ['JyffDb', 'vSfiyb', 'avSfapDb', 'avSffipDyj', 'ayfpji', 'aSyfipyi', 'avSfpDy', 'vaybj', 'ffpDb', 'JaSyfapyb'] 180.236000061 ['ayfpji', 'vaybj', 'aSyfipyi', 'avSfapDb', 'vSfiyb', 'avSffipDyj', 'ffpDb', 'avSfpDy', 'JyffDb', 'JaSyfapyb'] 478.786000013 ['aSyfipyi', 'avSfapDb', 'ayfpji', 'avSfpDy', 'vSfiyb', 'vaybj', 'ffpDb', 'JyffDb', 'JaSyfapyb', 'avSffipDyj'] 37.1860001087 ['JyffDb', 'vaybj', 'ayfpji', 'avSfpDy', 'ffpDb', 'aSyfipyi', 'avSffipDyj', 'vSfiyb', 'JaSyfapyb', 'avSfapDb'] 530.560000181 ['ayfpji', 'ffpDb', 'vaybj', 'vSfiyb', 'avSffipDyj', 'JaSyfapyb', 'avSfpDy', 'aSyfipyi', 'avSfapDb', 'JyffDb'] 879.066999912 ['avSfapDb', 'avSfpDy', 'vSfiyb', 'ffpDb', 'avSffipDyj', 'JyffDb', 'vaybj', 'ayfpji', 'JaSyfapyb', 'aSyfipyi']

Ostatni przypadek zakończył się niepowodzeniem, wyleciał wiele mówiący wyjątek MemoryError. Akurat ten wyjątek był skutkiem mojego błędu (nie usuwałem między krokami identycznych masek).

Po drobnych poprawkach i wprowadzeniu funkcji sortującej, przypadki testowe z poprzedniego przykładu teraz wykonują się znacznie szybciej (posortowane dane wejściowe, czas wykonania).

['gAdeOkmouk', 'gdyOkmusk', 'OgdyOmou', 'OAdeOaok', 'OyOamsk', '6OAeOks', 'yekamu', '6yeOmo', 'Oyauk', 'Aeao'] 1.2990000248 ['aSyfipDyji', 'vyfiaDbji', 'Jvyfipybj', 'avfiybi', 'JffaDji', 'avyiybi', 'vSfipy', 'avyaj', 'yiybi', 'ypDy'] 0.599999904633 ['OgeOkmosk', 'Ogdykausk', 'Odyeamok', 'OgOkmusk', 'gdykaou', '6OAeOks', 'OAdekos', 'gdyOao', 'gAyOk', 'OAeO'] 2.882999897 ['avSffipDyj', 'JaSyfapyb', 'aSyfipyi', 'avSfapDb', 'avSfpDy', 'ayfpji', 'JyffDb', 'vSfiyb', 'vaybj', 'ffpDb'] 0.365000009537 ['vSyfiybi', 'JSffiDyb', 'avSfpDbi', 'JffiDy', 'Jvfbji', 'vSayi', 'aSaji', 'JaSfy', 'JSaj', 'Sfpy'] 9.55900001526

To teraz można się zabrać za wymyślanie haseł wyjątkowo trudnych do złamania w ten sposób ;)

Oryginał tego wpisu dostępny jest pod adresem Kolejność ma znaczenie II

Autor: Paweł Goleń

Kontynuacja wpisu Hasła maskowane inaczej. Załóżmy, że mamy sekret:

123456

oraz dysponujemy następującymi hasłami jednorazowymi:

2346 356 125 236

Czy kolejność, w jakiej będziemy brać pod uwagę poszczególne hasła jednorazowe wpływa na efektywność odzyskiwania sekretu?

Czytaj dalej...

Podczas ostatniej dyskusji na temat haseł maskowanych pojawiła się sugestia, że jeśli atakujący “nie widzi”, które znaki są wpisywane, wówczas odgadnięcie pełnego hasła jedynie na podstawie przechwyconych fragmentów haseł, jest trudne. No, w każdym razie trudniejsze. Temat już wówczas mnie zaintrygował, ale Q4 zbliżał się nieubłaganie i temat zarzuciłem. Pora wrócić do tego tematu.

Czytaj dalej...

Tytuł tego wpisu jest celowo mylący, wcale nie mam zamiaru debatować. Chcę natomiast odnieść się do tego komentarza. Adam napisał:

Nie rozumiem ludzi którzy korzystają z takich bajerów jak zapamiętywanie haseł za pośrednictwem programów czy serwerów, kiedy wystarczy sobie napisać własną funkcję i miksować 1 hasło przez url + md5, base64 itd, a na koniec np ucinać do 10 znaków i w 2ga stronę nie jest to możliwe do odtworzenia w praktyce.

Różnica między KeePass a opisanym przez Adama podejście jest taka, że hasło generowane przez KeePass jest losowe (właściwie: może być losowe, jeśli użytkownik sobie takie wygeneruje), natomiast hasło uzyskiwane w wyniku opisanej metody jest “wyprowadzane” na podstawie kilku danych wejściowych. Jeśli ktoś będzie w stanie odgadnąć “hasło główne” oraz ustalić sposób “wyliczania” hasła “docelowego”, będzie w stanie uzyskać hasło dla dowolnej strony. Mamy tutaj security through obscurity (tajny sposób “wyliczania” hasła) oraz swoisty class break. Co z tego wynika? Nic.

Czytaj dalej...

Głębokie ukrycie doczekało się wpisu na Wikipedii. I wszystko byłoby w porządku, gdyby nie ten przykład:

http://example.com/29d9283aba927109a289b03812738d89201/2873944786672/10284.pdf

Wydaje mi się, że na temat trzeba spojrzeć nieco z szerszej perspektywy. A przy okazji – moim zdaniem głębokie ukrycie nie do końca zasługuje na oddzielny wpis w Wikipedii. Na dobrą sprawę jest to pewna forma security through obscurity, która w dodatku, w pewnych przypadkach i do pewnego czasu, działa.

Czytaj dalej...

Pokazanie przykładów niewłaściwego encodingu mamy za sobą (patrz: #1, #2, #3, #4 i #5). Na koniec przykład: http://bootcamp.threats.pl/lesson09b/, w którym encoding jest realizowany za pośrednictwem ESAPI (konkretnie owasp-esapi-php, jest to jeszcze wersja nieprodukcyjna). Dane wpisane przez użytkownika wypisywane są w trzech miejscach, w których encodowane są przy pomocy funkcji:

Funkcja doStuff obecnie coś robi, konkretnie wypisuje wartość otrzymanego parametru w drugim textarea. Zrobiłem to po to, by każdy mógł się przekonać, że te dziwne znaczki, które generuje ESAPI to rzeczywiście to, co zostało oryginalnie przekazane. A te dziwne znaczki wyglądają tak:

Dla encodeForJavaScript w kontekście atrybutu HTML:

demo 1

Dla encodeForJavaScript i encodeForHTMLAttribute w kontekście atrybutu HTML:

demo 2

Jeszcze raz dla encodeForJavaScript , tym razem w kontekście skryptu:

Mam nadzieję, że ten przykład wystarczająco dobrze pokazuje, że:

  • encoding może być prosty, wystarczy wywołać odpowiednią dla kontekstu funkcję,
  • encoding może być skuteczny (ktoś potrafi obejść encoding implementowany przez ESAPI i wykorzystany w tym przykładzie?),
  • mimo encodingu wszystko może nadal działać,

I tym optymistycznym akcentem kończę ten temat. Przynajmniej na jakiś czas.

Oryginał tego wpisu dostępny jest pod adresem Encoding: ESAPI

Autor: Paweł Goleń

Pora na zakończenie tematu przykładu z niewłaściwym encodingiem (patrz: #1, #2, #3 i #4). Ponownie, by nie przeciągać, dla tradycyjnego zestawu znaków testowych otrzymujemy:

Czy można tu coś zepsuć?

Czytaj dalej...