作者 :Yuppie001
作者主页 : 传送
本文专栏 :Web漏洞篇
🌟🌟🌟🌟🌟🌟🌟🌟
在 HTTP 协议的 POST 请求中,提交参数和文件至服务器时,会使用不同的字段值。Content-Type 字段的 application/x-www-form-urlencoded 和 multipart/form-data 是两种常见的表单编码类型。
application/x-www-form-urlencoded
- 这种编码方式将所有的表单数据编码为一个 URL 编码后的字符串。表单字段名和值会被序列化为 key1=value1&key2=value2 的格式,并且特殊字符会被编码(比如空格会被编码为 +,& 和 = 会被编码为 %26 和 %3D 等等)。
- 适用于普通的键值对数据传输,不适合上传文件。
- 适合用于小量数据提交和不需要文件上传的情况。
数据包如下:
POST /submit HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 23
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Referer: http://example.com/form
Origin: http://example.com
field1=value1&field2=value2
multipart/form-data
- 这种编码方式将每个表单字段分开处理,每个字段都包含在一个独立的部分(part)中。每个部分都有自己的内容类型(Content-Type),如果上传的是文件,还会包含文件的文件名。
- 适用于包含文件上传的表单和混合提交文本和二进制数据,因为它能携带二进制数据。
这里所说的“能携带二进制数据”是指 multipart/form-data 编码能够处理和传输非文本数据,如图像、音频、视频、PDF 文件等。这些文件内容并不需要进行特殊编码,可以直接在请求体中传输。这使得它非常适合用于文件上传和其他需要传输非文本数据的场景
以下是一个文件上传数据包的例子:
POST /file/upload.php HTTP/1.1
Host: 192.168.58.130
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------121362204533093779961666926442
Content-Length: (根据body计算)
Origin: http://192.168.58.130
Connection: close
Referer: http://192.168.58.130/file/upload.php
Upgrade-Insecure-Requests: 1
-----------------------------121362204533093779961666926442
Content-Disposition: form-data; name="upload"; filename="éšä¾¿å†™å†™.txt"
Content-Type: text/plain
这是我上传的文字:你好!
-----------------------------121362204533093779961666926442--
分析与解释
Content-Type
首先,Content-Type 的内容变为了 multipart/form-data; boundary=---------------------------121362204533093779961666926442。分号前指定了本次请求的内容类型是 multipart/form-data,后面的 boundary 定义了请求体中的分界线。boundary 用于分隔每一块内容,确保上传的文件内容与其他 POST 数据互不干扰。
Body结构
boundary 分界线后的第一行通常是 Content-Disposition 头。其值包含 form-data,表示这是表单数据。后面是 name 属性,指定了传输的参数名。如果是文件上传,还会有 filename 属性,指明上传的文件名。
文件上传
在文件上传部分,Content-Disposition 头中除了 name 属性外,还包含 filename 属性。紧跟其后的是 Content-Type 头,用于指定文件的 MIME 类型。
多部分数据提交
虽然 multipart/form-data 类型主要用于文件上传,但它也可以用于提交多个数据块,包括普通表单字段和文件。要区分文件和普通表单字段,可以检查 Content-Disposition 头中是否包含 filename 属性。如果存在 filename 属性,则该部分为文件上传;否则为普通表单字段。
这里以传输了包含多种类型数据的表单举例:
<form action="/submit" method="post" enctype="multipart/form-data">
<input type="text" name="username">
<input type="password" name="password">
<textarea name="description"></textarea>
<input type="submit">
</form>
在这种情况下,提交的表单数据可能会被编码为:
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="username"
example_user
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="password"
example_password
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="description"
This is an example description.
------WebKitFormBoundary7MA4YWxkTrZu0gW--