Ketika 'a' tidak sama dengan 'a'. Setelah satu retasan

Kisah yang tidak menyenangkan terjadi pada salah seorang teman saya. Tapi sejauh itu ternyata tidak menyenangkan bagi Mikhail, itu sama menghibur bagiku.

Saya harus mengatakan bahwa teman saya cukup pengguna UNIX : dia dapat menginstal sistem sendiri, menginstal mysql , php dan membuat pengaturan nginx paling sederhana.
Dan dia memiliki selusin situs yang didedikasikan untuk alat konstruksi.

Salah satu situs ini, yang didedikasikan untuk gergaji mesin, berada di mesin pencari TOP. Situs ini adalah resensi nirlaba, tetapi seseorang telah menemukan tenggorokannya dan menyerangnya. Entah DDoS , lalu brute force, maka komentar akan menulis cabul dan mengirim pelanggaran ke hosting dan ke ILV.
Tiba-tiba, semuanya menjadi tenang dan jeda ini tidak baik, dan situs mulai berangsur-angsur meninggalkan garis atas hasil.

gambar

Itu pepatah, lalu admin bersepeda sendiri.

Waktu mendekati tidur ketika telepon berdering: β€œSanya, Anda tidak akan melihat server saya? Bagi saya sepertinya mereka meretas saya, saya tidak bisa membuktikannya, tetapi perasaan itu belum pergi pada minggu ketiga. Mungkin aku harus dirawat karena paranoia? ”

Selanjutnya datang diskusi setengah jam yang dapat diringkas sebagai berikut:

  • tempat berkembang biaknya cukup subur;
  • cracker bisa mendapatkan hak pengguna super;
  • serangan (jika itu terjadi) ditargetkan secara khusus ke situs ini;
  • area masalah diperbaiki dan Anda hanya perlu memahami jika ada fakta penetrasi;
  • peretasan tidak dapat menyentuh kode situs dan basis data.

Mengenai paragraf terakhir.

gambar

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

Debian 9 dipasang di ujung depan dan pada saat panggilan sistem terisolasi dari dunia oleh firewall eksternal dan berhenti.

"Oke, beri aku akses," aku memutuskan untuk menunda tidur selama satu jam. "Aku akan melihat dengan mataku sendiri."

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 hack


Saya memulai server, pertama dalam mode penyelamatan . Saya memasang disk, membolak-balik authlog , histori , log sistem, dll., Jika memungkinkan, memeriksa tanggal pembuatan file, meskipun saya mengerti bahwa cracker normal akan "berkeringat" di belakangnya, dan Misha sudah tahu "terinjak" sambil mencari sendiri.

Saya mulai dalam mode normal, terutama belum tahu apa yang harus dicari, saya sedang belajar konfigurasi. Dia terutama tertarik pada nginx karena, secara umum, tidak ada yang lain selain dia di frontend.
Konfigurasi kecil, terstruktur dengan baik menjadi selusin file, saya hanya melihat melalui mereka hanya dengan cat ' pada gilirannya. Semuanya tampak bersih, tetapi Anda tidak pernah melewatkan beberapa termasuk , saya akan melakukan 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 cantumannya?"

 $ 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 

Yang kedua ditambahkan ke pertanyaan daftar: "Mengapa versi nginx kuno seperti itu?"

Selain itu, sistem percaya bahwa versi diinstal segar:

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

Saya menelepon:
- Misha, mengapa kamu membangun kembali nginx ?
- Okst, saya bahkan tidak tahu bagaimana melakukannya!
- Ok, well, tidur ...

Nginx dipasang kembali dan daftar listing untuk "-T" disembunyikan karena suatu alasan. Tidak ada keraguan tentang peretasan dan Anda hanya bisa menerimanya dan (karena Misha mengganti server dengan yang baru), pertimbangkan masalah yang diselesaikan.

Dan memang, karena seseorang mendapatkan hak akses root , masuk akal untuk melakukan hanya menginstal ulang sistem , dan mencari sesuatu yang kurang dikonsumsi di sana, tetapi kali ini rasa ingin tahu mengalahkan mimpi itu. Bagaimana cara mengetahui apa yang ingin mereka sembunyikan dari kita?

Mari kita coba lacak:

 $ strace nginx -T 

Kami melihat jejaknya jelas tidak cukup garis a la

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

Untuk bersenang-senang, bandingkan kesimpulannya

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

Saya pikir itu 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; 

direduksi menjadi bentuk:

  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 karena itu, daftar oleh -T tidak ditampilkan.

Tetapi bagaimana cara melihat konfigurasi kita?


Jika ide saya benar dan masalahnya hanya pada variabel ngx_dump_config, kami akan mencoba menginstalnya menggunakan gdb , karena kunci --dengan-cc-opt -g ada dan kami berharap optimasi -O2 tidak akan merugikan kami. Pada saat yang sama, karena saya tidak tahu bagaimana ngx_dump_config dapat diproses dalam kasus 'T' :, kami tidak akan memanggil blok ini, tetapi menginstalnya menggunakan case 't':

Mengapa saya bisa menggunakan '-t' bersama dengan '-T'
Memproses blok if (ngx_dump_config) muncul di dalamnya 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; } 

Tentu saja, jika kode diubah di bagian ini, dan tidak dalam kasus 'T' :, maka metode saya tidak akan berfungsi.

Tes nginx.conf
Setelah menyelesaikan masalah secara empiris, ditemukan bahwa untuk pengoperasian malware diperlukan konfigurasi nginx minimal dari formulir:

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

Kami akan menggunakannya untuk singkatnya dalam artikel.

Jalankan 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 


Langkah-langkahnya:

  • atur breakpoint di fungsi main ()
  • jalankan programnya
  • ubah nilai variabel yang mendefinisikan output dari config ngx_dump_config = 1
  • melanjutkan / mengakhiri program

Seperti yang dapat Anda lihat, konfigurasi sebenarnya berbeda dengan milik kami, kami memilih sepotong palsu dari itu:

 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 perhatikan apa yang terjadi di sini.

Didefinisikan oleh User-Agent 's yandex / google:

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

Halaman layanan Wordpress tidak termasuk :

 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 halaman html- perubahan 'o' menjadi 'o' dan 'a' ke 'a' :

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

Persisnya, kehalusannya adalah 'a'! = 'A' sama dengan 'o'! = 'O' :

gambar

Dengan demikian, bot mesin pencari menerima, alih-alih teks cyrillic 100% yang normal, sampah yang dimodifikasi yang diencerkan dengan bahasa Latin 'a' dan 'o' . Saya tidak berasumsi untuk membahas bagaimana ini mempengaruhi SEO, tetapi tidak mungkin bahwa hash literal seperti itu akan secara positif mempengaruhi posisi dalam SERP.

Apa yang dikatakan cowok dengan fantasi.

Referensi


Debugging 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

Source: https://habr.com/ru/post/id465355/


All Articles