How to safely write JSON data to file using PHP

2019-03-12 13:52发布

问题:

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;
}

回答1:

First of all: JSON is not JavaScript and vice versa. And JSON is even not a proper subset of JavaScript.

Besides that, since you neither interpret some user input as PHP nor some output as JavaScript, there is no need to worry. But don’t forget to specify your output properly:

header('Content-Type: application/json;charset=utf-8');
$s = file_get_contents('config.txt');
echo json_encode($s);


回答2:

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.



回答3:

I would always check the data returned to see if it is in a format I expect. Say you are saving an image... Check it using MIME checks etc. to make sure that it is an image. If you just save data as is on the server you could open the door for some potential security issues.

If you mean that you just save data about which images was viewed it could still pose a problem depending on how and where that data is accessed and used. So if you except an integer and nothing more, make sure that the data you receive and save is an integer and nothing more.