Bug w Visual Studio – serio?

Ostatnio sporo szumu wywołała informacja o bug-u Visual Studio, który kosztował pewnego człowieka prawie 6.5k$ (https://www.humankode.com/security/how-a-bug-in-visual-studio-2015-exposed-my-source-code-on-github-and-cost-me-6500-in-a-few-hours).  Tak czytając to i kilka innych postów dochodzę do wniosku, że mamy do czynienia z ciągiem małych błędów i niedopatrzeń, które się skumulowały i koniec końców uderzyły w tego na samym końcu.  Po pierwsze bug we wtyczce do GitHuba (nie w Visual Studio a w zewnętrznej wtyczce). W sumie mały błąd, niewielkie niedopatrzenie, ot jeden checkbox nie działający poprawie, tyle tylko, że stworzyło się publiczne repo a nie jak sądził developer – prywatne.

Wpadka….

Jak doszło zatem do tego, że 6485.39$ zniknęło z kieszeni (i pewnie kilka siwych włosów doszło w pakiecie? Nie, nie na głowie). Do repo poszły klucze do aws-a a że taki artefakt to cenna rzecz, jest wiele botów skanujące publiczne repozytoria w poszukiwaniu właśnie takich cukierków. To pozwoliło komuś zespawnować sporo maszyn np. do kopania bitcoinów za darmo (a raczej na koszt kogoś innego). No i tu pierwszy błąd developera. Tak cennych rzeczy nie wrzuca się do repo (nawet prywatnego) bo nigdy nie wiadomo, kiedy i gdzie stracimy nad tym kontrole. Serio patrz co wrzucasz do repozytorium. Czasem można znaleźć bardzo fajne rzeczy, jakieś prawdziwe numery pesel, connection stringi do baz danych (niektórych nawet publicznie dostępnych), nazwy użytkowników, hasła, numery telefonów i wszelkie klucze do API różnej maści. Naprawdę, takich rzeczy nie wrzucamy do kodu KROPKA. Bardzo Gość przynajmniej powinien to zaszyfrować!… ale serio? Czym by to rozszyfrowywał? Kodem? Tym, który jest w repo? Tym który był publiczny? Kolejny kiepski pomysł – w osobnym pliku niecommitowanym do repozytorium. Brzmi lepiej ale dalej słabo bo jeden mały błąd, jedna niedokonfigurowana maszyna ze złym gitignore i plik by wyleciał w sieć (tylko wtedy byłoby jaki to git zły bo przez niego straciłem 6500$).

Najlepiej by było, gdyby tego typu rzeczy w ogóle nie trafiały do repozytorium.

Do tego celu w Azure i AppHarbor i Heroku i pewnie w wielu innych służą zmienne środowiskowe czy jak to nazwać.

azure

Generalnie działa to tak, że super tajne ważne rzeczy wpisujemy (tu w przypadku azure-a) wpisujemy w sekcji connection strings lub app settings. Cały myk polega na tym, że aplikacja zamiast czytać z jakiegoś pliku czyta ze zmiennych systemowych/środowiskowych/przetworzonego configa. Analogicznie działa ten mechanizm w AppHarbour.

appharbour

Korzystam z tego w mvc oraz w nodzie i działa i da się. Kod jest czysty i może być publiczny. Co więcej nie muszę się zastanawiać za każdym razem, czy przypadkiem nie commituję pliku z tajnymi kluczami do storage-a czy czegoś tam innego.

Wracając do tematu, kolejny fackup. Czy serio w Amazonie nie można mieć różnych klucze do różnych zasobów? Wszystko jest dostępne z jednego klucza? Dzięki czemu można wydrenować podpiętą kartę? Inna sprawa dlaczego nie można (a może można tylko jak) ustawić limitów? Czy może jest jakiś sposób aby mieć konto „prepaid”.

Ostatnie ale pewnie najmniej ważne

Jeśli korzystam z publicznego serwera ale zakładam prywatne repo to robię to przez stronę dostawcy i sprawdzam czy aby na pewno repo jest tak stworzone jak chcę.  Tak samo upubliczniając jakiś zasób w OneDrive czy DropBox-ie. Jeśli chcę upublicznić jakiś zasób jednej osobie – to sprawdzam w trybie porno czy na pewno to jest dalej prywatne a nie publiczne.

Co wynikło zatem z całej tej afery?

Imho kilka dobrych rzeczy:

  • Amazon anulował rachunek i skontaktowali się z gościem, więc jest szansa, że wyciągną wnioski i wprowadzą jakieś ciekawe sposoby aby uniknąć takich rzeczy w przyszłości
  • Wtyczka do Visual Studio została naprawiona
  • Mam nadzieję, że nikt świadomie nie wsadzi API keys i innych sensytywnych wrażliwych danych do kodu i innych plików commitowanych do repozytorium – a przynajmniej zastanowi się dwa razy
  • Mam również nadzieję, że pokazałem alternatywne rozwiązanie w postaci app settings i connection string