Skip to content

Commit 97fcdac

Browse files
committed
Security fixes - sanitizing file upload
1 parent a7fa4d7 commit 97fcdac

File tree

5 files changed

+60
-12
lines changed

5 files changed

+60
-12
lines changed

src/Blogifier.Core/Providers/PostProvider.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,8 @@ public async Task<bool> Add(Post post)
236236
post.DateCreated = DateTime.UtcNow;
237237

238238
// sanitize HTML fields
239-
post.Content = post.Content.RemoveScriptTags();
240-
post.Description = post.Description.RemoveScriptTags();
239+
post.Content = post.Content.RemoveScriptTags().RemoveImgTags();
240+
post.Description = post.Description.RemoveScriptTags().RemoveImgTags();
241241

242242
await _db.Posts.AddAsync(post);
243243
return await _db.SaveChangesAsync() > 0;
@@ -251,8 +251,8 @@ public async Task<bool> Update(Post post)
251251

252252
existing.Slug = post.Slug;
253253
existing.Title = post.Title;
254-
existing.Description = post.Description.RemoveScriptTags();
255-
existing.Content = post.Content.RemoveScriptTags();
254+
existing.Description = post.Description.RemoveScriptTags().RemoveImgTags();
255+
existing.Content = post.Content.RemoveScriptTags().RemoveImgTags();
256256
existing.Cover = post.Cover;
257257
existing.PostType = post.PostType;
258258
existing.Published = post.Published;

src/Blogifier.Core/Providers/StorageProvider.cs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Blogifier.Core.Extensions;
22
using Blogifier.Shared;
33
using Microsoft.AspNetCore.Http;
4+
using Microsoft.Extensions.Configuration;
45
using System;
56
using System.Collections.Generic;
67
using System.IO;
@@ -26,10 +27,12 @@ public class StorageProvider : IStorageProvider
2627
{
2728
private string _storageRoot;
2829
private readonly string _slash = Path.DirectorySeparatorChar.ToString();
30+
private readonly IConfiguration _configuration;
2931

30-
public StorageProvider()
32+
public StorageProvider(IConfiguration configuration)
3133
{
3234
_storageRoot = $"{ContentRoot}{_slash}wwwroot{_slash}data{_slash}";
35+
_configuration = configuration;
3336
}
3437

3538
public bool FileExists(string path)
@@ -103,6 +106,13 @@ public async Task<bool> UploadFormFile(IFormFile file, string path = "")
103106
VerifyPath(path);
104107

105108
var fileName = GetFileName(file.FileName);
109+
110+
if(InvalidFileName(fileName))
111+
{
112+
Serilog.Log.Error($"Invalid file name: {fileName}");
113+
return false;
114+
}
115+
106116
var filePath = string.IsNullOrEmpty(path) ?
107117
Path.Combine(_storageRoot, fileName) :
108118
Path.Combine(_storageRoot, path + _slash + fileName);
@@ -307,6 +317,27 @@ string GetImgSrcValue(string imgTag)
307317
return imgTag.Substring(srcStart, srcEnd - srcStart);
308318
}
309319

320+
bool InvalidFileName(string fileName)
321+
{
322+
List<string> fileExtensions = new List<string>() { "png", "gif", "jpeg", "jpg", "zip", "7z", "pdf", "doc", "docx", "xls", "xlsx", "mp3", "mp4", "avi" };
323+
string configFileExtensions = _configuration.GetSection("Blogifier").GetValue<string>("FileExtensions");
324+
325+
if(!string.IsNullOrEmpty(configFileExtensions))
326+
{
327+
fileExtensions = new List<string>(configFileExtensions.Split(','));
328+
}
329+
330+
foreach(string ext in fileExtensions)
331+
{
332+
if(fileName.EndsWith(ext))
333+
{
334+
return false;
335+
}
336+
}
337+
338+
return true;
339+
}
340+
310341
#endregion
311342
}
312343
}

src/Blogifier.Shared/Extensions/StringExtensions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,11 @@ public static string RemoveScriptTags(this string str)
3737
Regex scriptRegex = new Regex(@"<script[^>]*>[\s\S]*?</script>");
3838
return scriptRegex.Replace(str, "");
3939
}
40+
41+
public static string RemoveImgTags(this string str)
42+
{
43+
Regex scriptRegex = new Regex(@"<img[^>]*>[\s\S]*?>");
44+
return scriptRegex.Replace(str, "");
45+
}
4046
}
4147
}

src/Blogifier/appsettings.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
}
88
},
99
"AllowedHosts": "*",
10-
"Blogifier": {
11-
"DbProvider": "SQLite",
12-
"ConnString": "Data Source=Blog.db",
13-
"Salt": "SECRET-CHANGE-ME!",
14-
"DemoMode": false
15-
}
10+
"Blogifier": {
11+
"DbProvider": "SQLite",
12+
"ConnString": "Data Source=Blog.db",
13+
"Salt": "SECRET-CHANGE-ME!",
14+
"DemoMode": false,
15+
"FileExtensions": "png,gif,jpeg,jpg,zip,7z,pdf,doc,docx,xls,xlsx,mp3,mp4,avi"
16+
}
1617
}

tests/Blogifier.Tests/StorageProviderTests.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using Blogifier.Core.Providers;
2+
using Microsoft.Extensions.Configuration;
3+
using System.Collections.Generic;
24
using System.Threading.Tasks;
35
using Xunit;
46

@@ -31,7 +33,15 @@ public async Task CanUploadBase64Image()
3133

3234
IStorageProvider GetSut()
3335
{
34-
return new StorageProvider();
36+
var inMemorySettings = new Dictionary<string, string> {
37+
{"Blgofier:FileExtensions", "png,gif,jpeg,jpg,zip"}
38+
};
39+
40+
IConfiguration configuration = new ConfigurationBuilder()
41+
.AddInMemoryCollection(inMemorySettings)
42+
.Build();
43+
44+
return new StorageProvider(configuration);
3545
}
3646
}
3747
}

0 commit comments

Comments
 (0)