Browse Source

Enforce checking for each IImageService

Former-commit-id: 6cf0ce4aa26bcf22a69fd93edffe2a4d6e3ced5c
Former-commit-id: 71b03adabd4ae82b229aae0157d5fe3697025765
af/merge-core
James South 11 years ago
parent
commit
f4a1195be5
  1. 13
      src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
  2. 11
      src/ImageProcessor.Web/Services/IImageService.cs
  3. 16
      src/ImageProcessor.Web/Services/LocalFileImageService.cs
  4. 79
      src/ImageProcessor.Web/Services/RemoteImageService.cs
  5. 2
      src/TestWebsites/MVC/Web.config

13
src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs

@ -328,6 +328,12 @@ namespace ImageProcessor.Web.HttpModules
string parts = !string.IsNullOrWhiteSpace(urlParameters) ? "?" + urlParameters : string.Empty;
string fullPath = string.Format("{0}{1}?{2}", requestPath, parts, queryString);
// Check whether the path is valid for other requests.
if (!isFileLocal && !currentService.IsValidRequest(requestPath + "?" + urlParameters))
{
return;
}
// Create a new cache to help process and cache the request.
DiskCache cache = new DiskCache(requestPath, fullPath, queryString);
string cachedPath = cache.CachedPath;
@ -548,12 +554,7 @@ namespace ImageProcessor.Web.HttpModules
}
// Return the file based service
if (ImageHelpers.IsValidImageExtension(path))
{
return services.FirstOrDefault(s => string.IsNullOrWhiteSpace(s.Prefix));
}
return null;
return services.FirstOrDefault(s => string.IsNullOrWhiteSpace(s.Prefix) && s.IsValidRequest(path));
}
#endregion
}

11
src/ImageProcessor.Web/Services/IImageService.cs

@ -43,6 +43,17 @@ namespace ImageProcessor.Web.Services
/// </summary>
Uri[] WhiteList { get; set; }
/// <summary>
/// Gets a value indicating whether the current request passes sanitizing rules.
/// </summary>
/// <param name="path">
/// The image path.
/// </param>
/// <returns>
/// <c>True</c> if the request is valid; otherwise, <c>False</c>.
/// </returns>
bool IsValidRequest(string path);
/// <summary>
/// Gets the image using the given identifier.
/// </summary>

16
src/ImageProcessor.Web/Services/LocalFileImageService.cs

@ -16,6 +16,8 @@ namespace ImageProcessor.Web.Services
using System.Threading.Tasks;
using System.Web;
using ImageProcessor.Web.Helpers;
/// <summary>
/// The local file image service for retrieving images from the file system.
/// </summary>
@ -67,6 +69,20 @@ namespace ImageProcessor.Web.Services
/// </summary>
public Uri[] WhiteList { get; set; }
/// <summary>
/// Gets a value indicating whether the current request passes sanitizing rules.
/// </summary>
/// <param name="path">
/// The image path.
/// </param>
/// <returns>
/// <c>True</c> if the request is valid; otherwise, <c>False</c>.
/// </returns>
public bool IsValidRequest(string path)
{
return ImageHelpers.IsValidImageExtension(path);
}
/// <summary>
/// Gets the image using the given identifier.
/// </summary>

79
src/ImageProcessor.Web/Services/RemoteImageService.cs

@ -14,7 +14,6 @@ namespace ImageProcessor.Web.Services
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Security;
using System.Threading.Tasks;
using ImageProcessor.Web.Helpers;
@ -84,6 +83,44 @@ namespace ImageProcessor.Web.Services
/// </summary>
public Uri[] WhiteList { get; set; }
/// <summary>
/// Gets a value indicating whether the current request passes sanitizing rules.
/// </summary>
/// <param name="path">
/// The image path.
/// </param>
/// <returns>
/// <c>True</c> if the request is valid; otherwise, <c>False</c>.
/// </returns>
public bool IsValidRequest(string path)
{
// Check the url is from a whitelisted location.
Uri url = new Uri(path);
string upper = url.Host.ToUpperInvariant();
// Check for root or sub domain.
bool validUrl = false;
foreach (Uri uri in this.WhiteList)
{
if (!uri.IsAbsoluteUri)
{
Uri rebaseUri = new Uri("http://" + uri.ToString().TrimStart(new[] { '.', '/' }));
validUrl = upper.StartsWith(rebaseUri.Host.ToUpperInvariant()) || upper.EndsWith(rebaseUri.Host.ToUpperInvariant());
}
else
{
validUrl = upper.StartsWith(uri.Host.ToUpperInvariant()) || upper.EndsWith(uri.Host.ToUpperInvariant());
}
if (validUrl)
{
break;
}
}
return validUrl;
}
/// <summary>
/// Gets the image using the given identifier.
/// </summary>
@ -96,10 +133,6 @@ namespace ImageProcessor.Web.Services
public async Task<byte[]> GetImage(object id)
{
Uri uri = new Uri(id.ToString());
// Check the url is from a whitelisted location.
this.CheckSafeUrlLocation(uri);
RemoteFile remoteFile = new RemoteFile(uri)
{
MaxDownloadSize = int.Parse(this.Settings["MaxBytes"]),
@ -132,41 +165,5 @@ namespace ImageProcessor.Web.Services
return buffer;
}
/// <summary>
/// Returns a value indicating whether the current url is in a list of safe download locations.
/// </summary>
/// <param name="url">
/// The <see cref="System.Uri"/> to check against.
/// </param>
private void CheckSafeUrlLocation(Uri url)
{
string upper = url.Host.ToUpperInvariant();
// Check for root or sub domain.
bool validUrl = false;
foreach (Uri uri in this.WhiteList)
{
if (!uri.IsAbsoluteUri)
{
Uri rebaseUri = new Uri("http://" + uri.ToString().TrimStart(new[] { '.', '/' }));
validUrl = upper.StartsWith(rebaseUri.Host.ToUpperInvariant()) || upper.EndsWith(rebaseUri.Host.ToUpperInvariant());
}
else
{
validUrl = upper.StartsWith(uri.Host.ToUpperInvariant()) || upper.EndsWith(uri.Host.ToUpperInvariant());
}
if (validUrl)
{
break;
}
}
if (!validUrl)
{
throw new SecurityException("Application is not configured to allow remote file downloads from this domain.");
}
}
}
}

2
src/TestWebsites/MVC/Web.config

@ -27,7 +27,7 @@
<system.web>
<httpRuntime targetFramework="4.5" />
<httpRuntime targetFramework="4.5" requestPathInvalidCharacters="&lt;,&gt;,*,%,&amp;,\,?" />
<!--<customErrors mode="Off"/>-->
<compilation debug="true" targetFramework="4.5" />

Loading…
Cancel
Save