SSM ドキュメントでのコマンド実行制限を考えてみた
こんにちは、森田です。
SSM ドキュメントでのコマンド実行制限を考える機会があったため、そのまとめ記事となります。
前提
ユーザーが SSM ドキュメントを利用して、コマンドを実行するケースを想定しています。
また、ドキュメントタイプは、セッションドキュメントとします。
コマンド単体での制限
SSM ドキュメントでは、 allowedPattern を使って正規表現でコマンド単位での実行制限をかけることができます。
例えば、以下のドキュメントでは、lsとtail のみの実行が可能となります。
schemaVersion: '1.0'
description: Run only ls and tail
sessionType: InteractiveCommands
parameters:
command:
type: String
description: Allowed command
allowedPattern: ^(ls|tail)$
properties:
linux:
commands: "{{ command }}"
runAsElevated: true
以下のようなコマンドは実行できるようになります。
aws ssm start-session --target インスタンスID \
--document-name ドキュメント名 \
--parameters command="ls"
一方で、このドキュメントでは、コマンド単体での実行のみ可能なためオプションの指定ができません。
aws ssm start-session --target インスタンスID \
--document-name ドキュメント名 \
--parameters command="ls -l"
コマンド単体、オプションでの制限
今度は、オプションについてもドキュメント内に記載して制限を行います。
parametersにoptionを追加して、許可するオプションを記述します。
schemaVersion: '1.0'
description: Run ls and tail with options
sessionType: InteractiveCommands
parameters:
command:
type: String
description: Allowed command
allowedPattern: ^(ls|tail)$
option:
type: String
description: Allowed option
allowedPattern: ^(-l|-a)$
properties:
linux:
commands: "{{ command }} {{option}}"
runAsElevated: true
aws ssm start-session --target インスタンスID \
--document-name ドキュメント名 \
--parameters command="ls",option="-l"
aws ssm start-session --target インスタンスID \
--document-name ドキュメント名 \
--parameters command="ls",option="-s"
このドキュメントでは、許可されたオプションは実行できますが、オプションをすべて定義することは現実的ではないですね。
また、 ls -l | grep zip のようなパイプ処理をしたい場合にもこの記述では対応できません。
コマンド単体、パイプでの制限
今度は、コマンド単体で制限を行いながら、パイプ処理が行えるようなケースを考えてみます。
また、パイプ処理についても実行できるコマンドに制限をかけたいです。
このケースを実現させるには、parametersのallowedPatternだけでは難しく、properties内のcommands側で制御すればできます。
ただし、commands側で制御するため、 SSM ドキュメント自体は実行できる状態となります。
例えば、以下の記述であれば、aliasを使用して、mysqlコマンドを事前に無効化することができます。
schemaVersion: '1.0'
description: Restrictions on commands and pipes (mysql prohibited)
sessionType: InteractiveCommands
parameters:
command:
type: String
description: Allowed command
allowedPattern: ^(ls|tail)$
option:
type: String
description: option
properties:
linux:
commands: |
alias mysql="echo 'mysql command is disabled'"
{{command}} {{option}}
runAsElevated: true
このドキュメントを使って以下のコマンドを実行してみます。
aws ssm start-session --target インスタンスID \
--document-name ドキュメント名 \
--parameters command="ls",option="-l| mysql --version"
すると、以下のように実行自体はできるものの、mysqlが無効化されていることが表示されます。
mysql command is disabled --version
Exiting session with sessionId: xxx-wezw6qkmkctzhjbpl2lkldzi6m.
ただし、このケースでも直接 /usr/bin/mysql を実行されるケースには対応できません。
mysql自体のコマンド入力を禁止するために、以下のようにsedを使ってmysqlの文字をリプレイスすることで上記のようなケースに無理やり対応させることはできます。
schemaVersion: '1.0'
description: Restrictions on commands and pipes (mysql prohibited)
sessionType: InteractiveCommands
parameters:
command:
type: String
description: Allowed command
allowedPattern: ^(ls|tail)$
option:
type: String
description: Allowed option
properties:
linux:
commands: |
cleaned_command=$(echo "{{command}} {{option}}" | sed 's/mysql//g')
echo "実行されるコマンド: $cleaned_command"
eval "$cleaned_command"
runAsElevated: true
実行されるコマンド: ls -l| /usr/bin/ --version
sh: line 3: /usr/bin/: Is a directory
ただ、このような方法では、コマンドの作り込みが必要となるため、コマンド制限が厳しい場合は、上記のようなドキュメントもマッチしない可能性があります。
まとめ
SSM ドキュメント内のパラメータを使ったコマンド実行制限については、正規表現で行うため、表現できる制限には限界があります。
また、properties内のcommands側である程度はどうにかできますが、厳しい制限をかけたい場合はマッチしないかと思います。