diff options
author | Christopher Smith <chris@jalakai.co.uk> | 2013-03-20 00:06:07 +0000 |
---|---|---|
committer | Christopher Smith <chris@jalakai.co.uk> | 2013-03-22 00:36:52 +0000 |
commit | 0f4e009215bfa3136d334fa557335266637a7585 (patch) | |
tree | 6a713cf999d4797534e5954c31e8b46654cc2db5 | |
parent | 2ab296805f9b647d3fe46cad4a7f275c45f171a8 (diff) | |
download | rpg-0f4e009215bfa3136d334fa557335266637a7585.tar.gz rpg-0f4e009215bfa3136d334fa557335266637a7585.tar.bz2 |
add a token to fetch urls requiring image resize/crop to prevent external DDOS via fetch
-rw-r--r-- | inc/common.php | 4 | ||||
-rw-r--r-- | inc/media.php | 24 | ||||
-rw-r--r-- | lib/exe/fetch.php | 8 |
3 files changed, 34 insertions, 2 deletions
diff --git a/inc/common.php b/inc/common.php index 471eb91b5..27f90b53b 100644 --- a/inc/common.php +++ b/inc/common.php @@ -436,6 +436,10 @@ function exportlink($id = '', $format = 'raw', $more = '', $abs = false, $sep = function ml($id = '', $more = '', $direct = true, $sep = '&', $abs = false) { global $conf; if(is_array($more)) { + // add token for resized images + if($more['w'] || $more['h']){ + $more['tok'] = media_get_token($id,$more['w'],$more['h']); + } // strip defaults for shorter URLs if(isset($more['cache']) && $more['cache'] == 'cache') unset($more['cache']); if(!$more['w']) unset($more['w']); diff --git a/inc/media.php b/inc/media.php index 2268ad877..7f2fd2d1d 100644 --- a/inc/media.php +++ b/inc/media.php @@ -1865,6 +1865,30 @@ function media_crop_image($file, $ext, $w, $h=0){ } /** + * Calculate a token to be used to verify fetch requests for resized or + * cropped images have been internally generated - and prevent external + * DDOS attacks via fetch + * + * @param string $id id of the image + * @param int $w resize/crop width + * @param int $h resize/crop height + * + * @author Christopher Smith <chris@jalakai.co.uk> + */ +function media_get_token($id,$w,$h){ + // token is only required for modified images + if ($w || $h) { + $token = auth_cookiesalt().$id; + if ($w) $token .= '.'.$w; + if ($h) $token .= '.'.$h; + + return substr(md5($token),0,6); + } + + return ''; +} + +/** * Download a remote file and return local filename * * returns false if download fails. Uses cached file if available and diff --git a/lib/exe/fetch.php b/lib/exe/fetch.php index a558a3db8..48aa22fe2 100644 --- a/lib/exe/fetch.php +++ b/lib/exe/fetch.php @@ -32,7 +32,7 @@ if(!defined('SIMPLE_TEST')) { } // check for permissions, preconditions and cache external files - list($STATUS, $STATUSMESSAGE) = checkFileStatus($MEDIA, $FILE, $REV); + list($STATUS, $STATUSMESSAGE) = checkFileStatus($MEDIA, $FILE, $REV, $WIDTH, $HEIGHT); // prepare data for plugin events $data = array( @@ -180,7 +180,7 @@ function sendFile($file, $mime, $dl, $cache, $public = false) { * @param $file reference to the file variable * @returns array(STATUS, STATUSMESSAGE) */ -function checkFileStatus(&$media, &$file, $rev = '') { +function checkFileStatus(&$media, &$file, $rev = '', $width=0, $height=0) { global $MIME, $EXT, $CACHE, $INPUT; //media to local file @@ -200,6 +200,10 @@ function checkFileStatus(&$media, &$file, $rev = '') { if(empty($media)) { return array(400, 'Bad request'); } + // check token for resized images + if (($width || $height) && media_get_token($media, $width, $height) !== $INPUT->str('tok')) { + return array(412, 'Precondition Failed'); + } //check permissions (namespace only) if(auth_quickaclcheck(getNS($media).':X') < AUTH_READ) { |