上傳偽技術~很多人都以為判斷了后綴,判斷了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;    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM