How to secure the HTTP Callback mode

How to secure the HTTP Callback mode

This week, we are going to talk about the HTTP Callback mode. More particularly, how to authenticate a YoctoHub and to make sure that an intruder can't insert invalid data in your system.





Let's imagine that you wish to measure temperature, humidity and pressure in different locations. Thanks to the Yocto-Meteo and the YoctoHub-Wireless-g, you created several autonomous weather stations. You managed to configure the YoctoHub-Wireless-g for them to use the HTTP Callback and for them to connect themselves on your PHP script (www.exemple.com/http_callback.php) once per hour.

To differentiate the weather stations, you provide a location to your callback as a parameter on the URL. For example, the YoctoHub taking measures in Cartigny uses the following URL: www.exemple.com/http_callback.php?location=Cartigny

YoctoHub configuration for the Cartigny location
YoctoHub configuration for the Cartigny location



Your code probably looks something like this one:

// Sets up the API to work in HTTP Callback mode
if(YAPI::RegisterHub('callback', $errmsg) != YAPI_SUCCESS) {
    print("Unable to start the API in callback mode ($errmsg)");
    die();
}

// retrieves the location
$location = $_GET['location'];
...
$tempSensor = YTemperature::FirstTemperature();
$humSenor = YHumidity::FirstHumidity();
$pressSensor = YPressure::FirstPressure();
if ($tempSensor && $humSenor && $pressSensor) {
    $temp = $tempSensor->get_currentValue();
    $hum = $humSenor->get_currentValue();
    $pre = $pressSensor->get_currentValue();
    $timestamp = time();
    mysql_query("insert into weather "
        . "(timestamp,temperature,humidity,pressure, $location) "
        . "values ($timestamp,$temp,$hum,$pre,$location)");
}
...



This piece of code works well, and it is very similar to the one we used in a previous post :-)

However, it isn't possible to detect whether an intruder tries to upload invalid measures. Anyone knowing your callback URL can connect himself and add measures.

To solve this issue, let's have a look at several solutions:

  1. Checking the serial number of your or YoctoHub-Wireless-g in your PHP script.
  2. Enabling HTTP authentication on your PHP server.
  3. Using an MD5 signature.


Checking the serial number


This is the simplest method. You only need to keep a list containing the serial numbers of the Yoctopuce modules that you are using and to ignore unknown ones.

In the following example, we retrieve the temperature sensor serial number and we check that the serial number is included in our list.

$serial = $tempSensor->get_module()->get_serialNumber();
if (!validate_serial($serial)) {
    print("Unknown serial number: You are a hacker!");
    die();
}



Unfortunately, this solution is not very robust. If someone intercepts a communication, that person can find the serial number in the content sent by the YoctoHub-Wireless-g and then use it to skirt your test.

HTTP authentication


HTTP authentication allows you to identify yourself to the HTTP server using a user name and a password. This mechanism is not managed by the Yoctopuce library, but by the web server. The method to configure the user list and the HTTP passwords depends on the web server that you are using. Most hosts offer a web interface enabling your to perform this task very easily.

When you have configured you server to protect your callback script with a user name and a password, you must configure the YoctoHub-Wireless-g so that they use these identifiers. In the HTTP callback configuration window, select "HTTP Authentication" and fill in the "user" and "password" fields.

Example of an HTTP callback using HTTP authentication
Example of an HTTP callback using HTTP authentication



When the callback next runs, the YoctoHub-Wireless-g authenticates itself to the web server and posts new values. If the YoctoHub-Wireless-g doesn't provide the correct password, the web server rejects the connection even before running your script.

In the opposite to the previous solution, the password is never sent to the server (unless you use the "HTTP basic" authentication). Thus, even if someone listens in on the network traffic between a weather station and your server, that person cannot find the password.

This system also enables you to provide distinct user names and passwords for each weather station. This prevents you from having to change the configuration of all weather stations if a single password is discovered.

HTTP authentication provides a good means to authenticate a client on a server, but it remains vulnerable to a "man in the middle attack" type.

MD5 signature


The third method to authenticate a YoctoHub on a server is the MD5 signature. In the opposite to the HTTP authentication, this mechanism uses only a password that the two parties know. In this mode, the YoctoHub-Wireless-g signs the content that it sends with the MD5 algorithm. The MD5 signature is computed on the sent content AND on the Hub password. When the Yoctopuce library treats this content, it computes the MD5 signature on the received data and on the library password. When calling YAPI.RegisterHub, the library checks that this signature corresponds to the one sent by the Hub. If it is not the case, it returns an error. The password is never sent on the network, each party uses its own password.

Each party signs the content with its password
Each party signs the content with its password



To enable the MD5 signature on the YoctoHub-Wireless-g, you must select the "MD5 signature" as security type and enter the password in the HTTP callback configuration window.

HTTP callback example using the MD5 signature
HTTP callback example using the MD5 signature



On the server side, the password is given during the call to YAPI.RegisterHub with the following syntax: "md5:password@callback". For example, to check the signature with the "MyPaSSW0rD" password, you must use the following piece of code:

if(YAPI::RegisterHub('md5:MyPaSSW0rD@callback', $errmsg) != YAPI_SUCCESS) {
    print("Unable to start the API in callback mode ($errmsg)");
    die();
}



Computing the MD5 signature on the whole content sent to the server has some benefits. It helps you to detect a potential data corruption during communications. You can detect a "replay attack" because all the Yoctopuce modules post their internal clock: the MD5 signature is therefore automatically date stamped.

With some cunning, you can use a different password for each YoctoHub. As the whole request content is signed, you can add additional parameters in the URL. In the weather station example, you can define a unique password for each weather station and use the location given in the URL to find the corresponding password. In this example, the get_pass_from_location function asks the database for the password to be used for the location of the weather station.

$location = $_GET['place'];
$passwd = get_pass_from_location($location);

if(YAPI::RegisterHub('md5:'.$passwd.'@callback', $errmsg) != YAPI_SUCCESS) {
    print("Unable to start the API in callback mode ($errmsg)");
    die();
}



What about confidentiality?


So far, we have spoken about authentication but not about encryption. Indeed, our modules cannot encrypt the data transmitted over the network for now. A complete HTTPS support (up to date with current security standards) would be too large to fit in our devices without introducing more problematic limitations.

In real life, the privacy of measurements transmitted by callback is seldom the top priority. In the few cases where it would be needed, we recommend using one of the tiny industrial VPN-router available on the market, which offer a secure channel and encrypt all communications. These VPN offer a much better security than a limited HTTPS support. To handle intermediate cases where just a simple encryption would be desirable, we are working on a solutions than could encrypt the content of the HTTP callback payload without requiring a full HTTPS stack.

Conclusion


It is quite possible to secure the connection between a YoctoHub and your PHP code. The data sent between the YoctoHubs and the server can be listened to, but it is not possible to inject invalid data to your application.

Add a comment No comment yet Back to blog












Yoctopuce, get your stuff connected.