I have been tasked with adding security to an application after it failed an audit. one of the issues are unrestricted file uploads.
I have set the allowed file types in the JavaScript and it correctly dis-allows the user to upload file types of .exe,
$('#up_ItemImg').fineUploader({
button: $('#up_ItemImg'),
uploaderType: 'basic',
request: {
endpoint: '/Admin/_customer/CustomerWS.ashx?method=SaveImage&customerID=' + customerID
},
validation: {
allowedExtensions: ['jpeg', 'jpg', 'png', 'bmp', 'gif', 'tiff'],
sizeLimit: 5242880 // 5 MB = 1024 * 1024 * 5 bytes
},
}).on('complete', function (event, id, fileName, responseJSON) {
if (responseJSON.success) {
$("#imgCustomerLogo").attr("src", responseJSON.data);
}
}).on('error', function (id, name, errorReason, errorReason2) {
if (errorReason2 == 'Upload failure reason unknown') {
return;
}
if (errorReason2.indexOf('XHR returned response code') == 0) {
return;
}
alert(errorReason2);
});
problem comes in, if you use something like fiddler and modify that request, changing the .jpg to .exe and re-executing the request it succeeds.
I am a bit out of my depth here to be honest, How would I go about stopping something like that from happening?
Related
I have used this angular azure blob service for uploading blob (image) on azure storage.
This is uploading image successfully on azure storage but if we look into the azure account there is a folder created with the selected image name instead of the actual image.
upload() {
if (this.currentFile !== null) {
const baseUrl = this.blob.generateBlobUrl(
this.Config,
this.currentFile.name
);
console.log(baseUrl);
this.config = {
baseUrl: baseUrl,
sasToken: this.Config.sas,
blockSize:
this.currentFile.size > 1024 * 1024 * 32
? 1024 * 1024 * 4
: 1024 * 512, // OPTIONAL, default value is 1024 * 32
file: this.currentFile,
complete: () => {
console.log("Transfer completed !");
},
error: err => {
console.log("Error:", err);
},
progress: percent => {
console.log("Transfer completed =", percent);
// this.percent = percent;
}
};
console.log(this.config);
this.blob.upload(this.config);
}
}
This is the upload function responsible for upload the image. Please let me know what is wrong here.
I am using this with angular 8.
This is the Github link for the NPM source code.
Following is my config objct containing SAS token details:
Config: UploadParams = {
sas:
"https://demo.blob.core.windows.net/?sv=2019-02-02&ss=bfqt&srt=sco&sp=rwdlacup&se=2020-04-13T22:29:27Z&st=2020-04-13T14:29:27Z&spr=https,http&sig=PBJ62e8SU5%2FAef5Npmun5nvzZanb5UbVXqhJ17U1bGE%3D",
storageAccount: "demo",
containerName: "demo-images"
}
I believe the problem is in the name of the blob. Assuming you copied the blob name correctly in one of the comments, it is coming up as:
https://demo.blob.core.windows.net/demo-images/download.jpghttps:/
If you notice, there is a trailing slash (/) in your blob name and because of this the portal UI (or for that matter any other Storage Explorer UI) will treat this as a virtual folder and hence you're seeing this as a folder.
Please check your code again specifically how you're setting the name of the blob. It should be https://demo.blob.core.windows.net/demo-images/download.jpg.
UPDATE
As I suspected, there's an issue with the sas parameter in your config object. You're passing SAS URL instead of SAS Token. Please change your sas parameter to something like:
?sv=2019-02-02&ss=bfqt&srt=sco&sp=rwdlacup&se=2020-04-13T22:29:27Z&st=2020-04-13T14:29:27Z&spr=https,http&sig=PBJ62e8SU5%2FAef5Npmun5nvzZanb5UbVXqhJ17U1bGE%3D
I am trying to upload a sound file from ngCordova's $cordovaCapture service to UploadCare. The uploadcare.fileFrom('object') keeps failing with an'upload' error. I have the public key set. I am able to upload the file by sending it through and tag and accessing document.getElementById('fileTag').files[0].
$cordovaCapture.captureAudio()
.then(function (audioData) {
return uploadcare.fileFrom('object', audioData[0])
.done(function (fileInfo) {
console.log(fileInfo);
}).fail(function (err) {
console.log(err);
})
})
the audioData[0] object looks like this
MediaFile {
end:0
fullPath:"file:/storage/emulated/0/Sounds/Voice%20002.m4a"
lastModified:null
lastModifiedDate:1481324751000
localURL:"cdvfile://localhost/sdcard/Sounds/Voice%20002.m4a"
name:"Voice 002.m4a"
size:49227
start:0
type:"audio/mpeg"
} __proto__:File
I thought the problem might be that the object is a MediaFile rather than a File but I could use some help casting one to the other.
FileEntry
filesystem:FileSystem
fullPath:"/Sounds/Voice 002.m4a"
isDirectory:false
isFile:true
name:"Voice 002.m4a"
nativeURL:"file:///storage/emulated/0/Sounds/Voice%20002.m4a"
__proto__:Entry
File
end:49227
lastModified:1481324751000
lastModifiedDate:1481324751000
localURL:"cdvfile://localhost/sdcard/Sounds/Voice%20002.m4a"
name:"Voice 002.m4a"
size:49227
start:0
type:"audio/mpeg"
__proto__:Object
using window.resolveLocalFileSystemUrl() you end up with the above FileEntry object that give the above File object but uploadcare still fails with an "upload" error.
Using ngCordova $cordovaFileTransfer() you can send audio files to uploadcare.
var fileName = filePath.split('/').pop();
var uploadcareOptions = {
fileKey: "file",
fileName: fileName,
chunkedMode: false,
mimeType: 'audio/mp4',
params: {
"UPLOADCARE_PUB_KEY": "upload-care-public-key",
"UPLOADCARE_STORE": 'auto',
fileName: fileName
}
};
return $cordovaFileTransfer.upload('https://upload.uploadcare.com/base/', filePath, uploadcareOptions)
The important part is to specify the mime type when sending files as uploadcare will assume it's a image otherwise.
uploadcare.fileFrom uploads a file from a native file object. Try this:
window.resolveLocalFileSystemURL(audioData[0].localURL,function(fileEntry){
fileEntry.file(function(file) {
uploadcare.fileFrom('object', file);
...
});
});
In Chrome Apps, I'm downloading a blob content from a server using JavaScript XHR (Angular $http GET in particular, with response type 'blob')
How should I save this to chrome application's file system?
Currently using an Angular wrapper on HTML5 filesystem API
https://github.com/maciel310/angular-filesystem
I do not want to show user a popup (hence I can't use chrome.fileSystem. chooseEntry )
The chrome.fileSystem.requestFileSystem API is only supported by Kiosk-only apps.
Hence I'm using HTML5 FileSystem API instead of chrome's.
I'm using following code to make XHR to fetch blob.
$http({
url: SERVER_URL+"/someVideo.mp4",
method: "GET",
responseType: "blob"
}).then(function(response) {
console.log(response);
fileSystem.writeBlob(response.name, response).then(function() {
console.log("file saved");
}, function(err) {
console.log(err);
});
}, function (response) {
});
This is my writeBlob method
writeBlob: function(fileName, blob, append) {
append = (typeof append == 'undefined' ? false : append);
var def = $q.defer();
fsDefer.promise.then(function(fs) {
fs.root.getFile(fileName, {create: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
if(append) {
fileWriter.seek(fileWriter.length);
}
var truncated = false;
fileWriter.onwriteend = function(e) {
//truncate all data after current position
if (!truncated) {
truncated = true;
this.truncate(this.position);
return;
}
safeResolve(def, "");
};
fileWriter.onerror = function(e) {
safeReject(def, {text: 'Write failed', obj: e});
};
fileWriter.write(blob);
}, function(e) {
safeReject(def, {text: "Error creating file", obj: e});
});
}, function(e) {
safeReject(def, {text: "Error getting file", obj: e});
});
}, function(err) {
def.reject(err);
});
return def.promise;
},
This shows SECURITY_ERR as It was determined that certain files are unsafe for access within a Web application, or that too many calls are being made on file resources.
What's the solution for this?
I've tried using --allow-file-access-from-files flag while launching app. It doesn't help.
Chrome Application's sandbox storage doesn't allow files to be stored in root directory (i.e. / )
Modify the code to save it in a specific sub-directory under it.
For example -
fileSystem.writeBlob("/new"+response.name, response).then(function() {
console.log("file saved");
}, function(err) {
console.log(err);
});
This would successfully save the file under /new/ directory.
To expand on this, here is a full example app on how to download a file and save the blob and display it back to the user.
https://github.com/PierBover/chrome-os-app-download-example
Hello I'm using EAjaxUpload extension to upload files and its working perfectly and files are uploaded I want to add a description to each file. I used the onComplete to have the function here's my code :
$uploadfile = $this->widget('ext.EAjaxUpload.EAjaxUpload',
array(
'id' => 'uploadFile',
'config' => array(
'action' => Yii::app()->createUrl('objective/upload'),
'allowedExtensions' => array("docx", "pdf", "pptx"),//array("jpg","jpeg","gif","exe","mov" and etc...
'sizeLimit' => 5 * 1024 * 1024,// maximum file size in bytes
//'minSizeLimit'=>10*1024*1024,// minimum file size in bytes
'onComplete' => "js:function(id, fileName, responseJSON){
console.log(responseJSON);
var filedescription= prompt('file description');
if (filedescription != null) {
document.getElementById('demo').innerHTML =
filedescription;
return filedescription;
}
}",
//'messages'=>array(
// 'typeError'=>"{file} has invalid extension. Only {extensions} are allowed.",
// 'sizeError'=>"{file} is too large, maximum file size is {sizeLimit}.",
// 'minSizeError'=>"{file} is too small, minimum file size is {minSizeLimit}.",
// 'emptyError'=>"{file} is empty, please select files again without it.",
// 'onLeave'=>"The files are being uploaded, if you leave now the upload will be cancelled."
// ),
'showMessage' => "js:function(message){ alert(message); }"
)
));
Now I want to return var filedescription to upload action in controller. How can I do that?
Thanks,
1.onComplete is called after your upload request is already processed by "objective/upload" action. So you have possibility to ask and set description as parameter BEFORE request:
'onSubmit' => "js:function(id, fileName){
// add filedescriton to post parameters:
this.params.filedescription = 'some file description';
}"
In controller "objective/upload" action you can access it as $_POST['filedescription'].
2.Other possibility is to create separate action for saving description (and additional file processing...) and call it from onComplete:
In onComplete:
$.post( 'saveUploadedFileDescription', { filedescription: 'some file description', fileName: fileName } );
In controller:
actionSaveUploadedFileDescription($filedescription,$filename) {
// ....
}
I am trying to setup a test implementation of FineUploader, but I am running into a problem with chunking. I have debug set to true, and everything seems to be going great until the very end of the process where I get the following errors:
"[Fine Uploader 5.0.2] All chunks have been uploaded for 0 - finalizing...." custom.fineuploader-5.0.2.js:207
"[Fine Uploader 5.0.2] Submitting All Chunks Done request for 0" custom.fineuploader-5.0.2.js:207
"[Fine Uploader 5.0.2] Sending POST request for 0" custom.fineuploader-5.0.2.js:207
"[Fine Uploader 5.0.2] Received response status 200 with body: {"error":"Server error. Not a multipart request. Please set forceMultipart to default value (true).","uploadName":null,"template":"undefined","category":"undefined"}" custom.fineuploader-5.0.2.js:207
"[Fine Uploader 5.0.2] Finalize successful for 0"
The bottom error says "Server error. Not a multipart request. Please set forceMultipart to default value (true).", but as far as I can tell my code it setup that way already. Here is what I have in the code for it:
var uploadHandler = $('#fine-uploader').fineUploader({
debug: true,
request: {
endpoint: 'server/endpoint.php',
forceMultipart: true,
params: // send the values to backend file (endpoint.php)
{
template:function() {
return $("#price_template_id").val();
},
category:function(){
return $("#category_id").val();
}
}
},
validation: { // validation for the images uploaded
allowedExtensions: ['jpeg', 'jpg'],
sizeLimit: 20971520 // 20 MB = 20 * 1024 * 1024 bytes 20971520
},
editFilename: {
enabled: true
},
display: { //display image on upload
fileSizeOnSubmit: true
},
resume: { //enable resume on upload
enabled: true
},
retry: { //enable retry on upload
enableAuto: true
},
forceMultipart: {
enabled: true
},
chunking: { //enable chunking on upload
concurrent: {
enabled: true
},
enabled: true,
partSize: 200000, //200KB per chunk
success: {
endpoint: 'server/endpoint.php'
}
},
template: "qq-template",
autoUpload: true,
showMessage: function(message) { //show message if any error occur during uplaod process
alert(message);
}
})
You can see/test the implementation here: http://web3.instaproofs.com/temp/fineuploaderv3/
Any ideas on what I am doing wrong with this?
Thanks!
Your server is not properly handling the "all chunks done" POST request. This is not a multipart encoded request. It is sent by Fine Uploader after the last chunk has successfully been uploaded to the server. This POST contains a URL-encoded message-body with information about the completed chunked file. Your server should combine all chunks associated with the file and then respond appropriately. More info at http://docs.fineuploader.com/branch/master/features/concurrent-chunking.html#server-side-implications.