やりたいこと
作成したアプリが、引用符で囲まれていないプログラムパス(Unquoted Program Path) の脆弱性に対して問題ないことを確認したい。
VisualStudio2019使用、C#/C++で書いたアプリに対してその脆弱性をどう確認すればよいか?調べてもパッとでてこなかったので、調べたことをメモ。
(恐らくこれで理解あってると思うが、誤りあれば指摘いただけるとありがたいです)
引用符で囲まれていないプログラムパス(Unquoted Program Path) の脆弱性 とは?
CreateProcess
シリーズの関数を使ってプロセスを起動しようとしたときに起きる脆弱性。
CreateProcess
シリーズの関数というのは、下記の関数。→こちら
CreateProcessA
関数のページに、その脆弱性について、下記のように書いている。→こちら
これは例えば、
c:\program files\sub dir\programname.exe
というexeをCreateProcessA関数で起動しようとしたときに、
関数の1個目の引数「lpApplicationName」をNULLにして、「lpCommandLine」に
c:\program files\sub dir\programname.exe
という文字列を入れて起動することができるが、
if( !CreateProcessA( NULL, // 1個目の引数lpApplicationName
"c:\program files\sub dir\programname.exe",// 2個目の引数lpCommandLine
NULL,NULL,FALSE,0,NULL,NULL,&si,&pi ) )
その場合、CreateProcessA関数は
- c:\program.exe
- c:\program files\sub.exe
- c:\program files\sub dir\program.exe
- c:\program files\sub dir\programname.exe
という順番で解釈をして、(存在しなかったら次、また存在しなかったら次、という感じで)exeを実行しようとする、というのがCreateProcess
シリーズの関数の仕様なので、
もし、通常は存在しないc:\program.exe
というexeが、悪意あるプログラムとしてそこに置かれていたら、programname.exe
を呼び出したかった実装者の意図とは関係なく、c:\program.exe
が呼ばれてしまう。
という脆弱性。
大丈夫なパターンメモ
c:\program files\sub dir\programname.exe
を呼ぶときに、同じCreateProcessA
関数を使う場合でも、1個目の引数「lpApplicationName」をNULLにせずに、そこにプログラムのフルパスを入れて呼び出すこともできる。
if( !CreateProcessA("c:\program files\sub dir\programname.exe", // 1個目の引数lpApplicationName
"/a /b", // 2個目の引数lpCommandLine(exeへの引数になる)
NULL,NULL,FALSE,0,NULL,NULL,&si,&pi ) )
その場合は、上のような問題は発生しない。
(Program.exeをC直下などに置いて試した結果、発生しなかった。)
確認のしかた
確認① CreateProcess()シリーズの関数を使っているかどうか調べる
CreateProcess()シリーズの関数の仕様で、上のページに書いてあるようなUnquoted Program Path脆弱性が発生するので、
CreateProcess()シリーズ関数を使用していなければ問題なしとする。
- CreateProcessマクロ
- CreateProcessA関数
- CreateProcessAsUserA関数
- CreateProcessAsUserW関数
- CreateProcessW関数
確認② CreateProcess()を使っている場合の対処を実施
lpApplicationNameをNULLにして、lpCommandLineにパスを指定してプロセスを起動するようなコードになっていないか確認。
lpApplicationNameをNULLにしてなければOK。
lpApplicationNameをNULLにして、lpCommandLineでパスを指定していたらNG。
その場合は、lpCommandLineのパスの指定の文字列を、「""」でかこってやる。
→こちらのページを参照。
確認③ VisualStudio2019の静的解析で、その脆弱性にあたる指摘が出ていないことを確認する
静的解析の指摘「C6277」がその脆弱性に当たる指摘のため、静的解析を行い、C6277が出ないことを確認。
C6277とは
https://docs.microsoft.com/ja-jp/cpp/code-quality/c6277?view=vs-2019
※今回は、下記の設定で静的解析を実施。(C#は関係ないと思うが、一応)
PJ種類 | 静的解析ルール |
---|---|
C++ | Microsoftネイティブ推奨規則 |
C++/CLI | Microsoft混合(C++/CLR)推奨規則 |
C# | Microsoftマネージド推奨規則 |
参照
C6277(Unquoted Program Path への静的解析指摘)
https://docs.microsoft.com/ja-jp/cpp/code-quality/c6277?view=msvc-160
NULL application name with an unquoted path in call to CreateProcess
https://help.semmle.com/wiki/display/CCPPOBJ/NULL+application+name+with+an+unquoted+path+in+call+to+CreateProcess
CWE-428: Unquoted Search Path or Element
https://cwe.mitre.org/data/definitions/428.html
易し目の解説
http://securitychecklist.net/security/cyber-attack/Unquoted-Program-Path.html