File Upload'da Content-Type'a Güvenmek
image/png diyen bir .exe

Avatar endpoint'i image/* kabul etti. Tarayıcı dosya seçicisi type'ı doğru gönderir. curl göndermez. Postman'de type'ı ben yazdım, gövdeye elf koydum, 201 aldım. Statik servis o dosyayı /uploads/a.png diye sundu. Uzantı yalan, içerik yalan, header yalan.
static bool LooksLikePng(ReadOnlySpan head) =>
head.Length >= 8
&& head[0] == 0x89 && head[1] == (byte)'P' && head[2] == (byte)'N' && head[3] == (byte)'G';
app.MapPost("/api/avatar", async (IFormFile file, IWebHostEnvironment env, CancellationToken ct) =>
{
if (file.Length is <= 0 or > 2_000_000)
return Results.BadRequest();
await using var stream = file.OpenReadStream();
var head = new byte[8];
if (await stream.ReadAsync(head.AsMemory(), ct) < 8 || !LooksLikePng(head))
return Results.BadRequest();
var name = $"{Guid.NewGuid():N}.png";
var path = Path.Combine(env.ContentRootPath, "avatars", name);
await using var disk = File.Create(path);
stream.Position = 0;
await stream.CopyToAsync(disk, ct);
return Results.Created($"/avatars/{name}", new { name });
});
Sihirli bayt yeterli değil: polyglot ve içine gömülü script ayrı konu. Yine de Content-Type tek kapı olmaktan çıkar. Kayıt adı Guid, uzantı senin verdiğin, dosya uygulama kökünün dışında, servis Content-Disposition: attachment. image/png sözüne bakmayı bıraktım.
Yorumlar
Yorumlar (0)
Yorumlar üyelere açık. Üye ol · Giriş yap