在我看来,你不应该在没有自己设置主机的情况下使用Url.Link() 或Url.Action() 向用户发送内容。您将他们暴露给可能的Host Header Attack -> Password Reset Poisoning。
如果 IIS 具有接受 80/443 上的连接的绑定,则可以更改主机标头,进而影响 Url.Link() 或 Url.Action() 方法。如果您查看我在下面提出的请求,我将连接到 http://hostheaderattack,但正在操作 host 标头。
概念证明 (PoC):
网址链接:
public class TestController : ApiController
{
public IHttpActionResult Get()
{
var callbackUrl = Url.Link("Default", new
{
Controller = "Home",
Action = "Index",
});
return Ok(callbackUrl);
}
}
网址.操作:
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Title = $"Url Created: {Url.Action("Index", "Home", "", Request.Url.Scheme)}";
return View();
}
}
我也在这里演示过:
https://security.stackexchange.com/questions/170755/host-header-attack-password-reset-poisoning-asp-net-web-api-2-hosted-as-az/170759#170759
更多关于主机头攻击的阅读:
https://www.acunetix.com/blog/articles/automated-detection-of-host-header-attacks/
你应该做的是永远不要相信用户请求并手动构造与主机的 url。
手动主机名示例:
Url.Action:Url.Action("Index", "Home", null, Request.Url.Scheme, "example.com")
对于 Url.Link 它有点棘手,但可以这样做:
public class TestController : ApiController
{
// GET api/<controller>
public IHttpActionResult Get()
{
var callbackUrl = Url.Link("Default", new
{
Controller = "Home",
Action = "Index",
});
callbackUrl = ReplaceHost(callbackUrl, "example.com");
return Ok(callbackUrl);
}
private string ReplaceHost(string original, string newHostName)
{
var builder = new UriBuilder(original);
builder.Host = newHostName;
return builder.Uri.ToString();
}
}
ReplaceHost 方法的来源:
https://stackoverflow.com/a/479812/3850405