📜 ⬆️ ⬇️

Undocumented secure_link features

Starting from version 0.8.50 in Nginx secure_link module there has been a significant improvement in protecting links from counterfeiting. Oddly enough, the new features are still not reflected in the official documentation [ 1 ]. The description in English can be found on the Nginx Community site [ 2 ], as well as Sysoev’s explanations regarding these changes [ 3 ]. PHP code for generating secure links can be found in the nginx forum [ 4 ].
In general, the innovation looks like this:

nginx.conf:
 location ~ ^ / p / (? <secure> [\ w -] +, \ d +) / (? <secured_stuff>. +) $ {
      secure_link $ secure; 
      # in this example '$ secure' = "HASH, TIMESTAMP"
      secure_link_md5 PASSWORD $ secure_link_expires $ secured_stuff;
      # '$ secure_link_expires' is a nginx variable containing the value after the comma from 'secure_link' = TIMESTAMP

      if ($ secure_link = "") {return 403;  } # invalid link
      if ($ secure_link == 0) {return 410;  } # expired link
     
      # link is ok, do something here
 }


The URL might look like: / p / HASH, TIMESTAMP / ANYTHING where
PASSWORD secret password
TIMESTAMP is the time to which the link in unix epoch is valid.
ANYTHING arbitrary text
Base64-URL-encoded HASH [ 5 ] md5 hash from the secure_link_md5 template ($ secured_stuff = ANYTHING in this example). The characters '=' after base64 can be omitted
')
Nginx has a couple of implicit nuances in md5 sum calculation:
1. the string to be counted from the URL ($ secured_stuff) is decoded from the URL encoding to the original view
2. md5 hash should be transmitted in binary format for encoding to base64

PHP code can be like this:
$time = time() + EXPIRE_TTL; # = TIMESTAMP $hash = md5(PASSWORD.$time.$secured_stuff, true); $hash = strtr( base64_encode($hash), array( '+' => '-', '/' => '_', '=' => '' )); $url = 'http://example.tld/p/$hash.','.$time.'/'.$secured_stuff; 


Arguments and cookies can also be used to transfer hash and time:
for a URL like
  http://example.com/p/files/top_secret.pdf?st=PIrEk4JX5gJPTGmvqJG41g&e=1324527723 

where the argument st is a hash of PASSWORD, the URI and the argument e
location views
 
 location / p / {
      secure_link $ arg_st, $ arg_e;  # this must match the URI part related 
      secure_link_md5 PASSWORD $ uri $ arg_e;  # PASSWORD is the secret token
      ....
 }

As it is not difficult to guess, you can use the client’s IP address when generating the hash.

References:
[1] sysoev.ru/nginx/docs/http/ngx_http_secure_link_module.html
[2] wiki.nginx.org/HttpSecureLinkModule
[3] nginx.org/pipermail/nginx/2010-September/022324.html
[4] forum.nginx.org/read.php?21 , 126363,128324 # msg-128324
[5] en.wikipedia.org/wiki/Base64#URL_applications

Source: https://habr.com/ru/post/120907/


All Articles