Skip to content

Commit

Permalink
fix: soap action parsing for malformed data
Browse files Browse the repository at this point in the history
  • Loading branch information
Dominik Baran committed May 31, 2024
1 parent 0c709cd commit 4420b22
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 6 deletions.
65 changes: 65 additions & 0 deletions src/SoapCore.Tests/InvalidXMLTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,71 @@ public async Task DuplicatedElement()
Assert.IsTrue(body.Contains("<TestResult>a c</TestResult>"));
}

[DataTestMethod]
[DataRow("application/soap+xml; charset=utf-8; action=\"Request\"")]
[DataRow("application/soap+xml; charset=utf-8; action=\"Request/\"")]
[DataRow("application/soap+xml; charset=utf-8; action=\"testRequest/\"")]
[DataRow("application/soap+xml; charset=utf-8; action=\"TESTRequest/\"")]
[DataRow("application/soap+xml; charset=utf-8; action=\"/\"")]
[DataRow("application/soap+xml; charset=utf-8; action=\"https://dos.brianfeucht.com/test/\"")]
[DataRow("application/soap+xml; charset=utf-8; action=\"https://dos.brianfeucht.com/test\"")]
[DataRow("application/soap+xml; charset=utf-8; action=\"https://dos.brianfeucht.com/TEST\"")]
[DataRow("application/soap+xml; charset=utf-8; action=\"https://dos.brianfeucht.com/Test\"")]
public async Task InvalidSoapActionContentType(string contentType)
{
// Arrange
var logger = NullLoggerFactory.Instance.CreateLogger<SoapEndpointMiddleware<CustomMessage>>();

var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<DuplicatedElementService>();
serviceCollection.AddSoapCore();

var options = new SoapOptions()
{
Path = "/Service.asmx",
EncoderOptions = new[]
{
new SoapEncoderOptions
{
MessageVersion = MessageVersion.Soap12WSAddressing10,
WriteEncoding = Encoding.UTF8,
ReaderQuotas = XmlDictionaryReaderQuotas.Max
}
},
ServiceType = typeof(DuplicatedElementService),
SoapModelBounder = new MockModelBounder(),
SoapSerializer = SoapSerializer.XmlSerializer
};

var soapCore = new SoapEndpointMiddleware<CustomMessage>(logger, _ => Task.CompletedTask, options);

var context = new DefaultHttpContext();
context.Request.Path = new PathString("/Service.asmx");
context.Request.Method = "POST";
context.Response.Body = new MemoryStream();

// Act
var request = @"
<soap12:Envelope xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope"" xmlns:rlx=""https://dos.brianfeucht.com/"">
<soap12:Body>
<rlx:Test>
<eventRef>a</eventRef>
<other>c</other>
</rlx:Test>
</soap12:Body>
</soap12:Envelope>";
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(request), false);
context.Request.ContentType = contentType;

await soapCore.Invoke(context, serviceCollection.BuildServiceProvider());

// Assert
context.Response.Body.Seek(0, SeekOrigin.Begin);
using var response = new StreamReader(context.Response.Body, Encoding.UTF8);
var body = await response.ReadToEndAsync();
Assert.IsTrue(body.Contains("<TestResult>a c</TestResult>"));
}

[ServiceContract(Namespace = "https://dos.brianfeucht.com/")]
public class DenialOfServiceProofOfConcept
{
Expand Down
6 changes: 6 additions & 0 deletions src/SoapCore/HeadersHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ public static string GetSoapAction(HttpContext httpContext, ref Message message)
}
}

if (soapAction != null &&
(string.IsNullOrEmpty(GetTrimmedSoapAction(soapAction)) || string.IsNullOrEmpty(GetTrimmedClearedSoapAction(soapAction))))
{
soapAction = string.Empty;
}

if (string.IsNullOrEmpty(soapAction))
{
if (!string.IsNullOrEmpty(message.Headers.Action))
Expand Down
16 changes: 10 additions & 6 deletions src/SoapCore/SoapEndpointMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,11 @@ bool TryGetRequestValue(string key, out StringValues value)
context.Response.ContentType = "text/xml";

var ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms, new XmlWriterSettings() { Encoding = DefaultEncodings.UTF8 });
XmlWriter writer = XmlWriter.Create(ms, new XmlWriterSettings
{
Encoding = DefaultEncodings.UTF8,

});
XmlDictionaryWriter dictionaryWriter = XmlDictionaryWriter.CreateDictionaryWriter(writer);

bodyWriter.WriteBodyContents(dictionaryWriter);
Expand Down Expand Up @@ -566,15 +570,15 @@ private async Task<Message> ProcessMessage(Message requestMessage, SoapMessageEn

private bool TryGetOperation(string methodName, out OperationDescription operation)
{
operation = _service.Operations.FirstOrDefault(o => o.SoapAction.Equals(methodName, StringComparison.Ordinal)
|| o.Name.Equals(HeadersHelper.GetTrimmedSoapAction(methodName), StringComparison.Ordinal)
|| methodName.Equals(HeadersHelper.GetTrimmedSoapAction(o.Name), StringComparison.Ordinal));
operation = _service.Operations.FirstOrDefault(o => o.SoapAction.Equals(methodName, StringComparison.OrdinalIgnoreCase)
|| o.Name.Equals(HeadersHelper.GetTrimmedSoapAction(methodName), StringComparison.OrdinalIgnoreCase)
|| methodName.Equals(HeadersHelper.GetTrimmedSoapAction(o.Name), StringComparison.OrdinalIgnoreCase));

if (operation == null)
{
operation = _service.Operations.FirstOrDefault(o =>
methodName.Equals(HeadersHelper.GetTrimmedClearedSoapAction(o.SoapAction), StringComparison.Ordinal)
|| methodName.Contains(HeadersHelper.GetTrimmedSoapAction(o.Name)));
methodName.Equals(HeadersHelper.GetTrimmedClearedSoapAction(o.SoapAction), StringComparison.OrdinalIgnoreCase)
|| methodName.IndexOf(HeadersHelper.GetTrimmedSoapAction(o.Name), StringComparison.OrdinalIgnoreCase) >= 0);
}

return operation != null;
Expand Down

0 comments on commit 4420b22

Please sign in to comment.