Так что у меня возникла блестящая идея троллить злоумышленника, придумав абсурдный ответ на имитацию побега с пути.
Когда-то это делало что-то интересное
GET /../../etc/passwd HTTP/1.0
Поэтому я написал:
app.MapGet("/../../etc/passwd", () => """
root:ZghOT0eRm4U9s:0:0::/:/bin/sh
""");
Но это совершенно не работает:
GET /../../etc/passwd HTTP/1.0
HTTP/1.1 404 Not Found
Content-Length: 0
Connection: close
Date: Tue, 27 Aug 2024 01:51:19 GMT
Server: Kestrel
Что с этим случилось?
(Это тролльская запись app.MapGet(), которая тратит время скрипт-кидди. Если она никогда не будет исправлена, небольшая потеря. Он использует минимальный API, потому что все приложение будет использовать минимальный API для всего, включая статическое разрешение файлов.)
Этим занимается Kestrel, который превращает путь /../../etc/passwd
в просто /etc/passwd
.
Из тестов Kestrel, например Http2 / Http3:
// ...
[InlineData("/a/b/c/../d", "/a/b/d")] // Navigation processed
[InlineData("/a/b/c/../../../../d", "/d")] // Navigation escape prevented
// ...
public async Task Path_DecodedAndNormalized(string input, string expected)
следовательно, «обратная навигация» обрабатывается до «корня приложения», но не далее, поэтому ваш шаблон маршрута на уровне приложения должен быть просто /etc/passwd
:
app.MapGet("/etc/passwd", ...);
УПД
Идея в том, что
/etc/passwd
— это 404, но../../etc/
пароль что-то возвращает.
Затем вы можете попробовать получить «необработанную цель» и, например, использовать конвейер условного обработчика (добавьте его где-нибудь в начале конвейера):
app.UseWhen(context =>
{
var httpRequestFeature = context.Features.Get<IHttpRequestFeature>();
var rawTarget = httpRequestFeature?.RawTarget;
return rawTarget == "/../../etc/passwd";
},
appBuilder => appBuilder.Run(
ctx => ctx.Response.WriteAsync("root:ZghOT0eRm4U9s:0:0::/:/bin/sh")));
Идея, в частности, в том, что /etc/passwd — это ошибка 404, но ../../etc/password возвращает что-то, поэтому сканер думает, что обнаружил ошибку. В любом случае, любопытство, не важное.
@Джошуа, пожалуйста, посмотри обновление.
Вы имеете в виду, что пытаетесь запросить что-то вроде
http://localhost:5082/../etc/passwd
?