So, I was still developing for a site that using Orchard CMS. I finally get into security testing. Well, that’s a lot of effort to do. 😀
But what I got is that there is double extension threat to my application. At first, I manage to fix it through Media module on Orchard. Then I think it was already safe and clear. I am patiently waiting for the result. What I got is the opposite. The threat still shows up. And it brings me to one conclusion: the problem is in the Piedone Avatar (the current module that I use for avatars in my site).
As usual, I debug the application first, put breakpoints here and there. Searching for the suitable location and looking for the steps. I got the way and I put some modification. The modification that I made is on the IAvatarsService interface , AvatarsServiceExtension class, and AvatarsService (for I have made a modification on the interface).
Here is the added code:
IAvatarsService
... /// <summary> /// Saves an avatar file /// </summary> /// <param name="id">Id of the content item (user) to attach the file to</param> /// <param name="stream">The content of the file</param> /// <param name="extension">The extension of the file</param> /// <param name="filename">The name of the file (for double extension checking)</param> /// <returns>True or false indicating success or failure</returns> bool SaveAvatarFile(int id, Stream stream, string extension, string filename); ...
AvatarsServiceExtension
... /// <summary> /// Saves an avatar file /// </summary> /// <param name="id">Id of the content item (user) to attach the file to</param> /// <param name="postedFile">A posted image file</param> /// <returns>True or false indicating success or failure</returns> public static bool SaveAvatarFile(this IAvatarsService service, int id, HttpPostedFileBase postedFile) { return service.SaveAvatarFile(id, postedFile.InputStream, Path.GetExtension(postedFile.FileName), postedFile.FileName); // I add postedFile.FileName so that it will check the extension first. } ...
AvatarService
... public bool SaveAvatarFile(int id, Stream stream, string extension, string filename) { ... if (containsHarmfulDoubleExtension(filename) || !IsFileAllowed(filePath)) { ValidationDictionary.AddError(AvatarsServiceValidationKey.NotAllowedFileType, T("This file type is not allowed as an avatar.")); return false; } ... } /// <summary> /// To check whether it have a double extension (and harmful) or not. /// Leave the file be like it is if there is a double extension if not harmful /// </summary> /// <param name="filename">name of the file</param> /// <returns>true if contains</returns> public bool containsHarmfulDoubleExtension(string filename) { string harmfulExtensions = "exe php cs ascx cshtml html obj class java bat deb vb vbe reg php3 php4 php5"; bool hasil = false; List<string> splittedFileName = filename.Split('.').ToList<string>(); if (splittedFileName.Count == 2) return false; else { // more dots are found. splittedFileName.RemoveAt(0); // remove the first element (considered as a name) foreach (string singleBlast in splittedFileName) { hasil = harmfulExtensions.ToUpperInvariant().Contains(singleBlast.ToUpperInvariant()); if (hasil == true) break; } } return hasil; } ...
If there is any suggestion you may add or repair on my code, well, please be kind 🙂