Skip to content

Commit

Permalink
Sanitizers and validators added.
Browse files Browse the repository at this point in the history
  • Loading branch information
JarLob committed Nov 17, 2018
1 parent 80fa8b4 commit a1a2e92
Show file tree
Hide file tree
Showing 35 changed files with 1,440 additions and 375 deletions.
34 changes: 34 additions & 0 deletions SecurityCodeScan.Test/Helpers/CsToVbConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Text;
using System.Text.RegularExpressions;

namespace SecurityCodeScan.Test.Helpers
{
internal static class CsToVbConverter
{
public static string CSharpReplaceToVBasic(this string cs)
{
var vbString = cs;
vbString = Regex.Replace(vbString, @"default\(([^\)]*)\)", "DirectCast(Nothing, $1)");
vbString = Regex.Replace(vbString, @"\(([^\s\)]+)\)([\w]+)", "DirectCast($2, $1)");
vbString = Regex.Replace(vbString, @"\bnew\s*\[\s*\]\s*({.*?})", "$1");
vbString = Regex.Replace(vbString, @"({(\s*[^\s]*))\s*=", "With {.$2 =");
vbString = Regex.Replace(vbString, @"(<(\s*[^>]*\s*)>)", "(Of $2)");

var vb = new StringBuilder(vbString);
vb.Replace("null", "Nothing");
vb.Replace(";", "\r\n");
vb.Replace("new ", "New ");
vb.Replace("var ", "Dim ");
vb.Replace("typeof", "GetType");
vb.Replace("'", "\"");
vb.Replace("this.", "Me.");
vb.Replace("static ", "Shared ");
vb.Replace("using ", "Imports ");
vb.Replace("out ", "");
vb.Replace("[]", "()");

vbString = vb.ToString();
return vbString;
}
}
}
6 changes: 6 additions & 0 deletions SecurityCodeScan.Test/Helpers/DiagnosticVerifier.Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.VisualStudio.TestTools.UnitTesting.Logging;

namespace SecurityCodeScan.Test.Helpers
{
Expand Down Expand Up @@ -102,6 +103,11 @@ public static ReferenceAssemblies GetCache(Version dotNetVersion)
IEnumerable<MetadataReference> references = null,
bool includeCompilerDiagnostics = false)
{
foreach (var source in sources)
{
Logger.LogMessage("{0}", source);
}

var documents = GetDocuments(sources, dotNetVersion, language, references);
return (await GetSortedDiagnosticsFromDocuments(analyzers,
options,
Expand Down
12 changes: 10 additions & 2 deletions SecurityCodeScan.Test/SecurityCodeScan.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<ItemGroup>
<Reference Include="AntiXssLibrary, Version=4.3.0.0, Culture=neutral, PublicKeyToken=d127efab8a9c114f, processorArchitecture=MSIL">
<HintPath>..\packages\AntiXSS.4.3.0\lib\net40\AntiXssLibrary.dll</HintPath>
</Reference>
<Reference Include="Castle.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll</HintPath>
<Private>True</Private>
Expand All @@ -56,6 +59,9 @@
<Reference Include="fastjson, Version=2.1.0.0, Culture=neutral, PublicKeyToken=6b75a806b86095cd, processorArchitecture=MSIL">
<HintPath>..\packages\fastJSON.2.1.21\lib\net40\fastjson.dll</HintPath>
</Reference>
<Reference Include="HtmlSanitizationLibrary, Version=4.3.0.0, Culture=neutral, PublicKeyToken=d127efab8a9c114f, processorArchitecture=MSIL">
<HintPath>..\packages\AntiXSS.4.3.0\lib\net40\HtmlSanitizationLibrary.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
</Reference>
Expand Down Expand Up @@ -305,8 +311,8 @@
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Runtime.Serialization.Formatters.Soap" />
<Reference Include="System.Security" />
<Reference Include="System.Text.Encodings.Web, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encodings.Web.4.3.1\lib\netstandard1.0\System.Text.Encodings.Web.dll</HintPath>
<Reference Include="System.Text.Encodings.Web, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encodings.Web.4.5.0\lib\netstandard1.0\System.Text.Encodings.Web.dll</HintPath>
</Reference>
<Reference Include="System.Transactions" />
<Reference Include="System.ValueTuple, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
Expand Down Expand Up @@ -346,6 +352,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Helpers\CsToVbConverter.cs" />
<Compile Include="Tests\AspxAnalyzerTest.cs" />
<Compile Include="Tests\Audit\AuditTest.cs" />
<Compile Include="Tests\Audit\CsrfTokenAnalyzerAuditTest.cs" />
Expand All @@ -365,6 +372,7 @@
<Compile Include="Tests\Taint\OpenRedirectAnalyzerTest.cs" />
<Compile Include="Tests\Taint\LdapInjectionAnalyzerTest.cs" />
<Compile Include="Tests\Taint\SqlInjectionAnalyzerTest.cs" />
<Compile Include="Tests\Taint\TaintAnalyzerSanitizerTest.cs" />
<Compile Include="Tests\Taint\TaintTransferTest.cs" />
<Compile Include="Tests\Taint\UnsafeDeserializationTests.cs" />
<Compile Include="Tests\UnsafeDeserializationAnalyzerTests.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
Expand Down Expand Up @@ -97,7 +96,6 @@ class PathTraversal
}}
";

sink = sink.Replace("null", "Nothing");
var visualBasicTest = $@"
#Disable Warning BC50001
Imports System
Expand All @@ -111,7 +109,7 @@ Class PathTraversal
Public Shared Sub Run(path As String, contents As IEnumerable(Of String), flag As Boolean, fileMode As FileMode,
access as FileAccess, share As FileShare, bytes As Byte(), fileSecurity As FileSecurity,
fileOptions As FileOptions)
{sink}
{sink.CSharpReplaceToVBasic()}
End Sub
End Class
";
Expand Down Expand Up @@ -192,7 +190,6 @@ public static void Run(bool flag, int digit, System.Text.Encoding encoding)
}}
";

sink = sink.Replace("null", "Nothing");
var visualBasicTest = $@"
#Disable Warning BC50001
Imports System
Expand All @@ -204,7 +201,7 @@ Imports System.Security.AccessControl
Class PathTraversal
Public Shared Sub Run(flag As Boolean, digit As Int32, encoding As System.Text.Encoding)
{sink}
{sink.CSharpReplaceToVBasic()}
End Sub
End Class
";
Expand Down Expand Up @@ -241,8 +238,6 @@ public static void Run(string textInput, Stream streamInput, TextReader textRead
}}
";

sink = sink.Replace("null", "Nothing");
sink = Regex.Replace(sink, "default\\(([^\\)]*)\\)", "DirectCast(Nothing, $1)");
var visualBasicTest = $@"
#Disable Warning BC50001
Imports System.IO
Expand All @@ -251,7 +246,7 @@ Imports System.Xml
Class PathTraversal
Public Shared Sub Run(textInput As String, streamInput As Stream, textReaderInput As TextReader, xmlReaderInput As XmlReader)
Dim reader As XMLReader = {sink}
Dim reader As XMLReader = {sink.CSharpReplaceToVBasic()}
End Sub
End Class
";
Expand Down
60 changes: 58 additions & 2 deletions SecurityCodeScan.Test/Tests/Config/ConfigTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public void EmptyUserConfig_NoChanges()
var newConfig = Manager.GetProjectConfiguration(options.AdditionalFiles);

//ensuring that field count matches count of properties tested below (test should fail and be updated if someone adds new field in Configuration)
Assert.AreEqual(9, typeof(Configuration).GetFields().Length);
Assert.AreEqual(10, typeof(Configuration).GetFields().Length);

Assert.AreEqual(StartupConfiguration.AuditMode, newConfig.AuditMode);
Assert.AreEqual(StartupConfiguration.Behavior.Count, newConfig.Behavior.Count);
Expand All @@ -45,6 +45,7 @@ public void EmptyUserConfig_NoChanges()
Assert.AreEqual(StartupConfiguration.PasswordFields.Count, newConfig.PasswordFields.Count);
Assert.AreEqual(StartupConfiguration.ConstantFields.Count, newConfig.ConstantFields.Count);
Assert.AreEqual(StartupConfiguration.AntiCsrfAttributes.Count, newConfig.AntiCsrfAttributes.Count);
Assert.AreEqual(StartupConfiguration.SanitizerTypeNameToBit.Count, newConfig.SanitizerTypeNameToBit.Count);
}

[TestMethod]
Expand All @@ -54,7 +55,7 @@ public void MergingUserConfig_NoChanges()
var newConfig = Manager.GetProjectConfiguration(options.AdditionalFiles);

// ensuring that field count matches count of properties tested below
Assert.AreEqual(9, typeof(Configuration).GetFields().Length);
Assert.AreEqual(10, typeof(Configuration).GetFields().Length);

Assert.AreEqual(StartupConfiguration.AuditMode, newConfig.AuditMode);
Assert.AreEqual(StartupConfiguration.Behavior.Count, newConfig.Behavior.Count);
Expand All @@ -65,6 +66,7 @@ public void MergingUserConfig_NoChanges()
Assert.AreEqual(StartupConfiguration.PasswordFields.Count, newConfig.PasswordFields.Count);
Assert.AreEqual(StartupConfiguration.ConstantFields.Count, newConfig.ConstantFields.Count);
Assert.AreEqual(StartupConfiguration.AntiCsrfAttributes.Count, newConfig.AntiCsrfAttributes.Count);
Assert.AreEqual(StartupConfiguration.SanitizerTypeNameToBit.Count, newConfig.SanitizerTypeNameToBit.Count);
}

[TestMethod]
Expand All @@ -76,5 +78,59 @@ public void DifferentConfigVersion_ChangesIgnored()
Assert.AreNotEqual(StartupConfiguration.MinimumPasswordValidatorProperties, 0);
Assert.AreEqual(StartupConfiguration.MinimumPasswordValidatorProperties, newConfig.MinimumPasswordValidatorProperties);
}

[DataTestMethod]
[DataRow(" ()", true)]
[DataRow("() ", true)]
[DataRow("", true)]
[DataRow("(", true)]
[DataRow(")", true)]
[DataRow("((", true)]
[DataRow("))", true)]
[DataRow(")(", true)]
[DataRow("())", true)]
[DataRow("(System.String)", false)]
[DataRow("( System.String)", true)]
[DataRow("(System.String aaa)", true)]
[DataRow("(string)", true)]
[DataRow("(System.String, System.String)", true)]
[DataRow("(System.String, System.String)", false)]
[DataRow("(System.String, out System.String)", false)]
[DataRow("(this System.String, System.String)", true)]
[DataRow("(System.String, params System.String[])", false)]
[DataRow("(System.String[])", false)]
public void ArgTypesValidation(string payload, bool shouldThrow)
{
var options = ConfigurationTest.CreateAnalyzersOptionsWithConfig($@"
Behavior:
Bla:
Namespace: NS
ClassName: CL
Member: method
Name: Foo
ArgTypes: ""{payload}""
");

if (shouldThrow)
Assert.ThrowsException<Exception>(() => Manager.GetProjectConfiguration(options.AdditionalFiles));
else
Manager.GetProjectConfiguration(options.AdditionalFiles);
}

[DataTestMethod]
[DataRow("[aaa]", false)]
[DataRow("[aaa,aaa]", true)]
[DataRow("[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59]", true)]
[DataRow("[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58]", false)]
public void SanitizerTypesValidation(string payload, bool shouldThrow)
{
var options = ConfigurationTest.CreateAnalyzersOptionsWithConfig($@"
SanitizerTypes: {payload}");

if (shouldThrow)
Assert.ThrowsException<Exception>(() => Manager.GetProjectConfiguration(options.AdditionalFiles));
else
Manager.GetProjectConfiguration(options.AdditionalFiles);
}
}
}
2 changes: 1 addition & 1 deletion SecurityCodeScan.Test/Tests/Config/ConfigurationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace SecurityCodeScan.Test.Config
public class ConfigurationTest
{
private const string ConfigName = "SecurityCodeScan.config.yml";
private static readonly Version ConfigVersion = new Version(1,0);
private static readonly Version ConfigVersion = new Version(2,0);
private const string ConfigText = "Version: {0}\r\n{1}";

public static AnalyzerOptions CreateAnalyzersOptionsWithConfig(string configSource, Version version = null)
Expand Down
4 changes: 2 additions & 2 deletions SecurityCodeScan.Test/Tests/ExternalFileAnalyzerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ public ExternalFileAnalyzerTest(IExternalFileAnalyzer analyzer)
protected async Task<Mock<Action<Diagnostic>>> Analyze(string source, string path, CancellationToken cancellationToken = default(CancellationToken))
{
var additionalTextMock = new Mock<AdditionalText>();
additionalTextMock.Setup(text => text.Path).Returns(path); //The path is read when the diagnostic is report
additionalTextMock.Setup(text => text.Path).Returns(path); //The path is read when the diagnostic is reported
additionalTextMock.Setup(text => text.GetText(cancellationToken)).Returns(SourceText.From(source));

var diagnosticReportMock = new Mock<Action<Diagnostic>>(MockBehavior.Loose); //Will record the reported diagnostic...
diagnosticReportMock.Setup(x => x(It.IsAny<Diagnostic>()))
.Callback<Diagnostic>(diagnostic =>
{
if (diagnostic != null)
Logger.LogMessage($"Was: \"{diagnostic.GetMessage()}\"");
Logger.LogMessage("Was: \"{0}\"", diagnostic.GetMessage());
});

var compilation = new CompilationAnalysisContext(null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ protected override IEnumerable<DiagnosticAnalyzer> GetDiagnosticAnalyzers(string
[DataTestMethod]
public async Task HardCodePasswordFalsePositive(string value)
{
var vbValue = value.Replace("null", "Nothing");
var vbValue = value.CSharpReplaceToVBasic();

var cSharpTest = $@"
using System;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ public static void Run(string input, string[] propertiesToLoad, DirectoryEntry e
}}
}}
";
sink = sink.Replace("null", "Nothing")
.Replace(";", "\r\n")
.Replace("new ", "New ");

var visualBasicTest = $@"
#Disable Warning BC50001
Expand All @@ -80,7 +77,7 @@ Imports System.DirectoryServices
Namespace sample
Class MyFoo
Public Shared Sub Run(input As System.String, propertiesToLoad() As System.String, entry As DirectoryEntry, scope As SearchScope )
Dim temp = {sink}
Dim temp = {sink.CSharpReplaceToVBasic()}
End Sub
End Class
End Namespace
Expand Down
28 changes: 13 additions & 15 deletions SecurityCodeScan.Test/Tests/Taint/LinqSqlInjectionAnalyzerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,20 @@ protected override IEnumerable<DiagnosticAnalyzer> GetDiagnosticAnalyzers(string

protected override IEnumerable<MetadataReference> GetAdditionalReferences() => References;

[DataRow("ctx.ExecuteQuery<UserEntity>(input)", true)]
[DataRow("ctx.ExecuteQuery<UserEntity>(\"select\")", false)]
[DataRow("ctx.ExecuteQuery(typeof(UserEntity), input)", true)]
[DataRow("ctx.ExecuteQuery(typeof(UserEntity), \"select\")", false)]
[DataRow("ctx.ExecuteQuery<Object>(input)", true)]
[DataRow("ctx.ExecuteQuery<Object>(\"select\")", false)]
[DataRow("ctx.ExecuteQuery(typeof(Object), input)", true)]
[DataRow("ctx.ExecuteQuery(typeof(Object), \"select\")", false)]
[DataRow("ctx.ExecuteCommand(input)", true)]
[DataRow("ctx.ExecuteCommand(\"select\")", false)]
[DataTestMethod]
public async Task LinqInjection(string sink, bool warn)
{
var cSharpTest = $@"
using System.Data.Linq;
#pragma warning disable 8019
using System.Data.Linq;
using System;
#pragma warning restore 8019
namespace VulnerableApp
{{
Expand All @@ -46,17 +49,14 @@ public class LyncInjectionTP
return 0;
}}
}}
class UserEntity
{{
}}
}}";
sink = sink.Replace("null", "Nothing")
.Replace("<UserEntity>", "(Of UserEntity)")
.Replace("typeof", "GetType");
sink = sink.CSharpReplaceToVBasic();

var visualBasicTest = $@"
Imports System.Data.Linq
#Disable Warning BC50001
Imports System.Data.Linq
Imports System
#Enable Warning BC50001
Namespace VulnerableApp
Public Class LyncInjectionTP
Expand All @@ -66,8 +66,6 @@ Return 0
End Function
End Class
Class UserEntity
End Class
End Namespace
";

Expand Down

0 comments on commit a1a2e92

Please sign in to comment.