Blocking ftp file transfer based on md5 hash doesn't work

I am trying to detect and block ftp file transfer based on md5 hash list but suricata fails to detect file based on hash-

drop ftp-data any any → any any (msg:“Block file transfer over FTP by md5hash”; flow:established; filestore; filemd5:“blacklist_md5”; ftpdata_command:retr; classtype: suspicious-filename-detect; sid:3200002; rev:1;)

However, suricata is able to detect and block file transfer based on filename-

drop ftp-data any any → any any (msg:“Block file transfer over FTP by filename”; flow:established; filestore; filename:“test.zip”; ftpdata_command:retr; sid:3200003; rev:1; )

Noticed same behavior with suricata versions: 6.0.10 and 7.0.6 on debian 11 and ubuntu 20.04 respectively.

Can anyone help?

Does the content of blacklist_md5 match the md5 of test.zip?

Yes, it does. Same blacklist works with http based signature.

blacklist_md5:
0a36fd59837f65ecec597b7952770598

Here are eve logs for reference:

{"timestamp":"2024-07-09T15:56:27.263063+0530","flow_id":687377577139635,"event_type":"ftp","src_ip":"x.x.x.x","src_port":52082,"dest_ip":"x.x.x.x","dest_port":21,"proto":"TCP","tx_id":10,"community_id":"1:ib0VINODXEW6L/NO9MQ++xPIQFg=","ftp":{"command":"SIZE","command_data":"test.zip","command_truncated":false,"completion_code":["213"],"reply":["358"],"reply_received":"yes","reply_truncated":false}}
{"timestamp":"2024-07-09T15:56:27.349066+0530","flow_id":687377577139635,"event_type":"ftp","src_ip":"x.x.x.x","src_port":52082,"dest_ip":"x.x.x.x","dest_port":21,"proto":"TCP","tx_id":11,"community_id":"1:ib0VINODXEW6L/NO9MQ++xPIQFg=","ftp":{"command":"MDTM","command_data":"test.zip","command_truncated":false,"completion_code":["213"],"reply":["20210302122213"],"reply_received":"yes","reply_truncated":false}}
{"timestamp":"2024-07-09T15:56:27.437163+0530","flow_id":687377577139635,"event_type":"ftp","src_ip":"x.x.x.x","src_port":52082,"dest_ip":"x.x.x.x","dest_port":21,"proto":"TCP","tx_id":12,"community_id":"1:ib0VINODXEW6L/NO9MQ++xPIQFg=","ftp":{"command":"PASV","completion_code":["227"],"reply":["Entering Passive Mode (0,0,0,0,39,29)."],"dynamic_port":10013,"reply_received":"yes","reply_truncated":false}}
{"timestamp":"2024-07-09T15:56:27.687829+0530","flow_id":687377577139635,"event_type":"ftp","src_ip":"x.x.x.x","src_port":52082,"dest_ip":"x.x.x.x","dest_port":21,"proto":"TCP","tx_id":13,"community_id":"1:ib0VINODXEW6L/NO9MQ++xPIQFg=","ftp":{"command":"RETR","command_data":"test.zip","command_truncated":false,"completion_code":["150","226"],"reply":["Opening BINARY mode data connection for test.zip (358 bytes).","Transfer complete."],"reply_received":"yes","reply_truncated":false}}
{"timestamp":"2024-07-09T15:56:27.687829+0530","flow_id":2226277244448348,"parent_id":687377577139635,"event_type":"ftp_data","src_ip":"x.x.x.x","src_port":34887,"dest_ip":"x.x.x.x","dest_port":10013,"proto":"TCP","tx_id":0,"community_id":"1:5H2B8wOjxUaic+AvpUchi+f0Ar4=","ftp_data":{"filename":"test.zip","command":"RETR"}}
{"timestamp":"2024-07-09T15:56:27.687829+0530","flow_id":2226277244448348,"parent_id":687377577139635,"event_type":"fileinfo","src_ip":"x.x.x.x","src_port":10013,"dest_ip":"x.x.x.x","dest_port":34887,"proto":"TCP","community_id":"1:5H2B8wOjxUaic+AvpUchi+f0Ar4=","app_proto":"ftp-data","fileinfo":{"filename":"test.zip","sid":[],"magic":"Zip archive data, at least v1.0 to extract","gaps":false,"state":"CLOSED","md5":"0a36fd59837f65ecec597b7952770598","sha256":"1841c6b8f7bced635a6a24cd7fd913b6f64ffb4e6e60300182b2199b10dbe2cd","stored":false,"size":358,"tx_id":0}}

Would you be able to share a pcap ?

@Philippe_Antoine I found one mistake in ftp rule where I was using the quotes on filemd5 keyword which was not supported-

[ERRCODE: SC_ERR_INVALID_SIGNATURE(39)] - quotes on filemd5 keyword that doesn’t support them: ‘filemd5’

So after removing the quotes suricata is detecting the file transfer over FTP based on md5hash and generating the drop alert as well but its not actually blocking the transfer, the file was transferred to client successfully.

Update rule-

drop ftp-data any any -> any any (msg:"Block file transfer over FTP by md5hash"; flow:established; filestore; filemd5:blacklist_md5; ftpdata_command:retr; classtype: suspicious-filename-detect; sid:3200002; rev:1;)

Alert log-

07/17/2024-15:41:25.424704  [Drop] [**] [1:3200002:1] Block file transfer over FTP by md5hash [**] [Classification: A suspicious filename was detected] [Priority: 2] {TCP} x.x.x.x:10010 -> 10.10.11.2:57099

Here is the pcap for your reference-
ftp-test.pcap (2.4 KB)

1 Like

Are you using stream.inline aka IPS mode ?

Yes. I am running suricata in IPS mode with NFQ-

/usr/bin/suricata -c /etc/suricata/suricata.yaml --pidfile /run/suricata.pid -q 0

And stream.inline was set to auto. However, I have tried changing setting to yes explicitly as well but it was same result. Here is the stream config for your reference-

stream:
  memcap: 64mb
  #memcap-policy: ignore
  checksum-validation: yes      # reject incorrect csums
  #midstream: false
  #midstream-policy: ignore
  inline: yes                  # auto will use inline mode in IPS mode, yes or no set it statically
  bypass: yes
  reassembly:
    memcap: 256mb
    #memcap-policy: ignore
    depth: 1mb                  # reassemble 1mb into a stream
    toserver-chunk-size: 2560
    toclient-chunk-size: 2560
    randomize-chunk-size: yes
    #randomize-chunk-range: 10
    #raw: yes
    #segment-prealloc: 2048
    #check-overlap-different-data: true

Please add your full suricata.yaml and also how you did setup the netfilter part.