一些网络设备,比如防火墙或者审计系统,一般都有文件过滤的功能,可以对用户上网传输的文件进行过滤,比如可以限制用户通过ftp下载word文档,也就是文件类型为doc或者docx的文件。
那么文件过滤的功能是怎么实现呢?这里说一下大概的实现思路。
1、文件识别理论基础
首先,用户上网传输文件一般大都是经过传输层的tcp协议,了解tcp协议的同学应该知道,tcp报文一般不分片,而是使用分段,那么一个文件一般都很大,所以一个tcp分段报文是传输不完的,那么一个文件必然就会存在很多tcp分段报文中,所以在进行文件识别和过滤之前,需要先将文件的内容正确的还原出来,所以第一步涉及到tcp分段的重组,当然今天重点只是讲文件识别和过滤,tcp分段重组下次再单独讲。完成tcp分段重组,重组文件内容之后,我们需要先识别文件的类型,那么如何识别文件的类型呢?
这里我们还要注意一点,文件扩展名并不等同于文件类型,比如一个文件名为aaa.txt的文件,它的文件扩展名为txt,文件类型也为txt,但是如果我把文件名改完aaa.exe,那它的文件扩展名就变成了exe,但实际文件类型还是为txt,所以两者并不等同。我们在做文件过滤时,不是以文件扩展名来限制的,而是以文件类型。因为用户可以通过修改文件扩展名来逃避文件过滤检查。
那么我们到底怎么来识别一个文件的类型呢?其实就是通过文件的魔数,也叫file magic,也就是每个文件都带有自己的特征,这个特征我们直接用对应软件打开看不到,但是windows通过Notepad++(安装HEX-Editor插件)或者linux通过hexdump工具查看文件的二进制数就可以看到。比如我们通过Nodepad++查看一个PNG文件:
PNG的文件魔数就是文件头是以89 50 4E 47开头,以AE 42 60 82结尾,下面这张图列出了一些常见文件的魔数:
更多文件魔数见链接https://www.garykessler.net/library/file_sigs.html
知道了文件魔数,我们就可以根据文件魔数来进行文件识别了,然后将识别的文件类型与文件过滤策略的文件类型进行比较,就可以实现文件的过滤了。
当然如果文件过滤策略里面还涉及到了协议比如HTTP、FTP、SMB、SMTP等等,方向比如上传下载,那么还得识别用户具体是通过什么协议以及具体操作文件的动作,这有涉及到协议分析的内容了。
2、文件过滤编码实现方案
好了,有了上面的理论基础,现在我们来考虑一下具体编码的实现思路。
第一种方案,我们已经有了文件魔数表,可以自己根据tcp分段重组之后的文件内容来进行文件魔数匹配确定文件类型,然后再进行文件过滤策略匹配实现文件过滤功能。
第二种方案,我们还可以借助第三方开源库libmagic来实现,libmagic维护了一个文件魔数的数据库magic.mgc,并且提供了相应的API,我们只需要把要识别的文件内容或者文件名通过调用libmagic的API,它就可以告诉我们文件对应的文件类型描述,根据文件类型的描述与文件过滤策略进行匹配就可以实现文件过滤功能。这里只是说思路,ligmagic的具体使用后面咱们再细说。其实linux的file命令就用到了libmagic,我们用file命令查看一下PNG文件的文件类型描述:
另外,在suricata中实现filemagic规则的时候也用到了libmagic,不过感觉使用libmagic有一个麻烦的地方是,它的API返回的是文件类型描述信息,并且没有看到它有一个总的文件类型描述信息的列表,而且这个描述信息可能不同版本的libmagic库还不一样,导致与文件过滤策略匹配可能会存在不对应的情况,在suricata中也存在同样的问题(https://redmine.openinfosecfoundation.org/issues/437),另外个人感觉如果指定suricata中filemagic规则也不太好指定,例如
filemagic:"executable for MS Windows";
就是我如何知道我想过滤的文件类型的关键字是"executable for MS Windows",这个从哪里来? 这个问题还有待研究。