|
| 1 | +# SQLMap `-r` 参数误识别 GET 请求为 POST 请求 —— GitHub Issue 报告 |
| 2 | + |
| 3 | +--- |
| 4 | + |
| 5 | +## Issue 标题 |
| 6 | + |
| 7 | +`-r` option incorrectly treats GET request as POST when request file contains trailing newlines |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## 问题描述 / Description |
| 12 | + |
| 13 | +When using SQLMap with the `-r` option to load an HTTP request from a file, if the request file contains **trailing newlines after the standard HTTP empty line** (i.e., more than one `\r\n` or `\n` at the end), SQLMap incorrectly interprets the request as a **POST request**, regardless of the actual HTTP method specified in the request line. |
| 14 | + |
| 15 | +This behavior affects any HTTP method (GET, PUT, DELETE, etc.) when the request file is not strictly terminated after the single empty line that separates headers from the body. |
| 16 | + |
| 17 | +A typical scenario where this bug is triggered: the original request is a POST (see "Original Request" below), but after editing it in Burp Repeater to change the method to GET and removing the body, the generated request file may still contain trailing newlines. SQLMap then incorrectly treats the edited GET request as POST. |
| 18 | + |
| 19 | +--- |
| 20 | + |
| 21 | +## 复现步骤 / Steps to Reproduce |
| 22 | + |
| 23 | +### Original Request (for context) |
| 24 | + |
| 25 | +The original HTTP request before editing was a POST with a JSON body: |
| 26 | + |
| 27 | +```http |
| 28 | +POST /api/user/login HTTP/1.1 |
| 29 | +Host: 127.0.0.1:9527 |
| 30 | +Content-Length: 37 |
| 31 | +sec-ch-ua-platform: "Windows" |
| 32 | +Accept-Language: zh-CN,zh;q=0.9 |
| 33 | +sec-ch-ua: "Chromium";v="145", "Not:A-Brand";v="99" |
| 34 | +Content-Type: application/json |
| 35 | +sec-ch-ua-mobile: ?0 |
| 36 | +User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36 |
| 37 | +Accept: */* |
| 38 | +Origin: http://127.0.0.1:9527 |
| 39 | +Sec-Fetch-Site: same-origin |
| 40 | +Sec-Fetch-Mode: cors |
| 41 | +Sec-Fetch-Dest: empty |
| 42 | +Referer: http://127.0.0.1:9527/ |
| 43 | +Accept-Encoding: gzip, deflate, br |
| 44 | +Connection: keep-alive |
| 45 | +
|
| 46 | +{"username":"test","password":"test"} |
| 47 | +``` |
| 48 | + |
| 49 | +### Reproducible Request File |
| 50 | + |
| 51 | +After editing the request in Burp Repeater (changing method to GET and removing the body), create a file `requests.txt` with the following content. Note that it ends with **two empty lines** instead of one: |
| 52 | + |
| 53 | +```http |
| 54 | +GET /api/user/login HTTP/1.1 |
| 55 | +Host: 127.0.0.1:9527 |
| 56 | +Content-Length: 0 |
| 57 | +sec-ch-ua-platform: "Windows" |
| 58 | +Accept-Language: zh-CN,zh;q=0.9 |
| 59 | +sec-ch-ua: "Chromium";v="145", "Not:A-Brand";v="99" |
| 60 | +Content-Type: application/json |
| 61 | +sec-ch-ua-mobile: ?0 |
| 62 | +User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36 |
| 63 | +Accept: */* |
| 64 | +Origin: http://127.0.0.1:9527 |
| 65 | +Sec-Fetch-Site: same-origin |
| 66 | +Sec-Fetch-Mode: cors |
| 67 | +Sec-Fetch-Dest: empty |
| 68 | +Referer: http://127.0.0.1:9527/ |
| 69 | +Accept-Encoding: gzip, deflate, br |
| 70 | +Connection: keep-alive |
| 71 | +
|
| 72 | +
|
| 73 | +``` |
| 74 | + |
| 75 | +> **Note:** The file ends with **two empty lines** instead of one. In other words, there are extra newline characters after the standard HTTP empty line. |
| 76 | +
|
| 77 | +Run SQLMap with the `-r` option: |
| 78 | + |
| 79 | +```bash |
| 80 | +python sqlmap.py -r requests.txt --batch --level=1 --risk=1 |
| 81 | +``` |
| 82 | + |
| 83 | +To verify the actual HTTP method sent by SQLMap, you can proxy the traffic through Burp Suite or any other intercepting proxy using the `--proxy` option: |
| 84 | + |
| 85 | +```bash |
| 86 | +python sqlmap.py -r requests.txt --batch --level=1 --risk=1 --proxy=http://127.0.0.1:8080 |
| 87 | +``` |
| 88 | + |
| 89 | +Observe that SQLMap treats this as a **POST request** and attempts to inject into the "body" parameters, even though the request method is explicitly `GET`. |
| 90 | + |
| 91 | +--- |
| 92 | + |
| 93 | +## 预期行为 / Expected Behavior |
| 94 | + |
| 95 | +SQLMap should respect the HTTP method specified in the request line (`GET` in this case) and should not incorrectly infer `POST` solely based on trailing newlines in the request file. |
| 96 | + |
| 97 | +According to RFC 7230, the empty line (`CRLF CRLF`) marks the end of the header section. Any content **after** that empty line constitutes the message body. However, **trailing empty lines alone** (without actual body content) should not cause SQLMap to change the request method or assume the presence of a body. |
| 98 | + |
| 99 | +--- |
| 100 | + |
| 101 | +## 实际行为 / Actual Behavior |
| 102 | + |
| 103 | +SQLMap detects "content" after the first empty line (even if it's just additional newline characters) and proceeds to: |
| 104 | +- Treat the request as a **POST request** |
| 105 | +- Attempt to parse and inject into what it believes is the request body |
| 106 | +- Ignore or mishandle URL/query parameters that should be the actual injection targets |
| 107 | + |
| 108 | +--- |
| 109 | + |
| 110 | +## 环境信息 / Environment |
| 111 | + |
| 112 | +- **SQLMap version:** 1.10 (also affects 1.9.11.3 and likely earlier versions) |
| 113 | +- **Python version:** 3.10+ |
| 114 | +- **OS:** Windows 10 (also reproducible on Windows 11 and Linux) |
| 115 | + |
| 116 | +--- |
| 117 | + |
| 118 | +## 根因分析 / Root Cause Analysis |
| 119 | + |
| 120 | +The issue appears to be in how SQLMap parses the request file when the `-r` option is used. Specifically, the parser likely checks for the presence of **any bytes after the first `\r\n\r\n`** (or `\n\n`) sequence. If trailing newlines exist, the parser assumes there is a message body and consequently switches the request method to `POST`. |
| 121 | + |
| 122 | +A more robust approach would be: |
| 123 | +1. Strip trailing whitespace/newlines from the end of the request file **before** determining if a body exists. |
| 124 | +2. Only treat the request as having a body if there is **non-whitespace content** after the header-empty-line. |
| 125 | +3. Always preserve the HTTP method explicitly stated in the request line. |
| 126 | + |
| 127 | +--- |
| 128 | + |
| 129 | +## 影响范围 / Impact |
| 130 | + |
| 131 | +This bug affects automated workflows and third-party tools (e.g., Burp Suite extensions, custom scripts) that generate HTTP request files for SQLMap. It is common for text editors, logging tools, or programmatic file writers to append trailing newlines, making this issue easy to trigger unintentionally. |
| 132 | + |
| 133 | +--- |
| 134 | + |
| 135 | +## 建议修复 / Suggested Fix |
| 136 | + |
| 137 | +In the request file parsing logic (likely within `lib/request/connect.py` or similar), consider stripping trailing newlines before deciding whether a body is present: |
| 138 | + |
| 139 | +```python |
| 140 | +# Pseudo-code suggestion |
| 141 | +raw_request = read_file(request_file) |
| 142 | +# Split headers and body at the first empty line |
| 143 | +header_part, _, body_part = raw_request.partition('\r\n\r\n') |
| 144 | +# Strip trailing whitespace from the body before evaluation |
| 145 | +body_part = body_part.rstrip('\r\n') |
| 146 | +if not body_part: |
| 147 | + # No actual body content; preserve the original method |
| 148 | + has_body = False |
| 149 | +else: |
| 150 | + has_body = True |
| 151 | +``` |
| 152 | + |
| 153 | +Alternatively, ensure that the HTTP method from the request line is never overridden unless explicitly requested by the user (e.g., via `--method`). |
| 154 | + |
| 155 | +--- |
| 156 | + |
| 157 | +## 附件 / Attachments |
| 158 | + |
| 159 | +- `requests.txt` — Minimal reproducible request file (see "Steps to Reproduce" above) |
| 160 | + |
| 161 | +--- |
| 162 | + |
| 163 | +## 备注 / Additional Notes |
| 164 | + |
| 165 | +This issue was discovered while integrating SQLMap with the [SQLMap WebUI](https://github.com/c0ny1/sqlmap-webui) project, where HTTP request files are generated programmatically. Trailing newlines occasionally occur during file generation, leading to unexpected POST behavior on what should be GET-based scans. |
| 166 | + |
| 167 | +Thank you for maintaining SQLMap! |
| 168 | + |
| 169 | +--- |
0 commit comments