0

以下は、私が書いたプログラムの小さな抜粋です。ルーチンは (パーミッション 0600) を通過しfilenamelistます。これには、ファイル拡張子. ファイル名のリストは、プログラムの別の部分から取得されます。directoryFileOne\nAnotherFile\nThird file\nEXTENSION

filenamelistシステム上の他のファイルを削除するために悪用される可能性があることを少し心配しています. それをロックするより良い方法はありますか?もともと、削除するファイルへのフルパスを保存していましたが、後でディレクトリとファイル拡張子を分離してハードコーディングし、難読化しようとしました。

私は偏執狂的かもしれませんが、悪意のあるユーザー (!) がfilenamelist何らかの方法で他のファイル パスで を汚染する可能性があります。たとえば、../../another-directory/donotdeleteme.sysまたは私が考えることさえできない何らかの方法でそれをエスケープします。

では、以下の削除ルーチンを悪用して外部のファイルを削除することはできますdirectoryか? 大災害を防ぐためにさらにロックダウンする方法について何か提案はありますか?

PS: プログラムは、操作の一部としてユーザーのホーム ディレクトリ外のファイルを変更するため、ルートとして実行する必要があります。

#define EXTENSION ".stuff"
char *directory = calloc( 28 );
directory = "/usr/local/share/stuffings/";
char *filenamelist = calloc( 24 );
filenamelist = "/etc/stuffing/files.lst";

void delete_files( char* filenamelist, char* directory ) {

  if ( access( filenamelist, F_OK | R_OK ) == 0 ) {
    FILE *filenamelist_fp = fopen( filenamelist, "r" );
    char filename[200];

    while( fgets( filename, 200, filenamelist_fp ) != NULL ) {
      char *pos;
      char *path = calloc( ( strlen( directory ) + strlen( filename ) + strlen( EXTENSION ) + 1 ), sizeof( char ) );

      if ( ( pos=strchr( filename, '\n' ) ) != NULL )
       *pos = '\0';

      strcat( path, directory );
      strcat( path, filename );
      strcat( path, EXTENSION );

      if ( access( path, F_OK | W_OK ) == 0 )
        unlink( path );
      free( path );
    }

    fclose( filenamelist_fp );
    unlink( filenamelist );
  }
} /* © */
4

1 に答える 1

4

ファイル名に文字が埋め込まれていないことを確認するチェックを追加する/と、指定されたディレクトリの外にあるファイルを削除しても完全に安全になります (POSIX プラットフォームを想定)。残念ながら、これにより、指定されたディレクトリの下のサブディレクトリ内のファイルも削除されなくなります。これで問題がなければ、そのソリューションを使用できます。

指定されたディレクトリのサブディレクトリ内のファイルの削除をサポートする必要がある場合、最初のステップは..パス名のコンポーネントとして表示されないようにすることですが、それだけでは十分ではありません: 指定されたディレクトリの下のディレクトリへのシンボリックリンクに注意する必要があります、それらに従うと、ツリー外のファイルが削除される可能性があるためです。この場合の最も堅牢な解決策は、おそらくパス名の各コンポーネントを自分で解析し、各ディレクトリ コンポーネントを手動で開き(結果と事後openatを比較して、シンボリック リンクをたどっていないことを確認します)、最後に使用することです。ファイルを削除します。fstatlstatunlinkat

ところで、あなたの への呼び出しaccess( filenamelist, F_OK | R_OK)は冗長で不要です。ファイルを開く前にファイルへのアクセスをテストしても意味がありません。ファイルだけでもかまいませんfopen()

于 2012-12-27T19:45:55.293 に答える