javascriptphpdatetimeexec

PHP exec date -s runs fine but does not update datetime


Here my simple PHP file:

<?php
if (strtoupper($_SERVER['REQUEST_METHOD']) === 'POST') {
    if (isset($_POST['datetime'])) {
        $datetime = htmlspecialchars($_POST['datetime']);
        $datetime[10] = ' ';
        $datetime = substr($datetime, 0, 19);
        die (json_encode(exec('date -s' . escapeshellarg($datetime))));
    }
}

here the javascript snippet that sends data:

function syncTime() {
    let data = new FormData();
    data.set("datetime", new Date().toISOString());

    fetch("datetime.php", {
        method: 'POST',
        body: data
    })
        .then(response => response.json())
        .then(json => console.log(json));
        .catch(err => console.log('Request Failed', err));
}

The sent content is like this:

2023-09-08T20:49:28.696Z

after cleaning it up $datetime looks like:

2023-09-08 20:49:28

hence the executed command is:

date -s "2023-09-08 20:49:28"

the command is successfully executed because I receive back the output:

Fri Sep  8 20:49:28 UTC 2023

but checking the actual date on server reveals the command was not actually executed:

# date
Thu Jan  1 08:34:07 UTC 1970

But if I manually type the very same command above it works:

# date -s "2023-09-08 20:49:28"
Fri Sep  8 20:49:28 UTC 2023
# date
Fri Sep  8 20:49:28 UTC 2023

What is happening here? I'm working on Linux for Raspberry Pi 3 and apache2 is running as root.


Solution

  • the command is successfully executed because I receive back the output:

    Fri Sep  8 20:49:28 UTC 2023
    

    This is not necessarily true. You can't determine success based on output. If you check the exit status of the command (by passing $result_code as a parameter to exec()), you'll likely find it to be non-zero (indicating an error).

    apache2 is running as root

    This is almost certainly not true. It's running as www-data or some other non-priv user. So when it execs the script, it doesn't have permission to set the clock. However, the date command still outputs the date in this case, which is what you're seeing. If you were to capture stderr as well, you'd get:

    date: cannot set date: Operation not permitted
    Fri Sep  8 08:49:28 PM EDT 2023