0

以下是我编写的程序的一小段摘录。该例程通过filenamelist(权限 0600),其中包含存储的行分隔文件名列表,这些文件名都存储在directory(如FileOne\nAnotherFile\nThird file\n)中,文件扩展名为EXTENSION. 文件名列表来自我程序的另一部分。

我有点担心filenamelist会被滥用来删除系统上的其他文件。有没有更好的锁定方法?最初我存储了要删除的文件的完整路径,但后来分离并硬编码了目录和文件扩展名以试图混淆它。

我可能是偏执狂,但恶意用户(!)可能会filenamelist以某种方式毒害其他文件路径。例如../../another-directory/donotdeleteme.sys或以某种我什至无法想到的方式逃避它。

那么下面的删除例程可以被滥用来删除外部文件directory吗?关于如何进一步锁定它以防止 cat·astrophe 的任何建议?

PS:该程序必须以root身份运行,因为它的操作是修改用户主目录之外的文件。

#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(比较结果fstatlstat事后以确保您没有遵循符号链接),并unlinkat在最后使用删除文件。

顺便说一句,你的电话access( filenamelist, F_OK | R_OK)是多余的和不必要的。在打开文件之前测试对文件的访问是没有意义的。你也可以只是fopen()文件。

于 2012-12-27T19:45:55.293 回答