Skip to content

Commit

Permalink
Add Simple Detections for some common saas (#554)
Browse files Browse the repository at this point in the history
* Add detections for some SAAS services

* Improve comment detection for urls with protocol specification in languages with // as the comment format

* Update font awesome reference

* Update tagreportgroups.json

* Update test cases for multiline strings

* Remove unused imports
  • Loading branch information
gfs authored Jul 27, 2023
1 parent 4bb352a commit 8a78a52
Show file tree
Hide file tree
Showing 12 changed files with 208 additions and 18 deletions.
3 changes: 1 addition & 2 deletions AppInspector.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Running;

namespace ApplicationInspector.Benchmarks;

Expand Down
1 change: 0 additions & 1 deletion AppInspector.Benchmarks/WriterBench.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Reflection;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using DotLiquid;
using Microsoft.ApplicationInspector.CLI;
using Microsoft.ApplicationInspector.Commands;
using Microsoft.ApplicationInspector.RulesEngine;
Expand Down
1 change: 0 additions & 1 deletion AppInspector.CLI/Writers/AnalyzeSarifWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using Microsoft.ApplicationInspector.Commands;
using Microsoft.ApplicationInspector.RulesEngine;
using Microsoft.CodeAnalysis.Sarif;
Expand Down
1 change: 0 additions & 1 deletion AppInspector.CLI/Writers/JsonWriter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.IO;
using System.Net.Sockets;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.ApplicationInspector.Commands;
Expand Down
2 changes: 1 addition & 1 deletion AppInspector.CLI/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/all.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.20/c3.css" rel="stylesheet"/>
<link href="html/resources/css/appinspector.css" rel="stylesheet" type="text/css"/>

Expand Down
19 changes: 17 additions & 2 deletions AppInspector.CLI/preferences/tagreportgroups.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@
"searchPattern": "^CloudServices.AdvertisingNetwork.*",
"displayName": "Advertising network",
"detectedIcon": "fas fa-ad"
},
{
"searchPattern": "^CloudServices.SalesForce$",
"displayName": "Salesforce",
"detectedIcon": "fa-solid fa-cloud"
},
{
"searchPattern": "^CloudServices.ServiceNow$",
"displayName": "ServiceNow",
"detectedIcon": "fa-solid fa-bell-concierge"
},
{
"searchPattern": "^CloudServices.WorkDay$",
"displayName": "WorkDay",
"detectedIcon": "fa-solid fa-calendar-day"
}
]
},
Expand Down Expand Up @@ -315,12 +330,12 @@
"detectedIcon": "far fa-file-archive"
},
{
"searchPattern": "^Metric.Code.HTMLForm.Defined$",
"searchPattern": ".Code.HTMLForm.Defined$",
"displayName": "HTML form",
"detectedIcon": "far fa-window-maximize"
},
{
"searchPattern": "^Metric.Code.Exception.Caught$",
"searchPattern": ".Code.Exception.Caught$",
"displayName": "Exception caught",
"detectedIcon": "fas fa-meteor"
},
Expand Down
1 change: 0 additions & 1 deletion AppInspector.Common/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;

Expand Down
43 changes: 39 additions & 4 deletions AppInspector.RulesEngine/TextContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,15 +243,50 @@ public TextContainer(string content, string language, Languages languages, ILogg
}
}

private int GetPrefixLocation(int startOfLineIndex, int currentIndex, string prefix, bool multiline)
{
// Find the first potential index of the prefix
var prefixLoc = FullContent.LastIndexOf(prefix, currentIndex, StringComparison.Ordinal);
if (prefixLoc != -1)
{
// TODO: Possibly support quoted multiline comment markers
if (multiline)
{
return prefixLoc;
}
if (prefixLoc < startOfLineIndex)
{
return -1;
}
// Check how many quote marks occur on the line before the prefix location
// TODO: This doesn't account for multi-line strings
var numDoubleQuotes = FullContent[startOfLineIndex..prefixLoc].Count(x => x == '"');
var numSingleQuotes = FullContent[startOfLineIndex..prefixLoc].Count(x => x == '\'');

// If the number of quotes is odd, this is in a string, so not actually a comment prefix
// It might be like var address = "http://contoso.com";
if (numDoubleQuotes % 2 == 1 || numSingleQuotes % 2 == 1)
{
return GetPrefixLocation(startOfLineIndex, prefixLoc, prefix, multiline);
}
}

return prefixLoc;
}

/// <summary>
/// Populates the CommentedStates Dictionary based on the index and the provided comment prefix and suffix
/// </summary>
/// <param name="index">The character index in FullContent</param>
/// <param name="prefix">The comment prefix</param>
/// <param name="suffix">The comment suffix</param>
private void PopulateCommentedStatesInternal(int index, string prefix, string suffix)
private void PopulateCommentedStatesInternal(int index, string prefix, string suffix, bool multiline)
{
var prefixLoc = FullContent.LastIndexOf(prefix, index, StringComparison.Ordinal);
// Get the line boundary for the prefix location
var startOfLine = GetLineBoundary(index);
// Get the index of the prefix
var prefixLoc = GetPrefixLocation(startOfLine.Index, index, prefix, multiline);

if (prefixLoc != -1)
{
if (!CommentedStates.ContainsKey(prefixLoc))
Expand Down Expand Up @@ -287,13 +322,13 @@ public void PopulateCommentedState(int index)
// Populate true for the indexes of the most immediately preceding instance of the multiline comment type if found
if (!string.IsNullOrEmpty(prefix) && !string.IsNullOrEmpty(suffix))
{
PopulateCommentedStatesInternal(index, prefix, suffix);
PopulateCommentedStatesInternal(index, prefix, suffix, true);
}

// Populate true for indexes of the most immediately preceding instance of the single-line comment type if found
if (!CommentedStates.ContainsKey(index) && !string.IsNullOrEmpty(inline))
{
PopulateCommentedStatesInternal(index, inline, "\n");
PopulateCommentedStatesInternal(index, inline, "\n", false);
}

var i = index;
Expand Down
1 change: 0 additions & 1 deletion AppInspector.Tests/Commands/TestVerifyRulesCmd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using CommandLine;
using Microsoft.ApplicationInspector.Commands;
using Microsoft.ApplicationInspector.Common;
using Microsoft.ApplicationInspector.Logging;
Expand Down
80 changes: 80 additions & 0 deletions AppInspector.Tests/RuleProcessor/QuotedStringsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System.IO;
using System.Linq;
using Microsoft.ApplicationInspector.Logging;
using Microsoft.ApplicationInspector.RulesEngine;
using Microsoft.CST.RecursiveExtractor;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Serilog.Events;

namespace AppInspector.Tests.RuleProcessor;

[TestClass]
public class QuotedStringsTests
{

private const string testDoubleQuotesAreCode = "var url = \"https://contoso.com\"; // contoso.com";
private const string testSingleQuotesAreCode = "var url = 'https://contoso.com'; // contoso.com";
private const string testSingleLineWithQuotesInComment = "// var url = 'https://contoso.com';";
private const string testSingleLineWithDoubleQuotesInComment = "// var url = 'https://contoso.com';";
private const string testMultiLine = @"/*
https://contoso.com
*/";
private const string testMultiLineWithoutProto = @"
/*
contoso.com
*/";
private const string testMultiLineWithResultFollowingCommentEnd = @"
/*
contoso.com
*/ var url = ""https://contoso.com""";

private static string detectContosoRule = @"
[
{
""id"": ""RE000001"",
""name"": ""Testing.Rules.Quotes"",
""tags"": [
""Testing.Rules.Quotes""
],
""severity"": ""Critical"",
""description"": ""Find contoso.com"",
""patterns"": [
{
""pattern"": ""contoso.com"",
""type"": ""regex"",
""confidence"": ""High"",
""scopes"": [
""code""
]
}
],
""_comment"": """"
}
]
";

private readonly ILoggerFactory _loggerFactory =
new LogOptions { ConsoleVerbosityLevel = LogEventLevel.Verbose }.GetLoggerFactory();

private readonly Microsoft.ApplicationInspector.RulesEngine.Languages _languages = new();

[DataRow(testDoubleQuotesAreCode,1)]
[DataRow(testSingleQuotesAreCode,1)]
[DataRow(testMultiLine,0)]
[DataRow(testMultiLineWithoutProto,0)]
[DataRow(testMultiLineWithResultFollowingCommentEnd,1)]
[DataRow(testSingleLineWithQuotesInComment,0)]
[DataRow(testSingleLineWithDoubleQuotesInComment,0)]
[DataTestMethod]
public void QuotedStrings(string content, int numIssues)
{
RuleSet rules = new(_loggerFactory);
rules.AddString(detectContosoRule, "contosorule");
Microsoft.ApplicationInspector.RulesEngine.RuleProcessor ruleProcessor =
new Microsoft.ApplicationInspector.RulesEngine.RuleProcessor(rules, new RuleProcessorOptions());
_languages.FromFileNameOut("testfile.cs", out LanguageInfo info);
Assert.AreEqual(numIssues,
ruleProcessor.AnalyzeFile(content, new FileEntry("testfile.cs", new MemoryStream()), info).Count());
}
}
5 changes: 1 addition & 4 deletions AppInspector.Tests/RuleProcessor/XmlAndJsonTests.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
using System;
using System.IO;
using System.Linq;
using System.IO;
using Microsoft.ApplicationInspector.RulesEngine;
using Microsoft.CST.RecursiveExtractor;
using Microsoft.VisualBasic.CompilerServices;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace AppInspector.Tests.RuleProcessor;
Expand Down
69 changes: 69 additions & 0 deletions AppInspector/rules/default/cloud_services/saas.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[
{
"name": "SaaS: Salesforce",
"id": "AI060001",
"description": "SaaS: Salesforce Rest API",
"tags": [
"CloudServices.Salesforce"
],
"severity": "moderate",
"patterns": [
{
"confidence": "high",
"pattern": "my\\.salesforce\\.com",
"type": "regex",
"scopes": [
"code"
],
"modifiers": [
"i"
]
}
]
},
{
"name": "SaaS: ServiceNow",
"id": "AI060002",
"description": "SaaS: ServiceNow Rest API",
"tags": [
"CloudServices.ServiceNow"
],
"severity": "moderate",
"patterns": [
{
"confidence": "high",
"pattern": "service-now\\.com/api",
"type": "regex",
"scopes": [
"code"
],
"modifiers": [
"i"
]
}
]
}
,
{
"name": "SaaS: WorkDay",
"id": "AI060000",
"description": "SaaS: WorkDay Rest API",
"tags": [
"CloudServices.WorkDay"
],
"severity": "moderate",
"patterns": [
{
"confidence": "high",
"pattern": "workday.com",
"type": "regex",
"scopes": [
"code"
],
"modifiers": [
"i"
]
}
]
}
]

0 comments on commit 8a78a52

Please sign in to comment.