CVE-2021-22947: STARTTLS protocol injection via MITM
What the report claims
A man-in-the-middle can inject cleartext forged responses to future encrypted commands by pipelining them to the STARTTLS response.
Compare with curl's recorded outcome
Known vulnerability
A real vulnerability: CVE-2021-22947 STARTTLS protocol injection via MITM
Shown for comparison after analysis. The pipeline did not see this label.
ProveIt's finding
The available evidence does not settle the report. A maintainer should investigate.
Why this finding?
- The provided source code (lib/urldata.h) contains only the CURLcode enum and unrelated constants, not the IMAP/POP3/SMTP STARTTLS implementation.
- Deterministic checks report 'nothing_to_check' for the cited code refs.
- STARTTLS command injection is a known vulnerability class (CVE-2021-22947 is a real CVE), but the provided code does not confirm or contradict its presence in curl's implementation.
- The report references an attached test case that is not included in the materials.
What still needs checking
- The IMAP, POP3, and SMTP STARTTLS handling code (likely in lib/imap.c, lib/pop3.c, lib/smtp.c) showing how the cleartext-to-TLS transition is managed and whether pipelined responses are flushed or rejected.
- The referenced test case to understand the exact reproduction scenario.
How this analysis ran 5 claims · 0 citations verified
Checked against curl master on 2021-09-09 (1fbd822b6455). Test evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.
Review a draft reply to the reporter
Edit and verify before sending.
Thank you for the report. The provided materials only include lib/urldata.h (CURLcode definition), which does not contain the STARTTLS handling logic for IMAP, POP3, or SMTP. To assess this, we need the protocol-specific STARTTLS implementation (e.g., lib/imap.c, lib/pop3.c, lib/smtp.c) and the attached test case you mentioned. Could you provide those files or point to the exact functions handling the STARTTLS response and the transition to encrypted mode?
Inspect all claims and source code 5 claims · 1 code excerpts
Report claims
A man-in-the-middle can inject cleartext forged responses to future encrypted commands by pipelining them to the STARTTLS response.
Read the reasoning
The claim describes a STARTTLS protocol injection vulnerability. The provided code (lib/urldata.h lines 122-199) only shows the CURLcode enum definition and unrelated constants. No STARTTLS handling code for IMAP, POP3, or SMTP is present in the provided source. The deterministic checks confirm 'nothing_to_check' for the cited code refs (CURLcode, CURL, CURLcode::CURLE_OK).
in the STARTTLS response
Read the reasoning
Location claim ('in the STARTTLS response') cannot be verified because the STARTTLS response handling code is not in the provided source.
pipelining them to the STARTTLS response
Read the reasoning
Trigger claim ('pipelining them to the STARTTLS response') cannot be verified without the protocol state machine code that processes STARTTLS transitions.
Mailbox content forgery (IMAP, POP3). Sent mail content forgery (SMTP).
Read the reasoning
Impact claim (mailbox/sent mail forgery) depends on the existence of the injection flaw, which cannot be assessed from the provided code.
Use the attached test case within the curl test system. It is based on IMAP FETCH with explicit TLS. Upon test failure, the downloaded file contains "You've been hacked!" rather than the requested mail.
Read the reasoning
Reproduction references an attached test case ('based on IMAP FETCH with explicit TLS') that is not provided. The curl test system code is not in the provided source.
Read the original report
Source code
| 122 | typedef CURLcode (*Curl_datastream)(struct Curl_easy *data, |
| 123 | struct connectdata *conn, |
| 124 | int *didwhat, |
| 125 | bool *done, |
| 126 | int select_res); |
| 127 | #endif |
| 128 | |
| 129 | #include "mime.h" |
| 130 | #include "imap.h" |
| 131 | #include "pop3.h" |
| 132 | #include "smtp.h" |
| 133 | #include "ftp.h" |
| 134 | #include "file.h" |
| 135 | #include "vssh/ssh.h" |
| 136 | #include "http.h" |
| 137 | #include "rtsp.h" |
| 138 | #include "smb.h" |
| 139 | #include "mqtt.h" |
| 140 | #include "wildcard.h" |
| 141 | #include "multihandle.h" |
| 142 | #include "quic.h" |
| 143 | #include "c-hyper.h" |
| 144 | |
| 145 | #ifdef HAVE_GSSAPI |
| 146 | # ifdef HAVE_GSSGNU |
| 147 | # include <gss.h> |
| 148 | # elif defined HAVE_GSSAPI_GSSAPI_H |
| 149 | # include <gssapi/gssapi.h> |
| 150 | # else |
| 151 | # include <gssapi.h> |
| 152 | # endif |
| 153 | # ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H |
| 154 | # include <gssapi/gssapi_generic.h> |
| 155 | # endif |
| 156 | #endif |
| 157 | |
| 158 | #ifdef HAVE_LIBSSH2_H |
| 159 | #include <libssh2.h> |
| 160 | #include <libssh2_sftp.h> |
| 161 | #endif /* HAVE_LIBSSH2_H */ |
| 162 | |
| 163 | #define READBUFFER_SIZE CURL_MAX_WRITE_SIZE |
| 164 | #define READBUFFER_MAX CURL_MAX_READ_SIZE |
| 165 | #define READBUFFER_MIN 1024 |
| 166 | |
| 167 | /* The default upload buffer size, should not be smaller than |
| 168 | CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in |
| 169 | a write callback. |
| 170 | |
| 171 | The size was 16KB for many years but was bumped to 64KB because it makes |
| 172 | libcurl able to do significantly faster uploads in some circumstances. Even |
| 173 | larger buffers can help further, but this is deemed a fair memory/speed |
| 174 | compromise. */ |
| 175 | #define UPLOADBUFFER_DEFAULT 65536 |
| 176 | #define UPLOADBUFFER_MAX (2*1024*1024) |
| 177 | #define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE |
| 178 | |
| 179 | #define CURLEASY_MAGIC_NUMBER 0xc0dedbadU |
| 180 | #define GOOD_EASY_HANDLE(x) \ |
| 181 | ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER)) |
| 182 | |
| 183 | /* the type we use for storing a single boolean bit */ |
| 184 | #ifdef _MSC_VER |
| 185 | typedef bool bit; |
| 186 | #define BIT(x) bool x |
| 187 | #else |
| 188 | typedef unsigned int bit; |
| 189 | #define BIT(x) bit x:1 |
| 190 | #endif |
| 191 | |
| 192 | #ifdef HAVE_GSSAPI |
| 193 | /* Types needed for krb5-ftp connections */ |
| 194 | struct krb5buffer { |
| 195 | void *data; |
| 196 | size_t size; |
| 197 | size_t index; |
| 198 | BIT(eof_flag); |
| 199 | }; |