前端页面如下:(index.html)

<!DOCTYPE>
<html><head><title>Upload File Test</title></head><body><form enctype='multipart/form-data' action="/cgi-bin/LocalVideoUpload" method="post"><input type="file" name='pics' multiple><input type="file" name='another_pic'><input type="submit"></form ></body>
</html>

从中可以看到,使用了一个表单作为上传内容,其中enctype属性表明这个表单在上传的时候使用multipart/form-data格式。表单中有两个输入框,在浏览器里会显示为【选择文件】。其中pics可以选择多个文件上传,another_pic只能选择一个文件上传。

那么什么是multipart/form-data格式呢?

首先根据标准文档和搜索到的资料,这是一种Content-Type,而且是建立于POST请求方式基础上的。其本身意味着整个表单数据编码为一条消息,每个控件的数据对应消息的一部分。

先用Wireshark抓一下包,这里要注意的是,由于wireshark没法抓localhost环回的包,因此我在本地的另一个设备上设置了一个代理,这样请求会经过该设备的中转,从而能够被wireshark捕获到。当然也有更好的办法,比如配置路由,安装rawpacp等等.... 可以参考 这个博客

抓到的包大概是这样:

这里用了wireshark的过滤条件:ip.src eq 192.168.31.102 and ip.dst eq 192.168.31.51 and ip.proto eq TCP,这样能够筛选出从102机器发往51机器的所有TCP报文,沿着SYN查找带有PSH,ACK的报文(其中PSH表示push操作位,意味着发送方希望接收方立刻处理数据,具体参见 这个博客 ,在截图中还可以看到很多TCP segment of a reassembled PDU这样的提示,这表明TCP报文经过了分片,可以参考 这个博客。关于更多的wireshark过滤条件语法,参见 这个博客)然后右键报文——追踪TCP流,就会弹出来这样一个窗口:

这里就可以看到报文的格式了。在Content-Type中,multipart/form-data被指定,随后跟着一个boundary参数顾名思义就是消息的边界分隔符。在POST的正文中可以看到,每个消息以--{$boundary}开始。最后一个消息后附带一个--{$boundary}--表示结束。整个POST的正文长度(包括一大堆的分隔符和内部消息头)为Content-Length。

这样,在CGI中,接收到CONTENT_TYPE和CONTENT_LENGTH参数后,分析是不是multipart/form-data,如果是就提取出来boundary,读取post内容,根据boundary分割输入数据,解析内部请求头。(此处代码较多,就不贴了)

需要注意的是,如果CGI运行在Windows下,而且上传的文件中包含二进制数据,此时需要将标准输入流设置成二进制模式,具体参见 这个博客。

有关内部消息头中的Content-Disposition,可以参考 这里。另外Content-Disposition还可以被用在响应头中,用于下载文件,具体参考 这个博客。

由于内部消息头没有Content-Length,因此没有办法预知这一部分有多少数据,只能不断读入然后判断是否遇到了边界。

需要小心的是,内部消息头指出的filename可能是经过精心编辑的带有类似 ../ 的路径,如果直接使用有可能会覆盖其他文件,从而为攻击提供了可乘之机。

这里再介绍一种能够显示上传进度的前端页面写法:(摘自 这个博客)

<!DOCTYPE html>
<html>
<head><title>Upload Files using XMLHttpRequest - Minimal</title><script type="text/javascript">function fileSelected() {var file = document.getElementById('fileToUpload').files[0];if (file) {var fileSize = 0;if (file.size > 1024 * 1024)fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';elsefileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';document.getElementById('fileName').innerHTML = 'Name: ' + file.name;document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize;document.getElementById('fileType').innerHTML = 'Type: ' + file.type;}}function uploadFile() {var fd = new FormData();fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);var xhr = new XMLHttpRequest();xhr.upload.addEventListener("progress", uploadProgress, false);xhr.addEventListener("load", uploadComplete, false);xhr.addEventListener("error", uploadFailed, false);xhr.addEventListener("abort", uploadCanceled, false);xhr.open("POST", "/cgi-bin/LocalVideoUpload");//修改成自己的接口xhr.send(fd);}function uploadProgress(evt) {if (evt.lengthComputable) {var percentComplete = Math.round(evt.loaded * 100 / evt.total);document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';}else {document.getElementById('progressNumber').innerHTML = 'unable to compute';}}function uploadComplete(evt) {/* 服务器端返回响应时候触发event事件*/alert(evt.target.responseText);}function uploadFailed(evt) {alert("There was an error attempting to upload the file.");}function uploadCanceled(evt) {alert("The upload has been canceled by the user or the browser dropped the connection.");}</script>
</head>
<body><form id="form1" enctype="multipart/form-data" method="post"><div class="row"><label for="fileToUpload">Select a File to Upload</label><br /><input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();"/></div><div id="fileName"></div><div id="fileSize"></div><div id="fileType"></div><div class="row"><input type="button" onclick="uploadFile()" value="Upload" /></div><div id="progressNumber"></div></form>
</body>
</html>

此外,还可以使用libcurl库和winhttp库来直接对cgi发起上传文件的POST请求,可以参考 这个博客。

POST上传数据的时候,除了multipart/form-data外,还有默认的application/x-www-from-urlencoded类型,这种类型会将数据转化为键值对key=value&key2=value2这样的,同时还会对数据进行编码(不适合文件上传)。还有raw类型,其Content-Type为text/plain或者application/json,text/html这样的。其内容不会被修改。有关更多的Content-Type内容,可以参考 这个博客。除此之外还有一种binary类型,其Content-Type为application/octet-stream,由于没有分隔符,因此只能上传一个文件。

C/C++ CGI处理文件上传相关推荐

  1. c语言实现cgi之文件上传和下载

    作者 QQ群:852283276 微信:arm80x86 微信公众号:青儿创客基地 B站:主页 https://space.bilibili.com/208826118 参考 CGI实现文件的上传和下 ...

  2. boa(web服务器)之交叉编译、移植、cgi、文件上传篇

    boa简介 BOA 服务器是一个小巧高效的web服务器,是一个运行于unix或linux下的,支持CGI的.适合于嵌入式系统的单任务的http服务器. 源代码开放.性能高.由于它是一个单任务的Web服 ...

  3. 文件上传失败解决过程

    写了一个html+cgi实现文件上传的功能,使用html始终无法将文件上传上去,cgi解析不到文件名和文件内容.使用postman就可以上传成功.下面是源文件: post.html <!DOCT ...

  4. Java中的文件上传2(Commons FileUpload:commons-fileupload.jar)

    相比上一篇使用Servlet原始去实现的文件上传(http://www.cnblogs.com/EasonJim/p/6554669.html),使用组件去实现相对来说功能更多,省去了很多需要配置和处 ...

  5. php上传漏洞绕过gd库,jQuery File Upload任意文件上传漏洞

    事件背景 jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个JavaScript代码库(或JavaScript框架).jQuery File Upload一个jQ ...

  6. 00截断上传绕过_【文件上传与解析】文件上传与解析漏洞总结v1.0

    点击上方"公众号" 可以订阅哦! Hello,各位小伙伴晚上好~ 这里是依旧勤劳写公众号的小编~ 今天本公众号将推出一个新的模块,那就是漏洞知识点总结模块!!!(此处应有掌声~) ...

  7. CTFshow 文件上传 web153

    目录 思路 总结 思路 先上传带shell的png文件,上传成功 把文件后缀改成php,上传失败,改成xxxxx上传成功,得知是黑名单过滤, 上传phtml后缀,可以成功上传,但是无法解析,可以试试上 ...

  8. web安全之文件上传漏洞攻击与防范方法

    一. 文件上传漏洞与WebShell的关系 文件上传漏洞是指网络攻击者上传了一个可执行的文件到服务器并执行.这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等.这种攻击方式是最为直接和有效 ...

  9. png文件头_文件上传总结

    可以参考upload-labs 检验规则 1.客户端javascript校验 通常在前端进行过滤,我们可以通过命名1.php.jpg上传,然后修改数据包文件名filename=1.php上传.或者直接 ...

最新文章

  1. MIT与FAIR提出「mixup」,利用数据和标签的随机线性插值提高神经网络的健壮性
  2. http的“无连接”指的是_【38期】一份tcp、http面试指南,常考点都给你了
  3. 【Unity/Kinect】获取预制的手势信息KinectInterop.HandState
  4. DKhadoop安装配置教程与常见问题解决方法
  5. Leetcode上的解法看不懂?试着用动画的方式去辅助理解
  6. 港航环境变化引起的错误解决方法
  7. CodeForces - 786BLegacy——线段树建图+最短路
  8. 全国80几所重点大学ftp资源库(经常逛逛可能有惊喜哦)很难收集的,知道其他的友友可以留言完善...
  9. [react] 说说你对reader的context的理解
  10. 工厂好的html页面,jquery中被誉为工厂函数的是什么?
  11. 工厂电子产品工艺文件_建智能工厂,人机如何达到最佳组合?
  12. java过时_Java 语言的几个缺陷之四: 过时的 JavaBean
  13. np.where使用:根据条件生成新的数组
  14. linux generic什么意思_Linux下ps aux中进程状态为Ss,S+, Rs,Ds是什么意思?
  15. BootStrap中的日期时间组件datetimepicker
  16. Java列表removeAll(Collection)示例
  17. Web安全之CSRF攻击
  18. 全国航空机场分布矢量数据/旅游景点poi/全国港口码头分布/地铁站分布/火车站分布/2020年POI矢量数据
  19. HDU-1150 Machine Schedule 二分图匹配
  20. cad帧数测试软件,怎样让cad运行速度更快_cad如何设置运行更流畅

热门文章

  1. python中arange是什么意思_python中arange是什么意义【Python教程】,python,arange
  2. 民航导航技术发展及北斗应用分析
  3. ABAP:多页签的选择屏幕
  4. 一份不错的正则入门文章
  5. AcWing 1089 烽火传递 题解(动态规划—DP—单调队列优化DP)
  6. JavaSocket简单通信
  7. 攻击微软、三星等大型企业的黑客组织LAPSUS$成员被逮捕
  8. go拼接字符串不如php,golang 字符串拼接性能的对比分析
  9. 解决spring boot 报错问题:Disconnected from the target VM, address: ‘127.0.0.1:51596
  10. macOS配置vim