ネストされた参照悪夢:リモートホストからEメールを送信する

ネストされた参照悪夢:リモートホストからEメールを送信する

SSH経由でアクセスするリモートホストから添付ファイルを含む電子メールを(私の端末で)送信する必要があります。リモートでタスクを実行するには、次のものを使用していることが既にわかっています。

ssh -p myport [email protected] "doSomething"

また、添付ファイルを含む電子メールを送信するために必要なものも知っています。

echo "Mail content" | mailx -s "Mail title" -a attachment.txt -S from="myname@gmail" destname@gmail

したがって、この2つの簡単な組み合わせは、doSomething最初の行を2番目の行の内容全体に置き換えることです。もちろん、これはひどいネストされた二重引用符のために機能しません。どうすればこれを行いますか(可能であればきれいに)?助けてくれてありがとう。

ベストアンサー1

単純な場合は、一重引用符を使用してローカルシェルのコマンドを保護するか、二重引用符を\"

echo "Mail content" | ssh -p myport [email protected] 'mailx -s "Mail title" -a attachment.txt -S from="myname@gmail" destname@gmail'
# or
echo "Mail content" | ssh -p myport [email protected] "mailx -s \"Mail title\" -a attachment.txt -S from=\"myname@gmail\" destname@gmail"

もっと複雑な場合、最も簡単な方法は区切り文字を使用して変数を設定することです。

read -r -d '' mailcmd <<'CMD'
echo "quotin'" 'this would be a "nightmare" indeed.' | mailx -s "Anthony's Email" -a attachment.txt -S from="myname@gmail" destname@gmail
CMD
ssh -p myport [email protected] "$mailcmd"

少なくともbashでは、シェルに変数を参照するように要求できます。これは、より迷惑な操作(チェーン2呼び出しなど)を実行する必要があるssh場合に役立ちます。

$ printf '%q\n' "$mailcmd"
echo\ \"quotin\'\"\ \'this\ would\ be\ a\ \"nightmare\"\ indeed.\'\ \|\ mailx\ -s\ \"Anthony\'s\ Email\"\ -a\ attachment.txt\ -S\ from=\"myname@gmail\"\ destname@gmail

ご覧のとおり、自動引用は最小バックスラッシュに最適化されていません。

ローカル変数を含める

コマンドに変数を使用する必要がある場合、sshは有効な特殊ケースを提供します。 sshは、SendEnvオプション(クライアント)とオプション(サーバー)でAcceptEnv指定された環境変数を渡すことができます。環境変数を渡すと、リモート側シェルはその変数を正常に拡張します(ここにドキュメントに「$ varname」が含まれている場合、リモート側シェルもその変数を拡張します)。

それ以外の最も簡単な方法は、区切られた文書から引用符を省略することです。これは拡張を引き起こします($望ましくない場所でエスケープする必要があることを意味しますが)。

$ var1="hello world"
$ read -r -d '' mailcmd <<CMD
echo "$var1" "\$var1"
CMD
$ echo "$mailcmd"
echo "hello world" "$var1"

拡張を閉じるこのような閉じるタグを引用するCMD代わりに。をどのように使用したかに注意してください。'CMD'したがって、これを参照しないことで拡張が得られます。期待どおりに"$var1"拡張されますが、hello world前にバックスラッシュを置くと拡張を避けることができます。バックティックや拡張を含むすべての拡張が有効になります$(…)。また、var1は単に置き換えられます。シェルはここでエスケープを実行しないため、var1に二重引用符などが含まれている場合、この方法は機能しません。 %q を使用できる場所は次のとおりです。

$ var1='hello "world"'
$ read -r -d '' mailcmd <<CMD
echo $(printf '%q' "$var1") "\$var1"
CMD
$ echo "$mailcmd"
echo hello\ \"world\" "$var1"

警告の言葉:渡されたデータが攻撃者によって破損する可能性がある場合は、次のことを行う必要があります。非常に注意深い。エスケープ時のわずかなエラー(または関連するすべてのシェル間でエスケープする必要がある項目の別の定義)は、任意のコード実行不良になる可能性があります。必要なエスケープがすべて存在するか正しいかを確認するよりも、より強力なデータ配信システムを構築する方が簡単です。たくさんセキュリティの脆弱性により引き続きエラーが発生します。

おすすめ記事