diff --git a/BlogEngine/BlogEngine.Core/Data/UsersRepository.cs b/BlogEngine/BlogEngine.Core/Data/UsersRepository.cs index 605100963..a574298e4 100644 --- a/BlogEngine/BlogEngine.Core/Data/UsersRepository.cs +++ b/BlogEngine/BlogEngine.Core/Data/UsersRepository.cs @@ -98,6 +98,9 @@ public BlogUser Add(BlogUser user) if (!Security.IsAuthorizedTo(Rights.CreateNewUsers)) throw new UnauthorizedAccessException(); + if (user.UserName.Contains("/") || user.UserName.Contains(@"\")) + throw new ApplicationException("Error adding new user; Invalid character detected in UserName"); + // create user var usr = Membership.CreateUser(user.UserName, user.Password, user.Email); if (usr == null) diff --git a/BlogEngine/BlogEngine.Core/Providers/FileSystemProviders/XmlFileSystemProvider.cs b/BlogEngine/BlogEngine.Core/Providers/FileSystemProviders/XmlFileSystemProvider.cs index e45cb6c03..0c6b263ed 100644 --- a/BlogEngine/BlogEngine.Core/Providers/FileSystemProviders/XmlFileSystemProvider.cs +++ b/BlogEngine/BlogEngine.Core/Providers/FileSystemProviders/XmlFileSystemProvider.cs @@ -28,7 +28,7 @@ private static string BlogAbsolutePath(string VirtualPath) private static string RelativeFilePath(string VirtualPath) { VirtualPath = VirtualPath.Replace("//","/").Trim(); - if (VirtualPath.ToLower().Contains(FileContainerRoot.ToLower())) + if (VirtualPath.ToLower().Contains(FileContainerRoot.ToLower()+"/") || VirtualPath.ToLower() == FileContainerRoot.ToLower()) return VirtualPath; // ex: Oct 18 2012, added this to handle the case on the File Manager where if diff --git a/BlogEngine/BlogEngine.Core/Services/Syndication/BlogML/BlogReader.cs b/BlogEngine/BlogEngine.Core/Services/Syndication/BlogML/BlogReader.cs index 8d81ad0ce..0ed4b4b58 100644 --- a/BlogEngine/BlogEngine.Core/Services/Syndication/BlogML/BlogReader.cs +++ b/BlogEngine/BlogEngine.Core/Services/Syndication/BlogML/BlogReader.cs @@ -53,13 +53,15 @@ public string XmlData /// /// Gets an XmlReader that converts BlogML data saved as string into XML stream /// - private XmlTextReader XmlReader + private XmlReader XmlReader { get { var byteArray = Encoding.UTF8.GetBytes(this.xmlData); var stream = new MemoryStream(byteArray); - return new XmlTextReader(stream); + XmlReaderSettings settings = new XmlReaderSettings(); + settings.XmlResolver = null; + return XmlReader.Create(stream, settings); } } diff --git a/BlogEngine/BlogEngine.NET/AppCode/Api/FileManagerController.cs b/BlogEngine/BlogEngine.NET/AppCode/Api/FileManagerController.cs index cebca856a..e3fa41b96 100644 --- a/BlogEngine/BlogEngine.NET/AppCode/Api/FileManagerController.cs +++ b/BlogEngine/BlogEngine.NET/AppCode/Api/FileManagerController.cs @@ -1,4 +1,5 @@ -using BlogEngine.Core.Data.Contracts; +using BlogEngine.Core; +using BlogEngine.Core.Data.Contracts; using BlogEngine.Core.FileSystem; using BlogEngine.Core.Providers; using System; @@ -24,6 +25,11 @@ public IEnumerable Get(int take = 10, int skip = 0, string path = [HttpPut] public HttpResponseMessage ProcessChecked([FromBody]List items) { + if (!Security.IsAdministrator) + { + throw new UnauthorizedAccessException(); + } + if (items == null || items.Count == 0) throw new HttpResponseException(HttpStatusCode.ExpectationFailed); @@ -36,10 +42,10 @@ public HttpResponseMessage ProcessChecked([FromBody]List items) if (item.IsChecked) { if(item.FileType == FileType.File || item.FileType == FileType.Image) - BlogService.DeleteFile(item.FullPath); + BlogService.DeleteFile(Extensions.SanitizePath(item.FullPath)); if (item.FileType == FileType.Directory) - BlogService.DeleteDirectory(item.FullPath); + BlogService.DeleteDirectory(Extensions.SanitizePath(item.FullPath)); } } } @@ -49,7 +55,11 @@ public HttpResponseMessage ProcessChecked([FromBody]List items) [HttpPut] public HttpResponseMessage AddFolder(FileInstance folder) { - BlogService.CreateDirectory(folder.FullPath + "/" + folder.Name); + if (!Security.IsAdministrator) + { + throw new UnauthorizedAccessException(); + } + BlogService.CreateDirectory(Extensions.SanitizePath(folder.FullPath) + "/" + Extensions.SanitizePath(folder.Name)); return Request.CreateResponse(HttpStatusCode.OK); } diff --git a/BlogEngine/BlogEngine.NET/AppCode/Api/UploadController.cs b/BlogEngine/BlogEngine.NET/AppCode/Api/UploadController.cs index ad6b01192..688ada454 100644 --- a/BlogEngine/BlogEngine.NET/AppCode/Api/UploadController.cs +++ b/BlogEngine/BlogEngine.NET/AppCode/Api/UploadController.cs @@ -64,6 +64,8 @@ public HttpResponseMessage Post(string action, string dirPath = "") dir = BlogService.GetDirectory("/avatars"); var dot = fileName.LastIndexOf("."); var ext = dot > 0 ? fileName.Substring(dot) : ""; + if (User.Identity.Name.Contains("/") || User.Identity.Name.Contains(@"\")) + throw new ApplicationException("Invalid character detected in UserName"); var profileFileName = User.Identity.Name + ext; var imgPath = HttpContext.Current.Server.MapPath(dir.FullPath + "/" + profileFileName); @@ -157,4 +159,4 @@ private void UploadVideo(string virtualFolder, HttpPostedFile file, string fileN } #endregion -} \ No newline at end of file +} diff --git a/BlogEngine/BlogEngine.NET/Global.asax b/BlogEngine/BlogEngine.NET/Global.asax index 0056bc608..2fd043a71 100644 --- a/BlogEngine/BlogEngine.NET/Global.asax +++ b/BlogEngine/BlogEngine.NET/Global.asax @@ -12,4 +12,17 @@ { BlogEngineConfig.SetCulture(sender, e); } + + protected void Application_PreSendRequestHeaders () + { + var httpContext = HttpContext.Current; + if (httpContext != null) { + var cookieValueSuffix = "; SameSite=Strict"; + var cookies = httpContext.Response.Cookies; + for (var i = 0; i < cookies.Count; i++) + { + var cookie = cookies[i]; cookie.Value += cookieValueSuffix; + } + } + } \ No newline at end of file diff --git a/README.md b/README.md index 821bd4d60..e25437ff2 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,57 @@ -This repository provides latest source code for BlogEngine.NET project. -
+

+ BlogEngine is an open source blogging platform since 2007.
Easily customizable. Many free built-in Themes, Widgets, and Plugins. +


- -BlogEngine Website -   - -BlogEgnien Features -   - -BlogEngine Themes -   - -BlogEngine Docs -   - -BlogEngine Donate - +- **[Website](https://blogengine.io/)** +- **[Docs](https://blogengine.io/support/get-started/)** +- **[Themes](https://blogengine.io/themes/)** +- **[Custom Design Theme](https://blogengine.io/themes/custom/)** +- **[Contact us](https://blogengine.io/support/)** +
+
-
-
+## Get Started +1. Requirements + You need a Windows Hosting that supports ASP.NET 4.5 and above. +2. Download + Get the latest BlogEngine and extract the zip file on the root of your website. +3. Write Permissions + Add write permissions to the App_Data and Custom folders on your server. +4. Done + Navigate to admin panel by adding /admin/ to your website's URL. + For example: https://yourwebsite.com/admin/
+ Username: admin
+ Password: admin
+

-# Installation +## Development -There are two download options for BlogEngine.NET: - -### 1. Web Project -This is an ideal option that you just need to download and copy BlogEngine files on your website and then everything is ready: +Environment: -Requirements: - * ASP.NET 4.5 + +- Visual Studio +- ASP.NET 4.5+ Steps: -1. **[Download](https://github.com/rxtur/BlogEngine.NET/releases/download/v3.3.6.0/3360.zip)** and extract zip file on root of your website. -2. Add write permissions to the `App_Data` and `Custom` folder. -3. Installation is done. -4. You can navigate to administration by adding `/admin/` to your website's URL, for example: `http://yourblog.com/admin/` -5. Username: `admin` Password `admin` +- Clone repository +- Open solution in Visual Studio 2015 + +- Build and run solution to load website in the browser +- You can navigate to administration on: http://localhost:64079/admin/ +- Username: admin Password admin +

-### 2. Source Code -This is the developer option. If you are interested is seeing how things work or want to add to the functionality, this is your option. - -Environment: - * Visual Studio 2015 + - * ASP.NET 4.5 + - -Steps: - 1. Clone repository - 2. Open solution in Visual Studio 2015 + - 3. Build and run solution to load website in the browser - 4. You can navigate to administration on: `http://localhost:64079/admin/` - 5. Username: `admin` Password `admin` +## Security Update -### 3. Security Update After install, update `machineKey` in `Web.config` with values generated with tool [like this](https://www.allkeysgenerator.com/Random/ASP-Net-MachineKey-Generator.aspx). This will prevent known exploit (reported Sep 2019). This only effects if you use default `admin` account. +

-# Screenshot -More screenshots on the [website](https://blogengine.io). +## Copyright and License -![dashboard-3](https://cloud.githubusercontent.com/assets/1932785/11760070/0012f9d8-a052-11e5-84a8-e9097cb85f23.png) +Code released under the MS-RL License. Docs released under Creative Commons.
+Copyright 2007–2023 BlogEngine