假设我有一个C#
MVC应用程序,它有一个控制器方法,返回3种内容类型之一:image png, image jpeg, or application pdf
。我已经读过可以拥有包含XSS
有效载荷的图像。编码/转义这些返回内容的最佳方法是什么,这样它们就不容易受到XSS
的攻击?控制器方法如下所示:
string contentType = "image/png";
MemoryStream mem = new MemoryStream();
if (ImageFormat == null || ImageFormat == "")
{
image.Save(mem, System.Drawing.Imaging.ImageFormat.Png);
}
else
{
if (ImageFormat.ToUpper() == "PNG") image.Save(mem, System.Drawing.Imaging.ImageFormat.Png);
if (ImageFormat.ToUpper() == "JPEG")
{
image.Save(mem, System.Drawing.Imaging.ImageFormat.Jpeg);
contentType = "image/jpeg";
}
}
mem.Position = 0;
mem.Seek(0, SeekOrigin.Begin);
return this.Image(mem, contentType);
Image在这里定义了以下类:
using …
namespace x.Classes
{
public static class ControllerExtensions
{
public static ImageResult Image(this Controller controller, Stream imageStream, string contentType)
{
return new ImageResult(imageStream, contentType);
}
}
}
并使用以下命令编写OutputStream:
using …
namespace x.Classes
{
public class ImageResult : ActionResult
{
public ImageResult(Stream imageStream, string contentType)
{
if (imageStream == null)
throw new ArgumentNullException("imageStream");
if (contentType == null)
throw new ArgumentNullException("contentType");
this.ImageStream = imageStream;
this.ContentType = contentType;
}
public Stream ImageStream { get; private set; }
public string ContentType { get; private set; }
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = this.ContentType;
byte[] buffer = new byte[4096];
while (true)
{
int read = this.ImageStream.Read(buffer, 0, buffer.Length);
if (read == 0)
break;
response.OutputStream.Write(buffer, 0, read);
}
response.End();
}
}
}
有没有办法让我在这里转义/编码写入OutputStream的缓冲区:`
response.OutputStream.Write(buffer, 0, read);
为了防止XSS
攻击?例如,如果这是返回的HTML
:
response.OutputStream.Write(HttpUtility.HtmlEncode(buffer), 0, read);
但是我们知道我们正在返回一个jpeg,pdf或png,这意味着Html
编码在这里不起作用。那么我们用什么来安全地逃避/编码image / pdf?
当你准备好buffer
时,为时已晚。与HTML相同,您希望对这些文件中的任何用户输入进行上下文敏感编码,而不是整个事件。
现在,对于图像,这在XSS的上下文中没有多大意义,图像由图像渲染器渲染,而不是html,因此不会运行任何javascript。上传图像的一般最佳实践是在服务器上处理它们并将它们保存为新图像,因为这会删除所有不必要的东西,但如果您的处理器本身是攻击的目标,它也有风险。
例如SVG是一个不同的野兽,SVG可以包含代码,PDF也可以。但同样,PDF将在客户端上使用PDF查看器打开,而不是在Web应用程序的上下文中,即使PDF查看器是浏览器本身(浏览器希望将PDF中的Javascript与网页分开,即使原点是相同)。
但是PDF中的javascript仍然是客户端的问题。在PDF中运行的Javascript可能会做有害的事情,其中最简单的是消耗客户端资源(即某种类型的DoS),或者它可能会试图以某种方式利用查看器漏洞而脱离PDF上下文。因此,攻击将是一个用户上传恶意PDF以供其他人下载。我认为你能做的最好的事情是扫描上传的恶意软件文件(无论如何你都应该这样做)。
如果从用户输入(图像,PDF)生成所有这些,那么您使用的库应该正确编码值,以便恶意用户无法在PDF中注入代码。当PDF已经生成时,您无法再“修复”它,用户输入与代码混合在一起。
还要确保在响应中设置以下标题(当然还有正确的Content-Type):X-Content-Type-Options: nosniff
您不需要对图像本身进行编码,您需要编码/转义图像的链接。
例如:
<a href="image.url.png?logout">链接标题</a>
其中image.url.png?logout
来自用户输入。
你会将image.url.png?logout
编码为image.url.png%3Flogout
,这样它就会对攻击者无效。