]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
ftp: adds server side detection
authorPhilippe Antoine <pantoine@oisf.net>
Fri, 1 Jul 2022 11:30:46 +0000 (13:30 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 17 Jul 2024 04:13:39 +0000 (06:13 +0200)
src/app-layer-ftp.c

index fc64d1eb20fbed1b047bc2edaf99f981af11b316..a1a99d4bd701eac65f13d0497074f0f178599547 100644 (file)
@@ -965,6 +965,31 @@ static AppProto FTPUserProbingParser(
     return ALPROTO_FTP;
 }
 
+static AppProto FTPServerProbingParser(
+        Flow *f, uint8_t direction, const uint8_t *input, uint32_t len, uint8_t *rdir)
+{
+    // another check for minimum length
+    if (len < 5) {
+        return ALPROTO_UNKNOWN;
+    }
+    // begins by 220
+    if (input[0] != '2' || input[1] != '2' || input[2] != '0') {
+        return ALPROTO_FAILED;
+    }
+    // followed by space or hypen
+    if (input[3] != ' ' && input[3] != '-') {
+        return ALPROTO_FAILED;
+    }
+    if (f->alproto_ts == ALPROTO_FTP || (f->todstbytecnt > 4 && f->alproto_ts == ALPROTO_UNKNOWN)) {
+        // only validates FTP if client side was FTP
+        // or if client side is unknown despite having received bytes
+        if (memchr(input + 4, '\n', len - 4) != NULL) {
+            return ALPROTO_FTP;
+        }
+    }
+    return ALPROTO_UNKNOWN;
+}
+
 static int FTPRegisterPatternsForProtocolDetection(void)
 {
     if (AppLayerProtoDetectPMRegisterPatternCI(
@@ -987,7 +1012,15 @@ static int FTPRegisterPatternsForProtocolDetection(void)
                 IPPROTO_TCP, ALPROTO_FTP, "PORT ", 5, 0, STREAM_TOSERVER) < 0) {
         return -1;
     }
-
+    // Only check FTP on known ports as the banner has nothing special beyond
+    // the response code shared with SMTP.
+    if (!AppLayerProtoDetectPPParseConfPorts(
+                "tcp", IPPROTO_TCP, "ftp", ALPROTO_FTP, 0, 5, NULL, FTPServerProbingParser)) {
+        // STREAM_TOSERVER here means use 21 as flow destination port
+        // and NULL, FTPServerProbingParser means use probing parser to client
+        AppLayerProtoDetectPPRegister(IPPROTO_TCP, "21", ALPROTO_FTP, 0, 5, STREAM_TOSERVER, NULL,
+                FTPServerProbingParser);
+    }
     return 0;
 }