How to safely write JSON data to file using PHP

Max Barnas picture Max Barnas · May 31, 2011 · Viewed 38.7k times · Source

I've got HTML form for editing images. All data is stored in JSON. When I change current image, I want to save changes, through PHP script, to a text file. If I return to previous image, this configuration will be send again from this file to the form.

My question is:

How to write/read this kind of data safely. Where and how effectively check data to prevent some JS/PHP code injections?

I have attached some concept code below:

JavaScript (using jQuery):

// Writing
$.ajax({
    global: false,
    type: "POST",
    cache: false,
    dataType: "json",
    data: ({
        action: 'write',
        config: JavaScriptJSON_Obj
    }),
    url: 'read-write.php'
});

// Reading
$.ajax({
    global: false,
    type: "POST",
    cache: false,
    dataType: "json",
    data: ({
        action: 'read'
    }),
    url: 'read-write.php',
    success: function(data){
        JavaScriptJSON_Obj = data;
    }
});

PHP example (read-write.php):

switch ($_REQUEST['action']) {
    case 'write':
        file_put_contents('config.txt', $_REQUEST['config']);
        break;
    case 'read':
        $s = file_get_contents('config.txt');
        echo json_encode($s);
        break;
}

Answer

Jakob Egger picture Jakob Egger · May 31, 2011

The problem with your code is that it won't work, security issues aside. You must either serialize the data, or encode it to json BEFORE storing it in a file, ie. like this:

switch ($_REQUEST['action']) {
    case 'write':
        file_put_contents('config.txt', json_encode($_REQUEST['config']));
        break;
    case 'read':
        readfile('config.txt');
        break;
}

Serialising works like this:

switch ($_REQUEST['action']) {
    case 'write':
        file_put_contents('config.txt', serialize($_REQUEST['config']));
        break;
    case 'read':
        $data = unserialize(file_get_contents('config.txt'));
        echo json_encode($data);
        break;
}

As long as you make sure that the path you read/write to is correct, there are no code injection problems with this code. The only potential problem is if you can choose what file to use (rather than hardcode "config.txt" into the code). Then you'd have to validate to make sure the file is in a given directory etc.