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.
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