]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
ftp: FTPParseResponse bufferizes lines
authorPhilippe Antoine <contact@catenacyber.fr>
Mon, 16 Mar 2020 13:46:51 +0000 (14:46 +0100)
committerJeff Lucovsky <jeff@lucovsky.org>
Wed, 22 Apr 2020 11:53:10 +0000 (07:53 -0400)
Protects against evasion by TCP packet splitting

The problem arised if the FTP response is split on multiple packets

The fix is to bufferize the content, until we get a complete line

(cherry picked from commit a6294d6ec25d0f2f0b5d25f7a824c7325e8f87ce)

src/app-layer-ftp.c

index 9574cf98f99feaba770e6cde5620a8952ec9274c..ee17f24d46036a3d3fb0d975fb0ac1a655903064 100644 (file)
@@ -735,7 +735,12 @@ static int FTPParseResponse(Flow *f, void *ftp_state, AppLayerParserState *pstat
     if (unlikely(input_len == 0)) {
         return 1;
     }
+    state->input = input;
+    state->input_len = input_len;
+    /* toclient stream */
+    state->direction = 1;
 
+    while (FTPGetLine(state) >= 0) {
     FTPTransaction *tx = FTPGetOldestTx(state);
     if (tx == NULL) {
         tx = FTPTransactionCreate(state);
@@ -750,7 +755,7 @@ static int FTPParseResponse(Flow *f, void *ftp_state, AppLayerParserState *pstat
 
     state->curr_tx = tx;
     if (state->command == FTP_COMMAND_AUTH_TLS) {
-        if (input_len >= 4 && SCMemcmp("234 ", input, 4) == 0) {
+        if (state->current_line_len >= 4 && SCMemcmp("234 ", state->current_line, 4) == 0) {
             AppLayerRequestProtocolTLSUpgrade(f);
         }
     }
@@ -784,32 +789,33 @@ static int FTPParseResponse(Flow *f, void *ftp_state, AppLayerParserState *pstat
     }
 
     if (state->command == FTP_COMMAND_PASV) {
-        if (input_len >= 4 && SCMemcmp("227 ", input, 4) == 0) {
-            FTPParsePassiveResponse(f, ftp_state, input, input_len);
+        if (state->current_line_len >= 4 && SCMemcmp("227 ", state->current_line, 4) == 0) {
+            FTPParsePassiveResponse(f, ftp_state, state->current_line, state->current_line_len);
         }
     }
 
     if (state->command == FTP_COMMAND_EPSV) {
-        if (input_len >= 4 && SCMemcmp("229 ", input, 4) == 0) {
-            FTPParsePassiveResponseV6(f, ftp_state, input, input_len);
+        if (state->current_line_len >= 4 && SCMemcmp("229 ", state->current_line, 4) == 0) {
+            FTPParsePassiveResponseV6(f, ftp_state, state->current_line, state->current_line_len);
         }
     }
 
-    if (likely(input_len)) {
+    if (likely(state->current_line_len)) {
         FTPString *response = FTPStringAlloc();
         if (likely(response)) {
-            response->len = CopyCommandLine(&response->str, input, input_len);
+            response->len = CopyCommandLine(&response->str, state->current_line, state->current_line_len);
             TAILQ_INSERT_TAIL(&tx->response_list, response, next);
         }
     }
 
     /* Handle preliminary replies -- keep tx open */
-    if (FTPIsPPR(input, input_len)) {
-        return retcode;
+    if (FTPIsPPR(state->current_line, state->current_line_len)) {
+        continue;
     }
-
 tx_complete:
     tx->done = true;
+    }
+
     return retcode;
 }