Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IAST] Vulnerability and Evidence truncation #5302

Merged
merged 7 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,13 @@ internal class Iast
/// Configuration key for IAST verbosity.
/// Default value is INFORMATION
/// </summary>
public const string IastTelemetryVerbosity = "DD_IAST_TELEMETRY_VERBOSITY";
public const string TelemetryVerbosity = "DD_IAST_TELEMETRY_VERBOSITY";

/// <summary>
/// Configuration key for IAST evidence max lenght in chars.
/// Default value is 250
/// </summary>
public const string TruncationMaxValueLength = "DD_IAST_TRUNCATION_MAX_VALUE_LENGTH";
}
}
}
18 changes: 10 additions & 8 deletions tracer/src/Datadog.Trace/Iast/EvidenceConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ internal class EvidenceConverter : JsonConverter<Evidence?>
// If a tainted range intersects with a sensitive range, the corresponding source must be redacted also.

private bool _redactionEnabled;
private int _maxValueLength;

public EvidenceConverter(bool redactionEnabled)
public EvidenceConverter(int maxValueLength, bool redactionEnabled)
{
_redactionEnabled = redactionEnabled;
_maxValueLength = maxValueLength;
}

public override bool CanRead => false;
Expand Down Expand Up @@ -78,7 +80,7 @@ public override void WriteJson(JsonWriter writer, Evidence? evidence, JsonSerial
if (evidenceValue.Ranges == null || evidenceValue.Ranges.Length == 0)
{
writer.WritePropertyName("value");
writer.WriteValue(evidenceValue.Value);
writer.WriteTruncatableValue(evidenceValue.Value, _maxValueLength);
}
else
{
Expand All @@ -96,7 +98,7 @@ public override void WriteJson(JsonWriter writer, Evidence? evidence, JsonSerial
writer.WriteEndObject();
}

private static void ToJsonTaintedValue(JsonWriter writer, string value, Range[] ranges)
private void ToJsonTaintedValue(JsonWriter writer, string value, Range[] ranges)
{
writer.WriteStartArray();
int start = 0;
Expand All @@ -120,12 +122,12 @@ private static void ToJsonTaintedValue(JsonWriter writer, string value, Range[]
writer.WriteEndArray();
}

private static void WriteValuePart(JsonWriter writer, string? value, Source? source = null)
private void WriteValuePart(JsonWriter writer, string? value, Source? source = null)
{
if (value == null) { return; }
writer.WriteStartObject();
writer.WritePropertyName("value");
writer.WriteValue(value);
writer.WriteTruncatableValue(value, _maxValueLength);
if (source != null)
{
writer.WritePropertyName("source");
Expand All @@ -135,15 +137,15 @@ private static void WriteValuePart(JsonWriter writer, string? value, Source? sou
writer.WriteEndObject();
}

private static void WriteRedactedValuePart(JsonWriter writer, string? value, Source? source = null)
private void WriteRedactedValuePart(JsonWriter writer, string? value, Source? source = null)
{
writer.WriteStartObject();
writer.WritePropertyName("redacted");
writer.WriteValue(true);
if (value != null)
{
writer.WritePropertyName("pattern");
writer.WriteValue(value);
writer.WriteTruncatableValue(value, _maxValueLength);
}

if (source != null)
Expand All @@ -155,7 +157,7 @@ private static void WriteRedactedValuePart(JsonWriter writer, string? value, Sou
writer.WriteEndObject();
}

private static void Write(JsonWriter writer, ValuePart part)
private void Write(JsonWriter writer, ValuePart part)
{
if (part.IsRedacted)
{
Expand Down
2 changes: 1 addition & 1 deletion tracer/src/Datadog.Trace/Iast/IastModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ internal static void OnExecutedSinkTelemetry(IastInstrumentedSinks sink)

internal static VulnerabilityBatch GetVulnerabilityBatch()
{
return new VulnerabilityBatch(EvidenceRedactorLazy.Value);
return new VulnerabilityBatch(iastSettings.TruncationMaxValueLength, EvidenceRedactorLazy.Value);
}

// This method adds web vulnerabilities, with no location, only on web environments
Expand Down
14 changes: 11 additions & 3 deletions tracer/src/Datadog.Trace/Iast/Settings/IastSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ internal class IastSettings
public const int VulnerabilitiesPerRequestDefault = 2;
public const int MaxConcurrentRequestDefault = 2;
public const int RequestSamplingDefault = 30;
public const int TruncationMaxValueLengthDefault = 250;

/// <summary>
/// Default keys readaction regex if none specified via env DD_IAST_REDACTION_KEYS_REGEXP
Expand Down Expand Up @@ -65,8 +66,8 @@ public IastSettings(IConfigurationSource source, IConfigurationTelemetry telemet
.WithKeys(ConfigurationKeys.Iast.RegexTimeout)
.AsDouble(200, val1 => val1 is >= 0).Value;

IastTelemetryVerbosity = config
.WithKeys(ConfigurationKeys.Iast.IastTelemetryVerbosity)
TelemetryVerbosity = config
.WithKeys(ConfigurationKeys.Iast.TelemetryVerbosity)
.GetAs(
getDefaultValue: () => IastMetricsVerbosityLevel.Information,
converter: value => value.ToLowerInvariant() switch
Expand All @@ -78,6 +79,11 @@ public IastSettings(IConfigurationSource source, IConfigurationTelemetry telemet
_ => ParsingResult<IastMetricsVerbosityLevel>.Failure()
},
validator: null);

TruncationMaxValueLength = config
.WithKeys(ConfigurationKeys.Iast.TruncationMaxValueLength)
.AsInt32(TruncationMaxValueLengthDefault, x => x > 0)
.Value;
}

public bool Enabled { get; set; }
Expand Down Expand Up @@ -106,7 +112,9 @@ public IastSettings(IConfigurationSource source, IConfigurationTelemetry telemet

public double RegexTimeout { get; }

public IastMetricsVerbosityLevel IastTelemetryVerbosity { get; }
public IastMetricsVerbosityLevel TelemetryVerbosity { get; }

public int TruncationMaxValueLength { get; }

public static IastSettings FromDefaultSources()
{
Expand Down
9 changes: 6 additions & 3 deletions tracer/src/Datadog.Trace/Iast/SourceConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ internal class SourceConverter : JsonConverter<Source>
// When redacted output is:
// { "origin": "http.request.parameter.name", "name": "name", "redacted": true }

public SourceConverter()
private int _maxValueLength;

public SourceConverter(int maxValueLength)
{
_maxValueLength = maxValueLength;
}

public override bool CanRead => true;
Expand Down Expand Up @@ -63,13 +66,13 @@ public override void WriteJson(JsonWriter writer, Source? source, JsonSerializer
if (source.RedactedValue != null)
{
writer.WritePropertyName("pattern");
writer.WriteValue(source.RedactedValue);
writer.WriteTruncatableValue(source.RedactedValue, _maxValueLength);
}
}
else if (source.Value != null)
{
writer.WritePropertyName("value");
writer.WriteValue(source.Value);
writer.WriteTruncatableValue(source.Value, _maxValueLength);
}

writer.WriteEndObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal class ExecutedTelemetryHelper
private const string SinkExecutedTag = "executed.sink.";
private const string PropagationExecutedTag = BasicExecutedTag + "executed.propagation";
private const string RequestTaintedTag = BasicExecutedTag + "request.tainted";
private static IastMetricsVerbosityLevel _verbosityLevel = Iast.Instance.Settings.IastTelemetryVerbosity;
private static IastMetricsVerbosityLevel _verbosityLevel = Iast.Instance.Settings.TelemetryVerbosity;
private int[] _executedSinks = new int[Trace.Telemetry.Metrics.IastInstrumentedSinksExtensions.Length];
private int[] _executedSources = new int[Trace.Telemetry.Metrics.IastInstrumentedSourcesExtensions.Length];
private int _executedPropagations = 0;
Expand Down
90 changes: 90 additions & 0 deletions tracer/src/Datadog.Trace/Iast/TruncatedVulnerabilities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// <copyright file="TruncatedVulnerabilities.cs" company="Datadog">
// 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.
// </copyright>

#nullable enable

using System;
using System.Collections.Generic;
using Datadog.Trace.Iast.SensitiveData;
using Datadog.Trace.Iast.Settings;
using Datadog.Trace.Vendors.Newtonsoft.Json;
using Datadog.Trace.Vendors.Newtonsoft.Json.Linq;
using Datadog.Trace.Vendors.Newtonsoft.Json.Utilities;

namespace Datadog.Trace.Iast;

/// <summary>
/// Custom JSON serializer for <see cref="Datadog.Trace.Iast.Source"/> struct
/// </summary>
internal struct TruncatedVulnerabilities
{
private const string MaxSizeExceeded = "MAX SIZE EXCEEDED";

private List<Vulnerability> vulnerabilities;

public TruncatedVulnerabilities(List<Vulnerability> vulnerabilities)
{
this.vulnerabilities = vulnerabilities;
}

public List<Vulnerability> Vulnerabilities => vulnerabilities;

public class VulnerabilityConverter : JsonConverter<Vulnerability?>
{
public VulnerabilityConverter()
{
}

public override bool CanRead => true;

public override Vulnerability? ReadJson(JsonReader reader, Type objectType, Vulnerability? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}

public override void WriteJson(JsonWriter writer, Vulnerability? value, JsonSerializer serializer)
{
if (value != null)
{
writer.WriteStartObject();
writer.WritePropertyName("type");
writer.WriteValue(value.Value.Type);
writer.WritePropertyName("evidence");
serializer.Serialize(writer, value.Value.Evidence);
writer.WritePropertyName("hash");
writer.WriteValue(value.Value.Hash);
writer.WritePropertyName("location");
serializer.Serialize(writer, value.Value.Location);

writer.WriteEndObject();
}
}
}

public class EvidenceConverter : JsonConverter<Evidence?>
{
public EvidenceConverter()
{
}

public override bool CanRead => true;

public override Evidence? ReadJson(JsonReader reader, Type objectType, Evidence? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}

public override void WriteJson(JsonWriter writer, Evidence? value, JsonSerializer serializer)
{
if (value != null)
{
writer.WriteStartObject();
writer.WritePropertyName("value");
writer.WriteValue(MaxSizeExceeded);
writer.WriteEndObject();
}
}
}
}
36 changes: 36 additions & 0 deletions tracer/src/Datadog.Trace/Iast/TruncationUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// <copyright file="TruncationUtils.cs" company="Datadog">
// 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.
// </copyright>

#nullable enable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Datadog.Trace.Iast.Settings;
using Datadog.Trace.Vendors.Newtonsoft.Json;

namespace Datadog.Trace.Iast;

internal static class TruncationUtils
{
private const string TRUNCATED = "truncated";
private const string RIGHT = "right";

public static void WriteTruncatableValue(this JsonWriter writer, string? value, int maxValueLength)
{
if (value != null && value.Length > maxValueLength && maxValueLength > 0)
{
writer.WriteValue(value.Substring(0, maxValueLength));
writer.WritePropertyName(TRUNCATED);
writer.WriteValue(RIGHT);
}
else
{
writer.WriteValue(value);
}
}
}
Loading
Loading