diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9a4e68c4a443..c4858c768167 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -101,6 +101,7 @@ AspectsDefinitions.g.cs @DataDog/asm-dotnet /tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/HashAlgorithm/ @DataDog/asm-dotnet /tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Process/ @DataDog/asm-dotnet /tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/StackTraceLeak/ @DataDog/asm-dotnet +/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/RestSharp/ @DataDog/asm-dotnet /tracer/test/test-applications/integrations/Samples.ProcessStart @DataDog/asm-dotnet # Profiler diff --git a/Datadog.Trace.sln b/Datadog.Trace.sln index c211f079779e..cf146ffdab76 100644 --- a/Datadog.Trace.sln +++ b/Datadog.Trace.sln @@ -576,6 +576,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RuntimeMetricsShutdown", "t EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.Debugger.AspNetCore5", "tracer\test\test-applications\debugger\Samples.Debugger.AspNetCore5\Samples.Debugger.AspNetCore5.csproj", "{3978A7D5-7B6E-4152-9C3A-5852F1F6E223}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Generated", "Generated", "{E1B0F72C-991A-409D-9266-DE5ED1BD940E}" + ProjectSection(SolutionItems) = preProject + tracer\build\PackageVersionsLatestMajors.g.props = tracer\build\PackageVersionsLatestMajors.g.props + tracer\build\PackageVersionsLatestMinors.g.props = tracer\build\PackageVersionsLatestMinors.g.props + tracer\build\PackageVersionsLatestSpecific.g.props = tracer\build\PackageVersionsLatestSpecific.g.props + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1609,6 +1616,7 @@ Global {0D996EEE-7C04-4888-AF48-9C1E2F261A00} = {BAF8F246-3645-42AD-B1D0-0F7EAFBAB34A} {C4ABF344-3263-45D5-A074-03FB206FF309} = {498A300E-D036-49B7-A43D-821D1CAF11A5} {3978A7D5-7B6E-4152-9C3A-5852F1F6E223} = {16427BFB-B4C6-46A9-A290-8EA51FF73FEA} + {E1B0F72C-991A-409D-9266-DE5ED1BD940E} = {A0C5FBBB-CFB2-4FB9-B8F0-55676E9DCF06} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F} @@ -1661,7 +1669,6 @@ Global tracer\test\test-applications\Samples.Shared\Samples.Shared.projitems*{536f1d82-d40c-4e33-b7fa-76a0f17bf672}*SharedItemsImports = 5 tracer\test\test-applications\Samples.Shared\Samples.Shared.projitems*{560e1104-9a6e-41e7-ab3d-85ba2740a0f7}*SharedItemsImports = 5 tracer\test\test-applications\Samples.Shared\Samples.Shared.projitems*{56de0d44-e9e5-48da-baea-2934b1e28d4e}*SharedItemsImports = 5 - tracer\test\test-applications\Samples.Shared\Samples.Shared.projitems*{5a806f4b-39e7-4f38-b36f-f5cfc4f8760a}*SharedItemsImports = 13 tracer\test\test-applications\Samples.Shared\Samples.Shared.projitems*{5c2829c2-ed0d-414c-b5a0-2bfdca07b493}*SharedItemsImports = 5 tracer\test\test-applications\Samples.Shared\Samples.Shared.projitems*{5e290fa1-e87b-4782-b977-eb5fa6c96efe}*SharedItemsImports = 5 tracer\test\test-applications\Samples.Shared\Samples.Shared.projitems*{5ee6b6eb-b768-47ec-882b-8dcaca2b1360}*SharedItemsImports = 5 diff --git a/tracer/build/_build/Honeypot/IntegrationGroups.cs b/tracer/build/_build/Honeypot/IntegrationGroups.cs index f83290df2de9..a91e1c683b46 100644 --- a/tracer/build/_build/Honeypot/IntegrationGroups.cs +++ b/tracer/build/_build/Honeypot/IntegrationGroups.cs @@ -110,6 +110,7 @@ static IntegrationMap() NugetPackages.Add("Microsoft.AspNetCore.Session", new [] { "Microsoft.AspNetCore.Session" }); NugetPackages.Add("Microsoft.TestPlatform.PlatformAbstractions", Array.Empty()); NugetPackages.Add("Microsoft.VisualStudio.TraceDataCollector", Array.Empty()); + NugetPackages.Add("RestSharp", Array.Empty()); // Manual instrumentation NugetPackages.Add("Datadog.Trace.Manual", new string[] { }); diff --git a/tracer/build/supported_versions.json b/tracer/build/supported_versions.json index e9eb96478946..ee5227b5da09 100644 --- a/tracer/build/supported_versions.json +++ b/tracer/build/supported_versions.json @@ -1141,6 +1141,13 @@ } ] }, + { + "integrationName": "Ssrf", + "assemblyName": "RestSharp", + "minAssemblyVersionInclusive": "104.0.0", + "maxAssemblyVersionInclusive": "112.65535.65535", + "packages": [] + }, { "integrationName": "StackExchangeRedis", "assemblyName": "StackExchange.Redis", @@ -1284,4 +1291,4 @@ } ] } -] \ No newline at end of file +] diff --git a/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml b/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml index 4b07603c13e9..b4ea1f6bddfb 100644 --- a/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml +++ b/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml @@ -120,6 +120,7 @@ + diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/RestSharp/UrlEncode2Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/RestSharp/UrlEncode2Integration.cs new file mode 100644 index 000000000000..051110286aa0 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/RestSharp/UrlEncode2Integration.cs @@ -0,0 +1,82 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +#nullable enable + +using System; +using System.ComponentModel; +using Datadog.Trace.ClrProfiler.CallTarget; +using Datadog.Trace.Iast; +using Datadog.Trace.Vendors.Serilog; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp; + +/// +/// System.Security.Cryptography.HashAlgorithm instrumentation +/// +[InstrumentMethod( + AssemblyName = "RestSharp", + TypeName = "RestSharp.Extensions.StringExtensions", + MethodName = "UrlEncode", + ReturnTypeName = ClrNames.String, + ParameterTypeNames = new[] { ClrNames.String, "System.Text.Encoding" }, + MinimumVersion = "104.0.0", + MaximumVersion = "112.*.*", + InstrumentationCategory = InstrumentationCategory.Iast, + IntegrationName = nameof(Configuration.IntegrationId.Ssrf))] +[Browsable(false)] +[EditorBrowsable(EditorBrowsableState.Never)] +public class UrlEncode2Integration +{ + private static bool errorLogged = false; + + /// + /// OnMethodBegin callback + /// + /// String being escaped. + /// Encoding being used. + /// Calltarget state value + internal static CallTargetState OnMethodBegin(string value, System.Text.Encoding encoding) + { + return new CallTargetState(null, value); + } + + /// + /// OnMethodEnd callback + /// + /// Type of the target + /// Type of the return value + /// Return value. + /// Exception instance in case the original code threw an exception. + /// Calltarget state value + /// CallTargetReturn + internal static CallTargetReturn OnMethodEnd(TReturn returnValue, Exception exception, CallTargetState state) + { + try + { + if (exception is null && returnValue is string value) + { + if (state.State is string input) + { + var newValue = IastModule.OnSsrfEscape(input, value); + if (newValue is not null) + { + returnValue = (TReturn)(object)newValue; + } + } + } + } + catch (Exception e) + { + if (!errorLogged) + { + Log.Error(e, "Error escaping Url with encoding"); + errorLogged = true; + } + } + + return new CallTargetReturn(returnValue); + } +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/RestSharp/UrlEncodeIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/RestSharp/UrlEncodeIntegration.cs new file mode 100644 index 000000000000..7ef5237f69c0 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/RestSharp/UrlEncodeIntegration.cs @@ -0,0 +1,81 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +#nullable enable + +using System; +using System.ComponentModel; +using Datadog.Trace.ClrProfiler.CallTarget; +using Datadog.Trace.Iast; +using Datadog.Trace.Vendors.Serilog; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp; + +/// +/// System.Security.Cryptography.HashAlgorithm instrumentation +/// +[InstrumentMethod( + AssemblyName = "RestSharp", + TypeName = "RestSharp.Extensions.StringExtensions", + MethodName = "UrlEncode", + ReturnTypeName = ClrNames.String, + ParameterTypeNames = new[] { ClrNames.String }, + MinimumVersion = "104.0.0", + MaximumVersion = "112.*.*", + InstrumentationCategory = InstrumentationCategory.Iast, + IntegrationName = nameof(Configuration.IntegrationId.Ssrf))] +[Browsable(false)] +[EditorBrowsable(EditorBrowsableState.Never)] +public class UrlEncodeIntegration +{ + private static bool errorLogged = false; + + /// + /// OnMethodBegin callback + /// + /// String being escaped. + /// Calltarget state value + internal static CallTargetState OnMethodBegin(string value) + { + return new CallTargetState(null, value); + } + + /// + /// OnMethodEnd callback + /// + /// Type of the target + /// Type of the return value + /// Return value. + /// Exception instance in case the original code threw an exception. + /// Calltarget state value + /// CallTargetReturn + internal static CallTargetReturn OnMethodEnd(TReturn returnValue, Exception exception, CallTargetState state) + { + try + { + if (exception is null && returnValue is string value) + { + if (state.State is string input) + { + var newValue = IastModule.OnSsrfEscape(input, value); + if (newValue is not null) + { + returnValue = (TReturn)(object)newValue; + } + } + } + } + catch (Exception e) + { + if (!errorLogged) + { + Log.Error(e, "Error escaping Url"); + errorLogged = true; + } + } + + return new CallTargetReturn(returnValue); + } +} diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs index a40b43b5c375..5595d308cdc8 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs @@ -237,7 +237,8 @@ internal static partial class AspectDefinitions " [AspectMethodInsertBefore(\"System.Net.WebClient::UploadValuesTaskAsync(System.Uri,System.Collections.Specialized.NameValueCollection)\",\"\",[1],[False],[None],Default,[])] ReviewUri(System.Uri)", " [AspectMethodInsertBefore(\"System.Net.WebClient::UploadValuesTaskAsync(System.Uri,System.String,System.Collections.Specialized.NameValueCollection)\",\"\",[2],[False],[None],Default,[])] ReviewUri(System.Uri)", "[AspectClass(\"System.Private.Corelib;System.Runtime\",[None],Sink,[Ssrf])] Datadog.Trace.Iast.Aspects.System.Net.WebUtilityAspect", -" [AspectMethodReplace(\"System.Net.WebUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] Review(System.String)", +" [AspectMethodReplace(\"System.Net.WebUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] XssEscape(System.String)", +" [AspectMethodReplace(\"System.Net.WebUtility::UrlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String)", "[AspectClass(\"System.Web\",[None],Propagation,[])] Datadog.Trace.Iast.Aspects.System.Web.HttpCookieAspect", " [AspectMethodReplace(\"System.Web.HttpCookie::get_Value()\",\"\",[0],[False],[None],Default,[])] GetValue(System.Web.HttpCookie)", "[AspectClass(\"System.Web\",[None],Sink,[TrustBoundaryViolation])] Datadog.Trace.Iast.Aspects.System.Web.SessionState.HttpSessionStateBaseAspect", @@ -256,7 +257,9 @@ internal static partial class AspectDefinitions " [AspectMethodInsertBefore(\"System.Web.Mvc.Controller::Redirect(System.String)\",\"\",[0],[False],[None],Default,[])] Redirect(System.String)", " [AspectMethodInsertBefore(\"System.Web.Mvc.Controller::RedirectPermanent(System.String)\",\"\",[0],[False],[None],Default,[])] Redirect(System.String)", "[AspectClass(\"System.Web;System.Runtime.Extensions;System.Web.HttpUtility\",[None],Sink,[Ssrf])] Datadog.Trace.Iast.Aspects.System.Net.HttpUtilityAspect", -" [AspectMethodReplace(\"System.Web.HttpUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] Review(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] XssEscape(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::UrlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::UrlEncode(System.String,System.Text.Encoding)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String,System.Text.Encoding)", "[AspectClass(\"System.Xml,System.Xml.ReaderWriter,System.Xml.XPath.XDocument\",[None],Sink,[XPathInjection])] Datadog.Trace.Iast.Aspects.SystemXmlAspect", " [AspectMethodInsertBefore(\"System.Xml.XmlNode::SelectNodes(System.String)\",\"\",[0],[False],[None],Default,[])] ReviewPath(System.String)", " [AspectMethodInsertBefore(\"System.Xml.XmlNode::SelectNodes(System.String,System.Xml.XmlNamespaceManager)\",\"\",[1],[False],[None],Default,[])] ReviewPath(System.String)", diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs index 63808d099aa8..3503dc627f97 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs @@ -602,6 +602,10 @@ static InstrumentationDefinitions() new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite.SQLiteCommand"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteScalar"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Object"), 1, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteScalarIntegration"), 0, 1), new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite.SQLiteCommand"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteScalar"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Object", "System.Data.CommandBehavior"), 2, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteScalarWithBehaviorIntegration"), 0, 1), + // Ssrf + new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp.Extensions.StringExtensions"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("UrlEncode"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.String", "System.String", "System.Text.Encoding"), 3, 104, 0, 0, 112, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncode2Integration"), 0, 4), + new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp.Extensions.StringExtensions"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("UrlEncode"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.String", "System.String"), 2, 104, 0, 0, 112, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncodeIntegration"), 0, 4), + // StackExchangeRedis new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis.ConnectionMultiplexer"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteAsyncImpl"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Threading.Tasks.Task`1[!!0]", "StackExchange.Redis.Message", "StackExchange.Redis.ResultProcessor`1[!!0]", "System.Object", "StackExchange.Redis.ServerEndPoint"), 5, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration"), 0, 1), new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis.ConnectionMultiplexer"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteAsyncImpl"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Threading.Tasks.Task`1[!!0]", "StackExchange.Redis.Message", "StackExchange.Redis.ResultProcessor`1[!!0]", "System.Object", "StackExchange.Redis.ServerEndPoint", "!!0"), 6, 2, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration_2_6_45"), 0, 1), @@ -705,6 +709,7 @@ internal static bool IsInstrumentedAssembly(string assemblyName) || assemblyName.StartsWith("Oracle.DataAccess,", StringComparison.Ordinal) || assemblyName.StartsWith("Oracle.ManagedDataAccess,", StringComparison.Ordinal) || assemblyName.StartsWith("RabbitMQ.Client,", StringComparison.Ordinal) + || assemblyName.StartsWith("RestSharp,", StringComparison.Ordinal) || assemblyName.StartsWith("Serilog,", StringComparison.Ordinal) || assemblyName.StartsWith("ServiceStack.Redis,", StringComparison.Ordinal) || assemblyName.StartsWith("StackExchange.Redis,", StringComparison.Ordinal) @@ -1091,6 +1096,9 @@ internal static bool IsInstrumentedAssembly(string assemblyName) "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0" => Datadog.Trace.Configuration.IntegrationId.ServiceStackRedis, + "Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncode2Integration" + or "Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncodeIntegration" + => Datadog.Trace.Configuration.IntegrationId.Ssrf, "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration_2_6_45" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteSyncImplIntegration" diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs index a982a9753a0d..c64b5782b1da 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs @@ -264,7 +264,8 @@ internal static partial class AspectDefinitions " [AspectMethodInsertBefore(\"System.Net.WebClient::UploadValuesTaskAsync(System.Uri,System.Collections.Specialized.NameValueCollection)\",\"\",[1],[False],[None],Default,[])] ReviewUri(System.Uri)", " [AspectMethodInsertBefore(\"System.Net.WebClient::UploadValuesTaskAsync(System.Uri,System.String,System.Collections.Specialized.NameValueCollection)\",\"\",[2],[False],[None],Default,[])] ReviewUri(System.Uri)", "[AspectClass(\"System.Private.Corelib;System.Runtime\",[None],Sink,[Ssrf])] Datadog.Trace.Iast.Aspects.System.Net.WebUtilityAspect", -" [AspectMethodReplace(\"System.Net.WebUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] Review(System.String)", +" [AspectMethodReplace(\"System.Net.WebUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] XssEscape(System.String)", +" [AspectMethodReplace(\"System.Net.WebUtility::UrlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String)", "[AspectClass(\"System.Text.Json\",[None],Source,[])] Datadog.Trace.Iast.Aspects.System.Text.Json.JsonDocumentAspects", " [AspectMethodReplace(\"System.Text.Json.JsonDocument::Parse(System.String,System.Text.Json.JsonDocumentOptions)\",\"\",[0],[False],[None],Default,[]);V2.49.0] Parse(System.String,System.Text.Json.JsonDocumentOptions)", " [AspectMethodReplace(\"System.Text.Json.JsonElement::GetString()\",\"\",[0],[True],[None],Default,[]);V2.49.0] GetString(System.Object)", @@ -278,7 +279,9 @@ internal static partial class AspectDefinitions " [AspectMethodInsertBefore(\"System.Web.Mvc.Controller::Redirect(System.String)\",\"\",[0],[False],[None],Default,[])] Redirect(System.String)", " [AspectMethodInsertBefore(\"System.Web.Mvc.Controller::RedirectPermanent(System.String)\",\"\",[0],[False],[None],Default,[])] Redirect(System.String)", "[AspectClass(\"System.Web;System.Runtime.Extensions;System.Web.HttpUtility\",[None],Sink,[Ssrf])] Datadog.Trace.Iast.Aspects.System.Net.HttpUtilityAspect", -" [AspectMethodReplace(\"System.Web.HttpUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] Review(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] XssEscape(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::UrlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::UrlEncode(System.String,System.Text.Encoding)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String,System.Text.Encoding)", "[AspectClass(\"System.Xml,System.Xml.ReaderWriter,System.Xml.XPath.XDocument\",[None],Sink,[XPathInjection])] Datadog.Trace.Iast.Aspects.SystemXmlAspect", " [AspectMethodInsertBefore(\"System.Xml.XmlNode::SelectNodes(System.String)\",\"\",[0],[False],[None],Default,[])] ReviewPath(System.String)", " [AspectMethodInsertBefore(\"System.Xml.XmlNode::SelectNodes(System.String,System.Xml.XmlNamespaceManager)\",\"\",[1],[False],[None],Default,[])] ReviewPath(System.String)", diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs index f6fdf3f74f17..fd94b1c317b8 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs @@ -613,6 +613,10 @@ static InstrumentationDefinitions() new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite.SQLiteCommand"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteScalar"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Object"), 1, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteScalarIntegration"), 0, 1), new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite.SQLiteCommand"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteScalar"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Object", "System.Data.CommandBehavior"), 2, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteScalarWithBehaviorIntegration"), 0, 1), + // Ssrf + new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp.Extensions.StringExtensions"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("UrlEncode"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.String", "System.String", "System.Text.Encoding"), 3, 104, 0, 0, 112, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncode2Integration"), 0, 4), + new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp.Extensions.StringExtensions"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("UrlEncode"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.String", "System.String"), 2, 104, 0, 0, 112, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncodeIntegration"), 0, 4), + // StackExchangeRedis new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis.ConnectionMultiplexer"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteAsyncImpl"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Threading.Tasks.Task`1[!!0]", "StackExchange.Redis.Message", "StackExchange.Redis.ResultProcessor`1[!!0]", "System.Object", "StackExchange.Redis.ServerEndPoint"), 5, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration"), 0, 1), new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis.ConnectionMultiplexer"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteAsyncImpl"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Threading.Tasks.Task`1[!!0]", "StackExchange.Redis.Message", "StackExchange.Redis.ResultProcessor`1[!!0]", "System.Object", "StackExchange.Redis.ServerEndPoint", "!!0"), 6, 2, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration_2_6_45"), 0, 1), @@ -716,6 +720,7 @@ internal static bool IsInstrumentedAssembly(string assemblyName) || assemblyName.StartsWith("Oracle.DataAccess,", StringComparison.Ordinal) || assemblyName.StartsWith("Oracle.ManagedDataAccess,", StringComparison.Ordinal) || assemblyName.StartsWith("RabbitMQ.Client,", StringComparison.Ordinal) + || assemblyName.StartsWith("RestSharp,", StringComparison.Ordinal) || assemblyName.StartsWith("Serilog,", StringComparison.Ordinal) || assemblyName.StartsWith("ServiceStack.Redis,", StringComparison.Ordinal) || assemblyName.StartsWith("StackExchange.Redis,", StringComparison.Ordinal) @@ -1115,6 +1120,9 @@ internal static bool IsInstrumentedAssembly(string assemblyName) "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0" => Datadog.Trace.Configuration.IntegrationId.ServiceStackRedis, + "Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncode2Integration" + or "Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncodeIntegration" + => Datadog.Trace.Configuration.IntegrationId.Ssrf, "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration_2_6_45" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteSyncImplIntegration" diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs index e535bc6f722d..4e89def8f0c3 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs @@ -262,7 +262,8 @@ internal static partial class AspectDefinitions " [AspectMethodInsertBefore(\"System.Net.WebClient::UploadValuesTaskAsync(System.Uri,System.Collections.Specialized.NameValueCollection)\",\"\",[1],[False],[None],Default,[])] ReviewUri(System.Uri)", " [AspectMethodInsertBefore(\"System.Net.WebClient::UploadValuesTaskAsync(System.Uri,System.String,System.Collections.Specialized.NameValueCollection)\",\"\",[2],[False],[None],Default,[])] ReviewUri(System.Uri)", "[AspectClass(\"System.Private.Corelib;System.Runtime\",[None],Sink,[Ssrf])] Datadog.Trace.Iast.Aspects.System.Net.WebUtilityAspect", -" [AspectMethodReplace(\"System.Net.WebUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] Review(System.String)", +" [AspectMethodReplace(\"System.Net.WebUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] XssEscape(System.String)", +" [AspectMethodReplace(\"System.Net.WebUtility::UrlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String)", "[AspectClass(\"System.Text.Json\",[None],Source,[])] Datadog.Trace.Iast.Aspects.System.Text.Json.JsonDocumentAspects", " [AspectMethodReplace(\"System.Text.Json.JsonDocument::Parse(System.String,System.Text.Json.JsonDocumentOptions)\",\"\",[0],[False],[None],Default,[]);V2.49.0] Parse(System.String,System.Text.Json.JsonDocumentOptions)", " [AspectMethodReplace(\"System.Text.Json.JsonElement::GetString()\",\"\",[0],[True],[None],Default,[]);V2.49.0] GetString(System.Object)", @@ -276,7 +277,9 @@ internal static partial class AspectDefinitions " [AspectMethodInsertBefore(\"System.Web.Mvc.Controller::Redirect(System.String)\",\"\",[0],[False],[None],Default,[])] Redirect(System.String)", " [AspectMethodInsertBefore(\"System.Web.Mvc.Controller::RedirectPermanent(System.String)\",\"\",[0],[False],[None],Default,[])] Redirect(System.String)", "[AspectClass(\"System.Web;System.Runtime.Extensions;System.Web.HttpUtility\",[None],Sink,[Ssrf])] Datadog.Trace.Iast.Aspects.System.Net.HttpUtilityAspect", -" [AspectMethodReplace(\"System.Web.HttpUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] Review(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] XssEscape(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::UrlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::UrlEncode(System.String,System.Text.Encoding)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String,System.Text.Encoding)", "[AspectClass(\"System.Xml,System.Xml.ReaderWriter,System.Xml.XPath.XDocument\",[None],Sink,[XPathInjection])] Datadog.Trace.Iast.Aspects.SystemXmlAspect", " [AspectMethodInsertBefore(\"System.Xml.XmlNode::SelectNodes(System.String)\",\"\",[0],[False],[None],Default,[])] ReviewPath(System.String)", " [AspectMethodInsertBefore(\"System.Xml.XmlNode::SelectNodes(System.String,System.Xml.XmlNamespaceManager)\",\"\",[1],[False],[None],Default,[])] ReviewPath(System.String)", diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs index 13adf791c00d..50bec2f96cca 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs @@ -609,6 +609,10 @@ static InstrumentationDefinitions() new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite.SQLiteCommand"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteScalar"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Object"), 1, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteScalarIntegration"), 0, 1), new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite.SQLiteCommand"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteScalar"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Object", "System.Data.CommandBehavior"), 2, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteScalarWithBehaviorIntegration"), 0, 1), + // Ssrf + new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp.Extensions.StringExtensions"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("UrlEncode"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.String", "System.String", "System.Text.Encoding"), 3, 104, 0, 0, 112, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncode2Integration"), 0, 4), + new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp.Extensions.StringExtensions"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("UrlEncode"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.String", "System.String"), 2, 104, 0, 0, 112, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncodeIntegration"), 0, 4), + // StackExchangeRedis new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis.ConnectionMultiplexer"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteAsyncImpl"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Threading.Tasks.Task`1[!!0]", "StackExchange.Redis.Message", "StackExchange.Redis.ResultProcessor`1[!!0]", "System.Object", "StackExchange.Redis.ServerEndPoint"), 5, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration"), 0, 1), new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis.ConnectionMultiplexer"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteAsyncImpl"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Threading.Tasks.Task`1[!!0]", "StackExchange.Redis.Message", "StackExchange.Redis.ResultProcessor`1[!!0]", "System.Object", "StackExchange.Redis.ServerEndPoint", "!!0"), 6, 2, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration_2_6_45"), 0, 1), @@ -711,6 +715,7 @@ internal static bool IsInstrumentedAssembly(string assemblyName) || assemblyName.StartsWith("Oracle.DataAccess,", StringComparison.Ordinal) || assemblyName.StartsWith("Oracle.ManagedDataAccess,", StringComparison.Ordinal) || assemblyName.StartsWith("RabbitMQ.Client,", StringComparison.Ordinal) + || assemblyName.StartsWith("RestSharp,", StringComparison.Ordinal) || assemblyName.StartsWith("Serilog,", StringComparison.Ordinal) || assemblyName.StartsWith("ServiceStack.Redis,", StringComparison.Ordinal) || assemblyName.StartsWith("StackExchange.Redis,", StringComparison.Ordinal) @@ -1106,6 +1111,9 @@ internal static bool IsInstrumentedAssembly(string assemblyName) "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0" => Datadog.Trace.Configuration.IntegrationId.ServiceStackRedis, + "Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncode2Integration" + or "Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncodeIntegration" + => Datadog.Trace.Configuration.IntegrationId.Ssrf, "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration_2_6_45" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteSyncImplIntegration" diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs index 4a365fa23c42..ae9b51314c2f 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/AspectsDefinitionsGenerator/AspectsDefinitions.g.cs @@ -251,7 +251,8 @@ internal static partial class AspectDefinitions " [AspectMethodInsertBefore(\"System.Net.WebClient::UploadValuesTaskAsync(System.Uri,System.Collections.Specialized.NameValueCollection)\",\"\",[1],[False],[None],Default,[])] ReviewUri(System.Uri)", " [AspectMethodInsertBefore(\"System.Net.WebClient::UploadValuesTaskAsync(System.Uri,System.String,System.Collections.Specialized.NameValueCollection)\",\"\",[2],[False],[None],Default,[])] ReviewUri(System.Uri)", "[AspectClass(\"System.Private.Corelib;System.Runtime\",[None],Sink,[Ssrf])] Datadog.Trace.Iast.Aspects.System.Net.WebUtilityAspect", -" [AspectMethodReplace(\"System.Net.WebUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] Review(System.String)", +" [AspectMethodReplace(\"System.Net.WebUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] XssEscape(System.String)", +" [AspectMethodReplace(\"System.Net.WebUtility::UrlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String)", "[AspectClass(\"System.Web\",[None],Sink,[UnvalidatedRedirect])] Datadog.Trace.Iast.Aspects.System.Web.HttpResponseAspect", " [AspectMethodInsertBefore(\"System.Web.HttpResponse::Redirect(System.String)\",\"\",[0],[False],[None],Default,[])] Redirect(System.String)", " [AspectMethodInsertBefore(\"System.Web.HttpResponse::Redirect(System.String,System.Boolean)\",\"\",[1],[False],[None],Default,[])] Redirect(System.String)", @@ -261,7 +262,9 @@ internal static partial class AspectDefinitions " [AspectMethodInsertBefore(\"System.Web.Mvc.Controller::Redirect(System.String)\",\"\",[0],[False],[None],Default,[])] Redirect(System.String)", " [AspectMethodInsertBefore(\"System.Web.Mvc.Controller::RedirectPermanent(System.String)\",\"\",[0],[False],[None],Default,[])] Redirect(System.String)", "[AspectClass(\"System.Web;System.Runtime.Extensions;System.Web.HttpUtility\",[None],Sink,[Ssrf])] Datadog.Trace.Iast.Aspects.System.Net.HttpUtilityAspect", -" [AspectMethodReplace(\"System.Web.HttpUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] Review(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::HtmlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] XssEscape(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::UrlEncode(System.String)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String)", +" [AspectMethodReplace(\"System.Web.HttpUtility::UrlEncode(System.String,System.Text.Encoding)\",\"\",[0],[False],[None],Default,[])] SsrfEscape(System.String,System.Text.Encoding)", "[AspectClass(\"System.Xml,System.Xml.ReaderWriter,System.Xml.XPath.XDocument\",[None],Sink,[XPathInjection])] Datadog.Trace.Iast.Aspects.SystemXmlAspect", " [AspectMethodInsertBefore(\"System.Xml.XmlNode::SelectNodes(System.String)\",\"\",[0],[False],[None],Default,[])] ReviewPath(System.String)", " [AspectMethodInsertBefore(\"System.Xml.XmlNode::SelectNodes(System.String,System.Xml.XmlNamespaceManager)\",\"\",[1],[False],[None],Default,[])] ReviewPath(System.String)", diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs index 13adf791c00d..50bec2f96cca 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs @@ -609,6 +609,10 @@ static InstrumentationDefinitions() new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite.SQLiteCommand"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteScalar"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Object"), 1, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteScalarIntegration"), 0, 1), new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("System.Data.SQLite.SQLiteCommand"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteScalar"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Object", "System.Data.CommandBehavior"), 2, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteScalarWithBehaviorIntegration"), 0, 1), + // Ssrf + new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp.Extensions.StringExtensions"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("UrlEncode"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.String", "System.String", "System.Text.Encoding"), 3, 104, 0, 0, 112, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncode2Integration"), 0, 4), + new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("RestSharp.Extensions.StringExtensions"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("UrlEncode"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.String", "System.String"), 2, 104, 0, 0, 112, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncodeIntegration"), 0, 4), + // StackExchangeRedis new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis.ConnectionMultiplexer"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteAsyncImpl"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Threading.Tasks.Task`1[!!0]", "StackExchange.Redis.Message", "StackExchange.Redis.ResultProcessor`1[!!0]", "System.Object", "StackExchange.Redis.ServerEndPoint"), 5, 1, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration"), 0, 1), new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("StackExchange.Redis.ConnectionMultiplexer"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("ExecuteAsyncImpl"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Threading.Tasks.Task`1[!!0]", "StackExchange.Redis.Message", "StackExchange.Redis.ResultProcessor`1[!!0]", "System.Object", "StackExchange.Redis.ServerEndPoint", "!!0"), 6, 2, 0, 0, 2, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration_2_6_45"), 0, 1), @@ -711,6 +715,7 @@ internal static bool IsInstrumentedAssembly(string assemblyName) || assemblyName.StartsWith("Oracle.DataAccess,", StringComparison.Ordinal) || assemblyName.StartsWith("Oracle.ManagedDataAccess,", StringComparison.Ordinal) || assemblyName.StartsWith("RabbitMQ.Client,", StringComparison.Ordinal) + || assemblyName.StartsWith("RestSharp,", StringComparison.Ordinal) || assemblyName.StartsWith("Serilog,", StringComparison.Ordinal) || assemblyName.StartsWith("ServiceStack.Redis,", StringComparison.Ordinal) || assemblyName.StartsWith("StackExchange.Redis,", StringComparison.Ordinal) @@ -1106,6 +1111,9 @@ internal static bool IsInstrumentedAssembly(string assemblyName) "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0" => Datadog.Trace.Configuration.IntegrationId.ServiceStackRedis, + "Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncode2Integration" + or "Datadog.Trace.ClrProfiler.AutoInstrumentation.RestSharp.UrlEncodeIntegration" + => Datadog.Trace.Configuration.IntegrationId.Ssrf, "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteAsyncImplIntegration_2_6_45" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.StackExchange.ConnectionMultiplexerExecuteSyncImplIntegration" diff --git a/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/HttpClientAspect.cs b/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/HttpClientAspect.cs index 19c7ce112c3f..aeaae8c14573 100644 --- a/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/HttpClientAspect.cs +++ b/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/HttpClientAspect.cs @@ -129,7 +129,7 @@ public static Uri ReviewUri(Uri parameter) #endif [AspectMethodInsertBefore("System.Net.Http.HttpMessageInvoker::SendAsync(System.Net.Http.HttpRequestMessage,System.Threading.CancellationToken)", 1)] #if !NETFRAMEWORK - public static object ReviewHttpRequestMessage(HttpRequestMessage parameter) + public static HttpRequestMessage ReviewHttpRequestMessage(HttpRequestMessage parameter) { try { diff --git a/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebClientAspect.cs b/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebClientAspect.cs index 3b662e1a4b05..1d64943bca5d 100644 --- a/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebClientAspect.cs +++ b/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebClientAspect.cs @@ -51,7 +51,7 @@ public class WebClientAspect [AspectMethodInsertBefore("System.Net.WebClient::UploadValuesTaskAsync(System.String,System.Collections.Specialized.NameValueCollection)", 1)] [AspectMethodInsertBefore("System.Net.WebClient::UploadValuesTaskAsync(System.String,System.String,System.Collections.Specialized.NameValueCollection)", 2)] [AspectMethodInsertBefore("System.Net.WebClient::set_BaseAddress(System.String)")] - public static object Review(string parameter) + public static string Review(string parameter) { try { @@ -125,7 +125,7 @@ public static object Review(string parameter) [AspectMethodInsertBefore("System.Net.WebClient::UploadValuesAsync(System.Uri,System.String,System.Collections.Specialized.NameValueCollection,System.Object)", 3)] [AspectMethodInsertBefore("System.Net.WebClient::UploadValuesTaskAsync(System.Uri,System.Collections.Specialized.NameValueCollection)", 1)] [AspectMethodInsertBefore("System.Net.WebClient::UploadValuesTaskAsync(System.Uri,System.String,System.Collections.Specialized.NameValueCollection)", 2)] - public static object ReviewUri(Uri parameter) + public static Uri ReviewUri(Uri parameter) { try { diff --git a/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebRequestAspect.cs b/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebRequestAspect.cs index 2c3ad219aac5..731f55d61632 100644 --- a/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebRequestAspect.cs +++ b/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebRequestAspect.cs @@ -24,7 +24,7 @@ public class WebRequestAspect /// the parameter [AspectMethodInsertBefore("System.Net.WebRequest::Create(System.String)")] [AspectMethodInsertBefore("System.Net.WebRequest::CreateHttp(System.String)")] - public static object Review(string parameter) + public static string Review(string parameter) { try { @@ -46,7 +46,7 @@ public static object Review(string parameter) [AspectMethodInsertBefore("System.Net.WebRequest::Create(System.Uri)")] [AspectMethodInsertBefore("System.Net.WebRequest::CreateDefault(System.Uri)")] [AspectMethodInsertBefore("System.Net.WebRequest::CreateHttp(System.Uri)")] - public static object Review(Uri parameter) + public static Uri Review(Uri parameter) { try { diff --git a/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebUtilityAspect.cs b/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebUtilityAspect.cs index b3dbe86d0619..8c334eb2c65b 100644 --- a/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebUtilityAspect.cs +++ b/tracer/src/Datadog.Trace/Iast/Aspects/System.Net/WebUtilityAspect.cs @@ -19,12 +19,12 @@ namespace Datadog.Trace.Iast.Aspects.System.Net; public class WebUtilityAspect { /// - /// Launches a SSRF vulnerability if the url is tainted + /// Escapes the HTML string making it safe for XSS /// /// the sensitive parameter of the method /// the parameter [AspectMethodReplace("System.Net.WebUtility::HtmlEncode(System.String)")] - public static string? Review(string? parameter) + public static string? XssEscape(string? parameter) { var result = WebUtility.HtmlEncode(parameter); try @@ -36,7 +36,31 @@ public class WebUtilityAspect } catch (Exception ex) { - IastModule.Log.Error(ex, $"Error invoking {nameof(WebUtilityAspect)}.{nameof(Review)}"); + IastModule.Log.Error(ex, $"Error invoking {nameof(WebUtilityAspect)}.{nameof(XssEscape)}"); + } + + return result; + } + + /// + /// Escapes the URL string making it safe for SSRF + /// + /// the sensitive parameter of the method + /// the parameter + [AspectMethodReplace("System.Net.WebUtility::UrlEncode(System.String)")] + public static string? SsrfEscape(string? parameter) + { + var result = WebUtility.UrlEncode(parameter); + try + { + if (parameter is not null && result is not null) + { + return IastModule.OnSsrfEscape(parameter, result); + } + } + catch (Exception ex) + { + IastModule.Log.Error(ex, $"Error invoking {nameof(WebUtilityAspect)}.{nameof(SsrfEscape)}"); } return result; diff --git a/tracer/src/Datadog.Trace/Iast/Aspects/System.Web/HttpUtilityAspect.cs b/tracer/src/Datadog.Trace/Iast/Aspects/System.Web/HttpUtilityAspect.cs index 50ea2aa96f57..aff78e6cd9c5 100644 --- a/tracer/src/Datadog.Trace/Iast/Aspects/System.Web/HttpUtilityAspect.cs +++ b/tracer/src/Datadog.Trace/Iast/Aspects/System.Web/HttpUtilityAspect.cs @@ -4,9 +4,7 @@ // using System; -using System.Net; using Datadog.Trace.Iast.Dataflow; -using Datadog.Trace.Iast.Propagation; #nullable enable @@ -19,14 +17,14 @@ namespace Datadog.Trace.Iast.Aspects.System.Net; public class HttpUtilityAspect { /// - /// Launches a SSRF vulnerability if the url is tainted + /// Escapes the HTML string making it safe for XSS /// /// the sensitive parameter of the method /// the parameter [AspectMethodReplace("System.Web.HttpUtility::HtmlEncode(System.String)")] - public static string? Review(string? parameter) + public static string? XssEscape(string? parameter) { - var result = WebUtility.HtmlEncode(parameter); + var result = global::System.Web.HttpUtility.HtmlEncode(parameter); try { if (parameter is not null && result is not null) @@ -36,7 +34,56 @@ public class HttpUtilityAspect } catch (Exception ex) { - IastModule.Log.Error(ex, $"Error invoking {nameof(HttpUtilityAspect)}.{nameof(Review)}"); + IastModule.Log.Error(ex, $"Error invoking {nameof(HttpUtilityAspect)}.{nameof(XssEscape)}"); + } + + return result; + } + + /// + /// Escapes the URL string making it safe for SSRF + /// + /// the sensitive parameter of the method + /// the parameter + [AspectMethodReplace("System.Web.HttpUtility::UrlEncode(System.String)")] + public static string? SsrfEscape(string? parameter) + { + var result = global::System.Web.HttpUtility.UrlEncode(parameter); + try + { + if (parameter is not null && result is not null) + { + return IastModule.OnSsrfEscape(parameter, result); + } + } + catch (Exception ex) + { + IastModule.Log.Error(ex, $"Error invoking {nameof(HttpUtilityAspect)}.{nameof(SsrfEscape)}"); + } + + return result; + } + + /// + /// Launches a SSRF vulnerability if the url is tainted + /// + /// the sensitive parameter of the method + /// encoding used to encode the string + /// the parameter + [AspectMethodReplace("System.Web.HttpUtility::UrlEncode(System.String,System.Text.Encoding)")] + public static string? SsrfEscape(string? parameter, global::System.Text.Encoding e) + { + var result = global::System.Web.HttpUtility.UrlEncode(parameter, e); + try + { + if (parameter is not null && result is not null) + { + return IastModule.OnSsrfEscape(parameter, result); + } + } + catch (Exception ex) + { + IastModule.Log.Error(ex, $"Error invoking {nameof(HttpUtilityAspect)}.{nameof(SsrfEscape)}"); } return result; diff --git a/tracer/src/Datadog.Trace/Iast/Aspects/System/StringAspects.cs b/tracer/src/Datadog.Trace/Iast/Aspects/System/StringAspects.cs index 7c15a74d9fc9..6efc6d7eff77 100644 --- a/tracer/src/Datadog.Trace/Iast/Aspects/System/StringAspects.cs +++ b/tracer/src/Datadog.Trace/Iast/Aspects/System/StringAspects.cs @@ -1107,7 +1107,7 @@ public static string Format(string format, object arg0) var result = string.Format(format, arg0); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, format, arg0); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, format, arg0); } catch (Exception ex) { @@ -1130,7 +1130,7 @@ public static string Format(string format, object arg0, object arg1) var result = string.Format(format, arg0, arg1); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, format, arg0, arg1); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, format, arg0, arg1); } catch (Exception ex) { @@ -1154,7 +1154,7 @@ public static string Format(string format, object arg0, object arg1, object arg2 var result = string.Format(format, arg0, arg1, arg2); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, format, arg0, arg1, arg2); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, format, arg0, arg1, arg2); } catch (Exception ex) { @@ -1176,7 +1176,7 @@ public static string Format(string format, object[] args) var result = string.Format(format, args); try { - PropagationModuleImpl.PropagateResultWhenInputArrayTainted(result, format, args); + PropagationModuleImpl.PropagateWholeResultWhenInputArrayTainted(result, format, args); } catch (Exception ex) { @@ -1199,7 +1199,7 @@ public static string Format(IFormatProvider provider, string format, object arg0 var result = string.Format(provider, format, arg0); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, format, arg0); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, format, arg0); } catch (Exception ex) { @@ -1223,7 +1223,7 @@ public static string Format(IFormatProvider provider, string format, object arg0 var result = string.Format(provider, format, arg0, arg1); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, format, arg0, arg1); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, format, arg0, arg1); } catch (Exception ex) { @@ -1248,7 +1248,7 @@ public static string Format(IFormatProvider provider, string format, object arg0 var result = string.Format(provider, format, arg0, arg1, arg2); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, format, arg0, arg1, arg2); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, format, arg0, arg1, arg2); } catch (Exception ex) { @@ -1271,7 +1271,7 @@ public static string Format(IFormatProvider provider, string format, object[] ar var result = string.Format(provider, format, args); try { - PropagationModuleImpl.PropagateResultWhenInputArrayTainted(result, format, args); + PropagationModuleImpl.PropagateWholeResultWhenInputArrayTainted(result, format, args); } catch (Exception ex) { @@ -1297,7 +1297,7 @@ public static string Replace(string target, string oldValue, string newValue, bo var result = target.Replace(oldValue, newValue, ignore, culture); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target, oldValue, newValue); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, target, oldValue, newValue); } catch (Exception ex) { @@ -1321,7 +1321,7 @@ public static string Replace(string target, string oldValue, string newValue, St var result = target.Replace(oldValue, newValue, comparison); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target, oldValue, newValue); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, target, oldValue, newValue); } catch (Exception ex) { @@ -1345,7 +1345,7 @@ public static string Replace(string target, char oldChar, char newChar) var result = target.Replace(oldChar, newChar); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, target); } catch (Exception ex) { @@ -1368,7 +1368,7 @@ public static string Replace(string target, string oldValue, string newValue) var result = target.Replace(oldValue, newValue); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target, oldValue, newValue); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, target, oldValue, newValue); } catch (Exception ex) { @@ -1390,7 +1390,7 @@ public static string[] Split(string target, char[] separator) var result = target.Split(separator); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultsWhenInputTainted(result, target); } catch (Exception ex) { @@ -1413,7 +1413,7 @@ public static string[] Split(string target, char[] separator, int count) var result = target.Split(separator, count); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultsWhenInputTainted(result, target); } catch (Exception ex) { @@ -1436,7 +1436,7 @@ public static string[] Split(string target, char[] separator, StringSplitOptions var result = target.Split(separator, options); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultsWhenInputTainted(result, target); } catch (Exception ex) { @@ -1460,7 +1460,7 @@ public static string[] Split(string target, char[] separator, int count, StringS var result = target.Split(separator, count, options); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultsWhenInputTainted(result, target); } catch (Exception ex) { @@ -1483,7 +1483,7 @@ public static string[] Split(string target, string[] separator, StringSplitOptio var result = target.Split(separator, options); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultsWhenInputTainted(result, target); } catch (Exception ex) { @@ -1507,7 +1507,7 @@ public static string[] Split(string target, string[] separator, int count, Strin var result = target.Split(separator, count, options); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultsWhenInputTainted(result, target); } catch (Exception ex) { @@ -1533,7 +1533,7 @@ public static string[] Split(string target, string separator, int count, StringS var result = target.Split(separator, count, options); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultsWhenInputTainted(result, target); } catch (Exception ex) { @@ -1556,7 +1556,7 @@ public static string[] Split(string target, string separator, StringSplitOptions var result = target.Split(separator, options); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultsWhenInputTainted(result, target); } catch (Exception ex) { @@ -1579,7 +1579,7 @@ public static string[] Split(string target, char separator, StringSplitOptions o var result = target.Split(separator, options); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultsWhenInputTainted(result, target); } catch (Exception ex) { @@ -1603,7 +1603,7 @@ public static string[] Split(string target, char separator, int count, StringSpl var result = target.Split(separator, count, options); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultsWhenInputTainted(result, target); } catch (Exception ex) { @@ -1626,7 +1626,7 @@ public static string Copy(string target) var result = string.Copy(target); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, target); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, target); } catch (Exception ex) { diff --git a/tracer/src/Datadog.Trace/Iast/Aspects/System/UriAspect.cs b/tracer/src/Datadog.Trace/Iast/Aspects/System/UriAspect.cs index eb3e43ba6ca1..878de9d7cd4f 100644 --- a/tracer/src/Datadog.Trace/Iast/Aspects/System/UriAspect.cs +++ b/tracer/src/Datadog.Trace/Iast/Aspects/System/UriAspect.cs @@ -28,7 +28,7 @@ public static Uri Init(string uriBase) var result = new Uri(uriBase); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.OriginalString, uriBase); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.OriginalString, uriBase); } catch (Exception ex) { @@ -53,7 +53,7 @@ public static Uri Init(Uri uriBase, string uriText, bool escape) #pragma warning restore CS0618 // Type or member is obsolete try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.OriginalString, uriBase.OriginalString, uriText); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.OriginalString, uriBase.OriginalString, uriText); } catch (Exception ex) { @@ -75,7 +75,7 @@ public static Uri Init(Uri uriBase, string relativeUri) var result = new Uri(uriBase, relativeUri); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.OriginalString, uriBase.OriginalString, relativeUri); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.OriginalString, uriBase.OriginalString, relativeUri); } catch (Exception ex) { @@ -97,7 +97,7 @@ public static Uri Init(Uri uriBase, Uri relativeUri) var result = new Uri(uriBase, relativeUri); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.OriginalString, uriBase.OriginalString, relativeUri.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.OriginalString, uriBase.OriginalString, relativeUri.OriginalString); } catch (Exception ex) { @@ -121,7 +121,10 @@ public static Uri Init(string uriBase, bool dontEscape) #pragma warning restore CS0618 // Type or member is obsolete try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.OriginalString, uriBase); + if (dontEscape) + { + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.OriginalString, uriBase); + } } catch (Exception ex) { @@ -143,7 +146,7 @@ public static Uri Init(string uriBase, UriKind uriKind) var result = new Uri(uriBase, uriKind); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.OriginalString, uriBase); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.OriginalString, uriBase); } catch (Exception ex) { @@ -166,7 +169,7 @@ public static Uri Init(string uriBase, in UriCreationOptions options) var result = new Uri(uriBase, in options); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.OriginalString, uriBase); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.OriginalString, uriBase); } catch (Exception ex) { @@ -192,7 +195,7 @@ public static bool TryCreate(string uri, UriKind kind, out Uri? uriCreated) { if (uriCreated is not null) { - PropagationModuleImpl.PropagateResultWhenInputTainted(uriCreated.OriginalString, uri); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(uriCreated.OriginalString, uri); } } catch (Exception ex) @@ -219,7 +222,7 @@ public static bool TryCreate(string uri, in UriCreationOptions options, out Uri? { if (uriCreated is not null) { - PropagationModuleImpl.PropagateResultWhenInputTainted(uriCreated.OriginalString, uri); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(uriCreated.OriginalString, uri); } } catch (Exception ex) @@ -246,7 +249,7 @@ public static bool TryCreate(Uri? baseUri, string? relativeUri, out Uri? uriCrea { if (uriCreated is not null) { - PropagationModuleImpl.PropagateResultWhenInputTainted(uriCreated.OriginalString, baseUri?.OriginalString, relativeUri); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(uriCreated.OriginalString, baseUri?.OriginalString, relativeUri); } } catch (Exception ex) @@ -272,7 +275,7 @@ public static bool TryCreate(Uri? baseUri, Uri? relativeUri, out Uri? uriCreated { if (uriCreated is not null) { - PropagationModuleImpl.PropagateResultWhenInputTainted(uriCreated.OriginalString, baseUri?.OriginalString, relativeUri?.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(uriCreated.OriginalString, baseUri?.OriginalString, relativeUri?.OriginalString); } } catch (Exception ex) @@ -294,7 +297,7 @@ public static string UnescapeDataString(string uri) var result = Uri.UnescapeDataString(uri); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, uri); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, uri); } catch (Exception ex) { @@ -317,7 +320,7 @@ public static string EscapeUriString(string uri) #pragma warning restore SYSLIB0013 try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, uri); + result = IastModule.OnSsrfEscape(uri, result)!; } catch (Exception ex) { @@ -338,7 +341,7 @@ public static string EscapeDataString(string uri) var result = Uri.EscapeDataString(uri); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, uri); + result = IastModule.OnSsrfEscape(uri, result)!; } catch (Exception ex) { @@ -359,7 +362,7 @@ public static string GetAbsoluteUri(Uri instance) var result = instance.AbsoluteUri; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, instance.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, instance.OriginalString); } catch (Exception ex) { @@ -380,7 +383,7 @@ public static string GetAbsolutePath(Uri instance) var result = instance.AbsolutePath; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, instance.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, instance.OriginalString); } catch (Exception ex) { @@ -401,7 +404,7 @@ public static string GetLocalPath(Uri instance) var result = instance.LocalPath; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, instance.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, instance.OriginalString); } catch (Exception ex) { @@ -427,7 +430,7 @@ public static string GetLocalPath(Uri instance) { if (!string.IsNullOrWhiteSpace(result)) { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, uri.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, uri.OriginalString); } } catch (Exception ex) @@ -452,7 +455,7 @@ public static string GetLocalPath(Uri instance) { if (!string.IsNullOrWhiteSpace(result?.OriginalString)) { - PropagationModuleImpl.PropagateResultWhenInputTainted(result!.OriginalString, uri.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result!.OriginalString, uri.OriginalString); } } catch (Exception ex) @@ -474,7 +477,7 @@ public static string GetHost(Uri instance) var result = instance.Host; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, instance.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, instance.OriginalString); } catch (Exception ex) { @@ -495,7 +498,7 @@ public static string GetPathAndQuery(Uri instance) var result = instance.PathAndQuery; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, instance.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, instance.OriginalString); } catch (Exception ex) { @@ -516,7 +519,7 @@ public static string GetAuthority(Uri instance) var result = instance.Authority; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, instance.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, instance.OriginalString); } catch (Exception ex) { @@ -537,7 +540,7 @@ public static string GetQuery(Uri instance) var result = instance.Query; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, instance.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, instance.OriginalString); } catch (Exception ex) { @@ -559,7 +562,7 @@ public static string GetQuery(Uri instance) var result = instance!.ToString(); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, (instance as Uri)?.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, (instance as Uri)?.OriginalString); } catch (Exception ex) { diff --git a/tracer/src/Datadog.Trace/Iast/Aspects/System/UriBuilderAspect.cs b/tracer/src/Datadog.Trace/Iast/Aspects/System/UriBuilderAspect.cs index f5934b731660..2beca3d35c41 100644 --- a/tracer/src/Datadog.Trace/Iast/Aspects/System/UriBuilderAspect.cs +++ b/tracer/src/Datadog.Trace/Iast/Aspects/System/UriBuilderAspect.cs @@ -28,7 +28,7 @@ public static UriBuilder Init(string uriText) var result = new UriBuilder(uriText); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.Uri.OriginalString, uriText); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.Uri.OriginalString, uriText); } catch (Exception ex) { @@ -49,7 +49,7 @@ public static UriBuilder Init(Uri uri) var result = new UriBuilder(uri); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.Uri.OriginalString, uri.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.Uri.OriginalString, uri.OriginalString); } catch (Exception ex) { @@ -71,7 +71,7 @@ public static UriBuilder Init(string scheme, string host) var result = new UriBuilder(scheme, host); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.Uri.OriginalString, host); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.Uri.OriginalString, host); } catch (Exception ex) { @@ -94,7 +94,7 @@ public static UriBuilder Init(string scheme, string host, int port) var result = new UriBuilder(scheme, host, port); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.Uri.OriginalString, host); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.Uri.OriginalString, host); } catch (Exception ex) { @@ -118,7 +118,7 @@ public static UriBuilder Init(string scheme, string host, int port, string path) var result = new UriBuilder(scheme, host, port, path); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.Uri.OriginalString, host, path); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.Uri.OriginalString, host, path); } catch (Exception ex) { @@ -143,7 +143,7 @@ public static UriBuilder Init(string scheme, string host, int port, string path, var result = new UriBuilder(scheme, host, port, path, extra); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result.Uri.OriginalString, host, path, extra); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result.Uri.OriginalString, host, path, extra); } catch (Exception ex) { @@ -164,7 +164,7 @@ public static void SetHost(UriBuilder instance, string parameter) instance.Host = parameter; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(instance.Uri.OriginalString, parameter); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(instance.Uri.OriginalString, parameter); } catch (Exception ex) { @@ -183,7 +183,7 @@ public static void SetQuery(UriBuilder instance, string parameter) instance.Query = parameter; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(instance.Uri.OriginalString, parameter); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(instance.Uri.OriginalString, parameter); } catch (Exception ex) { @@ -202,7 +202,7 @@ public static void SetPath(UriBuilder instance, string parameter) instance.Path = parameter; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(instance.Uri.OriginalString, parameter); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(instance.Uri.OriginalString, parameter); } catch (Exception ex) { @@ -221,7 +221,7 @@ public static string GetHost(UriBuilder instance) var result = instance.Host; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, instance.Uri.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, instance.Uri.OriginalString); } catch (Exception ex) { @@ -242,7 +242,7 @@ public static string GetQuery(UriBuilder instance) var result = instance.Query; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, instance.Uri.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, instance.Uri.OriginalString); } catch (Exception ex) { @@ -263,7 +263,7 @@ public static string GetPath(UriBuilder instance) var result = instance.Path; try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, instance.Uri.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, instance.Uri.OriginalString); } catch (Exception ex) { @@ -285,7 +285,7 @@ public static string GetPath(UriBuilder instance) var result = instance!.ToString(); try { - PropagationModuleImpl.PropagateResultWhenInputTainted(result, (instance as UriBuilder)?.Uri?.OriginalString); + PropagationModuleImpl.PropagateWholeResultWhenInputTainted(result, (instance as UriBuilder)?.Uri?.OriginalString); } catch (Exception ex) { diff --git a/tracer/src/Datadog.Trace/Iast/IastModule.Escape.cs b/tracer/src/Datadog.Trace/Iast/IastModule.Escape.cs index d688a7f34dd8..211ff5f483c4 100644 --- a/tracer/src/Datadog.Trace/Iast/IastModule.Escape.cs +++ b/tracer/src/Datadog.Trace/Iast/IastModule.Escape.cs @@ -6,6 +6,7 @@ #nullable enable using System; +using System.Linq; using System.Net; using Datadog.Trace.Configuration; using Datadog.Trace.Iast.Helpers; @@ -15,24 +16,37 @@ namespace Datadog.Trace.Iast; internal static partial class IastModule { public static string? OnXssEscape(string? text, string? encoded) + { + return OnEscape(text, encoded, SecureMarks.Xss, IntegrationId.Xss); + } + + public static string? OnSsrfEscape(string? text, string? encoded) + { + return OnEscape(text, encoded, SecureMarks.Ssrf, IntegrationId.Ssrf); + } + + private static string? OnEscape(string? text, string? encoded, SecureMarks secureMarks, params IntegrationId[] integrations) { try { - if (!IastSettings.Enabled || string.IsNullOrEmpty(text)) + if (!IastSettings.Enabled || + text is null || encoded is null || + text.Length == 0 || encoded.Length == 0) { return encoded; } var tracer = Tracer.Instance; - if (!tracer.Settings.IsIntegrationEnabled(IntegrationId.Xss)) + if (integrations != null && !integrations.Any((i) => tracer.Settings.IsIntegrationEnabled(i))) { return encoded; } var scope = tracer.ActiveScope as Scope; var traceContext = scope?.Span?.Context?.TraceContext; + var iastContext = traceContext?.IastRequestContext; - if (traceContext?.IastRequestContext?.AddVulnerabilitiesAllowed() != true) + if (iastContext is null || iastContext.AddVulnerabilitiesAllowed() != true) { return encoded; } @@ -43,8 +57,21 @@ internal static partial class IastModule return encoded; } - // Add the mark (exclusion) to the tainted ranges - tainted.Ranges = Ranges.CopyWithMark(tainted.Ranges, SecureMarks.Xss); + // Special case. The encoded string is already tainted. We must check instance is not the same as the original text + if (object.ReferenceEquals(text, encoded)) + { + // return a new instance of the encoded string and taint it whole +#if NETCOREAPP3_0_OR_GREATER + var newEncoded = new string(encoded.AsSpan()); +#else + var newEncoded = new string(encoded.ToCharArray()); +#endif + iastContext.GetTaintedObjects().Taint(newEncoded, Ranges.CopyWithMark(tainted.Ranges, secureMarks)); + return newEncoded; + } + + // Taint the escaped string whole with the new secure marks + iastContext.GetTaintedObjects().Taint(encoded, [new Range(0, encoded.Length, tainted.Ranges[0].Source, tainted.Ranges[0].SecureMarks | secureMarks)]); } catch (Exception ex) { diff --git a/tracer/src/Datadog.Trace/Iast/IastModule.cs b/tracer/src/Datadog.Trace/Iast/IastModule.cs index 7b181fa39479..80b326d57874 100644 --- a/tracer/src/Datadog.Trace/Iast/IastModule.cs +++ b/tracer/src/Datadog.Trace/Iast/IastModule.cs @@ -214,7 +214,7 @@ internal static IastModuleResponse OnSSRF(string evidence) try { OnExecutedSinkTelemetry(IastInstrumentedSinks.Ssrf); - return GetScope(evidence, IntegrationId.Ssrf, VulnerabilityTypeName.Ssrf, OperationNameSsrf, NoDbSource); + return GetScope(evidence, IntegrationId.Ssrf, VulnerabilityTypeName.Ssrf, OperationNameSsrf, NoDbSource, exclusionSecureMarks: SecureMarks.Ssrf); } catch (Exception ex) { diff --git a/tracer/src/Datadog.Trace/Iast/Propagation/PropagationModuleImpl.cs b/tracer/src/Datadog.Trace/Iast/Propagation/PropagationModuleImpl.cs index 5db55d832ed7..9f0f82407f0b 100644 --- a/tracer/src/Datadog.Trace/Iast/Propagation/PropagationModuleImpl.cs +++ b/tracer/src/Datadog.Trace/Iast/Propagation/PropagationModuleImpl.cs @@ -9,7 +9,9 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using Datadog.Trace.Logging; +using Datadog.Trace.RemoteConfigurationManagement.Protocol.Tuf; using static Datadog.Trace.Telemetry.Metrics.MetricTags; namespace Datadog.Trace.Iast.Propagation; @@ -92,98 +94,186 @@ public static void AddTaintedSource(string? input, Source source) return result; } - public static object? PropagateResultWhenInputTainted(string? result, object? firstInput, object? secondInput = null, object? thirdInput = null, object? fourthInput = null) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryPropagateWholeResult(string? result, object? input, out TaintedObjects? taintedObjects) + { + IastModule.OnExecutedPropagationTelemetry(); + if (result is null || input is null || result == string.Empty) + { + taintedObjects = null; + return true; + } + + if (object.ReferenceEquals(result, input)) + { + taintedObjects = null; + return true; + } + + var iastContext = IastModule.GetIastContext(); + if (iastContext == null) + { + taintedObjects = null; + return true; + } + + taintedObjects = iastContext.GetTaintedObjects(); + + if (result.Equals(input)) + { + var tainted = taintedObjects.Get(input); + if (tainted is not null) + { + taintedObjects.Taint(result, tainted.Ranges); + } + + return true; + } + + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool PropagateWholeResultWhenInputTainted(string result, object? input, TaintedObjects taintedObjects) + { + if (input is not null) + { + var tainted = taintedObjects.Get(input); + if (tainted?.Ranges?.Count() > 0 && tainted.Ranges[0].Source is not null && taintedObjects.Get(result) is null) + { + taintedObjects.Taint(result, new Range[] { new Range(0, result.Length, tainted.Ranges[0].Source, tainted.Ranges[0].SecureMarks) }); + return true; + } + } + + return false; + } + + public static string? PropagateWholeResultWhenInputTainted(string? result, object? input1) { try { - IastModule.OnExecutedPropagationTelemetry(); - if (string.IsNullOrEmpty(result)) + if (TryPropagateWholeResult(result, input1, out var taintedObjects) || taintedObjects is null) { return result; } - var iastContext = IastModule.GetIastContext(); - if (iastContext == null) + PropagateWholeResultWhenInputTainted(result!, input1, taintedObjects); + } + catch (Exception error) + { + Log.Error(error, $"{nameof(PropagationModuleImpl)}.{nameof(PropagateWholeResultWhenInputTainted)} exception"); + } + + return result; + } + + public static object? PropagateWholeResultWhenInputTainted(string? result, object? input1, object? input2) + { + try + { + if (TryPropagateWholeResult(result, input1, out var taintedObjects) || taintedObjects is null) { return result; } - var taintedObjects = iastContext.GetTaintedObjects(); - - if (PropagateResultWhenInputTainted(result!, firstInput, taintedObjects) || - PropagateResultWhenInputTainted(result!, secondInput, taintedObjects) || - PropagateResultWhenInputTainted(result!, thirdInput, taintedObjects) || - PropagateResultWhenInputTainted(result!, fourthInput, taintedObjects)) + if (PropagateWholeResultWhenInputTainted(result!, input1, taintedObjects) || + PropagateWholeResultWhenInputTainted(result!, input2, taintedObjects)) { return result; } } catch (Exception error) { - Log.Error(error, $"{nameof(PropagationModuleImpl)}.{nameof(PropagateResultWhenInputTainted)} exception"); + Log.Error(error, $"{nameof(PropagationModuleImpl)}.{nameof(PropagateWholeResultWhenInputTainted)} exception"); } return result; } - public static object? PropagateResultWhenInputArrayTainted(string result, object? firstInput, object[]? otherInputs) + public static object? PropagateWholeResultWhenInputTainted(string? result, object? input1, object? input2, object? input3) { try { - IastModule.OnExecutedPropagationTelemetry(); - if (string.IsNullOrEmpty(result)) + if (TryPropagateWholeResult(result, input1, out var taintedObjects) || taintedObjects is null) { return result; } - var iastContext = IastModule.GetIastContext(); - if (iastContext == null) + if (PropagateWholeResultWhenInputTainted(result!, input1, taintedObjects) || + PropagateWholeResultWhenInputTainted(result!, input2, taintedObjects) || + PropagateWholeResultWhenInputTainted(result!, input3, taintedObjects)) { return result; } + } + catch (Exception error) + { + Log.Error(error, $"{nameof(PropagationModuleImpl)}.{nameof(PropagateWholeResultWhenInputTainted)} exception"); + } - var taintedObjects = iastContext.GetTaintedObjects(); + return result; + } - if (PropagateResultWhenInputTainted(result, firstInput, taintedObjects)) + public static object? PropagateWholeResultWhenInputTainted(string? result, object? input1, object? input2, object? input3, object? input4) + { + try + { + if (TryPropagateWholeResult(result, input1, out var taintedObjects) || taintedObjects is null) { return result; } - if (otherInputs?.Length > 0) + if (PropagateWholeResultWhenInputTainted(result!, input1, taintedObjects) || + PropagateWholeResultWhenInputTainted(result!, input2, taintedObjects) || + PropagateWholeResultWhenInputTainted(result!, input3, taintedObjects) || + PropagateWholeResultWhenInputTainted(result!, input4, taintedObjects)) { - for (int i = 0; i < otherInputs.Length; i++) - { - if (PropagateResultWhenInputTainted(result, otherInputs[i], taintedObjects)) - { - return result; - } - } + return result; } } catch (Exception error) { - Log.Error(error, $"{nameof(PropagationModuleImpl)}.{nameof(PropagateResultWhenInputArrayTainted)} exception"); + Log.Error(error, $"{nameof(PropagationModuleImpl)}.{nameof(PropagateWholeResultWhenInputTainted)} exception"); } return result; } - private static bool PropagateResultWhenInputTainted(string result, object? input, TaintedObjects taintedObjects) + public static object? PropagateWholeResultWhenInputArrayTainted(string result, object? input1, object[]? otherInputs) { - if (input is not null) + try { - var tainted = taintedObjects.Get(input); - if (tainted?.Ranges?.Count() > 0 && tainted.Ranges[0].Source is not null && taintedObjects.Get(result) is null) + if (TryPropagateWholeResult(result, input1, out var taintedObjects) || taintedObjects is null) { - taintedObjects.Taint(result, new Range[] { new Range(0, result.Length, tainted.Ranges[0].Source) }); - return true; + return result; + } + + if (PropagateWholeResultWhenInputTainted(result, input1, taintedObjects)) + { + return result; + } + + if (otherInputs?.Length > 0) + { + for (int i = 0; i < otherInputs.Length; i++) + { + if (PropagateWholeResultWhenInputTainted(result, otherInputs[i], taintedObjects)) + { + return result; + } + } } } + catch (Exception error) + { + Log.Error(error, $"{nameof(PropagationModuleImpl)}.{nameof(PropagateWholeResultWhenInputArrayTainted)} exception"); + } - return false; + return result; } - public static string[]? PropagateResultWhenInputTainted(string[]? results, object? input) + public static string[]? PropagateWholeResultsWhenInputTainted(string[]? results, object? input) { try { @@ -217,7 +307,7 @@ private static bool PropagateResultWhenInputTainted(string result, object? input } catch (Exception error) { - Log.Error(error, $"{nameof(PropagationModuleImpl)}.{nameof(PropagateResultWhenInputTainted)} exception"); + Log.Error(error, $"{nameof(PropagationModuleImpl)}.{nameof(PropagateWholeResultWhenInputTainted)} exception"); } return results; diff --git a/tracer/src/Datadog.Trace/Iast/Ranges.cs b/tracer/src/Datadog.Trace/Iast/Ranges.cs index ec335c76cee7..6c5ea0fcf4fc 100644 --- a/tracer/src/Datadog.Trace/Iast/Ranges.cs +++ b/tracer/src/Datadog.Trace/Iast/Ranges.cs @@ -199,7 +199,7 @@ internal static Range[] CopyWithMark(Range[] ranges, SecureMarks secureMarks) foreach (var range in ranges) { - var newRange = new Range(range.Start, range.Length, range.Source, secureMarks); + var newRange = new Range(range.Start, range.Length, range.Source, range.SecureMarks | secureMarks); newRanges.Add(newRange); } @@ -225,7 +225,7 @@ internal static bool ContainsUnsafeRange(IEnumerable? ranges) } /// - /// Returns an array of ranges without ranges that are marked with the given marks. + /// Returns an array of ranges without ranges that are not marked with the given marks. /// internal static Range[]? UnsafeRanges(Range[]? ranges, SecureMarks secureMarks) { diff --git a/tracer/src/Datadog.Trace/Iast/SecureMarks.cs b/tracer/src/Datadog.Trace/Iast/SecureMarks.cs index c1eaaa6e6b7c..7af1d7bfe1b1 100644 --- a/tracer/src/Datadog.Trace/Iast/SecureMarks.cs +++ b/tracer/src/Datadog.Trace/Iast/SecureMarks.cs @@ -14,4 +14,5 @@ internal enum SecureMarks : byte { None = 0, Xss = 1, + Ssrf = 2, } diff --git a/tracer/src/Datadog.Tracer.Native/iast/dataflow.cpp b/tracer/src/Datadog.Tracer.Native/iast/dataflow.cpp index d68dfe384404..fb7ddbf92d87 100644 --- a/tracer/src/Datadog.Tracer.Native/iast/dataflow.cpp +++ b/tracer/src/Datadog.Tracer.Native/iast/dataflow.cpp @@ -108,6 +108,7 @@ static const WSTRING _fixedMethodExcludeFilters[] = { WStr("System.Web.Http*"), WStr("MongoDB.*"), WStr("JetBrains*"), + WStr("RestSharp.Extensions.StringExtensions::UrlEncode*"), LastEntry, // Can't have an empty array. This must be the last element }; static const WSTRING _fixedMethodAttributeExcludeFilters[] = { diff --git a/tracer/test/Datadog.Trace.Security.IntegrationTests/IAST/AspNetCore5IastTests.cs b/tracer/test/Datadog.Trace.Security.IntegrationTests/IAST/AspNetCore5IastTests.cs index ef2b3db71636..65fa1d9eb3a6 100644 --- a/tracer/test/Datadog.Trace.Security.IntegrationTests/IAST/AspNetCore5IastTests.cs +++ b/tracer/test/Datadog.Trace.Security.IntegrationTests/IAST/AspNetCore5IastTests.cs @@ -350,7 +350,7 @@ await VerifyHelper.VerifySpans(spansFiltered, settings) } } -// Class to test particular features (not running all the default tests) +// Class to test particular features public class AspNetCore5IastTestsStackTraces : AspNetCore5IastTests { public AspNetCore5IastTestsStackTraces(AspNetCoreTestFixture fixture, ITestOutputHelper outputHelper) @@ -406,42 +406,6 @@ await VerifyHelper.VerifySpans(spans, settings) } } -public abstract class AspNetCore5IastTests50PctSamplingIastEnabled : AspNetCore5IastTests -{ - public AspNetCore5IastTests50PctSamplingIastEnabled(AspNetCoreTestFixture fixture, ITestOutputHelper outputHelper) - : base(fixture, outputHelper, enableIast: true, testName: "AspNetCore5IastTests50PctSamplingIastEnabled", isIastDeduplicationEnabled: false, vulnerabilitiesPerRequest: 100, samplingRate: 50) - { - } - - public override async Task TryStartApp() - { - EnableIast(IastEnabled); - EnableEvidenceRedaction(RedactionEnabled); - DisableObfuscationQueryString(); - SetEnvironmentVariable(ConfigurationKeys.Iast.IsIastDeduplicationEnabled, IsIastDeduplicationEnabled?.ToString() ?? string.Empty); - SetEnvironmentVariable(ConfigurationKeys.Iast.VulnerabilitiesPerRequest, VulnerabilitiesPerRequest?.ToString() ?? string.Empty); - SetEnvironmentVariable(ConfigurationKeys.Iast.RequestSampling, SamplingRate?.ToString() ?? string.Empty); - await Fixture.TryStartApp(this, enableSecurity: false, sendHealthCheck: false); - SetHttpPort(Fixture.HttpPort); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task TestIastWeakHashingRequestSampling() - { - var filename = "Iast.WeakHashing.AspNetCore5.IastEnabled"; - IncludeAllHttpSpans = true; - await TryStartApp(); - await TestWeakHashing(filename, Fixture.Agent); - - filename = "Iast.WeakHashing.AspNetCore5.IastDisabledFlag"; - await TestWeakHashing(filename, Fixture.Agent); - - filename = "Iast.WeakHashing.AspNetCore5.IastEnabled"; - await TestWeakHashing(filename, Fixture.Agent); - } -} - public class AspNetCore5IastTestsSpanTelemetryIastEnabled : AspNetCore5IastTests { public AspNetCore5IastTestsSpanTelemetryIastEnabled(AspNetCoreTestFixture fixture, ITestOutputHelper outputHelper) diff --git a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/InstrumentationTestsBase.cs b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/InstrumentationTestsBase.cs index d446b54fb656..7315939c4ef7 100644 --- a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/InstrumentationTestsBase.cs +++ b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/InstrumentationTestsBase.cs @@ -46,10 +46,10 @@ public class InstrumentationTestsBase : IDisposable private static MethodInfo _iastRequestContextProperty = _traceContextType.GetProperty("IastRequestContext", BindingFlags.NonPublic | BindingFlags.Instance)?.GetMethod; private static MethodInfo _operationNameProperty = _spanType.GetProperty("OperationName", BindingFlags.NonPublic | BindingFlags.Instance)?.GetMethod; private static MethodInfo _rangesProperty = _taintedObjectType.GetProperty("Ranges", BindingFlags.Public | BindingFlags.Instance)?.GetMethod; - private static MethodInfo _StartProperty = _rangeType.GetProperty("Start", BindingFlags.Public | BindingFlags.Instance)?.GetMethod; - private static MethodInfo _LengthProperty = _rangeType.GetProperty("Length", BindingFlags.Public | BindingFlags.Instance)?.GetMethod; + private static MethodInfo _startProperty = _rangeType.GetProperty("Start", BindingFlags.Public | BindingFlags.Instance)?.GetMethod; private static MethodInfo _lengthProperty = _rangeType.GetProperty("Length", BindingFlags.Public | BindingFlags.Instance)?.GetMethod; private static MethodInfo _sourceProperty = _rangeType.GetProperty("Source", BindingFlags.Public | BindingFlags.Instance)?.GetMethod; + private static MethodInfo _secureMarksProperty = _rangeType.GetProperty("SecureMarks", BindingFlags.Public | BindingFlags.Instance)?.GetMethod; private static MethodInfo _vulnerabilitiesProperty = _vulnerabilityBatchType.GetProperty("Vulnerabilities", BindingFlags.Public | BindingFlags.Instance)?.GetMethod; private static MethodInfo _vulnerabilityTypeProperty = _vulnerabilityType.GetProperty("Type", BindingFlags.Public | BindingFlags.Instance)?.GetMethod; private static MethodInfo _evidenceProperty = _vulnerabilityType.GetProperty("Evidence", BindingFlags.Public | BindingFlags.Instance)?.GetMethod; @@ -70,6 +70,14 @@ public class InstrumentationTestsBase : IDisposable protected static string WeakHashVulnerabilityType = "WEAK_HASH"; protected static string commandInjectionType = "COMMAND_INJECTION"; + [Flags] + public enum SecureMarks : byte + { + None = 0, + Xss = 1, + Ssrf = 2, + } + public InstrumentationTestsBase() { AssertInstrumented(); @@ -117,6 +125,20 @@ protected void AssertTainted(object tainted, string additionalInfo = "") GetTainted(tainted).Should().NotBeNull(tainted.ToString() + " is not tainted. " + additionalInfo); } + protected void AssertSecureMarks(object value, SecureMarks secureMarks) + { + AssertTainted(value); + string result = value.ToString(); + var tainted = GetTainted(value); + var ranges = _rangesProperty.Invoke(tainted, Array.Empty()) as Array; + + foreach (var range in ranges) + { + var rangeSecureMarks = (SecureMarks)_secureMarksProperty.Invoke(range, Array.Empty()); + rangeSecureMarks.Should().Be(secureMarks); + } + } + private object GetTainted(object tainted) { return _getTaintedObjectsMethod.Invoke(_taintedObjects, new object[] { tainted }); @@ -139,7 +161,7 @@ protected void AssertSpanGenerated(string operationName, int spansGenerated = 1) spans.Count.Should().Be(spansGenerated); } - protected void AssertVulnerable(string expectedType = null, string expectedEvidence = null, bool evidenceTainted = true, byte sourceType = 0, int vulnerabilities = 1) + protected void AssertVulnerable(string expectedType = null, string expectedEvidence = null, bool evidenceTainted = true, short sourceType = -1, int vulnerabilities = 1) { var vulnerabilityList = GetGeneratedVulnerabilities(); vulnerabilityList.Count.Should().Be(vulnerabilities); @@ -153,12 +175,12 @@ protected void AssertVulnerable(string expectedType = null, string expectedEvide var evidence = _evidenceProperty.Invoke(vulnerabilityList[0], Array.Empty()); var evidenceValue = _evidenceValueField.GetValue(evidence); - if (evidenceTainted) + if (evidenceTainted && sourceType >= 0) { var range = (_evidenceRangesField.GetValue(evidence) as Array).GetValue(0); var source = _sourceProperty.Invoke(range, Array.Empty()); var origin = (byte)_sourceOriginField.GetValue(source); - origin.Should().Be(sourceType); + origin.Should().Be((byte)sourceType); } if (!string.IsNullOrEmpty(expectedEvidence)) @@ -251,7 +273,7 @@ protected void AssertTaintedFormatWithOriginalCallCheck(object instrumented, Exp AssertTaintedFormatWithOriginalCallCheck(null, instrumented, notInstrumented); } - protected void AssertTaintedFormatWithOriginalCallCheck(object expected, object instrumented, Expression> notInstrumented) + protected object AssertTaintedFormatWithOriginalCallCheck(object expected, object instrumented, Expression> notInstrumented) { AssertTainted(instrumented); if (expected is not null) @@ -262,6 +284,8 @@ protected void AssertTaintedFormatWithOriginalCallCheck(object expected, object var notInstrumentedCompiled = notInstrumented.Compile(); var notInstrumentedResult = ExecuteFunc(notInstrumentedCompiled); instrumented.ToString().Should().Be(notInstrumentedResult.ToString()); + + return instrumented; } protected void AssertUntaintedWithOriginalCallCheck(Action instrumented, Expression notInstrumented) @@ -336,8 +360,8 @@ protected string FormatTainted(object value) foreach (var range in rangesList) { - var start = (int)_StartProperty.Invoke(range, Array.Empty()); - var length = (int)_LengthProperty.Invoke(range, Array.Empty()); + var start = (int)_startProperty.Invoke(range, Array.Empty()); + var length = (int)_lengthProperty.Invoke(range, Array.Empty()); result = result.Insert(start + length, "-+:"); result = result.Insert(start, ":+-"); } @@ -354,8 +378,8 @@ protected void ValidateRanges(object value) foreach (var range in ranges) { - var start = (int)_StartProperty.Invoke(range, Array.Empty()); - var length = (int)_LengthProperty.Invoke(range, Array.Empty()); + var start = (int)_startProperty.Invoke(range, Array.Empty()); + var length = (int)_lengthProperty.Invoke(range, Array.Empty()); (start + length).Should().BeLessThanOrEqualTo(result.Length); } } diff --git a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/SSRF/RestClientTests.cs b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/SSRF/RestClientTests.cs index c4b80f6c7e1d..ff50ff400956 100644 --- a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/SSRF/RestClientTests.cs +++ b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/SSRF/RestClientTests.cs @@ -1,6 +1,7 @@ using Xunit; using RestSharp; using System.Threading; +using System.Security.Policy; namespace Samples.InstrumentedTests.Iast.Vulnerabilities.SSRF; @@ -50,4 +51,52 @@ public void GivenARestSharpClient_WhenExecute_Vulnerable5() ExecuteFunc(() => client.Get(request)); AssertVulnerable("SSRF", sourceType: sourceType); } + + [Fact] + public void GivenATaintedQueryStringParameterEscaped_WhenExecute_NotVulnerable() + { + var client = new RestClient("https://www.google.com"); + var request = new RestRequest("/search"); + request.AddParameter("q1", taintedSafeParam, ParameterType.QueryString); + request.AddParameter("q2", taintedQuery, ParameterType.QueryString); + var fullUrl = client.BuildUri(request); + ExecuteFunc(() => client.ExecuteGet(request).ToString()); + AssertNotVulnerable(); + } + + [Fact] + public void TaintedUrlSegmentParameterEscaped_WhenExecute_NotVulnerable() + { + var client = new RestClient("https://www.google.com"); + var request = new RestRequest("/search{q1}{q2}"); + request.AddParameter("q1", taintedSafeParam, ParameterType.UrlSegment); + request.AddParameter("q2", taintedQuery, ParameterType.UrlSegment); + var fullUrl = client.BuildUri(request); + ExecuteFunc(() => client.ExecuteGet(request).ToString()); + AssertNotVulnerable(); + } + + [Fact] + public void TaintedQueryStringParameterNotEscaped_WhenExecute_Vulnerable() + { + var client = new RestClient("https://www.google.com"); + var request = new RestRequest("/search"); + request.AddParameter("q1", taintedSafeParam, ParameterType.QueryString, false); + request.AddParameter("q2", taintedQuery, ParameterType.QueryString, false); + var fullUrl = client.BuildUri(request); + ExecuteFunc(() => client.ExecuteGet(request).ToString()); + AssertVulnerable(); + } + + [Fact] + public void TaintedUrlSegmentParameterNotEscaped_WhenExecute_Vulnerable() + { + var client = new RestClient("https://www.google.com"); + var request = new RestRequest("/search{q1}{q2}"); + request.AddParameter("q1", taintedSafeParam, ParameterType.UrlSegment, false); + request.AddParameter("q2", taintedQuery, ParameterType.UrlSegment, false); + var fullUrl = client.BuildUri(request); + ExecuteFunc(() => client.ExecuteGet(request).ToString()); + AssertVulnerable(); + } } diff --git a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/SSRF/SSRFTests.cs b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/SSRF/SSRFTests.cs index 4bcf3f8ca8da..c32cb78b5f88 100644 --- a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/SSRF/SSRFTests.cs +++ b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/SSRF/SSRFTests.cs @@ -8,6 +8,7 @@ public class SSRFTests : InstrumentationTestsBase protected string notTaintedHost = "myhost"; protected string taintedHost = "localhost"; protected string taintedQuery = "e=22"; + protected string taintedSafeParam = "dd"; protected string taintedUrlValue = "http://127.0.0.1/invalid?q=1#e"; protected string taintedUrlValue2 = "http://127.0.0.1"; protected string file = "invalid@#file"; @@ -18,6 +19,7 @@ public SSRFTests() AddTainted(taintedUrlValue, sourceType); AddTainted(taintedUrlValue2, sourceType); AddTainted(taintedHost, sourceType); + AddTainted(taintedSafeParam, sourceType); AddTainted(taintedQuery, sourceType); } diff --git a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/SSRF/UrlEscapeTests.cs b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/SSRF/UrlEscapeTests.cs new file mode 100644 index 000000000000..a3147fb2d126 --- /dev/null +++ b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/SSRF/UrlEscapeTests.cs @@ -0,0 +1,74 @@ +using System; +using System.Net; +using System.Text; +using System.Web; +using Xunit; + +namespace Samples.InstrumentedTests.Iast.Vulnerabilities.StringPropagation; +public class UrlEscapeTests : InstrumentationTestsBase +{ + private string _taintedValue = "tainted"; + private string _taintedValue2 = "/tainted?p1=t1&p2=t2"; + private string _taintedFormat2Args = "format{0}{1}"; + private string _taintedFormat3Args = "format{0}{1}{2}"; + private string _taintedFormat1Arg = "format{0}"; + private string _untaintedString = "UntaintedString"; + private string _otherUntaintedString = "OtherUntaintedString"; + + public UrlEscapeTests() + { + AddTainted(_taintedValue); + AddTainted(_taintedValue2); + } + + [Fact] + public void GivenAValidTaintedString_WhenHttpUtilityEscaped_ResultIsTaintedWithSafeMark() + { + AssertSecureMarks( + AssertTaintedFormatWithOriginalCallCheck(":+-tainted-+:", + HttpUtility.UrlEncode(_taintedValue), + () => HttpUtility.HtmlEncode(_taintedValue)), + SecureMarks.Ssrf); + } + + [Fact] + public void GivenAnInvalidTaintedString_WhenHttpUtilityEscaped_ResultIsTaintedWithSafeMark() + { + AssertSecureMarks( + AssertTaintedFormatWithOriginalCallCheck(":+-%2ftainted%3fp1%3dt1%26p2%3dt2-+:", + HttpUtility.UrlEncode(_taintedValue2), + () => HttpUtility.UrlEncode(_taintedValue2)), + SecureMarks.Ssrf); + } + + [Fact] + public void GivenAnInvalidTaintedString_WhenHttpUtilityEscapedUTF8_ResultIsTaintedWithSafeMark1() + { + AssertSecureMarks( + AssertTaintedFormatWithOriginalCallCheck(":+-%2ftainted%3fp1%3dt1%26p2%3dt2-+:", + HttpUtility.UrlEncode(_taintedValue2, System.Text.Encoding.UTF8), + () => HttpUtility.UrlEncode(_taintedValue2)), + SecureMarks.Ssrf); + } + + [Fact] + public void GivenAValidTaintedString_WhenWebUtilityEscaped_ResultIsTaintedWithSafeMark() + { + AssertSecureMarks( + AssertTaintedFormatWithOriginalCallCheck(":+-tainted-+:", + WebUtility.UrlEncode(_taintedValue), + () => WebUtility.UrlEncode(_taintedValue)), + SecureMarks.Ssrf); + } + + [Fact] + public void GivenAnInvalidTaintedString_WhenWebUtilityEscaped_ResultIsTaintedWithSafeMark() + { + AssertSecureMarks( + AssertTaintedFormatWithOriginalCallCheck(":+-%2Ftainted%3Fp1%3Dt1%26p2%3Dt2-+:", + WebUtility.UrlEncode(_taintedValue2), + () => WebUtility.UrlEncode(_taintedValue2)), + SecureMarks.Ssrf); + } + +} diff --git a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/String/StringFormatTests.cs b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/String/StringFormatTests.cs index f00d9d79abe3..12e23632c57f 100644 --- a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/String/StringFormatTests.cs +++ b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/String/StringFormatTests.cs @@ -332,7 +332,9 @@ public void GivenATaintedFormatObject_WhenCallingFormatWithObjectArray_ResultIsT [Fact] public void GivenANotTaintedFormatObject_WhenCallingFormatWithObjectArray_ResultIsNotTainted2() { - AssertNotTainted(String.Format("Format{0}{1}", new object[] { "notTainted", "notTainted" })); + AssertUntaintedWithOriginalCallCheck("FormatnotTaintednotTainted", + String.Format("Format{0}{1}", new object[] { "notTainted", "notTainted" }), + () => String.Format("Format{0}{1}", new object[] { "notTainted", "notTainted" })); } [Fact] @@ -351,6 +353,15 @@ public void GivenATaintedFormatObject_WhenCallingFormatWithObjectArray_ResultIsT () => String.Format(_taintedFormat3Args, new object[] { "ww", "ww", "ww" })); } + [Fact] + public void GivenANotTaintedFormatObject_WhenCallingFormatWithTaintedObjectNoReplace_ResultIsNotTainted2() + { + AssertUntaintedWithOriginalCallCheck("Format", + String.Format("Format", _taintedValue), + () => String.Format("Format", _taintedValue)); + } + + #if NET8_0 // System.String Format(System.IFormatProvider, System.Text.CompositeFormat, System.Object[]) diff --git a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/String/StringReplaceTests.cs b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/String/StringReplaceTests.cs index d15fe0d4ed4e..367d98835e38 100644 --- a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/String/StringReplaceTests.cs +++ b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/String/StringReplaceTests.cs @@ -347,6 +347,24 @@ public void GivenATaintedObject_WhenCallingReplaceWithCharParametersNoReplace_Re AssertTaintedFormatWithOriginalCallCheck(":+-tainted-+:", _taintedValue.Replace('%', 'e'), () => _taintedValue.Replace('%', 'e')); } + [Fact] + public void GivenANonTaintedString_WhenCallingReplaceWithUntaintedReplace_ResultIsNonTainted() + { + AssertUntaintedWithOriginalCallCheck("UNT*new*INTED", "UNTAINTED".Replace("A", "*new*"), () => "UNTAINTED".Replace("A", "*new*")); + } + + [Fact] + public void GivenANonTaintedString_WhenCallingReplaceWithTaintedNoReplace_ResultIsNonTainted() + { + AssertUntaintedWithOriginalCallCheck("UNTAINTED", "UNTAINTED".Replace("%", _taintedValue), () => "UNTAINTED".Replace("%", _taintedValue)); + } + + [Fact] + public void GivenANonTaintedString_WhenCallingReplaceWithTaintedReplace_ResultIsTainted() + { + AssertTaintedFormatWithOriginalCallCheck(":+-UNtaintedAINtaintedED-+:", "UNTAINTED".Replace("T", _taintedValue), () => "UNTAINTED".Replace("T", _taintedValue)); + } + // testing Replace(string oldValue, string? newValue, bool ignoreCase, CultureInfo? culture) #if NETCOREAPP3_1_OR_GREATER diff --git a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/Xss/HtmlEscapeTests.cs b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/Xss/HtmlEscapeTests.cs new file mode 100644 index 000000000000..4bdc8d381fa0 --- /dev/null +++ b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/Vulnerabilities/Xss/HtmlEscapeTests.cs @@ -0,0 +1,58 @@ +using System.Net; +using System.Web; +using Xunit; + +namespace Samples.InstrumentedTests.Iast.Vulnerabilities.StringPropagation; +public class HtmlEscapeTests : InstrumentationTestsBase +{ + private string _taintedValue = "tainted"; + private string _taintedValue2 = ""; + + public HtmlEscapeTests() + { + AddTainted(_taintedValue); + AddTainted(_taintedValue2); + } + + [Fact] + public void GivenAValidTaintedString_WhenHttpUtilityEscaped_ResultIsTaintedWithSafeMark() + { + AssertSecureMarks( + AssertTaintedFormatWithOriginalCallCheck(":+-tainted-+:", + HttpUtility.HtmlEncode(_taintedValue), + () => HttpUtility.HtmlEncode(_taintedValue)), + SecureMarks.Xss); + } + + [Fact] + public void GivenAnInvalidTaintedString_WhenHttpUtilityEscaped_ResultIsTaintedWithSafeMark() + { + AssertSecureMarks( + AssertTaintedFormatWithOriginalCallCheck(":+-<tainted>-+:", + HttpUtility.HtmlEncode(_taintedValue2), + () => HttpUtility.HtmlEncode(_taintedValue2)), + SecureMarks.Xss); + } + + [Fact] + public void GivenAValidTaintedString_WhenWebUtilityEscaped_ResultIsTaintedWithSafeMark() + { + AssertSecureMarks( + AssertTaintedFormatWithOriginalCallCheck(":+-tainted-+:", + WebUtility.HtmlEncode(_taintedValue), + () => WebUtility.HtmlEncode(_taintedValue)), + SecureMarks.Xss); + } + + [Fact] + public void GivenAnInvalidTaintedString_WhenWebUtilityEscaped_ResultIsTaintedWithSafeMark() + { + AssertSecureMarks( + AssertTaintedFormatWithOriginalCallCheck(":+-<tainted>-+:", + WebUtility.HtmlEncode(_taintedValue2), + () => WebUtility.HtmlEncode(_taintedValue2)), + SecureMarks.Xss); + } + + +} diff --git a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/iast.runsettings b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/iast.runsettings index 4481567e4030..6e28d1dfd49b 100644 --- a/tracer/test/test-applications/integrations/Samples.InstrumentedTests/iast.runsettings +++ b/tracer/test/test-applications/integrations/Samples.InstrumentedTests/iast.runsettings @@ -1,3 +1,3 @@ - + \ No newline at end of file