Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何断言扩展名已更改为csv的exe文件是否为csv文件c#_C#_File_Validation_File Upload_Csvreader - Fatal编程技术网

如何断言扩展名已更改为csv的exe文件是否为csv文件c#

如何断言扩展名已更改为csv的exe文件是否为csv文件c#,c#,file,validation,file-upload,csvreader,C#,File,Validation,File Upload,Csvreader,因此,我需要创建一个文件验证程序来检查文件类型是否正确。最初,我们只是检查请求的内容类型,但一如既往,我们的测试人员通过简单地将exe文件的文件扩展名更改为.csv来绕过限制,这可能会愚弄我们的直接检查 这就是我目前在验证器中所做的 private bool IsCorrectFileType(IFormFile file) { using var reader = new StreamReader(file.OpenReadStream());

因此,我需要创建一个文件验证程序来检查文件类型是否正确。最初,我们只是检查请求的内容类型,但一如既往,我们的测试人员通过简单地将exe文件的文件扩展名更改为.csv来绕过限制,这可能会愚弄我们的直接检查

这就是我目前在验证器中所做的

private bool IsCorrectFileType(IFormFile file)
        {
            using var reader = new StreamReader(file.OpenReadStream());
            using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);

            try
            {
                csv.Read();
                csv.ReadHeader();
                List<string> headers = csv.Context.HeaderRecord.ToList();
            }
            catch (Exception _)
            {
                return false;
            }

            return true;
        }
private bool IsCorrectFileType(ifformfile)
{
使用var reader=newstreamreader(file.OpenReadStream());
使用var csv=new CsvReader(reader,CultureInfo.InvariantCulture);
尝试
{
csv.Read();
csv.ReadHeader();
列表标题=csv.Context.HeaderRecord.ToList();
}
捕获(异常)
{
返回false;
}
返回true;
}
我打算做的是,如果CSV阅读器在文件中找不到标题,那么我希望它会爆炸并返回false,但实际情况是,在所有非CSV文件类型的情况下,文件的全部内容都作为单个标题被读取。使它认为它确实是一个有效的csv文件,并返回true

在我的一生中,我无法找到一种方法来捕获CSV文件是否确实有效,因为在大多数情况下,CSV读取器可以读取所有流中的字节数据,在这种情况下,头记录的上下文看起来像是有效的CSV

令人恼火的是,我们永远不会上传一个只有一个头的文件,只是对头进行一次标准计数,看看它是否只有一个头来捕捉这个问题,这让人觉得很愚蠢

任何帮助都将不胜感激,因为我在这个问题上有点不知所措。 提前感谢,,
克里斯。

我会这样做的

  • 检查文件中是否有0x00字节。这些在二进制文件中很常见,但在文本文件中不允许,除非可能在最后作为空终止符。因此,这可以是一个相对快速的健全性检查

  • 将文件分成几行(例如,行分隔符拆分为
    \n
    \r
    ),然后检查每一行,确保其逗号数相同。请注意,某些列中可能包含逗号,您不能对这些列进行计数;包含嵌入逗号的列将用引号括起来以转义。因此,您需要编写一些代码来解析行以进行计数

  • 如果上述两个步骤都通过,则文件仍然可能无效,例如,如果文件包含无效的UTF序列。看看你是否想检查一下

  • 如果您对文件中应该包含的内容有所了解,请使用正则表达式验证每一行和每一列,以查看文件整体是否有效


  • 您可以只执行上面的步骤1、步骤1和步骤2或全部步骤,取决于这一点的重要性。

    在试验了csv解析器头上下文中非csv类型的字符串的外观之后,我能够断言它是否只是jibberish ie exe内容或jpg,因此它将在长字符串中包含非ascii字符

    下面的代码显示了我所做的检查是否是这种情况。如果是的话,它会拒绝它,如果不是的话,它会允许它被摄入

    /// <summary>
    /// Minimises chances of incorrect file types being passed to the service that have been
    /// maliciously changed to a csv format when the original is for example .exe .jpg and so on.
    /// </summary>
    /// <remarks>
    /// The function below checks if a header row exists in the incoming file. In all cases where the CsvReader is
    /// able to read the file it will either create a list of headers if the file is valid or subsequently if the file
    /// uploaded has been modifed to look like a csv file the Context.HeaderRecord will read in all of the content to a
    /// single header. If there is only one header in the file to make sure the file is valid I an running a string function
    /// on the header to make sure it definitely includes ascii charachters if not in the case of any file thats malliciously
    /// been changed it will load all of the bytes into the headerRecord which means it will fail the chack and fail validation.
    /// This will in turn minimise the chances of a malicious file thats had its name changed name changed from hitting the file processor.
    /// </remarks>
    private bool IsCsvFileFormat(IFormFile file)
    {
          using var reader = new StreamReader(file.OpenReadStream());
          using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
    
          try
          {
               csv.Read();
               csv.ReadHeader();
               var headerRecordList = csv.Context.HeaderRecord.ToList();
    
               if (headerRecordList.Count() == 1)
                   return !HasNonASCIIChars(headerRecordList.ElementAt(0));
           }
           catch (Exception _)
           {
                return false;
           }
    
           return true;
    }
    
    private bool HasNonASCIIChars(string str) =>
         (System.Text.Encoding.UTF8.GetByteCount(str) != str.Length);
    
    //
    ///最大限度地减少将错误文件类型传递给已删除的服务的可能性
    ///当原始文件为.exe.jpg等时,恶意更改为csv格式。
    /// 
    /// 
    ///下面的函数检查传入文件中是否存在标题行。在所有情况下,如果CsvReader
    ///如果文件有效,它将创建一个标题列表;如果文件无效,它将创建一个标题列表;如果文件无效,它将创建一个标题列表
    ///上传的内容已修改为csv文件,Context.HeaderRecord将把所有内容读入
    ///单头。如果文件中只有一个标头以确保文件有效,则可以运行字符串函数
    ///在头文件上,确保它肯定包含ascii字符(如果不是在任何文件中)
    ///如果已更改,它将把所有字节加载到headerRecord中,这意味着它将无法通过检查和验证。
    ///这将反过来最大限度地减少恶意文件因攻击文件处理器而更改名称的可能性。
    /// 
    私有bool IsCsvFileFormat(格式文件)
    {
    使用var reader=newstreamreader(file.OpenReadStream());
    使用var csv=new CsvReader(reader,CultureInfo.InvariantCulture);
    尝试
    {
    csv.Read();
    csv.ReadHeader();
    var headerRecordList=csv.Context.HeaderRecord.ToList();
    if(headerRecordList.Count()==1)
    return!hasnonasciachars(headerRecordList.ElementAt(0));
    }
    捕获(异常)
    {
    返回false;
    }
    返回true;
    }
    私有bool hasnonasciachars(字符串str)=>
    (System.Text.Encoding.UTF8.GetByteCount(str)!=str.Length);
    
    这有点相反,但它有帮助吗?从某种程度上说,这是有帮助的,但我认为问题更大,因为您需要针对我们不支持的每种文件格式进行保护。在这种情况下,如果我们能够以某种方式确定它是否是csv文件,则效果会更好。但据我所知,它只是一个逗号分隔的标准文本文件,因此这可能非常困难。我这么说的原因是,他们可以对jpeg、png、xls等等做同样的处理。我不确定你的CsvReader类来自哪里,我猜它来自于你无法控制的框架。与其使用它,不如直接读取文件的前x字节,看看是否可以用一系列分隔的字符串来解析它?这应该告诉你,你确实有一个CSV文件。我刚刚浏览了differe的内容