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

add MachineKeySessionSecurityTokenHandlerPlugin #172

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

2308652512
Copy link

The Ysoserial.net tool includes an exploit plugin for the SessionSecurityTokenHandler security issue. However, due to the fact that SessionSecurityTokenHandler employs DPAPI for encryption and decryption, it is often difficult to exploit in most cases.

Nevertheless, Microsoft's documentation on SessionSecurityTokenHandler mentions that for web scenarios requiring a similar security mechanism, one can use the MachineKeySessionSecurityTokenHandler. This class inherits from SessionSecurityTokenHandler and shares similar characteristics. The key difference is that MachineKeySessionSecurityTokenHandler utilizes MachineKey configuration information for encryption and decryption operations. Therefore, as long as the MachineKey configuration information can be obtained (for instance, through a web.config leak), it may be possible to exploit it, making it more susceptible to exploitation compared to SessionSecurityTokenHandler.

https://learn.microsoft.com/en-us/dotnet/api/system.identitymodel.services.tokens.machinekeysessionsecuritytokenhandler?view=netframework-4.8.1
图片

You can use code like the one below for testing:

            string payload = @"<SecurityContextToken xmlns='http://schemas.xmlsoap.org/ws/2005/02/sc'>
            	<Identifier xmlns='http://schemas.xmlsoap.org/ws/2005/02/sc'>
            		urn:unique-id:securitycontext:1
            	</Identifier>
            	<Cookie xmlns='http://schemas.microsoft.com/ws/2006/05/security'>payload</Cookie>
            </SecurityContextToken>";
            MachineKeySessionSecurityTokenHandler testrce = new MachineKeySessionSecurityTokenHandler();
            XmlReader tokenXML = XmlReader.Create(new StringReader(payload));
            testrce.ReadToken(tokenXML);

图片

After verifying the feasibility of this issue, I proceeded to generate the payload required for MachineKeySessionSecurityTokenHandler.ReadToken(). The format of this payload is similar to that generated by SessionSecurityTokenHandlerPlugin, with the only difference being in the node section of the XML data. MachineKeySessionSecurityTokenHandler relies on MachineKey configuration information for the encryption and decryption of the Cookie, which typically necessitates a complete web environment. However, I discovered a dependency on https://github.com/dmarlow/AspNetTicketBridge (which can be imported via NuGet) that allows for the generation of Cookies using the MachineKeyDataProtector.Protect() method. This requires the provision of information such as validationKey, decryptionKey, decryptionAlg, validationAlg, and purposes. Consequently, I developed this plugin to generate the payload required for MachineKeySessionSecurityTokenHandler.ReadToken().

图片

I have verified this plugin locally, and it functions correctly. However, it appears that my implementation has made significant changes to packages.config and ysoserial.csproj. There may be better implementation approaches available...

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 1 out of 3 changed files in this pull request and generated 2 suggestions.

Files not reviewed (2)
  • ysoserial/packages.config: Language not supported
  • ysoserial/ysoserial.csproj: Language not supported
Comments skipped due to low confidence (2)

ysoserial/Plugins/MachineKeySessionSecurityTokenHandlerPlugin.cs:24

  • The abbreviation 'PoC' should be expanded to 'Proof of Concept'.
* This PoC produces an error and may crash the application

ysoserial/Plugins/MachineKeySessionSecurityTokenHandlerPlugin.cs:93

  • [nitpick] The payload string has inconsistent indentation and should be corrected for better readability.
string payload = @"<SecurityContextToken xmlns='http://schemas.xmlsoap.org/ws/2005/02/sc'>

Tip: Leave feedback on Copilot's review comments with the 👎 and 👍 buttons to help improve review quality. Learn more


byte[] serializedData = (byte[])new TextFormattingRunPropertiesGenerator().GenerateWithNoTest("BinaryFormatter", inputArgs);
DeflateCookieTransform myDeflateCookieTransform = new DeflateCookieTransform();
MachineKeyDataProtector Protector = new MachineKeyDataProtector(validationKey, decryptionKey, decryptionAlg, validationAlg, purposes);
Copy link
Preview

Copilot AI Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variables validationKey, decryptionKey, decryptionAlg, and validationAlg should be validated to ensure they are not empty or invalid before being used.

Suggested change
MachineKeyDataProtector Protector = new MachineKeyDataProtector(validationKey, decryptionKey, decryptionAlg, validationAlg, purposes);
if (string.IsNullOrEmpty(validationKey) || string.IsNullOrEmpty(decryptionKey) || string.IsNullOrEmpty(decryptionAlg) || string.IsNullOrEmpty(validationAlg))
{
throw new ArgumentException("ValidationKey, DecryptionKey, DecryptionAlg, and ValidationAlg must not be empty.");
}
MachineKeyDataProtector Protector = new MachineKeyDataProtector(validationKey, decryptionKey, decryptionAlg, validationAlg, purposes);

Copilot is powered by AI, so mistakes are possible. Review output carefully before use.

Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
/**
* Author: L@2uR1te (@2308652512)
*
* Comments:
Copy link
Preview

Copilot AI Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The word 'Comments:' should be 'Comment:'.

Suggested change
* Comments:
* Comment:

Copilot is powered by AI, so mistakes are possible. Review output carefully before use.

Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
@irsdl
Copy link
Collaborator

irsdl commented Dec 2, 2024

I am not sure about some of the libraries inserted in the packages especially as it seems they are from .NET (core). I will have to review it properly thought by downloading and running it to see what we are trying to achieve here and whether we can simplify it.

@2308652512
Copy link
Author

I am not sure about some of the libraries inserted in the packages especially as it seems they are from .NET (core). I will have to review it properly thought by downloading and running it to see what we are trying to achieve here and whether we can simplify it.

Yes, I have also noticed this issue. Let me elaborate on this plugin to assist you in simplifying its implementation. As you can see, the most critical lines of code are actually these two:

MachineKeyDataProtector Protector = new MachineKeyDataProtector(validationKey, decryptionKey, decryptionAlg, validationAlg, purposes);
byte[] encryptedEncoded = Protector.Protect(deflateEncoded);

These two lines of code are used for encrypting serialized data, and I implemented them to achieve the functionality of the following method:
MachineKeyTransform.Encode()

图片

Tracing the execution flow of the aforementioned method will ultimately lead to:
System.Web.Security.Cryptography.NetFXCryptoService.Protect()
图片

The core logic of the encryption resides within this method. I have previously attempted to implement this method independently, and there are several key pieces of logic involved, such as:
SymmetricAlgorithm encryptionAlgorithm = this._cryptoAlgorithmFactory.GetEncryptionAlgorithm()

In fact, the method that is called is:
MachineKeyCryptoAlgorithmFactory.GetEncryptionAlgorithm()

This method executes the corresponding delegate based on the provided encryptionAlgorithm information (for example, AES). In the case of AES, it ultimately invokes the AesCryptoServiceProvider() method.

In summary, if we isolate NetFXCryptoService.Protect(), it can still be implemented quite effectively. However, after completing my implementation, I discovered that decryption resulted in errors, likely due to missing certain information (I suspect it might be the "purpose"), or there could be other critical pieces of information that I did not configure throughout the process. Consequently, I found the AspNetTicketBridge dependency, which contains a properly implemented Protect() method that can be directly invoked to achieve the desired functionality.

If you are interested in this process, you can run the following code in a web environment:

DeflateCookieTransform myDeflateCookieTransform = new DeflateCookieTransform();
            MachineKeyTransform Protector = new MachineKeyTransform();

byte[] DeflateEncode =  myDeflateCookieTransform.Encode(serializedData);
byte[] encryptedEncode = Protector.Encode(DeflateEncode);

Then set a breakpoint in the Protect() function, which should allow you to see the complete call stack and flow. Similarly, setting a breakpoint in the Unprotect() function will enable you to observe the decryption process.

@irsdl
Copy link
Collaborator

irsdl commented Dec 12, 2024

Hey @2308652512, I am very sorry for the delay on this. I will have a look at this in the coming week.

@2308652512
Copy link
Author

Hey @2308652512, I am very sorry for the delay on this. I will have a look at this in the coming week.

No problem at all! Please feel free to focus on your tasks. I hope this imperfect little plugin won't cause you any inconvenience. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants