上传伪技术~很多人都以为判断了后缀,判断了ContentType,判断了头文件就真的安全了。是吗?
今天群里有人聊图片上传,简单说下自己的经验(大牛勿喷)
0.如果你的方法里面是有指定路径的,记得一定要过滤../,比如你把 aa文件夹设置了权限,一些类似于exe,asp,php之类的文件不能执行,那么如果我在传路径的时候,前面加了一个../呢,这样这种服务器端的限制就跳过了。(DJ音乐站基本上都有这个问题,以及用某编辑器的同志)
1.常用方法:这种就是根据后缀判断是否是图片文件,需要注意的是这种格式:文件:1.asp;.jpg 1.asp%01.jpg 目录: 1.jpg/1.asp 1.jpg/1.php 等等,IIS和Nginx部分版本是有解析漏洞的(不要用文件原有名称,eg:1.asp.jpg=》去后缀后的名字就是1.asp)
/// <summary>
/// 图片上传
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public JsonResult UploadA(HttpPostedFileBase file)
{
if (file == null) { return Json(new { status = false, msg = "图片提交失败" }); }
if (file.ContentLength > 10485760) { return Json(new { status = false, msg = "文件10M以内" }); }
string filterStr = ".gif,.jpg,.jpeg,.bmp,.png";
string fileExt = Path.GetExtension(file.FileName).ToLower();
if (!filterStr.Contains(fileExt)) { return Json(new { status = false, msg = "图片格式不对" }); } //todo: md5判断一下文件是否已经上传过,如果已经上传直接返回 return Json(new { status = true, msg = sqlPath }); string path = string.Format("{0}/{1}", "/lotFiles", DateTime.Now.ToString("yyyy-MM-dd"));
string fileName = string.Format("{0}{1}", Guid.NewGuid().ToString("N"), fileExt);
string sqlPath = string.Format("{0}/{1}", path, fileName);
string dirPath = Request.MapPath(path); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); }
try
{
//todo:缩略图
file.SaveAs(Path.Combine(dirPath, fileName));
//todo: 未来写存数据库的Code
}
catch { return Json(new { status = false, msg = "图片保存失败" }); }
return Json(new { status = true, msg = sqlPath });
}
2.Context-Type的方法(很多人说这个安全性比上一个高。。。。。呃,也许吧,上面至少还有个文件后缀硬性判断,contentType这玩意抓个包,本地代理一开,直接就可以串改,传的是1.asp,你收的contextType依旧是图片格式,最后保存就玩完了)
/// <summary>
/// 图片上传
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public JsonResult UploadB(HttpPostedFileBase file)
{
if (file == null) { return Json(new { status = false, msg = "图片提交失败" }); }
if (file.ContentLength > 10485760) { return Json(new { status = false, msg = "文件10M以内" }); } //判断文件格式(MimeMapping)
var contentType = file.ContentType;
if (contentType == null) { return Json(new { status = false, msg = "图片提交失败" }); }
contentType = contentType.ToLower();
var extList = new Dictionary<string, string>() { { "image/gif", ".gif" }, { "image/jpeg", ".jpg" }, { "image/bmp", ".bmp" }, { "image/png", ".png" } };
if (!extList.ContainsKey(contentType)) { return Json(new { status = false, msg = "图片格式不对" }); } //todo: md5判断一下文件是否已经上传过,如果已经上传直接返回 return Json(new { status = true, msg = sqlPath }); string path = string.Format("{0}/{1}", "/lotFiles", DateTime.Now.ToString("yyyy-MM-dd"));
string fileName = string.Format("{0}{1}", Guid.NewGuid().ToString("N"), extList[contentType]);
string sqlPath = string.Format("{0}/{1}", path, fileName);
string dirPath = Request.MapPath(path); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); }
try
{
//todo:缩略图
file.SaveAs(Path.Combine(dirPath, fileName));
//todo: 未来写存数据库的Code
}
catch { return Json(new { status = false, msg = "图片保存失败" }); }
return Json(new { status = true, msg = sqlPath });
}
如果非要用这个,建议和第一个一起用
3.头文件判断,很多人都以为这是最终方案。。。。。。呃,也许吧。。。
先贴代码:
/*头文件参考:(我自己测是如有偏差请联系我)
7790:exe,dll
5666:psd
6677:bmp
7173:gif
13780:png
255216:jpg,jpeg
239187:js
6787:swf
7368:mp3
4838:wma
6063:xml
8297:rar
55122:7z
8075:docx,xlsx,pptx,vsdx,mmap,xmind,“zip”
208207:doc,xls,ppt,mpp,vsd
*/
/// <summary>
/// 判断扩展名是否是指定类型---默认是判断图片格式,符合返回true(没有释放stream,请手动:file.InputStream.Dispose();)
/// eg:图片+压缩+文档:"7173", "255216", "6677", "13780", "8297", "55122", "8075", "208207"
/// eg:img,"7173", "255216", "6677", "13780" //gif //jpg //bmp //png
/// eg:file,"8297", "55122", "8075", "208207" //rar //7z //zip + 文档系列
/// </summary>
/// <param name="stream">文件流</param>
/// <param name="fileTypes">文件扩展名</param>
/// <returns></returns>
public static bool CheckingExt(this Stream stream, params string[] fileTypes)
{
if (fileTypes == null || fileTypes.Length == 0) { fileTypes = new string[] { "7173", "255216", "6677", "13780" }; }
bool result = false;
string fileclass = ""; #region 读取头两个字节
var reader = new BinaryReader(stream);
byte[] buff = new byte[2];
try
{
reader.Read(buff, 0, 2);//读取每个文件的头两个字节
fileclass = buff[0].ToString() + buff[1].ToString();
}
catch (System.Exception ex) { stream.Dispose(); reader.Dispose(); return false; }
#endregion #region 校验
for (int i = 0; i < fileTypes.Length; i++)
{
if (fileclass == fileTypes[i])
{
result = true;
break;
}
}
#endregion
return result;
}
/// <summary>
/// 图片上传(理论上需要二次渲染下图片,微软Save的时候有应该有一定的验证[我把含有一句话木马的图片上传,最后会返回一张空图片])
/// </summary>
/// <returns></returns>
public JsonResult UploadC(HttpPostedFileBase file)
{
if (file == null) { return Json(new { status = false, msg = "图片提交失败" }); }
if (file.ContentLength > 10485760) { return Json(new { status = false, msg = "文件10M以内" }); }
string filterStr = ".gif,.jpg,.jpeg,.bmp,.png";
string fileExt = Path.GetExtension(file.FileName).ToLower();
if (!filterStr.Contains(fileExt)) { return Json(new { status = false, msg = "图片格式不对" }); }
//防止黑客恶意绕过,头文件判断文件后缀
if (!file.InputStream.CheckingExt())
{
//todo:一次危险记录
return Json(new { status = false, msg = "图片格式不对" });
}
//todo: md5判断一下文件是否已经上传过,如果已经上传直接返回 return Json(new { status = true, msg = sqlPath }); string path = string.Format("{0}/{1}", "/lotFiles", DateTime.Now.ToString("yyyy-MM-dd"));
string fileName = string.Format("{0}{1}", Guid.NewGuid().ToString("N"), fileExt);
string sqlPath = string.Format("{0}/{1}", path, fileName);
string dirPath = Request.MapPath(path); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); }
try
{
//todo:缩略图 + 水印
file.SaveAs(Path.Combine(dirPath, fileName));
//todo: 未来写存数据库的Code
}
catch { return Json(new { status = false, msg = "图片保存失败" }); }
return Json(new { status = true, msg = sqlPath });
}
其实这个很好欺骗的,好几种方法,简单说2种:
第1个,用Copy命令

生成了一句话图片木马

第2个,用edjpgcom 打开一张图片就可以直接插入一句话木马了

图片跟之前看起来没什么不同的

用WinHex看看~

上传测试

成功上传了

有人说把图片另存为其他格式就能消除一句话木马。。。。。呃,好吧,你可以这样理解~看图:

渗透的时候一般遇到这种图片上传后再二次渲染的,一般直接放弃,因为内部的一句话已经不存在了
至于二次渲染是什么鬼,可以先自行研究会,先睡了~~~

public static bool CheckingExt(this Stream stream, params string[] fileTypes) { if (fileTypes == null || fileTypes.Length == 0) { fileTypes = new string[] { "7173", "255216", "6677", "13780" }; } bool result = false; string fileclass = "";
#region 读取头两个字节 var reader = new BinaryReader(stream); byte[] buff = new byte[2]; try { reader.Read(buff, 0, 2);//读取每个文件的头两个字节 fileclass = buff[0].ToString() + buff[1].ToString(); } catch (System.Exception ex) { stream.Dispose(); reader.Dispose(); return false; } #endregion
#region 校验 for (int i = 0; i < fileTypes.Length; i++) { if (fileclass == fileTypes[i]) { result = true; break; } } #endregion return result; }
上传伪技术~很多人都以为判断了后缀,判断了ContentType,判断了头文件就真的安全了。是吗?的更多相关文章
- 很多人都在埋怨没有遇到好的团队,但好的团队不可能凭空出现,一流的团队不能仅靠团队成员努力,作为Leader,要有可行的规划,并坚定地执行、时势地调整(转)
<西游记>中的唐僧团队历经千难万险,终于求得真经,目标明确.分工合理为这支队伍最终走向成功奠定了基础.唐僧从一开始,就为这个团队设定了西天取经的目标,虽然经历各种挫折与磨难,但目标从未动摇 ...
- [转帖](区块链补习班)ERC20很多人都听过,但ERC是什么你真的了解吗?
(区块链补习班)ERC20很多人都听过,但ERC是什么你真的了解吗? http://baijiahao.baidu.com/s?id=1600948969290990883&wfr=spide ...
- 听说特斯拉花了4个月研发出新ERP,然后很多人都疯了
欢迎关注微信公众号:sap_gui (ERP咨询顾问之家) 最近这件事儿在SAP圈里炒的挺火的,最主要是因为这几个关键词: 放弃SAP.4个月.自研ERP: 这则新闻一出来,很多人都兴高采烈,都要疯了 ...
- MVC文件上传09-使用客户端jQuery-File-Upload插件和服务端Backload组件让每个用户有专属文件夹,并在其中创建分类子文件夹
为用户创建专属上传文件夹后,如果想在其中再创建分类子文件夹,该怎么做?可以在提交文件的视图中再添加一个隐藏域,并设置 name="uploadContext". 相关兄弟篇: MV ...
- 很多人都搞不清楚C语言和C++的关系!今天我们来一探究竟为大家解惑~
最近,身边有许多小伙伴已经开始学习编程了,但是呢,学习又会碰到许多的问题,其中作为新手小白提到最多的问题就是编程语言的选择. 每次遇到这种问题,看起来很简单,但是又有很多小伙伴搞不清编程语言之间的关系 ...
- 关于ajaxFileUpload图片上传,success和error都触发的情况
最近做到项目使用JQuery的插件ajaxFileUpload~~~ 遇到了非常领人匪夷所思的事情,当图片上传成功之后呢(success),它的error事件也被触发了,情况就是: 后端数据正确返回 ...
- 震惊!很多人都不知道 CSS Grid 框架早就有了!
前言 写作本文起源于知乎的一个问题:[CSS Grid 布局那么好,为什么至今没有人开发出基于 Grid 布局的前端框架呢?] 这篇文章拖沓了两个月,是因为真的不知道从哪里说好.这个问题的所有回答几乎 ...
- SVN上传的时候没法显示文件名,只显示后缀名
之前在用SVN上传android代码的时候,发现上传列表上的文件没法显示名字,只显示了后缀名,就像这样: 各种疑惑,最终发现解决方法: 右键单击操作栏的status: 然后在出现的选项里面将filen ...
- MVC文件上传08-使用客户端jQuery-File-Upload插件和服务端Backload组件让每个用户有专属文件夹
当需要为每个用户建立一个专属上传文件夹的时候,可以在提交文件的视图中添加一个隐藏域,并设置name="objectContext". 相关兄弟篇: MVC文件上传01-使用jque ...
随机推荐
- map<虽然一直不喜欢map>但突然觉得挺好用的
#include<iostream> #include<cmath> #include<cstdio> #include<algorithm> #inc ...
- Codeforces Round #257 (Div. 2)
A - Jzzhu and Children 找到最大的ceil(ai/m)即可 #include <iostream> #include <cmath> using name ...
- mysql存不了中文的解决办法
driver=com.mysql.jdbc.Driverurl=jdbc:mysql://127.0.0.1:3306/testdb?useUnicode=true&characterEnco ...
- 【BZOJ】4245: [ONTAK2015]OR-XOR
题意 给定一个长度为\(n(1 \le n \le 500000)\)的序列\(a_i(0 \le a_i \le 10^{18})\),将它划分为\(m(1 \le m \le n)\)段连续的区间 ...
- spring3.0使用annotation完全代替XML(续)
从回帖的反应来看,大多数人还是不赞成完全代替XML的,这点倒是在意料之中.我个人还是倾向于用代码来取代XML的Bean定义,当然这更多的是关乎个人偏好,不代表与我观点不同的人就是错的. 先来说说代码相 ...
- C#程序员开发WinForm必须知道的 Window 消息大全
不要以为下面的东西只有C++中才会用到哦! 消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了.例如,单击鼠标.改变窗口尺寸.按下键盘上的一个键都会使Windows发送一个消息给应用 ...
- (转)名称和本质 by王珢
名称和本质 by 王垠 我很喜欢 Richard Feynman 写的 <What Do You Care What Other People Think>.在最开头 Feynman 讲到 ...
- python反射问题
python中的__import__是以字符串的形式反射导入模块并以字符串的形式执行函数
- Probe在性能测试中的使用方式简介
简介: Lambda Probe(以前称为Tomcat Probe)是一款实时监控和管理的Apache Tomcat实例的基本工具. Lambda Probe 是基于 Web + AJAX 的强大的免 ...
- 浅谈PHP7新特性
1. 运算符(NULL 合并运算符) 把这个放在第一个说是因为我觉得它很有用.用法: $a = $_GET['a'] ?? 1; 它相当于: $a = isset($_GET['a']) ? $_GE ...