Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Güvenli sürücüler yazımı hakkında genel bir tartışma için bkz. Güvenilir Kernel-Mode Sürücüleri Oluşturma.
Aşağıdaki güvenli kodlama uygulamalarının ve genel cihaz sürücüsü kılavuzunun ötesinde, ağ sürücüleri güvenliği artırmak için aşağıdakileri yapmalıdır:
- Tüm ağ sürücüleri, kayıt defterinden okudukları değerleri doğrulamalıdır. Özellikle, NdisReadConfiguration veya NdisReadNetworkAddress çağıranı, kayıt defterinden okunan değerler hakkında herhangi bir varsayımda bulunmamalıdır ve okuduğu her kayıt defteri değerini doğrulamalıdır. NdisReadConfiguration çağıranı bir değerin sınırların dışında olduğunu belirlerse, bunun yerine varsayılan değeri kullanmalıdır. NdisReadNetworkAddress çağıranı bir değerin sınırların dışında olduğunu belirlerse, bunun yerine kalıcı orta erişim denetimi (MAC) adresini veya varsayılan adresi kullanmalıdır.
OID'ye özgü sorunlar
MiniportOidRequest veya MiniportCoOidRequest işlevlerinde bir miniport sürücüsü, sürücünün ayarlaması istenen nesne tanımlayıcısı (OID) değerini doğrulamalıdır. Sürücü, ayarlanacak değerin sınırların dışında olduğunu belirlerse, ayarlama isteği başarısız olmalıdır. Nesne tanımlayıcıları hakkında daha fazla bilgi için bkz. MiniPort Sürücü Bilgilerini Alma ve Ayarlama ve WMI için NDIS Desteği.
Bir ara sürücünün MiniportOidRequest işlevi temel alınan bir miniport sürücüsüne ayarlanmış bir işlem geçirmezse, işlevin OID değerini doğrulaması gerekir. Daha fazla bilgi için bkz. Ara Sürücü Sorgusu ve Ayarlama İşlemleri.
OID sorgu güvenlik yönergeleri
Sorgu OID'lerinin çoğu sistemdeki herhangi bir usermode uygulaması tarafından yayımlanabilir. Sorgu OID'leri için bu özel yönergeleri izleyin.
Her zaman arabellek boyutunun çıkış için yeterince büyük olduğunu doğrulayın. Çıkış arabelleği boyutu denetimi olmayan tüm sorgu OID işleyicileri bir güvenlik hatasına sahiptir.
if (oid->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG)) { oid->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG); return NDIS_STATUS_INVALID_LENGTH; }BytesWritten'e her zaman doğru ve en düşük değeri yazın. Aşağıdaki örnekte olduğu gibi
oid->BytesWritten = oid->InformationBufferLengthatamak bir uyarı işaretidir.// ALWAYS WRONG oid->DATA.QUERY_INFORMATION.BytesWritten = DATA.QUERY_INFORMATION.InformationBufferLength;İşletim sistemi BytesWritten baytlarını bir usermode uygulamasına geri kopyalar. BytesWritten, sürücünün gerçekte yazdığı bayt sayısından büyükse işletim sistemi başlatılmamış çekirdek belleğini usermode'a geri kopyalayabilir ve bu da bilgilerin açığa çıkmasıyla ilgili bir güvenlik açığı olabilir. Bunun yerine şuna benzer bir kod kullanın:
oid->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG);Değerleri arabellekten asla geri okumayın. Bazı durumlarda, bir OID'nin çıkış arabelleği doğrudan düşman kullanıcı modu işlemine eşlenir. Düşmanca işlem, siz yazdıktan sonra çıkış arabelleğinizi değiştirebilir. Örneğin, bir saldırgan yazıldıktan sonra NumElements'i değiştirebildiğinden aşağıdaki koda saldırılabilir:
output->NumElements = 4; for (i = 0 ; i < output->NumElements ; i++) { output->Element[i] = . . .; }Arabellekten geri okunmasını önlemek için yerel bir kopya tutun. Örneğin, yukarıdaki örneği düzeltmek için yeni bir yığın değişkeni tanıtın:
ULONG num = 4; output->NumElements = num; for (i = 0 ; i < num; i++) { output->Element[i] = . . .; }Bu yaklaşımla for döngüsü, çıkış arabelleğinden değil sürücünün yığın değişkeninden
numgeri okunur. Ayrıca sürücü, derleyicinin bu düzeltmeyi sessizce geri almasını önlemek için çıkış arabelleği anahtar sözcüğüylevolatileişaretlemelidir.
OID güvenlik yönergelerini ayarlama
Çoğu Set OID'leri, Yöneticiler veya Sistem güvenlik gruplarında yer alan bir kullanıcı modu uygulaması tarafından yayımlanabilir. Bunlar genel olarak güvenilen uygulamalar olsa da, miniport sürücüsünün bellek bozulmasına veya çekirdek kodu eklemesine izin vermemesi gerekir. Set OIDs için şu özel kuralları izleyin:
Girişin her zaman yeterince büyük olduğunu doğrulayın. Giriş arabellek boyutu denetimi olmayan herhangi bir OID kümesi işleyicisi güvenlik açığına sahiptir.
if (oid->DATA.SET_INFORMATION.InformationBufferLength < sizeof(ULONG)) { return NDIS_STATUS_INVALID_LENGTH; }OID yerleşik bir ofset ile doğrulanırken, yerleşik arabelleğin OID yükü içinde olup olmadığını doğrulamanız gerekir. Bunun için birkaç denetim gerekir. Örneğin , OID_PM_ADD_WOL_PATTERN denetlenmesi gereken ekli bir desen sunabilir. Doğru doğrulama için denetim gerekir:
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 taşmıyor
ULONG TotalSize = 0; if (!NT_SUCCESS(RtlUlongAdd(Pattern->PatternOffset, Pattern->PatternSize, &TotalSize) || TotalSize > InformationBufferLength) { return NDIS_STATUS_INVALID_LENGTH; }Bu iki denetim aşağıdaki örnekte olduğu gibi kod kullanılarak birleştirilebilir:
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 taşma yapmaz
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; }
Yöntem OID güvenlik yönergeleri
Yöntem OID'leri, Yöneticiler veya Sistem güvenlik gruplarında çalışan bir usermode uygulaması tarafından yayımlanabilir. Bunlar Bir Küme ve Sorgu birleşimidir, bu nedenle her iki önceki kılavuz listesi de Yöntem OID'leri için geçerlidir.
Diğer ağ sürücüsü güvenlik sorunları
Birçok NDIS miniport sürücüsü, NdisRegisterDeviceEx kullanarak bir denetim cihazını kullanıma sunar. Bunu yapanlar, WDM sürücüsüyle aynı güvenlik kurallarıyla IOCTL işleyicilerini denetlemelidir. Daha fazla bilgi için bkz. G/Ç Denetim Kodları için Güvenlik Sorunları.
İyi tasarlanmış NDIS miniport sürücüleri, belirli bir işlem bağlamında çağrılmaya güvenmemeli veya kullanıcı moduyla (IOCTL'ler ve OID'ler özel durum olduğunda) çok yakın etkileşim kurmamalıdır. Usermode tanıtıcılarını açan, usermode beklemeleri gerçekleştiren veya usermode kotasına göre bellek ayrılan bir miniport görmek kırmızı bayrak olabilir. Bu kod araştırılmalıdır.
Çoğu NDIS miniport sürücüsü paket yüklerini ayrıştırmada yer almamalıdır. Ancak bazı durumlarda gerekli olabilir. Bu durumda, sürücü güvenilmeyen bir kaynaktan verileri ayrıştırdığından bu kod çok dikkatli bir şekilde denetlenmelidir.
Çekirdek modu belleği ayrılırken standart olarak olduğu gibi, NDIS sürücüleri uygun NX Havuzu Opt-In Mekanizmalarını kullanmalıdır. WDK 8 ve daha yeni sürümlerde,
NdisAllocate*işlev ailesi doğru şekilde etkinleştirilmiştir.