CVE-2025-24894
Description
SPID.AspNetCore.Authentication is an AspNetCore Remote Authenticator for SPID. Authentication using Spid and CIE is based on the SAML2 standard which provides two entities: Identity Provider (IDP): the system that authenticates users and provides identity information (SAML affirmation) to the Service Provider, in essence, is responsible for the management of the credentials and identity of users; Service Provider (SP): the system that provides a service to the user and relies on the Identity Provider to authenticate the user, receives SAML assertions from the IdP to grant access to resources. The validation logic of the signature is central as it ensures that you cannot create a SAML response with arbitrary assertions and then impersonate other users. There is no guarantee that the first signature refers to the root object, it follows that if an attacker injects an item signed as the first element, all other signatures will not be verified. The only requirement is to have an XML element legitimately signed by the IdP, a condition that is easily met using the IdP's public metadata. An attacker could create an arbitrary SAML response that would be accepted by SPs using vulnerable SDKs, allowing him to impersonate any Spid and/or CIE user. This vulnerability has been addressed in version 3.4.0 and all users are advised to upgrade. There are no known workarounds for this vulnerability.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
SPID.AspNetCore.AuthenticationNuGet | < 3.4.0 | 3.4.0 |
Patches
2a5cf16d3f823093efa2273f8Fix xml signature verification and update to .net 9.0 (#84)
5 files changed · +65 −62
.github/workflows/dotnet.yml+5 −2 modified@@ -22,13 +22,16 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: 8.x + dotnet-version: 9.x - name: Restore dependencies run: dotnet restore working-directory: src - name: Build run: dotnet build --no-restore working-directory: src + - name: Test + run: dotnet test --no-build **/*Tests.csproj + working-directory: src - name: Restore dependencies run: dotnet restore working-directory: samples/1_SimpleSPWebApp @@ -41,7 +44,7 @@ jobs: - name: Update apt repo run: sudo apt update - name: Install dependencies - run: sudo apt install -y libxml2-dev libxmlsec1-dev libxmlsec1-openssl xmlsec1 python3-pip && pip install cryptography==38.0.4 + run: sudo apt install -y libxml2-dev libxmlsec1-dev libxmlsec1-openssl xmlsec1 python3-pip - name: Pip list run: pip list - name: Install spid-sp-test
samples/1_SimpleSPWebApp/SPID.AspNetCore.WebApp/SPID.AspNetCore.WebApp.csproj+6 −6 modified@@ -1,19 +1,19 @@ <Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> - <TargetFramework>net8.0</TargetFramework> + <TargetFramework>net9.0</TargetFramework> <CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory> </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.5" /> - <PackageReference Include="SPID.AspNetCore.Authentication" Version="3.3.0" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.1" /> + <!--<PackageReference Include="SPID.AspNetCore.Authentication" Version="3.3.0" />--> </ItemGroup> - <!--<ItemGroup> + <ItemGroup> <Reference Include="SPID.AspNetCore.Authentication"> - <HintPath>..\..\..\src\SPID.AspNetCore.Authentication\bin\Debug\net8.0\SPID.AspNetCore.Authentication.dll</HintPath> + <HintPath>..\..\..\src\SPID.AspNetCore.Authentication\bin\Debug\net9.0\SPID.AspNetCore.Authentication.dll</HintPath> </Reference> - </ItemGroup>--> + </ItemGroup> </Project>
samples/1_SimpleSPWebApp/SPID.AspNetCore.WebApp/wwwroot/spid/spid-aspnetcore-test-windows.pfx+0 −0 addedsrc/SPID.AspNetCore.Authentication/Helpers/XmlHelpers.cs+23 −35 modified@@ -3,6 +3,7 @@ using SPID.AspNetCore.Authentication.Resources; using System; using System.Collections.Concurrent; +using System.Linq; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.Xml; @@ -37,7 +38,7 @@ internal static XmlElement SignXMLDoc(XmlDocument doc, try { - privateKey = certificate.PrivateKey; + privateKey = certificate.GetRSAPrivateKey(); } catch (Exception ex) { @@ -81,31 +82,22 @@ internal static bool VerifySignature(XmlDocument signedDocument, IdentityProvide try { - SignedXml signedXml = new SignedXml(signedDocument); + XmlNodeList signatureNodes = signedDocument.GetElementsByTagName("Signature", SignedXml.XmlDsigNamespaceUrl); + + if (signatureNodes.Count == 0) + { + return false; + } if (identityProvider is not null) { - bool validated = false; - foreach (var certificate in identityProvider.X509SigningCertificates) - { - var publicMetadataCert = new X509Certificate2(Convert.FromBase64String(certificate)); - XmlNodeList nodeList = (signedDocument.GetElementsByTagName("ds:Signature")?.Count > 1) ? - signedDocument.GetElementsByTagName("ds:Signature") : - (signedDocument.GetElementsByTagName("ns2:Signature")?.Count > 1) ? - signedDocument.GetElementsByTagName("ns2:Signature") : - signedDocument.GetElementsByTagName("Signature"); - signedXml.LoadXml((XmlElement)nodeList[0]); - validated |= signedXml.CheckSignature(publicMetadataCert, true); - } - return validated; + return identityProvider.X509SigningCertificates + .Any(certificate => VerifyAllSignatures(signedDocument, signatureNodes, new X509Certificate2(Convert.FromBase64String(certificate)))); } else { - XmlNodeList nodeList = (signedDocument.GetElementsByTagName("ds:Signature")?.Count > 0) ? - signedDocument.GetElementsByTagName("ds:Signature") : - signedDocument.GetElementsByTagName("Signature"); - signedXml.LoadXml((XmlElement)nodeList[0]); - return signedXml.CheckSignature(); + + return VerifyAllSignatures(signedDocument, signatureNodes); } } catch (Exception) @@ -114,27 +106,23 @@ internal static bool VerifySignature(XmlDocument signedDocument, IdentityProvide } } - private static readonly ConcurrentDictionary<Type, XmlSerializer> serializers = new ConcurrentDictionary<Type, XmlSerializer>(); - /// <summary> - /// Serializes to XML document. - /// </summary> - /// <param name="o">The o.</param> - /// <returns></returns> - public static XmlDocument SerializeToXmlDoc(this object o) + private static bool VerifyAllSignatures(XmlDocument signedDocument, XmlNodeList signatureNodes, X509Certificate2? publicMetadataCert = null) { - XmlDocument doc = new XmlDocument() { PreserveWhitespace = true }; - - using XmlWriter writer = doc.CreateNavigator().AppendChild(); - if (!serializers.ContainsKey(o.GetType())) + bool internalResult = true; + foreach (var signatureNode in signatureNodes) { - var serializer = new XmlSerializer(o.GetType()); - serializers.AddOrUpdate(o.GetType(), serializer, (key, value) => serializer); + SignedXml signedXml = new(signedDocument); + signedXml.LoadXml((XmlElement)signatureNode); + internalResult &= publicMetadataCert is null + ? signedXml.CheckSignature() + : signedXml.CheckSignature(publicMetadataCert, true); } - serializers[o.GetType()].Serialize(writer, o); - return doc; + return internalResult; } + private static readonly ConcurrentDictionary<Type, XmlSerializer> serializers = new(); + public static XmlElement SerializeInternalExtensionToXmlElement(object o, string namespacePrefix, string xmlNamespace) { XmlDocument doc = SerializeExtensionToXmlElementInternal(o, namespacePrefix, xmlNamespace);
src/SPID.AspNetCore.Authentication/SPID.AspNetCore.Authentication.csproj+31 −19 modified@@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFrameworks>net8.0;net7.0;net6.0</TargetFrameworks> + <TargetFrameworks>net9.0;net8.0;net7.0;net6.0</TargetFrameworks> <LangVersion>latest</LangVersion> <Description>AspNetCore Remote Authenticator for SPID</Description> <Authors>Daniele Giallonardo, Stefano Mostarda</Authors> @@ -12,37 +12,49 @@ <PackageProjectUrl>https://github.com/italia/spid-aspnetcore</PackageProjectUrl> <PackageIcon>spid-nuget.png</PackageIcon> <PackageLicenseExpression>MIT</PackageLicenseExpression> - <PackageVersion>3.3.0</PackageVersion> - <Version>3.3.0</Version> - <AssemblyVersion>3.3.0</AssemblyVersion> - <FileVersion>3.3.0</FileVersion> - <InformationalVersion>3.3.0</InformationalVersion> + <PackageVersion>3.4.0</PackageVersion> + <Version>3.4.0</Version> + <AssemblyVersion>3.4.0</AssemblyVersion> + <FileVersion>3.4.0</FileVersion> + <InformationalVersion>3.4.0</InformationalVersion> <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> <PackageReadmeFile>README.md</PackageReadmeFile> <RepositoryUrl>https://github.com/italia/spid-aspnetcore</RepositoryUrl> </PropertyGroup> - <ItemGroup> + <ItemGroup> + <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute"> + <_Parameter1>SPID.AspNetCore.Authentication.Tests</_Parameter1> + </AssemblyAttribute> + </ItemGroup> + + <ItemGroup> <FrameworkReference Include="Microsoft.AspNetCore.App" /> </ItemGroup> - <ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net6.0'"> - <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" /> - <PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.0" /> - </ItemGroup> + <ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' "> + <PackageReference Include="Microsoft.Extensions.Http" Version="9.0.1" /> + <PackageReference Include="System.Security.Cryptography.Xml" Version="9.0.1" /> + <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="9.0.1" /> + </ItemGroup> - <ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' "> - <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.4" /> - </ItemGroup> + <ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' "> + <PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" /> + <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.12" /> + <PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.2" /> + </ItemGroup> <ItemGroup Condition=" '$(TargetFramework)' == 'net7.0' "> - <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.12" /> - </ItemGroup> + <PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" /> + <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.12" /> + <PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.2" /> + </ItemGroup> <ItemGroup Condition=" '$(TargetFramework)' == 'net6.0' "> - <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.21" /> - </ItemGroup> + <PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" /> + <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.21" /> + <PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.2" /> + </ItemGroup> <ItemGroup> <None Include="..\..\README.md" Pack="true" PackagePath="\" />
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
3News mentions
0No linked articles in our index yet.