Fix <img /> detection regex in web cmdlets (#12099)

This commit is contained in:
Joel Sallow (/u/ta11ow) 2020-03-24 13:51:55 -04:00 committed by GitHub
parent 3c81de6d26
commit f8fb77052f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 7 deletions

View file

@ -232,7 +232,7 @@ namespace Microsoft.PowerShell.Commands
if (s_imageRegex == null)
{
s_imageRegex = new Regex(@"<img\s+[^\s>]*>",
s_imageRegex = new Regex(@"<img\s[^>]*?>",
RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Compiled);
}
}

View file

@ -1900,7 +1900,51 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
}
}
Context "Regex Parsing" {
It 'correctly parses an image with id, class, and src attributes' {
$dosUri = Get-WebListenerUrl -Test 'Dos' -query @{
dosType = 'img-attribute'
}
$response = Invoke-WebRequest -Uri $dosUri
$response.Images | Should -Not -BeNullOrEmpty
}
}
Context "Denial of service" -Tag 'DOS' {
It "Image Parsing" {
Set-ItResult -Pending -Because "The pathological regex runs fast due to https://github.com/dotnet/runtime/issues/33399. Fixed in .NET 5 preview.2"
$dosUri = Get-WebListenerUrl -Test 'Dos' -query @{
dosType='img'
dosLength='5000'
}
$script:content = ''
[TimeSpan] $timeSpan = Measure-Command {
$response = Invoke-WebRequest -Uri $dosUri
$script:content = $response.content
$response.Images | out-null
}
$script:content | Should -Not -BeNullOrEmpty
# pathological regex
$regex = [RegEx]::new('<img\s+[^>]*>')
[TimeSpan] $pathologicalTimeSpan = Measure-Command {
$regex.Match($content)
}
$pathologicalRatio = $pathologicalTimeSpan.TotalMilliseconds/$timeSpan.TotalMilliseconds
Write-Verbose "Pathological ratio: $pathologicalRatio" -Verbose
# dosLength 4,000 on my 3.5 GHz 6-Core Intel Xeon E5 macpro produced a ratio of 12
# dosLength 5,000 on my 3.5 GHz 6-Core Intel Xeon E5 macpro produced a ratio of 21
# dosLength 10,000 on my 3.5 GHz 6-Core Intel Xeon E5 macpro produced a ratio of 75
# in some cases we will be running in a Docker container with modest resources
$pathologicalRatio | Should -BeGreaterThan 5
}
It "Charset Parsing" {
$dosUri = Get-WebListenerUrl -Test 'Dos' -query @{
dosType='charset'

View file

@ -29,33 +29,38 @@ namespace mvc.Controllers
}
StringValues dosLengths;
Int32 dosLength =1;
Int32 dosLength = 1;
if (Request.Query.TryGetValue("dosLength", out dosLengths))
{
Int32.TryParse(dosLengths.FirstOrDefault(), out dosLength);
}
string body = string.Empty;
switch(dosType)
switch (dosType)
{
case "img":
contentType = "text/html; charset=utf8";
body = "<img" + (new string(' ', dosLength));
break;
// This is not really a DOS test, but this is the best place for it at present.
case "img-attribute":
contentType = "text/html; charset=utf8";
body = "<img src=\"https://fakesite.org/image.png\" id=\"mainImage\" class=\"lightbox\">";
break;
case "charset":
contentType = "text/html; charset=melon";
body = "<meta " + (new string('.', dosLength));
break;
default:
throw new InvalidOperationException("Invalid dosType: "+dosType);
throw new InvalidOperationException("Invalid dosType: " + dosType);
}
// Content-Type must be applied right before it is sent to the client or MVC will overwrite.
Response.OnStarting(state =>
{
var httpContext = (HttpContext) state;
httpContext.Response.ContentType = contentType;
return Task.FromResult(0);
var httpContext = (HttpContext)state;
httpContext.Response.ContentType = contentType;
return Task.FromResult(0);
}, HttpContext);
Response.ContentLength = Encoding.UTF8.GetBytes(body).Length;