bash - fájlok keresése, melyek tartalmazzák azt a sort, ami...

...úgy kezdődik, hogy adott egy fix string, utána legalább 5, de akár több ezer (!) szóköz és a szóközök után pedig még legalább öt, szóköztől eltérő karakter van. Mindez egy sorban.

Számos, főleg Joomla és Wordpress alapú oldal kerül így, vagy úgy feltörésre. Nagyon sok alkalommal látok olyat, hogy a feltörés után meglévő fájlok első sorába beépül egy plusz sor. Ez a sor kezdődik a "<?php"-val, kb. két képernyőszélességnyi szóköz után pedig indul valami csúnya kód, aminek a végén megvan a "?>"

"Szerkesztő" nézetben ez nem is látszik, csak az első sor elején a "<?php". Ha sortöréssel nyitom meg, akkor válik láthatóvá a sor többi része is.

Eljutottam oda, hogy ki tudom listázni azon fájlokat, melyek a felsorolt kiterjesztésű fájlok valamelyikének megfelelnek és van bennük ilyen sztring:

"<?php__________________________________________________________________________________________________________________________"

Ezeket a fájlokat ezzel tudtam kerestetni:

find /root/Virus -iregex ".*\.\(php\|html\|htm\|js\)" -exec bash -c 'grep -q "<?php__________________________________________________________________________________________________________________________"' {} \; -print

Annyi a szépséghibája ennek, hogy nagy ritkán előfordulnak olyan kódok, ami "rendes" kód, a "<?php" után a kedves programozó még odatett akár 40-50 szóköz karaktert, majd nyomott egy entert. Így tehát akad némi "fals pozitív" találat is. De ha a keresés azt is figyelné, hogy a kb. száz szóköz után még ugyanabban a sorban van-e egyéb karakter, mely több, mint egy "?>", akkor az számomra tökéletes lenne.

De fogalmam sincs, hogy kéne ezt leprogramozni. Tudtok ebben segíteni?

Fontos lenne az, hogy egy "exec"-el megfogalmazható legyen. Ugyanis több, egyéb dologra is kerestetnék, azaz a find-del kerestetett fájlokat vizsgálnám, hogy van-e bennünk "valamisztring", VAGY a kérdéses "php sokszóköz és még pár egyéb karakter egy sorban" sor, így:


find /root/Virus -iregex ".*\.\(php\|html\|htm\|js\)" \( -exec grep -q 'valamifeltetel' {} \; -o -exec grep -q "<?php__________________________________________________________________________________________________________________________" {} \; \) -print

A sok "aláhúzás" karakter valójában szóköz, de a fórummotor több egymás utáni szóközt egy szóközre cserél, így nem annyira lenne látható a kód.

Hozzászólások

grep -lr --include="*.php" --include="*.html" --include="*.htm" --include="*.js" -E '^<\?php\s{5,}.*\?>$'

ez?

Köszi!

Ez majdnem jó!
Az van, hogy vannak olyan sorok, amik nem zárulnak le kérdőjel kacsacsőrrel. Ha ezt adom be:
grep -lr --include="*.php" --include="*.html" --include="*.htm" --include="*.js" -E '^<\?php\s{5,}.*$'
Akkor már majdnem jó, így viszont azokat is megtalálja, amelyek <?php-val indulnak, van utána pár szóköz, de semmi egyéb. Ezeket a találatokat kellene ignorálni.

Tehát olyasmi még kéne a keresés végéhez, ami a "<?php"-val kezdődik és "legalább öt szóköz után" (eddig ok) és "van még pár karakter" (ami nem szóköz és nem csak a "?>", azaz mondjuk a legalább öt szóköz után még legalább öt "nem szóköz" (és nem tabulátor) karakter).

Hasznos lehet még a base64_decode, gzinflate, eval függvényekre keresni és ha ezek a file első/utolsó néhány sorában vannak vagy ezek után nem könnyen olvasható (pl. gzip-el, base64enconde-olt vagy escape-elt) szöveg van, az is gyanús.

Előzd meg a problémát: a webszervert (és/vagy a php-fpm-et) futtató felhasználónak (pl.: www-data) ne legyen írás jogosultsága a webrootba. Ezt megoldhatod fájlrendszer jogosultságokkal is, de például apparmorral is. Utóbbival megadhatsz olyan mappákat, ahova mégis írhat a www-data.

Akadt még egy kis gondom :)

Vannak olyan sorok a fertőzést tartalmazó fájlokban, amelyek valahogy így néznek ki (az elejéből egy részlet):

<?php ${"\x47\x4c\x4fB\x41\x4c\x53"}["\x67i\x65q\x68\x6ai\x79e\x6a\x72g"]="\x75\x72\x69";${"\x47\x4c\x4f\x42\x41\x4cS"}["p\x69\x77\x64\x79\x73vi\x6bh"]="\x64u\x6d\x6d\x79_\x70\x61g\x65";${"\x47\x4cO\x42\x41\x4c\x53"}["\x72\x68\x74a\x78\x76c"]="\x69\x70\x5fke\x79\x73";${"\x47\x4c\x4f\x42\x41\x4c\x53"}["\x68\x70\x76g\x74\x67\x62w\x71"]="fi\x6c\x65\x6eam\x65";${"\x47LO\x42\x41\x4cS"}["\x6ag\x67\x70\x6c\x6d\x66\x6aq\x75\x70"]="\x63o\x6ete\x6e\x74";${"\x47\x4c\x4f\x42\x41LS"}["\x79\x6cf\x71\x6f\x66x"]="\x69\x70";${"\x47\x4c\x4fB\x41L\x53"}["\x61\x73\x69\x6f\x6e\x65\x65\x68\x62"]

Eddig ez tűnt egy jó keresésnek:

find /root/Virus -iregex ".*\.\(php\|html\|htm\|js\)" \( -exec grep -q '<?php.*\x\|\x.*<?php' {} \; \) -print

Ez olyan fájlokat keres, ami egy sorban tartalmaz "<?php"-t és "\x"-et, így, vagy fordított sorrendben. A "\x"-eket úgy értem, hogy a "\x" után még jön egy pár karakter, mint fent látszik.

A gond ezzel az, hogy vannak olyan valós kódrészletek, melyek tartalmaznak "<?php"-t és egy-két "\x"-es részt, de közel sem annyit, mint a fenti minta.

Olyat szeretnék, hogy a keresés akkor adjon találatot, ha a "<?php" sztring-el egy sorban szerepel még mondjuk legalább 20 darab "\x" is. És ami egy kicsit plusz lenne, praktikusnak tűnne, ha a keresés akkor adna találatot, ha ez ráadásul a fájl első 3 sorában szerepel. Ezzel már lehet, hogy nagyon elbonyolítom, de a "szarok" általában a fájlok elején vannak. Az a valós kódrészlet, amire pedig az eddigi keresésem fals pozitív jelzést adott, a fájl közepén volt, a "<?php" sztringgel egy sorban pedig két darab "\x"-es sztring volt.

Előre is köszi! :)