Automatyzujemy 2FA

W pracy od czasu do czasu potrzebujemy dostać się do serwera, który siedzi za srogimi firewallami i innymi VPN-ami. Nierzadko gdzieś tam po drodze trzeba wbić kod z generatora kodów jednorazowych w postaci aplikacji na smartfonie.

Pół biedy jeżeli robimy to raz na tydzień. Gorzej, jeżeli musimy się w ten sposób “męczyć” kilka razy dziennie. Zawsze jest ryzyko, że się palec omsknie przy wpisywaniu kodu, albo że akurat bateria w smartfonie padła i trzeba go najpierw podłączyć do prundu i tak dalej.

Jako osobnik kumaty leniwy lubię sobie automatyzować różne powtarzalne czynności, żeby mi nie zabierały za dużo czasu i ambarasu. Niedawno nauczyłem się jak zautomatyzować proces 2FA, dzielę się więc tą wiedzą z Czytelnikami – a nuż komuś się przyda?

Założenie jest takie, że siedzimy na Linuksie. Może też byc WSL2 (sprawdziłem, działa). Potrzebujemy też jednorazowego kodu QR do początkowego skonfigurowania aplikacji 2FA. Kod ten – w postaci pliku obrazka lub zwykłej naklejki – na ogół dostajemy od klienta, do którego się będziemy podłączać. Tutaj zakładam, że mamy plik obrazka. Jeżeli mamy tylko naklejkę, trzeba jej pstryknąć fotkę i zapisać w postaci pliku png.

Zaczynamy od zainstalowania niezbędnych programów: zbar-tools, oathtool i expect:

sudo apt install -y zbar-tools oathtool expect

Następnie uruchamiamy:

zbarimg /home/zbyszek/Downloads/kod-qr.png

(zastępujemy rzecz jasna powyższą ścieżkę do pliku png tym, co mamy u siebie)

W wyniku dostaniemy:

QR-Code:otpauth://totp/XXX@ZZZ?secret=YYY&issuer=ZZZ

XXX i ZZZ można teraz zignorować, natomiast YYY – długi, około 30-znakowy kod złożony z cyfr i wielkich liter – zapisujemy go sobie gdzieś na boku.

Teraz sprawdzamy, czy kod działa:

oathtool --totp --base32 YYY

(zamiast YYY wstawiamy nasz długi kod z poprzedniego kroku)

W odpowiedzi powinniśmy dostać jednorazowy kod sześciocyfrowy potrzebny do zalogowania się do systemu.

W zasadzie można by tutaj się zatrzymać, bo właśnie wyeliminowaliśmy z łańcucha zdarzeń konieczność sięgnięcia po smartfona w celu przepisania zeń kodu – zamiast tego możemy go teraz przepisać (albo nawet skopiować i wkleić) bezpośrednio z ekranu – ale pójdźmy dalej! Skoro mamy już ten kod (ważny na ogół przez około 60 sekund), spróbujmy teraz zautomatyzować cały proces logowania od A do Z.

Załóżmy, że oryginalnie nasz proces wygląda tak:

ssh byniek@mojserwer.pl -L 1234:mojserwer.pl:1234 -L 2345:mojserwer.pl:2345
Password:

…wpisujemy hasło, pukamy enter…

Verification code:

…sięgamy po smartfona i generujemy sześciocyfrowy kod 2FA, wpisujemy, pukamy enter i widzimy upragnione:

Tunnel started, shell disabled by the system administrator.

Naszym zadaniem będzie teraz wysłać automagicznie hasło i kod jednorazowy do procesu ssh. W tym celu skorzystamy z aplikacji expect (wnikliwy Czytelnik zauważy, że zainstalowaliśmy ją na samym początku), która potrafi do pewnego stopnia sterować aplikacją konsolową.

Napiszemy sobie teraz prościutki skrypt, któremu nadamy nazwę… dajmy na to zenon.sh:

#!/usr/bin/expect -f

set PASS "moje-haslo-do-ssh\r"
set CODE [exec oathtool --totp --base32 YYY]

spawn ssh byniek@mojserwer.pl -L 1234:mojserwer.pl:1234 -L 2345:mojserwer.pl:2345
expect "Password:"
send "$PASS"
expect "Verification code:"
send "$CODE\r"
interact

Wydarza się tutaj kilka całkiem interesujących rzeczy:

#!/usr/bin/expect -f

Linuksowcy wiedzą, reszcie tłumaczę: to jest tak zwany shebang, czyli mówimy systemowi jakiego programu ma użyć do wykonania reszty skryptu. Najczęściej można tam znaleźć #!/bin/bash ale my użyjemy expect.

set PASS "moje-haslo-do-ssh\r"

W expect zmienne ustawia się poleceniem set – tu ustawiamy zmienną PASS na nasze supertajne hasło, z enterem na końcu.

set CODE [exec oathtool --totp --base32 YYY]

Jeżeli chcemy, żeby zmienna przyjęła wartość wygenerowaną przez proces zewnętrzny, zamykamy wywołanie tego procesu w [exec ... ] – w tym przypadku do zmiennej CODE trafi nasz sześciocyfrowy kod jednorazowy. Uwaga: bez entera na końcu (dlatego dodajemy go potem).

spawn ssh byniek@mojserwer.pl -L 1234:mojserwer.pl:1234 -L 2345:mojserwer.pl:2345

Tutaj uruchamiamy (za pomocą spawn) aplikację ssh, która za chwilę zapyta nas o login i kod, a potem zestawi tunel.

expect "Password:"

Tu wydarza się największa magia aplikacji expect: będzie ona pilnie śledzić wszystkie teksty wygenerowane przez ssh aż natrafi na “Password:”

send "$PASS"

Za pomocą polecenia send wysyłamy do ssh nasze hasło (zapisane w zmiennej PASS). Przy okazji: zmienne tworzymy bez prefiksu $, ale używamy już z prefiksem.

expect "Verification code:"
send "$CODE\r"

Identycznie jak poprzednio, czekamy teraz na zapytanie o kod jednorazowy i wysyłamy go.

Skrypt kończymy poleceniem interact, które oddaje sterowanie do systemu operacyjnego.

Zapisujemy wszystko, jeszcze tylko szybkie chmod +x zenon.sh i od tej pory możemy uruchomić tunel jednym poleceniem, bez potrzeby sięgania po smartfona.

Oczywiście pamiętajmy, że taka automatyzacja oznacza znaczne zmniejszenie bezpieczeństwa – pomijamy bowiem krok interaktywny, wymagający sięgnięcia po dodatkowe urządzenie z kodem. Jak się nam ktoś włamie do komputera i ukradnie ten skrypt, będzie mógł potem zestawić tunel bez potrzeby generowania kodu. Musimy sami zdecydować czy nam się takie ryzyko opłaca czy nie.

Zapisz się
Powiadom o
guest
7 komentarzy
Inline Feedbacks
Zobacz wszystkie komentarze
7
0
Zapraszam do skomentowania wpisu.x
()
x