Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
A biztonságos illesztőprogramok írásáról a Megbízható Kernel-Mode illesztőprogramok létrehozása című témakörben olvashat bővebben.
A biztonságos kódolási eljárásokon és az általános eszközillesztő-útmutatáson túl a hálózati illesztőprogramoknak a következőkre van szükség a biztonság javítása érdekében:
- Minden hálózati illesztőprogramnak ellenőriznie kell a beállításjegyzékből beolvasott értékeket. A NdisReadConfiguration vagy a NdisReadNetworkAddress hívójának nem szabad feltételeznie a beállításjegyzékből beolvasott értékekre vonatkozó feltételezéseket, és ellenőriznie kell az összes beolvasott beállításjegyzék-értéket. Ha a NdisReadConfiguration hívója azt állapítja meg, hogy egy érték túllépi a határokat, akkor ehelyett egy alapértelmezett értéket kell használnia. Ha a NdisReadNetworkAddress hívója azt állapítja meg, hogy egy érték kívül esik a határokon, akkor az állandó médium hozzáférés-vezérlő (MAC) címet vagy egy alapértelmezett címet kell használnia.
OID-specifikus problémák
A miniport-illesztő MiniportOidRequest vagy MiniportCoOidRequest függvényeiben érvényesítenie kell az illesztőprogram által beállítani kívánt objektumazonosító (OID) értéket. Ha az illesztőprogram megállapítja, hogy a beállítandó érték nem határos, akkor a beállított kérés meghiúsul. Az objektumazonosítókkal kapcsolatos további információkért lásd a miniportillesztők információinak beszerzését és beállítását, valamint a WMI NDIS-támogatását.
Ha egy köztes illesztőprogram MiniportOidRequest függvénye nem ad át beállított műveletet egy mögöttes miniportillesztőnek, a függvénynek ellenőriznie kell az OID értékét. További információ: Köztes illesztőprogram lekérdezése és műveletek beállítása.
Az OID lekérdezési biztonsági irányelvei
A legtöbb lekérdezési azonosítót a rendszeren található bármely usermode-alkalmazás kibocsáthatja. Kövesse a lekérdezési azonosítókra vonatkozó alábbi irányelveket.
Mindig ellenőrizze, hogy a puffer mérete elég nagy-e a kimenethez. A kimeneti pufferméret-ellenőrzés nélküli lekérdezési OID-kezelő biztonsági hibával rendelkezik.
if (oid->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG)) { oid->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG); return NDIS_STATUS_INVALID_LENGTH; }Mindig írjon helyes és minimális értéket a BytesWritten fájlba. Ez egy piros jelölő, amelyet az alábbi példához hasonlóan kell hozzárendelni
oid->BytesWritten = oid->InformationBufferLength.// ALWAYS WRONG oid->DATA.QUERY_INFORMATION.BytesWritten = DATA.QUERY_INFORMATION.InformationBufferLength;Az operációs rendszer a BytesWritten bájtokat visszamásolja egy usermode alkalmazásba. Ha a BytesWritten nagyobb, mint az illesztőprogram által ténylegesen írt bájtok száma, akkor előfordulhat, hogy az operációs rendszer visszamásolja a nem inicializált kernelmemóriát a usermode-ba, ami információfeltárási biztonsági rés lenne. Ehelyett használja a következőhöz hasonló kódot:
oid->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG);Soha ne olvasson vissza értékeket a pufferből. Bizonyos esetekben az OID kimeneti puffere közvetlenül egy ellenséges felhasználói mód folyamatba van leképezve. A rosszindulatú folyamat megváltoztathatja a kimeneti puffert, miután írtál rá. Az alábbi kód például megtámadható, mert a támadó a megírás után módosíthatja a NumElements parancsot:
output->NumElements = 4; for (i = 0 ; i < output->NumElements ; i++) { output->Element[i] = . . .; }A pufferből való visszaolvasás elkerülése érdekében őrizze meg a helyi másolatot. A fenti példa kijavításához például vezessen be egy új veremváltozót:
ULONG num = 4; output->NumElements = num; for (i = 0 ; i < num; i++) { output->Element[i] = . . .; }Ezzel a módszerrel a for loop visszaolvassa az illesztőprogram veremváltozóját
num, és nem a kimeneti pufferből. Az illesztőnek meg kell jelölnie a kimeneti puffert avolatilekulcsszóval, hogy a fordító ne vonja vissza a javítást csendesen.
Az OID biztonsági irányelveinek beállítása
A legtöbb set OID-t a Rendszergazdák vagy a Rendszer biztonsági csoportokban futó usermode-alkalmazás állíthatja ki. Bár ezek általában megbízható alkalmazások, a miniport-illesztőnek továbbra sem szabad engedélyeznie a memória sérülését vagy a kernelkód injektálását. Kövesse az alábbi szabályokat az azonosítók beállításához:
Mindig ellenőrizze, hogy a bemenet elég nagy-e. A bemeneti pufferméret-ellenőrzés nélküli OID-készletkezelő biztonsági rést tartalmaz.
if (oid->DATA.SET_INFORMATION.InformationBufferLength < sizeof(ULONG)) { return NDIS_STATUS_INVALID_LENGTH; }Amikor beágyazott eltolással érvényesít egy OID-t, ellenőriznie kell, hogy a beágyazott puffer az OID terhelésen belül van-e. Ehhez több ellenőrzésre van szükség. Előfordulhat például, hogy OID_PM_ADD_WOL_PATTERN egy beágyazott mintát eredményez, amelyet ellenőrizni kell. A helyes ellenőrzéshez ellenőrizni kell:
InformationBufferSize >= sizeof(NDIS_PM_PACKET_PATTERN)
PmPattern = (PNDIS_PM_PACKET_PATTERN) InformationBuffer; if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN)) { Status = NDIS_STATUS_BUFFER_TOO_SHORT; *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN); break; }Pattern->PatternOffset + Pattern->PatternSize nem eredményez túlcsordulást
ULONG TotalSize = 0; if (!NT_SUCCESS(RtlUlongAdd(Pattern->PatternOffset, Pattern->PatternSize, &TotalSize) || TotalSize > InformationBufferLength) { return NDIS_STATUS_INVALID_LENGTH; }Ez a két ellenőrzés a következő példához hasonló kóddal kombinálható:
ULONG TotalSize = 0; if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN) || !NT_SUCCESS(RtlUlongAdd(Pattern->PatternSize, Pattern->PatternOffset, &TotalSize) || TotalSize > InformationBufferLength) { return NDIS_STATUS_INVALID_LENGTH; }InformationBuffer + Pattern->PatternOffset + Pattern->PatternLength nem okoz túlcsordulást
ULONG TotalSize = 0; if (!NT_SUCCESS(RtlUlongAdd(Pattern->PatternOffset, Pattern->PatternLength, &TotalSize) || (!NT_SUCCESS(RtlUlongAdd(TotalSize, InformationBuffer, &TotalSize) || TotalSize > InformationBufferLength) { return NDIS_STATUS_INVALID_LENGTH; }Pattern->PatternOffset + Pattern->PatternLength = InformationBufferSize<
ULONG TotalSize = 0; if(!NT_SUCCESS(RtlUlongAdd(Pattern->PatternOffset, Pattern->PatternLength, &TotalSize) || TotalSize > InformationBufferLength)) { return NDIS_STATUS_INVALID_LENGTH; }
Az OID metódus biztonsági irányelvei
A metódusazonosítókat a Rendszergazdák vagy a Rendszer biztonsági csoportokban futó felhasználómódú alkalmazások adhatják ki. Ezek egy halmaz és egy lekérdezés kombinációját képezik, így a fenti útmutatási listák a metódusazonosítókra is érvényesek.
Egyéb hálózati illesztőprogramokkal kapcsolatos biztonsági problémák
Számos NDIS miniport-illesztőprogram tesz elérhetővé egy vezérlőeszközt a NdisRegisterDeviceEx használatával. Az ezt végzőknek a WDM-illesztőprogramokkal megegyező biztonsági szabályokkal kell naplózást végezniük az IOCTL-kezelőiken. További információ: I/O-vezérlőkódok biztonsági problémái.
A jól megtervezett NDIS miniportillesztők nem támaszkodhatnak arra, hogy egy adott folyamatkörnyezetben hívják meg őket, és nem állhatnak szoros kapcsolatban a felhasználói móddal (kivételt képeznek az IOCTL-k és az OID-k). Figyelmeztető jel lenne, ha egy miniportot látna, amely megnyitott felhasználói módú leírókat, használta a felhasználói módú várakozásokat, vagy memóriát foglalt le felhasználói módú kvóta terhére. Ezt a kódot meg kell vizsgálni.
A legtöbb NDIS-miniportillesztőnek nem szabad részt vennie a csomagok hasznos adatainak elemzésében. Bizonyos esetekben azonban szükség lehet rá. Ha igen, ezt a kódot nagyon óvatosan kell naplózni, mivel az illesztőprogram nem megbízható forrásból elemzi az adatokat.
Ahogy a kernel módú memória kiosztásakor szokásos, az NDIS-illesztőprogramoknak a megfelelő NX-készlet Opt-In mechanizmusokat kell használniuk. A WDK 8 és újabb verzióiban a
NdisAllocate*függvénycsalád megfelelően van engedélyezve.