A következő összesített álkód van a C89-ben egy ssh kiszolgáló könyvtárból, amely csak olyan dolgokhoz nyújt hozzáférést, mint a git-shell (/bin/bash
helyébe a futtatandó program lép, így nem lehet mást tenni) :
struct _raw_uncapped_ssh_string { // no limit on the size of the string; uint32_t len; char non_null_terminated_string[]; // by protocol design it have a minimum length of 1 }; typedef struct _raw_uncapped_ssh_string raw_ssh_string; union buffer { void * uncapped_zlib_decompressed_network_data; // yes, the size is uncapped, so it’s possible to put 4Gb of // data in it that would be copied later into memory. zlib // allow easily to turn some Mb in Gb of data, but it’s not // the point of the question. raw_ssh_string st; }; get_command (compressed_network_data) { size_t len; char * command; buffer string=uncompress_to_buffer(compressed_network_data); len=ntohl(string.st.len)+1; command=malloc(len+1); command[len]=0; // here’s the point, both the string length and content as // well it’s supplied size is controlled by the attacker. memcpy(command,string.st.data,len); return command; }
Íme a parancs későbbi végrehajtása (a command
karakterlánc változatlan a get_command()
) után .
const char *args[]={"/bin/bash",command,NULL}; // /bin/bash isn’t the shell, it has been replaced by git‑shell. // redirect the program output to the network. dup2(stdin, 0); dup2(stdout,1); dup2(stdout,2); close(stdin); close(stdout); //if this return execution failed and print an error message return execv(args[0],(char * const *)args); // I don’t know which is the system, so I can’t know about the libc behaviour.
Nem tudom megtenni memcpy(command,string.st.data,0)
, mivel a memcpy
harmadik tagjának minimális mérete 1, és a kontextusomban a size_t
64 bites egész számot használ, puffertúlcsordulást nem tudok végrehajtani, mivel len
.
Csak annyit tehetek, hogy a len
értéket nagyobbra állítom, mint a string.st.data
számára kiosztott érték. Ez egy olyan puffer alulcsordulás, amely lehetővé teszi a fel nem osztott memória olvasását.
Tudom olvasni a kiszolgáló memóriáját, de nem látom, hogy egy nyilvános ssh-kiszolgáló milyen érzékeny adatokat képes tárolni (esetemben a ssh is public is .
Tehát a memcpy
lehetővé teszi a távoli puffer alulfolyását kód végrehajtása?
Megjegyzések
Válasz
Általában nem, a puffer alulcsordulása nem használható távoli kódfuttatáshoz. Mivel a támadók által vezérelt adatok soha nem hagyják el a számára lefoglalt helyet, soha nem képes átvenni a program végrehajtási folyamatát.
A puffer alulcsordulásának lehetősége van más típusú támadásokra is, mint pl. információ nyilvánosságra hozatala (ha a program számít arra, hogy a puffer eredeti tartalmát eltörlik az új adatok).
Megjegyzések
- Vagy ahogy én nemrégiben a git-ben látta, később puffertúlcsordulássá alakítja.
Válasz
Amikor ezt a választ eredetileg írtam , úgy tűnik, elsimítottam néhány félreértést, amelyet ön tart. Ezek a félreértések valószínűleg megakadályoznák a válaszom megértését. Az egyértelműség kedvéért ezt a szöveget nagyra fogom emelni, hogy hangsúlyt fektessek, és ne legyek tiszteletlen:
Az Ön által használt kifejezések közül sok nem azt jelenti, amit úgy gondolja, hogy jelent.
Például:
- “a
memcpy
” harmadik tagja nem létezik, mert amemcpy
függvény, nem pedigstruct
vagyunion
. - “Nem tudok puffertúlcsordulást végrehajtani, mivel van
len
” és nem fogyhat el a benzin, mivel van benzin. Könyörgöm a kérdés? Számomra megfelelő analógia, főleg, hogy elméletileg a kódod puffertúlcsordulást idézhet elő. - “Csak annyit tehetek, hogy beállítok
len
nagyobb értékre, mint azstring.st.data
. Ez egy puffer alulcsordulás … “ Nem, ez nem a puffer alulcsordulás definíciója. A puffer alulcsordulás akkor következik be, amikor egy tömböt kívülről elérsz egy negatív index, vagy egy olyan index segítségével, amely okozhat pointer aritmetikai csomagolás fordulhat elő. Ez utóbbi bizonyos konfigurációknál lehetséges (még “64 bites rendszereken is, bármit is jelent ez), de kétlem, hogy erre gondolt, amikor ezeket a szavakat írta, mert akkor követte őket a következővel: - “… lehetővé téve számomra a fel nem osztott memória elolvasását.” Azt hiszem, talán “inicializálatlan memóriára” gondoltál. Hogy világos legyek, azt hiszem, azt akartad kijelenteni, hogy “ve felosztott egy felesleget, és a felesleget inicializálatlanul hagyta , és talán szeretne tenni valamit ezzel kapcsolatban (lásd:
calloc
vagymemset
).
Vegyük egy pillanatra fontolóra a char *fubar = NULL;
… ez a fajta mutató általában nulla érték.A hivatkozások levonása null pointer dereference nak számít, de ha valami hasonlót írunk, mint 0["hello"]
, akkor ugyanazt kapjuk, mint a "hello"[0]
(vagyis "h"
). Így a nullpontos eltérés felhasználható a támadásokban, amikor a támadó vezérli a négyzet alakú zárójelek közötti kifejezést (ahogyan az Ön helyzetében is).
Visszatérve a fubar
dolog; mondjuk azt, hogy memset(&fubar, UCHAR_MAX, sizeof fubar);
, most fubar
mind 1 bites, vagyis lehet egy cím ez a legnagyobb cím, amelyet rendszerünk (elméletileg) be tudna fogadni. Mi van, ha hozzáférünk az fubar[1]
fájlhoz? Hogyan érheti el a legnagyobb cím után elemet? Ezután a cím visszavonul? Technikailag mindez nem meghatározott viselkedés, de ha ezt megnevezném a közös architektúrán, az a következő lenne:
- számtani túlcsordulás egy mutató, amely a következő irányba vezet …
- Nulla mutató-eltérés és / vagy potenciálisan puffer alulcsordulás .
egy puffer alulcsordul a
memcpy
oldalon a távoli kódfuttatáshoz?
puffer az alulcsordulás lehetővé teszi a támadó számára, hogy felülírja a memória régióiban található funkciómutatókat a kérdéses tömb előtt. Ha ezeket a funkciómutatókat shell-re mutatják, akkor akkor kell végrehajtani, amikor később újra meghívják őket.
Ebben a kissé homályos kódrészben a puffer alulcsordulásának kockázata jelenik meg, ha a int
szélesebb domain, mint uint32_t
, mivel az ntohl(string.st.len)+1
miatt a uint32_t
érték int
típus. Vegyük például, ha a INT_MIN
-4294967296
(ami eggyel kevesebb, mint 0 - UINT32_MAX
) és INT_MAX
4294967295
… ez lényegében egy 33 bites int
párnázás bájt szélességig; ritka, de lehetséges. Ebben a helyzetben az ntohl(string.st.len)+1
kifejezés nem uint32_t
típusú; ez “s int
típusú, és ahelyett, hogy visszaforgatna a 0-ra, amikor aláíratlan egész szám túlcsordulás fordul elő, valószínűleg a -4294967296
amikor aláírt egész szám túlcsordulás történik.
Ha garanciát keres a puffer alulcsordulás ra, használja a U
egész szó szerinti utótag (azaz ntohl(string.st.len)+1U
). Ekkor ebben a helyzetben a kifejezés vagy uint32_t
vagy unsigned int
lesz (attól függően, hogy melyik típus a legnagyobb domain).
Ha úgy gondolja, hogy a ntohl(string.st.len)
eggyel kevesebbet adhat vissza, mint az adott aláíratlan típus maximális értéke (bármi is legyen az), akkor len=ntohl(string.st.len)+1
a maximális értéket eredményezi, a malloc(len+1)
aláíratlan csomagolást okoz, így végül a malloc(0)
majd a command[len]=0
a tömb végén túl jól és valóban ír. Ezután természetesen “ szintén problémája lesz a memcpy(command,string.st.data,len);
vel (ez egy puffertúlcsordulás).
A puffer alulcsordul és a túlcsordulás nem az egyetlen kockázat. Ha nem “t ellenőrzi a malloc
és malloc
értéke NULL
, majd egy null mutató hivatkozás használható tetszőleges kódfuttatásra. Ez azt jelenti, hogy rendelkeznie kell módszerrel a malloc
hiba a hívónak. Ez azt is magában foglalja, hogy ugyanazzal a módszerrel ellenőrizheti és közölheti a csomagolási problémát a hívóval.
command[len] = 0
akkor ez puffertúlcsordulás, mivel alen
hosszúságú puffer maximális indexelen-1
. Alternatív megoldásként, ha a tényleges kódmalloc(len+1)
-t hajt végremalloc(len)
helyett, akkor hatalmas puffertúlcsordulást hozhat létre alen
érték a0xFFFFFFFF
értékre.len+1
, így a 0 értéknek érvényesnek kell lennie.string.st.len
-1 értékre állítja.