Skip to content
This repository has been archived by the owner on Sep 11, 2019. It is now read-only.

Added taint analysis sinks for open redirects and tests. #100

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RoslynSecurityGuard.Test/RoslynSecurityGuard.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@
<Compile Include="Tests\Password\HardcodedPasswordFieldTest.cs" />
<Compile Include="Tests\Password\SqlCredentialTest.cs" />
<Compile Include="Tests\Taint\ExecutionStateTest.cs" />
<Compile Include="Tests\Taint\OpenRedirectAnalyzerTest.cs" />
<Compile Include="Tests\Taint\TaintTransferTest.cs" />
<Compile Include="Tests\WeakPasswordValidatorPropertyAnalyzerTest.cs" />
<Compile Include="Tests\XssPreventionAnalyzerTest.cs" />
Expand Down
276 changes: 276 additions & 0 deletions RoslynSecurityGuard.Test/Tests/Taint/OpenRedirectAnalyzerTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RoslynSecurityGuard.Analyzers.Taint;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Xml;
using TestHelper;

namespace RoslynSecurityGuard.Test.Tests.Taint
{
[TestClass]
public class OpenRedirectAnalyzerTest : DiagnosticVerifier
{

protected override IEnumerable<DiagnosticAnalyzer> GetDiagnosticAnalyzers()
{
return new[] { new TaintAnalyzer() };
}

protected override IEnumerable<MetadataReference> GetAdditionnalReferences()
{
return new[] {
MetadataReference.CreateFromFile(typeof(System.Web.HttpResponse).Assembly.Location),
MetadataReference.CreateFromFile(typeof(Microsoft.AspNetCore.Http.HttpResponse).Assembly.Location),
MetadataReference.CreateFromFile(typeof(System.Web.Mvc.ActionResult).Assembly.Location)
};
}


[TestMethod]
public async Task OpenRedirectFound1()
{
var cSharpTest = @"
using System.Web;

class OpenRedirect
{
public static HttpResponse Response = null;

public static void Run(string input)
{
Response.Redirect(""https://"" + input + ""/home.html"");
}
}
";
var visualBasicTest = @"
Imports System.Web

Class OpenRedirect
Public Shared Response As HttpResponse

Public Shared Sub Run(input As String)
Response.Redirect(""https://"" + input + ""/home.html"")
End Sub
End Class
";
var expected = new DiagnosticResult
{
Id = "SG0036",
Severity = DiagnosticSeverity.Warning,
};
await VerifyCSharpDiagnostic(cSharpTest, expected);
await VerifyVisualBasicDiagnostic(visualBasicTest, expected);
}

[TestMethod]
public async Task OpenRedirectFound2()
{
var cSharpTest = @"
using System.Web;

class OpenRedirect
{
public static HttpResponse Response = null;

public static void Run(string input)
{
Response.Redirect(input, true);
}
}
";
var visualBasicTest = @"
Imports System.Web

Class OpenRedirect
Public Shared Response As HttpResponse

Public Shared Sub Run(input As String)
Response.Redirect(input, false)
End Sub
End Class
";
var expected = new DiagnosticResult
{
Id = "SG0036",
Severity = DiagnosticSeverity.Warning,
};
await VerifyCSharpDiagnostic(cSharpTest, expected);
await VerifyVisualBasicDiagnostic(visualBasicTest, expected);
}

[TestMethod]
public async Task OpenRedirectFound3()
{
var cSharpTest = @"
using Microsoft.AspNetCore.Http;

class OpenRedirect
{
public static HttpResponse Response = null;

public static void Run(string input)
{
Response.Redirect(input);
}
}
";
var visualBasicTest = @"
Imports Microsoft.AspNetCore.Http

Class OpenRedirect
Public Shared Response As HttpResponse

Public Shared Sub Run(input As String)
Response.Redirect(input)
End Sub
End Class
";
var expected = new DiagnosticResult
{
Id = "SG0036",
Severity = DiagnosticSeverity.Warning,
};
await VerifyCSharpDiagnostic(cSharpTest, expected);
await VerifyVisualBasicDiagnostic(visualBasicTest, expected);
}

[TestMethod]
public async Task OpenRedirectFound4()
{
var cSharpTest = @"
using Microsoft.AspNetCore.Http;

class OpenRedirect
{
public static HttpResponse Response = null;

public static void Run(string input)
{
Response.Redirect(input, true);
}
}
";
var visualBasicTest = @"
Imports Microsoft.AspNetCore.Http

Class OpenRedirect
Public Shared Response As HttpResponse

Public Shared Sub Run(input As String)
Response.Redirect(input, false)
End Sub
End Class
";
var expected = new DiagnosticResult
{
Id = "SG0036",
Severity = DiagnosticSeverity.Warning,
};
await VerifyCSharpDiagnostic(cSharpTest, expected);
await VerifyVisualBasicDiagnostic(visualBasicTest, expected);
}

[TestMethod]
public async Task OpenRedirectFound5()
{
var cSharpTest = @"
using System.Web.Mvc;

class OpenRedirect : Controller
{
public ActionResult Run(string input)
{
return Redirect(input);
}
}
";
var visualBasicTest = @"
Imports System.Web.Mvc

Public Class OpenRedirect
Inherits Controller

Public Function Run(input As String) as ActionResult
Return Redirect(input)
End Function
End Class
";
var expected = new DiagnosticResult
{
Id = "SG0036",
Severity = DiagnosticSeverity.Warning,
};
await VerifyCSharpDiagnostic(cSharpTest, expected);
await VerifyVisualBasicDiagnostic(visualBasicTest, expected);
}

[TestMethod]
public async Task OpenRedirectFound6()
{
var cSharpTest = @"
using System.Web.Mvc;

class OpenRedirect : Controller
{
public ActionResult Run(string input)
{
return RedirectPermanent(input);
}
}
";
var visualBasicTest = @"
Imports System.Web.Mvc

Public Class OpenRedirect
Inherits Controller

Public Function Run(input As String) as ActionResult
Return RedirectPermanent(input)
End Function
End Class
";
var expected = new DiagnosticResult
{
Id = "SG0036",
Severity = DiagnosticSeverity.Warning,
};
await VerifyCSharpDiagnostic(cSharpTest, expected);
await VerifyVisualBasicDiagnostic(visualBasicTest, expected);
}

[TestMethod]
public async Task OpenRedirectFalsePositive1()
{
var cSharpTest = @"
using System.Web;

class OpenRedirect
{
public static HttpResponse Response = null;

public static void Run(string input)
{
Response.Redirect(""https://example.com/home.html"");
}
}
";
var visualBasicTest = @"
Imports System.Web

Class OpenRedirect
Public Shared Response As HttpResponse

Public Shared Sub Run(input As String)
Response.Redirect(""https://example.com/home.html"")
End Sub
End Class
";

await VerifyCSharpDiagnostic(cSharpTest);
await VerifyVisualBasicDiagnostic(visualBasicTest);
}
}
}
5 changes: 5 additions & 0 deletions RoslynSecurityGuard/Config/Messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ SG0003:
title: Potential XPath injection with XmlDocument
description: The dynamic value passed to the XPath query should be validated

SG0036:
class: TaintAnalyzer
title: Potential OpenRedirect
description: The dynamic value passed to the redirect should be validated

# Various

SG0004:
Expand Down
57 changes: 57 additions & 0 deletions RoslynSecurityGuard/Config/Sinks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -398,3 +398,60 @@ StreamReader_Create_path_encoding_bool_int:
argTypes: (System.String, System.Text.Encoding, System.Boolean, System.Int32)
injectableArguments: 0
locale: SG0018

# Open Redirects

System.Web.HttpResponse_Redirect_string:
namespace: System.Web
className: HttpResponse
member: method
name: Redirect
argTypes: (System.String)
injectableArguments: 0
locale: SG0036

System.Web.HttpResponse_Redirect_string_bool:
namespace: System.Web
className: HttpResponse
member: method
name: Redirect
argTypes: (System.String, System.Boolean)
injectableArguments: 0
locale: SG0036

Microsoft.AspNetCore.Http.HttpResponse_Redirect_string:
namespace: Microsoft.AspNetCore.Http
className: HttpResponse
member: method
name: Redirect
argTypes: (System.String)
injectableArguments: 0
locale: SG0036

Microsoft.AspNetCore.Http.HttpResponse_Redirect_string_bool:
namespace: Microsoft.AspNetCore.Http
className: HttpResponse
member: method
name: Redirect
argTypes: (System.String, System.Boolean)
injectableArguments: 0
locale: SG0036


Controller_Redirect_string:
namespace: System.Web.Mvc
className: Controller
member: method
name: Redirect
argTypes: (System.String)
injectableArguments: 0
locale: SG0036

Controller_RedirectPermanent_string:
namespace: System.Web.Mvc
className: Controller
member: method
name: RedirectPermanent
argTypes: (System.String)
injectableArguments: 0
locale: SG0036