Jak bezpiecznie debugować aplikację internetową PHP bez ujawniania tajemnic konkurencji?

11

Ostatnio stworzyłem program. Zapomniałem usunąć 2 linie kodów. Ten błąd kosztował mnie 800 USD dziennie.

Programowałem z PHP. Jeśli użytkownik korzysta z serwera proxy, przekierowuje go w inne miejsce. Korzystanie z debuggera było niemożliwe, ponieważ część kodu zawiera moduł jonowy. Ponieważ program po prostu przekierowuje gdzie indziej, bez względu na wszystko, trudno jest zobaczyć, która część kodu jest wykonywana.

Dlatego wszędzie umieszczam informacje o debugowaniu. Pomyślałem, że i tak je usunę.

Najbardziej naturalnym sposobem debugowania jest oczywiście umieszczenie informacji debugujących w pliku. Problem w tym, że często używam proxy. Dlatego po zmianie programu często muszę pobrać plik tekstowy za pomocą filezilla. Często plik tekstowy nie pokazuje tego, co moim zdaniem powinien pokazać. W końcu postanowiłem po prostu wyświetlić błąd w sieci.

Rozważałem tryb debugowania. Obawiam się jednak, że zapomnę usunąć informacje debugowania.

Zastanawiałem się nad trybem debugowania, jeśli użytkownik na przykład? Tryb debugowania = 1. Byłem jednak paranoikiem, że mój konkurent może odgadnąć tajne słowo kluczowe.

Usunąłem większość informacji debugujących. Zapominam usunąć jeden, a ten pojawia się tylko wtedy, gdy użytkownicy korzystają z serwera proxy z właściwego kraju. Okazuje się, że nie mam pełnomocnika z właściwego kraju i nie zdawałem sobie z tego sprawy. Po 24 godzinach działania programu przesłałem go do mojej głównej domeny.

Mój konkurent, używając proxy, widzi kod debugowania. Kopiuje pomysł i tak traciłem 800 $ dziennie.

Z perspektywy czasu naprawdę trudno mi zrozumieć, gdzie popełniłem błąd. Byłem bardzo ostrożny. Ale to się stało.

Jak bezpiecznie debugować aplikację internetową PHP bez ujawniania tajemnic konkurencji?

użytkownik114310
źródło
5
Nie ma absolutnie żadnej pewności, a co dopiero oprogramowania wolnego od błędów.
Tar
1
Dokładne testowanie raz po raz po każdej zmianie wprowadzonej w programie / aplikacji, nawet jeśli jest to bardzo mała zmiana.
Rolen Koh
16
„Jak bezpiecznie debugować aplikację internetową, nie ujawniając tajemnic konkurentom?” - tworząc środowisko testowe naśladujące środowisko produkcyjne. Debugowanie na żywo powinno być naprawdę bardzo rzadko konieczne.
CodeCaster
8
Zastanawiam się, co może być tak krytycznego w dwóch liniach kodu debugującego, że jest on wart 800 $ dziennie. Czy to zrzuca twój prywatny klucz crpytographic?
Philipp
2
Jeśli wcześniej zarabiałeś ponad 800 USD dziennie ... czy to w ogóle ma znaczenie? Ale tak, nie uruchamiaj kodu debugowania na żywo! Możesz mieć wartość logiczną trybu debugowania konfiguracji w pliku. Kod debugowania jest drukowany tylko wtedy, gdy debug == true. Jest to co najmniej szybki i brudny sposób, nie warta odpowiedzi!
Anon343224user

Odpowiedzi:

37

Naprawdę trudno mi zrozumieć, gdzie popełniłem błąd

Głównym błędem było to, że wymyśliłeś koło na nowo. Zamiast używać domyślnych mechanizmów do rejestrowania, wymyśliłeś własny , który wyświetlał informacje na stronie. Struktura rejestrowania woli przechowywać dzienniki w plikach dziennika, umożliwiając późniejsze przejrzenie tych dzienników przez SSHing na serwerze.

Jeśli chodzi o błędy, tworzenie kodu wolnego od błędów wymaga użycia określonych technik, takich jak formalny dowód . Biorąc pod uwagę ich kosztowność, techniki te są odpowiednie do aplikacji o krytycznym znaczeniu dla życia, takich jak aplikacje kontrolujące ruch statków powietrznych lub promy kosmiczne, ale stanowią przesadę w prawie każdej aplikacji biznesowej.

■ Zobacz: Piszą właściwe rzeczy w magazynie Fast Company.
W artykule opisano metodologię stosowaną w NASA, a także koszty produkcji oprogramowania w ten sposób.

■ Patrz Mechanizing Proof (Mackenzie 2004).
Książka podsumowuje historię zautomatyzowanego dowodu oprogramowania, wyjaśniając zalety i wady takiego dowodu, a także powody, dla których firmy nie są powszechnie używane do pisania niezawodnego oprogramowania.

Biorąc to pod uwagę, istnieje wiele technik stosowanych w aplikacjach biznesowych w celu zapewnienia jakości oprogramowania. Obejmuje to między innymi:

  • Nieformalne przeglądy kodu,
  • Formalne kontrole kodu,
  • Testowanie,
  • Osobiste sprawdzanie kodu,
  • itp.

■ Patrz Kod pełny (McConnell 2004), Programowanie produktywności (Jones 1986a), Efektywność usuwania wad oprogramowania (Jones 1996) i Czego się nauczyliśmy o zwalczaniu wad (Shull i in. 2002).

Nie zapomnij również o ciągłej integracji i ciągłej dostawie. Pomaga w automatycznym przywracaniu aplikacji do wersji produkcyjnej, gdy poprawiona wersja wydaje się mieć problem, który został pominięty podczas przeglądów kodu i testów jednostkowych, ale został wykryty po wdrożeniu aplikacji.

■ Zobacz Sekret bezpiecznego bezpiecznego ciągłego wdrażania (wideo)
Wyjaśnia, jakie techniki zostały skonfigurowane w Google, aby zapobiec błędom, których nie można było znaleźć przed wdrożeniem, przez zbyt długi czas produkcji. Opisuje również, w pdiffjaki sposób został wykorzystany do wychwycenia błędów, w tym tych niezwiązanych z warstwą prezentacji.

Arseni Mourzenko
źródło
13

Nigdy nie powinieneś debugować w produkcji.

Zawsze powinieneś mieć środowisko testowe identyczne ze środowiskiem produkcyjnym i tam debugować.

Gdy musisz zmienić kod w środowisku testowym (np. W celu dodania instrukcji debugowania), upewnij się, że nie zostaną one wprowadzone do środowiska produkcyjnego.

Profesjonalna konfiguracja zwykle wygląda następująco:

Production
   ^
Staging
   ^
Development

Instancje „Production”, „Staging” i „Development” Twojej aplikacji powinny być możliwie identyczne, aby błąd występujący w „Production” mógł zostać odtworzony w „Staging” i „Development”, ale nadal być całkowicie oddzielony od nawzajem, aby cokolwiek wydarzyło się w jednym przypadku, nie wpłynęło na inne.

Kiedy musisz przeanalizować problem, robisz to w „Programowaniu”. Zgromadź instrukcje debugowania i eksperymentuj, ile chcesz. Po znalezieniu rozwiązania, zastosujesz tę poprawkę do niezmienionej bazy kodu w „Staging” i sprawdzisz, czy poprawka działa. Następnie promujesz poprawkę do „Produkcji”.

Odpowiedni system kontroli wersji i zarządzania kompilacją może ci w tym pomóc.

Philipp
źródło
1
To jest to co zrobiłem. Najpierw debuguję w innych domenach. Następnie przechodzę do nowych. Jednak błąd w tej innej domenie nadal tam był.
user114310
1
@ user114310, Twoje środowisko programistyczne / testujące po prostu nie powinno być dostępne dla świata zewnętrznego (albo na lokalnym hoście, albo wymagające VPN, lub podobnego). Jeśli wstawiłeś jakiś kod debugowania i nie usunąłeś go przed przejściem do produkcji, to jest to błąd ludzki i nie ma nic technologicznego, co mogłoby go ochronić; po prostu bądź bardziej ostrożny.
Brian S
3
@ user114310 Przepraszamy, nie rozumiem. Naprawiłeś błąd w przygotowaniu, ale kiedy zastosowałeś tę poprawkę do produkcji, błąd nadal tam był? Oznaczałoby to, że błąd nie został poprawnie odtworzony i przypadkowo naprawiono coś innego. Jeśli nie można odtworzyć błędu w fazie programowania, oznacza to, że środowisko programistyczne nie jest identyczne ze środowiskiem produkcyjnym. Kiedy odkryjesz, że musisz to naprawić, zanim będziesz mógł właściwie zbadać błąd.
Philipp
4

Jest to rzadko wykonywane, ponieważ wysiłek nie jest opłacalny. Nawet jeśli stracisz 800 $ dziennie, wysiłek udowodnienia, że ​​program jest poprawny szybko staje się większy, co oznacza, że ​​nie ma uzasadnienia biznesowego, aby to zrobić.

Jeśli pewność jest tego warta (np. W przypadku oprogramowania Space Shuttle lub kontroli rakietowej), wówczas przeprowadzasz formalną weryfikację, wyczerpujące testy wszystkich możliwych danych wejściowych itp. Oczywiście, jest to również niezwykle trudne, a także powolne i kosztowne. Ale projekty z budżetami wartymi miliardy dolarów mają też zwykle bardzo błyskotliwych ludzi. (A może po prostu kiedyś - dzisiejsze nagłówki wydają się zaprzeczać tej zasadzie).

Kilian Foth
źródło
1
Nawet NASA źle to rozumie. Możesz włożyć tyle wysiłku, ile chcesz, ale niektóre rzeczy są po prostu poza ludzkim zrozumieniem, a zatem bardzo trudno je zapewnić.
Phoshi
1
+1: Weryfikacja formalna jest rzeczą, dobrze byłoby, gdybyś mógł bardziej szczegółowo o tym powiedzieć. Wiem, że to jest coś, ale nie mam słów, aby znaleźć więcej szczegółów. Np. Weryfikacja poprzez przetestowanie wszystkich danych wejściowych, redukcja do skończonej statystyki, redukcja do logiki pierwszego rzędu. Jakie jest na to słowo? Czy ta weryfikacja jest dowodem? Myślę, że to jest.
Lyndon White
Istnieje weryfikacja formalna, ale istnieje także weryfikacja heurystyczna, która - choć nie jest pewna - może zapewnić weryfikację do pewnego poziomu ufności. Nie pamiętam wiele na ten temat ze studiów, ale jednym z narzędzi, które wykorzystaliśmy na kursie, był Spin, który moim zdaniem jest w stanie również wyczerpująco zweryfikować. Niektóre zawarte w nim opisy mogą odpowiadać poprawnemu słowu.
Rig
2

Czasami trzeba debugować system na żywo. Tak, powinieneś mieć kopię rozwojową lub testową. Ale zawsze będą różnice. Jest to szczególnie prawdziwe, jeśli kod działa na wolności na sprzęcie klienta. Lub potencjalnie wiele różnych instalacji klienta.

W przeszłości korzystałem z techniki & debugowania = 1 . Podejrzewam, że większość programistów PHP ma. To przerzuciło przełącznik w kodzie, który umożliwił bardziej pełne debugowanie w aplikacji. Informacje te zwykle byłyby zrzucane do pliku dziennika - zazwyczaj dziennika Apache (przy użyciu error_log ()). Ale możesz go również wydrukować. Na przykład nasz profiler zbierałby informacje, a następnie wyświetlał różne testy porównawcze na dole strony. Można również wyprowadzić informacje debugowania jako komentarz HTML lub w ukrytym elemencie, który jest widoczny tylko wtedy, gdy przeglądasz źródło strony.

Jeśli Twoja witryna ma „użytkowników”, możesz ograniczyć debugowanie tylko do konkretnego użytkownika. W ten sposób, jeśli ktoś spróbuje włączyć debugowanie, nadal nie będzie działać, dopóki nie zostanie zalogowany jako ten użytkownik.

Teraz wspomniałeś, że używasz FileZilla do łączenia się z serwerem. Deweloper naprawdę powinien mieć dostęp SSH do serwera. Ułatwi to debugowanie. Na przykład, jeśli wyprowadzasz swoje instrukcje debugowania na przykład do dziennika błędów Apache, możesz łatwo grepować ten plik na swój adres IP i zobaczyć informacje debugowania wygenerowane przez twoje ostatnie żądanie strony.

Grandmaster B.
źródło
1

Wszyscy inni opisali już ogólny przypadek:

Formalna walidacja (/ Sprawdzony kod): Nie jest to możliwe w przypadku programów z prawdziwego świata, chociaż istnieje jądro systemu operacyjnego o 4000 linii, co zostało formalnie udowodnione. Zajęło wielu rosyjskim doktorantom CS wiele miesięcy (proszę o komentarz, jeśli pamiętasz nazwę tego projektu)

Testowanie CI << Testy automatyczne << Testowanie : upewnij się, że używasz narzędzia pokrycia, aby sprawdzić, czy twoje przypadki testowe mają 100% pokrycia.

W konkretnym przypadku pozostawienia kodu debugowania w produkcji mam dwie opcje, z których obie wymagają ponownej kompilacji kodu źródłowego w ramach wdrożenia w nowym środowisku (testowanie / testowanie końcowe).

  1. Usuń go w czasie kompilacji. Zawijaj kod debugowania w strukturach takich jak C # i C, #ifdef DEBUGaby sprawdzić cel kompilacji (Debugowanie lub wydanie) i automatycznie usunąć je podczas kompilacji.

  2. Oflaguj go w czasie wdrażania. Umieść komentarz w pobliżu kodu, którego nie wolno uruchamiać w prawdziwym środowisku. Np. //TODO: Remove This Before DeploymentNastępnie, kiedy jest migrowany (wdrażany) do wersji testowej, przed skompilowaniem kodu, uruchom go za pomocą prostego skryptu, który sprawdza, czy //TODO:w kodzie źródłowym nie pozostały żadne komentarze flagowe (np. ).

Sugeruję pierwszy z nich, jeśli jest długoterminowy i będziesz chciał go ponownie (np. Pełny tryb rejestrowania), a później, jeśli jest to szybki hack podczas debugowania (np. Różne printfs rozrzucone po kodzie)

Lyndon White
źródło
0

Jak powiedzieli mi inni, wiele testów (jednostkowych i funkcjonalnych), jeśli to możliwe zautomatyzowanych i z dobrym pokryciem kodu, jest kluczem do posiadania oprogramowania, które w większości nie zawiera błędów.

Jeśli dobrze rozumiem opis twojego problemu, informacje debugowania są wyświetlane na stronie obsługiwanej przez twój serwer. W takim przypadku należy rozważyć umieszczenie tych informacji w odpowiednich dziennikach na serwerze. W ten sposób nigdy nie zostanie pokazany użytkownikowi końcowemu, nawet jeśli wdrożysz wersję „pełną” do wersji produkcyjnej. Jest to coś, co warto robić bez względu na projekt, nad którym pracujesz, chyba że masz bardzo dobre powody, aby zrobić inaczej.

KevinLH
źródło
0

To, co mówią inni o debugowaniu w produkcji, jest słuszne. Ale i tak czasami to robiłem. I myślę, że istnieją bezpieczniejsze sposoby na zrobienie tego niż twoje, chociaż nic nie jest niezawodne.

Sam nie potrzebuję tak wysokiego bezpieczeństwa, po prostu nie chcę, aby użytkownicy widzieli na swoich ekranach bełkot.

$debug = true;
$allowed_ips = array('192.168.0.220','173.46.89.255'); // limit to your own ip's. If your competitor knows them, though, he can spoof it! But if your stuff is not top secret, it's ok. 

if(!in_array($_SERVER['REMOTE_ADDR'],$allowed_ips) ) {
  $debug = false;
}

if($debug) {
  echo '<pre>' . print_r($some_variable) . '</pre>';
}

Teraz użytkownicy nie zobaczą twojego debugowania, chyba że naprawdę tego chcą. Jeśli Twoje 800 USD dziennie zależy od zachowania tych informacji debugowania w tajemnicy, nie używaj powyższego kodu . Ale jeśli informacje nie są tak wrażliwe, powyższe będzie znacznie lepsze niż zależenie od zmiennej GET lub ujawnienie swoich tajemnic całemu krajowi.

Alternatywnie możesz utworzyć debugklasę lub funkcję, która sprawdzi, czy drukowanie jest dozwolone, czy nie w oparciu o twoje kryteria. To jest to co robię.

Coś takiego:

class debug {
  public $on = false;
  public static function print($variable) {
    if($on) {
      echo '<pre>' . print_r($some_variable) . '</pre>';
    }
  }
}

debug::print($some_variable); // class checks if printing is allowed. If not, no printing occurs.

W przypadku mojego programu, który pozwoli mi zarobić 800 USD / dzień (w fazie rozwoju), używam modu Apache auth, aby wymagać hasła dostępu do dowolnej części witryny, a także ograniczać informacje debugowania do niektórych adresów IP. Twoje pytanie sprawia, że ​​myślę, że powinienem spojrzeć na lepsze bezpieczeństwo.

Buttle Butkus
źródło
0

Właściwie miałbym tutaj dwie dodatkowe weryfikacje. Jednym z nich jest &debug=1parametr w żądaniu. Możesz także użyć specjalnej zmiennej sesji lub ustawień plików cookie, które tylko Ty możesz aktywować poprzez wywołanie „tajnej” strony (najlepiej z uwierzytelnieniem).

Drugim sprawdzianem byłoby umieszczenie w pliku konfiguracyjnym tablicy z zakresem adresów IP i tylko wywołania z adresu IP w tej tablicy mogą wyzwalać funkcję debugowania. coś jak

W konfiguracji:

$debugAllowedIPs = array('127.0.0.1', '192.168.0.1', /* add more IPs here */);

Gdzieś, gdzie można uzyskać globalny dostęp, skorzystaj z następującej metody:

function getClientIp() {
    if (!empty($_SERVER['HTTP_CLIENT_IP']))  return $_SERVER['HTTP_CLIENT_IP'];
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) return $_SERVER['HTTP_X_FORWARDED_FOR'];
    return $_SERVER['REMOTE_ADDR'];
}

A w twoim kodzie wywołaj coś takiego:

if (in_array(getClientIp(), $debugAllowedIPs)) { /* show debug info here */ }

Należy pamiętać, że kod w getClientIp()metodzie nie jest bezpieczny, ponieważ wartość parametru $_SERVER['HTTP_X_FORWARDED_FOR']jest łatwa do sfałszowania, jednak powinna ona służyć uzyskaniu odpowiedzi na pytanie.

Tiamarkos
źródło