O wyciąganiu (błędnych) wniosków
Trzeba wyciągać wnioski, z tego, co się już wie. Sam tak uczyłem się jeździć na rolkach (bez ochraniaczy). Po dwóch bliskich spotkaniach z podłożem wyciągnąłem prosty wniosek – to boli. Był on może niezbyt błyskotliwy, ale motywował mnie bardzo skutecznie do tego, by raz popełnionych błędów nie powtórzyć w przyszłości. Ta metoda nauki zadziałała w moim przypadku bardzo dobrze, obyło się bez złamań, choć kilka efektownych spotkań z ziemią jeszcze udało mi się zaliczyć :) Tak samo w drugą stronę, jeśli jakieś działanie osiągnie pożądany skutek, należy je powtarzać (co oczywiście nie wyklucza poszukiwania lepszych rozwiązań). Ten wzorzec postępowania wpaja się nam, przedstawicielom homo sapiens , od najmłodszych lat. Stosujemy go nawet tam, gdzie nie do końca pasuje. Dziś kilka słów o wyciąganiu błędnych wniosków, a właściwie czynieniu błędnych założeń, w trakcie testów bezpieczeństwa aplikacji.
Czasami mam wrażenie, że programiści są wiernymi uczniami Sun Tzu , szczególnie w zakresie nauki o konieczności zaskoczenia przeciwnika i działaniach niekonwencjonalnych. O co chodzi? O to, że bardzo często aplikacje są niespójne. Nie wynika to oczywiście z tego, że złośliwi programiści w przypływie dobrego (czarnego?) humoru postanowili o czymś “zapomnieć” lub w tym-jednym-przypadku zrobić coś inaczej, niż wszędzie do tej pory. Powody są bardziej trywialne, na przykład:
- programistów jest wielu, mają różne umiejętności, te same rzeczy robią w różny sposób,
- aplikacje nie stają się lecz są rozwijane, często przez dłuższy czas i różnych programistów,
- korzystający ze sprawdzonego wzorca projektowego copy-and-paste , kopiowali z różnych źródeł,
- programiści działają pod presją czasu i by zdążyć na czas, idą na skróty ,
- (...),
Im aplikacja jest większa i starsza , tym większe jest prawdopodobieństwo, że będzie ona w rzeczywistości patchworkiem różnych technologii, frameworków, wzorców projektowych i błędów... Refaktoring systemu wciąż czeka na lepsze czasy. W skrajnych dwa parametry tego samego typu na tej samej formatce mogą być obsługiwane w zupełnie inny sposób , przez co wnioski wyciągnięte przy testowaniu parametru A mogą nie być prawdziwe dla sąsiedniego parametru B...
W tej chwili przypomina mi się pewien cytat:
Mamy znane wiadome. Rzeczy, o których wiemy, że je wiemy. Wiemy również, że istnieją znane niewiadome. Innymi słowy, wiemy, że są pewne rzeczy, których nie wiemy. Ale są również nieznane niewiadome – takie, o których nie wiemy, że ich nie wiemy.
Sytuacja, w której aplikacja jest w oczywisty sposób niespójna jest oczywiście zła i sama w sobie może być przesłanką co do prawdopodobieństwa istnienia w niej podatności lub wystąpienia ich w przyszłości. Niewątpliwą zaletą jest fakt, że jest to swoista znana niewiadoma. Wiemy, że aplikacja jest niespójna, więc nie możemy robić żadnych założeń w oparciu o dotychczasowe wyniki testów.
Dużo gorszą sytuacją jest przypadek, w którym nie wiemy (jeszcze) o tym, że aplikacja jest niespójna. Jesteśmy nawet przekonani, że jest wprost przeciwnie (do do tej pory jest/była spójna). To ten przypadek, w którym nie wiemy, że nie wiemy. Jeśli na 15 formatkach wszystkie wystąpienia pola określonego typu (np. daty) były poprawnie walidowane, to w kolejnych przypadkach sprawdza się to już wyrywkowo (redukcja przypadków testowych), aż trafia się na wyjątek rzekomo potwierdzający regułę... Albo co gorsza – nie trafia się (pół biedy), ale trafia na ten przypadek ktoś inny (cała bieda).
W tej chwili warto zastanowić się chwilę nad OWASP Application Security Verification Standard, na przykład nad takim punktem:
V5.2 Verify that a positive validation pattern is defined and applied to all input.
Jak należy rozumieć w tym przypadku all? Z jednej strony wystarczy wskazać jeden przypadek, w którym takiej walidacji nie ma by stwierdzić, że aplikacja nie spełnia tego wymagania, z drugiej strony stwierdzenie, że aplikacja spełnia ten warunek wymaga, przynajmniej w teorii, sprawdzenia każdego parametru, który przez aplikację jest akceptowany.
Osiągnięcie pełnego pokrycia aplikacji takimi testami jest możliwe, ale wraz ze wzrostem złożoności aplikacji coraz trudniejsze i, co tu dużo mówić, droższe. Ciekawym tematem może być kwestia wyboru odpowiedniej próby reprezentatywnej parametrów, na badania podstawie której, z odpowiednim/założonym prawdopodobieństwem, można wnioskować o bezpieczeństwie badanej aplikacji (przy okazji zwracam uwagę, że przy analizie ryzyka uwzględnia się nie tylko co może się stać i jak bardzo ZŁE to jest oraz z jakim prawdopodobieństwem może się to stać , ale również to, jak pewne są odpowiedzi na poprzednie dwa pytania).
Macie jakieś pomysły/propozycje w tym temacie? Czy jest to możliwe bez wcześniejszego “ujednolicenia” aplikacji?
Oryginał tego wpisu dostępny jest pod adresem O wyciąganiu (błędnych) wniosków
Autor: Paweł Goleń