Search code examples
javascriptjqueryajaxcoldfusioncfc

Delete file using Coldfusion via jQuery ajax


I am trying to delete image files, after populating data about the file in a modal.

My jQuery looks like this:

const deleteMedia = () => {
    const url = '../../includes/delete-media.cfc?method=deleteMedia';
    $(document).on('click', '.confirm-delete', () => {
        const fileName = $('.modal-wrapper').find('.file-name').text();
        $.ajax({
            url,
            type: 'POST',
            data: 'fileName=' + fileName,
            dataType: 'json',
            success(data) {
                console.log(data);
            },
            error(status) {
                console.log(status.statusText);
            }
        });
        return false;
    });
};

export default deleteMedia;

And my Coldfusion file delete-media.cfc:

<cffunction name="deleteMedia" access="remote" returnType="any" returnformat="json">
    <cfargument name="fileName" >
    <cfset requestBody = toString( getHttpRequestData().content ) />
    <!--- Double-check to make sure it's a JSON value. --->
    <cfif isJSON( requestBody )>
        <cfset VARIABLES.DeleteFileName = deserializeJSON( requestBody )>
        <cffile
            action = "delete"
            file = "C:\pathToSite\img\#variables.DeleteFileName#"
        >
        <cfdump var="#variables.DeleteFileName#">
    </cfif>
</cffunction>

This is sending fileName = fileName as data when I check in the Network panel, and returning a 200, although I cannot see contents of the cfdump.

I am OK with the FE, not so hot on CF, my guess is that my CF is overly complex but also not doing what I hope it would do. I did try and reference some stuff I wrote a while back, plus this:

How to use Ajax to pass Javascript variables to Coldfusion?

And this:

Passing and returning ColdFusion Structure via JQuery

Any ideas?


Solution

  • Yeah, this is still problematic that you're passing a file name as part of the request. Someone can get in there are wreak havoc with your files. Are you verifying that the file in question should even be accessible by the logged-in user? What if they pass in the value of someone else's file? This also seems vulnerable to a path traversal attack. If you pass in `filename=../../someReallyImportaintFile', will that be deleted? owasp.org/www-community/attacks/Path_Traversal

    If this is a personal site and not a business site, there's probably not much to worry about. If this was a client's site, I'd be more concerned.

    In Windows, I have Steam installed here:

    `D:\Steam\`. 
    

    I can open this path in Windows Explorer:

    `D:\Steam\bin`. 
    

    I can also open this path,

    `D:\Steam\bin\..\config`
    

    which lists D:\Steam\config

    If I fish around with

    `deleteFileName=..\..\Windows\some\folder\someFile` 
    

    I might be able to delete files from your Windows directory if your server permissions aren't set up to prevent CF from deleting anything on the server.

    Your CF user should not be the server's admin account, There are lockdown guides that can help prevent all kinds of security attacks.

    Ideally, you would store a list of your files in a database table and then reference a FileID as your delete request parameter.

    $(document).on('click', '.confirm-delete', () => {
        $.ajax({
            url,
            type: 'POST',
            data: 'fileID=' + $('#SomeHiddenField').val(),
            success(data) {
                console.log(data);
                hideOverlay();
            },
            error(status) {
                console.log(status.statusText);
            }
        });
    });
    

    Then, on the server, in best case scenario you verify

    • is the user logged in?
    • do they have access to this file?
    • do they have permission to delete this file?
    • Delete the physical file
    • Mark the record as deleted with the time it was deleted and by whom.