mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-05-15 06:02:28 +00:00
Add security & testing for file uploads
This commit is contained in:
parent
d1093fdf8f
commit
e0d14232d8
4 changed files with 92 additions and 2 deletions
27
ProjectLighthouse.Tests/ExampleFiles/TestGarbage.bin
Normal file
27
ProjectLighthouse.Tests/ExampleFiles/TestGarbage.bin
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<EFBFBD><EFBFBD>N<EFBFBD><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD><EFBFBD>▒;ݎ<>soVy<56><79>ʖQ<CA96>▒<EFBFBD>9؋<39>L`<60>
|
||||||
|
m<EFBFBD>]<5D><> <20><>!<21>p<EFBFBD>x/JY@<40><>{<7B><><EFBFBD><EFBFBD><EFBFBD>Yj<59>G<EFBFBD><47>4<EFBFBD><34><EFBFBD>O<EFBFBD>c{<7B><>9<EFBFBD><39><EFBFBD>|n=<3D>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>З<EFBFBD>O<EFBFBD><4F>œRF<52><46><EFBFBD>{<7B><><EFBFBD><EFBFBD>SQ<53><51>Fх <20><><EFBFBD><EFBFBD><EFBFBD>0><3E> <20><>hλ37=<3D><>,<2C>f<EFBFBD><66><EFBFBD>
|
||||||
|
<EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><EFBFBD><EFBFBD><EFBFBD>^<5E>ݳrY<72><59>I<EFBFBD><49><EFBFBD><EFBFBD><EFBFBD>/<2F>^<5E>ue<75>ױ~WϮ<57><CFAE><EFBFBD>6ҝ)S</<2F>AP,<2C><>[n<><6E><EFBFBD><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD>j1ܗ׆<DC97><D786><EFBFBD><EFBFBD>v<EFBFBD>J"IS<49>_<EFBFBD><5F>\R<><52>
|
||||||
|
!<21><>,<2C>1#<23><>o<EFBFBD>)y<><79>ᰅu <20>J<EFBFBD><4A><EFBFBD>a<EFBFBD>>gQ<67>ǰ<EFBFBD>VF~]<5D>~<7E><><EFBFBD><EFBFBD>GY5<59><35>o04<30><34>s[<5B><>FgƄ|<7C><>;<3B>p<EFBFBD>.<2E>O<EFBFBD>[<5B><>>d<>ɉ<EFBFBD>C<EFBFBD><43>M<EFBFBD><4D>9<EFBFBD>T:<3A><>)<29>N<EFBFBD><4E>;z'<27><>7<EFBFBD>>,<2C><><EFBFBD><EFBFBD>cc<63>h0<68><30><EFBFBD>+<2B>c<EFBFBD><63>
|
||||||
|
B<><42>▒<EFBFBD><E29692>lTFH /<2F>*<2A>m<EFBFBD><6D>F<EFBFBD>W<EFBFBD>̚<EFBFBD><CC9A>Q<EFBFBD><51>q<EFBFBD><71>ϰ<EFBFBD>R{<7B><><EFBFBD>߂O{<7B><>_D<5F><44>mM<6D>!<21><><EFBFBD><EFBFBD>?<3F>i-1(<28><>fK<66><4B>▒&<26><><EFBFBD>&l<><6C><EFBFBD>nI<6E><49>/▒<>6<EFBFBD><36><EFBFBD>
|
||||||
|
<20>H<EFBFBD>6<EFBFBD><36>m<EFBFBD>Ԯ<EFBFBD><D4AE>,<2C>F<EFBFBD>zuT<75><54><EFBFBD>D<EFBFBD>%<25>d<EFBFBD>C<EFBFBD><43>Q)N<><4E>hS<68>}mZ<6D>~<7E>>x<><78><EFBFBD>@<40> "A<>O<EFBFBD>n<EFBFBD><6E> ¸<><C2B8>jbh<62><68>[<5B><><EFBFBD><EFBFBD>p<EFBFBD>V<EFBFBD><56>^+<2B><><EFBFBD><EFBFBD>r<EFBFBD>F<EFBFBD><46> <20>]<5D><><EFBFBD>m{<7B><><EFBFBD><EFBFBD>ҋ<EFBFBD>v<EFBFBD><76>4^QA+<2B><><EFBFBD><EFBFBD>X^O<>D<EFBFBD><44><EFBFBD><EFBFBD>`<60><><EFBFBD>\Y3<59>q#<23>j<EFBFBD><6A>#E<>n<EFBFBD><6E>[<5B>禽<EFBFBD><E7A6BD>BÙ
|
||||||
|
<EFBFBD>E";<3B>/<2F>`<60>jS/_<>j9Ƒ<39>
|
||||||
|
<20><><EFBFBD>?<3F><><EFBFBD><EFBFBD><EFBFBD>V<EFBFBD><56><EFBFBD>\<5C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>9M<39><4D>i<EFBFBD><69>;k(<28><><EFBFBD>Z#
|
||||||
|
k<><6B>w<EFBFBD>M<EFBFBD>O
|
||||||
|
<20>r
|
||||||
|
?<3F>s~<7E><>Ԑ<EFBFBD>]<5D>!<21>^<5E>'<27>Kw<4B><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD>q7<71><37>)<29><><EFBFBD>X<EFBFBD>j<EFBFBD>o&<26>|{0<><30>*2<><32><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
<EFBFBD>b<EFBFBD>&Jh<4A>▒<EFBFBD>y<EFBFBD><79>7<EFBFBD><37><EFBFBD><<3C><> <20><>ꝱϷ<EA9DB1>g
|
||||||
|
+~<7E><>&<26>1S<31>\x<>Wf<57><66>J<EFBFBD>Ԓݣpd<70>2=<3D>W<EFBFBD>Ub<55><62><EFBFBD><EFBFBD>i<EFBFBD>?
|
||||||
|
<20><>5<EFBFBD><35>ں}<7D><>j<EFBFBD>e#=գ<><D5A3>Q<EFBFBD><51><EFBFBD>5<EFBFBD>rX6<58><36><EFBFBD>*<><DD8B><EFBFBD><EFBFBD>
|
||||||
|
<20>у<EFBFBD>j:1f<31>MG<4D><47><EFBFBD><EFBFBD><EFBFBD>ϮZ<CFAE><5A>3<EFBFBD><33>7<EFBFBD><37>-<2D>q<EFBFBD><71><EFBFBD><EFBFBD><EFBFBD><EFBFBD>oaE+<2B><>▒ m<> <20><><EFBFBD><EFBFBD>Q<EFBFBD>/7<><37>`<60>x['<27>7<EFBFBD>
|
||||||
|
-<2D><>nFV桖<56><E6A196>1<EFBFBD>smP<6D><50>v<EFBFBD>;<3B>B<EFBFBD><42>>X<><58>u-
|
||||||
|
M<EFBFBD>p%<25>3<EFBFBD><33>k )<29>y<EFBFBD> <20><><EFBFBD>œ &Z<>$<24><>(<28>(<28>u<EFBFBD>z<EFBFBD>~<7E><><EFBFBD><EFBFBD>'B%<25>:<3A><><鍷<><E98DB7><EFBFBD>
|
||||||
|
<20><>T
|
||||||
|
<EFBFBD><EFBFBD>=<3D>v<EFBFBD><76><EFBFBD>r<EFBFBD>U<EFBFBD><55><EFBFBD><EFBFBD><EFBFBD><EFBFBD>▒)<29><><EFBFBD>m<EFBFBD><6D><EFBFBD>d,<2C><>q(f.<2E><><EFBFBD>ίv<CEAF>Rߏ <20><>:<3A>F <20><>&V<><56>wZ<77>E&<26><><EFBFBD><EFBFBD>D<EFBFBD><44><EFBFBD><EFBFBD>
|
||||||
|
i <20><>9<EFBFBD><39><EFBFBD>%<25><><EFBFBD><EFBFBD>w<EFBFBD><77>eM▒<4D><E29692>/qH~q@<40><<3C><>YH<59><48><EFBFBD>BLKx<4B>V<EFBFBD><56><EFBFBD>v<EFBFBD>
|
||||||
|
<20><>t<EFBFBD>U<EFBFBD>1<EFBFBD>I<EFBFBD><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>|K<>HL8<4C>G<EFBFBD>O<EFBFBD><4F><EFBFBD><EFBFBD><EFBFBD>6̆~<7E> <20>s)<29><>۹<EFBFBD>zM<7A><4D><EFBFBD>0cG9<47>(<28><><EFBFBD><EFBFBD>$v<>ʑd<CA91>Uy<55><79><EFBFBD>_Sn<53>><3E><>G<EFBFBD><47><EFBFBD><EFBFBD><EFBFBD>y<EFBFBD>\I*(<28><><EFBFBD>
|
||||||
|
<20>ĀI<C480><49><EFBFBD>x<EFBFBD>cє8<D194>%<25>!c<>ٮb▒l<E29692><6C><EFBFBD><EFBFBD>.M<>u<EFBFBD><<3C>$GPx.-<2D>
|
||||||
|
<20><EFBFBD><DEB7><EFBFBD>!eF9
|
||||||
|
H`)[<5B><><EFBFBD>▒<EFBFBD><E29692><EFBFBD><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD><67><EFBFBD>n<EFBFBD>6j <20>͓<EFBFBD>a<EFBFBD>eߞ'<27><><EFBFBD><EFBFBD> ><3E>`28<32><38>0<EFBFBD><30>Q5d/Ǥ<><C7A4>q<EFBFBD>8<EFBFBD><38>J<EFBFBD>赱r<E8B5B1>iD(<28><>*<2A><>Z<EFBFBD>
|
||||||
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>>K4<4B><34>G<EFBFBD>]<5D>q\<5C>}m<><6D>3<EFBFBD><33><EFBFBD><EFBFBD>)<29>s&<26><>[<5B><><EFBFBD><EFBFBD>1T!<21><>t<EFBFBD>=ӱl<D3B1>;$<24><><EFBFBD><EFBFBD>~<7E><>vH`
|
||||||
|
Z,K<DEB3>_<EFBFBD>F<EFBFBD>?K)<29><><EFBFBD>i<EFBFBD><69>Ի<*)<29>e<EFBFBD>=<3D><>`<60>/i͐+U<>d<EFBFBD><64><EFBFBD>i<EFBFBD><69><EFBFBD><EFBFBD><EFBFBD>Wҭ<57><D2AD><EFBFBD>h<EFBFBD>[̃䝍<CC83>}<7D><>:<3A><><EFBFBD>Z<EFBFBD><5A><EFBFBD>υq<CF85>ɂnRcrx깼36<33><36>b<EFBFBD><62>9<EFBFBD>-"{<7B>a^j;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5>f<EFBFBD>[<5B><>̓o<CD83><6F><EFBFBD><EFBFBD>D`)<29><><EFBFBD><EFBFBD>F7<46><37>ݩ/<2F><>><3E><><EFBFBD><EFBFBD>h<EFBFBD><68>r<EFBFBD><72>M1<4D><31>(Tc0E4
|
||||||
|
Ol<4F>O<EFBFBD><4F>ƷB<C6B7>c桩<63><E6A1A9>ًM[<5B>{<7B><><EFBFBD>><3E>A^C
|
|
@ -47,5 +47,15 @@ namespace ProjectLighthouse.Tests {
|
||||||
|
|
||||||
return this.Client.SendAsync(requestMessage);
|
return this.Client.SendAsync(requestMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<HttpResponseMessage> UploadFileRequest(string endpoint, string filePath) {
|
||||||
|
return await this.Client.PostAsync(endpoint, new StringContent(await File.ReadAllTextAsync(filePath)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<HttpResponseMessage> AuthenticatedUploadFileRequest(string endpoint, string filePath) {
|
||||||
|
using var requestMessage = new HttpRequestMessage(HttpMethod.Post, endpoint);
|
||||||
|
requestMessage.Content = new StringContent(await File.ReadAllTextAsync(filePath));
|
||||||
|
return await this.Client.SendAsync(requestMessage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
44
ProjectLighthouse.Tests/Tests/UploadTests.cs
Normal file
44
ProjectLighthouse.Tests/Tests/UploadTests.cs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace ProjectLighthouse.Tests {
|
||||||
|
public class UploadTests : LighthouseTest {
|
||||||
|
public UploadTests() {
|
||||||
|
string assetsDirectory = Path.Combine(Environment.CurrentDirectory, "r");
|
||||||
|
if(Directory.Exists(assetsDirectory)) Directory.Delete(assetsDirectory, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ShouldNotAcceptScript() {
|
||||||
|
HttpResponseMessage response = await UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/scriptTest", "ExampleFiles/TestScript.ff");
|
||||||
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ShouldNotAcceptFarc() {
|
||||||
|
HttpResponseMessage response = await UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/farcTest", "ExampleFiles/TestFarc.farc");
|
||||||
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ShouldNotAcceptGarbage() {
|
||||||
|
HttpResponseMessage response = await UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/garbageTest", "ExampleFiles/TestGarbage.bin");
|
||||||
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ShouldAcceptTexture() {
|
||||||
|
HttpResponseMessage response = await UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/textureTest", "ExampleFiles/TestTexture.tex");
|
||||||
|
Assert.True(response.IsSuccessStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ShouldAcceptLevel() {
|
||||||
|
HttpResponseMessage response = await UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/levelTest", "ExampleFiles/TestLevel.lvl");
|
||||||
|
Assert.True(response.IsSuccessStatusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using ProjectLighthouse.Helpers;
|
||||||
using ProjectLighthouse.Serialization;
|
using ProjectLighthouse.Serialization;
|
||||||
|
using ProjectLighthouse.Types.Files;
|
||||||
using IOFile = System.IO.File;
|
using IOFile = System.IO.File;
|
||||||
|
|
||||||
namespace ProjectLighthouse.Controllers {
|
namespace ProjectLighthouse.Controllers {
|
||||||
|
@ -34,11 +37,17 @@ namespace ProjectLighthouse.Controllers {
|
||||||
// TODO: check if this is a valid hash
|
// TODO: check if this is a valid hash
|
||||||
[HttpPost("upload/{hash}")]
|
[HttpPost("upload/{hash}")]
|
||||||
public async Task<IActionResult> UploadResource(string hash) {
|
public async Task<IActionResult> UploadResource(string hash) {
|
||||||
string path = Path.Combine(Environment.CurrentDirectory, "r", hash);
|
string assetsDirectory = Path.Combine(Environment.CurrentDirectory, "r");
|
||||||
|
string path = Path.Combine(assetsDirectory, hash);
|
||||||
|
|
||||||
|
if(!Directory.Exists(assetsDirectory)) Directory.CreateDirectory(assetsDirectory);
|
||||||
if(IOFile.Exists(path)) this.Ok(); // no reason to fail if it's already uploaded
|
if(IOFile.Exists(path)) this.Ok(); // no reason to fail if it's already uploaded
|
||||||
|
|
||||||
|
LbpFile file = new(Encoding.ASCII.GetBytes(await new StreamReader(Request.Body).ReadToEndAsync()));
|
||||||
|
|
||||||
|
if(!FileHelper.IsFileSafe(file)) return this.UnprocessableEntity();
|
||||||
|
|
||||||
await IOFile.WriteAllTextAsync(path, await new StreamReader(Request.Body).ReadToEndAsync());
|
await IOFile.WriteAllBytesAsync(path, file.Data);
|
||||||
return this.Ok();
|
return this.Ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue