web-dev-qa-db-ja.com

strlen、strcpy、strcatによるバッファオーバーフロー

安全なコードレビューは初めてです。 strlenはnull文字が見つかるまで長さを計算することを知っています。これは、より大きなコードの一部です。

char* executeMount(char* password, char* path, int unmountOrMount)
 {
 char* catString = new char[(strlen("echo|set /p password=") + strlen(password) + strlen(" | runas /user:administrator \"mountvol ") + strlen(path) + 1)];
 strcpy(catString, "echo|set /p password=");
 strcat(catString, password);
 strcat(catString, " | runas /user:administrator \"mountvol ");
 strcat(catString, path);
 //Equivalent command: system("echo|set /p password=" + adminPassword + " | runas /user:administrator mountvol" + path);
 return catString;
 }

CatStringを返すと、バッファオーバーフローが発生しますか?

Strlenは、nullターミネータに到達するまですべての文字列を計算します。したがって、catStringはすべての文字列の合計+ 1(nullターミネーターの場合)です。 strcpyはecho | set/p password = "+ nullターミネータをコピーします。strcatを実行すると、nullターミネータが削除され、" password "が連結されますが、後続のstrcatはnullターミネータを削除せず、バッファオーバーフローを引き起こしませんか?私の考えは正しいですか?このコードは正しいですか?他の脅威に対して脆弱ですか?

1
Rochelle

C++を使用している(使用していない場合はnew charを使用できなかったため)。ここでは実際にstd::stringを使用する必要があります(戻り値を含む)。アップストリームコードで必要な場合は、.c_strを逆参照してconst char *ポインターを取得できます。

ただし、関数から単にstd::string.c_strを返す必要はありません。 std::stringはスコープ外になり、未定義の動作が発生します。

これにより、この文字カウント関連の要素を処理する必要がなくなります。

2
Joe

不正なstrlenが原因で、catStringを返すとバッファオーバーフローが発生しますか?

クイックスキムから、ストリングの長さはOKに見えます。唯一のリスクは、パラメーターがnullで終了していない場合です。この場合、コマンドラインにダンプされるパスワード/パスに続くものが何でも発生します。

このコードに他の脅威はありますか?

このコードには多くの問題がありますが、catString割り当て長によるバッファオーバーフローはそれらの1つではありません。ユーザーが有効なパスに続けて「; rmdir C:\ Windows/s」と入力すると、どうなりますか?または他のコマンド。

@Joeが指摘するように、これはおそらく文字配列(1つを返すことを含む)ではなくstd :: stringを使用する必要があります。文字配列を使用する場合は、ポインターをconstとしてマークし、関数内でそれらを変更しないようにし、コンパイラーの最適化を許可する必要があります。コマンドインジェクションを停止するには(およびスペースと特殊文字を含むパスワードを許可するには)、パスワードとパスを適切に引用符で囲んでエスケープする必要があります。また、アプリケーションがmountvolを直接呼び出すことを許可し、管理者アカウントのパスワードを渡す必要がないように、アクセス許可を使用する必要があるとも思います。

1
Hector