0

I am trying to secure a byte serving script, written in PHP, mostly taken from http://www.tuxxin.com/php-mp4-streaming/ to protect against linking the video directly and easy downloading. I therefore have placed the video outside the public http-root. The pseudo-streaming itself works perfectly fine.

The pages structure like this:
mysite.com/watchvideo.php:

<video>
  <source src="/media.php?t=<?= $t = Token::generate(); ?>" type="video/mp4">
</video>

mysite.com/media.php:

$token = isset($_GET["t"]) ? $_GET["t"] : "";

if (
    !Token::check($token)
    || $_SERVER["HTTP_REFERER"] !== "mysite.com/watchthisawesomevideo.php"
    ) {
        header("HTTP/1.1 403 Forbidden");
        exit;
}

do_the_byte_range_stuff();              // from tuxxin.com

The Token class simply generates a random string, saves it in the php-session and returns it, respectively when checking compares the parameter to the token stored in $_SESSION.

With this method I have the problem that some browsers, like stock and chrome 47 on Android 4.1.2 seem to hand over the streaming to some different process, therefore losing the HTTP_REFERER (possibly related: android issue 1780). If I unset the token on checking it subsequent requests to media.php get abortet. Same goes if I set a time limit for the token.

Once this is sorted I would hide the video and mirror its content onto a canvas.

What would be suitable security measures to protect against downloading the video file and making media.php inaccessible? I know there can't be absolute protection, but I want to make it reasonably difficult.

Edit: Please note that I am not looking for some form of DRM for the video as I know it could be simply recorded off the screen. I am looking for ways to get the video to the watchvideo-page making it only accessible from there and preventing hotlinking.

7
  • This is a hard question for us to answer as the definition of "reasonably difficult" is rather unclear. Jan 26, 2016 at 17:08
  • If the video is being transferred to the client, it's going to be relatively simple to grab the stream of data - Chrome will even let you save the file, even if it arrives through the PHP method above, which seems to be geared up to preventing other sites abusing the original site's bandwidth by embedding the video. It doesn't prevent downloading it at all.
    – Matthew
    Jan 26, 2016 at 17:14
  • If a client can play the video, he can save the video. You can make it difficult, but there's a lot of ways to bypass your measures. People recording Netflix is a proof of this.
    – ThoriumBR
    Jan 26, 2016 at 17:48
  • Please don't focus on the video itself, I know you could simply record it off the screen or grab the cache. What I'd like to know is how to handle media.php.
    – YPOC
    Jan 26, 2016 at 17:57
  • So if I'm reading this properly, you want to put an access control on media.php to ensure that the content only gets served through watchvideo.php?
    – Ohnana
    Jan 26, 2016 at 20:03

1 Answer 1

1

You can set a cookie when the user requests watchvideo.php, containing a hash of values identifying the client, like user agent, IP address, and so:

<?php
 $ip = $_SERVER['REMOTE_ADDR'];
 $browser = implode(':', $_SERVER['HTTP_USER_AGENT']);
 $userFingerprint = md5($browser . $ip);
 setcookie('userdata', $userFingerprint, time() + 10); //expires in 10 sec
?>

On media.php, you read the cookie back:

<?php
 $ip = $_SERVER['REMOTE_ADDR'];
 $browser = implode(':', $_SERVER['HTTP_USER_AGENT']);
 $userFingerprint = md5($browser . $ip);
 if ($_COOKIE['userdata'] != $userFingerprint) {
    header("HTTP/1.1 403 Forbidden");
    exit;
 }
 do_the_byte_range_stuff();
?>

I used MD5, because I don't care about collisions here, I just want a fast hash. You can go overkill and employ BCrypt or PBKDF2, but you absolutely don't have to.

2
  • Thank you for your answer, but with this solution there's still the problem that subsequent requests to media.php (i.e. buffering) get forbidden and directly opening media.php is possible for 10 seconds.
    – YPOC
    Jan 27, 2016 at 14:35
  • @YPOC you could set a long lasting cookie on media.php, so buffering would not be broken. Opening watchvideo.php during this interval could clean the cookie, so the client could only watch one video at a time on one browser.
    – ThoriumBR
    Jan 28, 2016 at 20:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .