Skip to content

Commit 07e14bb

Browse files
committed
Fixes file disclosure vulnerability in image_resized.php
- Do not allow protocol handlers or absolute paths - Force absolute paths related to the current directory - Some minor changes
1 parent 5539dcb commit 07e14bb

1 file changed

Lines changed: 74 additions & 56 deletions

File tree

image_resized.php

Lines changed: 74 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -11,70 +11,93 @@
1111

1212
// <img src="image_resized.php?format=jpg&w=100&h=200&q=85&imgfile=test.jpg" alt="" border="0">
1313

14-
$img_target = (isset($_GET['format'])) ? strtolower(trim($_GET['format'])) : 'jpg';
15-
$img_file = (isset($_GET['imgfile'])) ? trim($_GET['imgfile']) : 'img/leer.gif';
16-
$img_width = (isset($_GET['w'])) ? intval($_GET['w']) : 0;
17-
$img_height = (isset($_GET['h'])) ? intval($_GET['h']) : 0;
18-
$img_quality= (isset($_GET['q']) && intval($_GET['q']) <= 100 && intval($_GET['q'])) ? intval($_GET['q']) : 75;
19-
20-
$img_file = str_replace(array('http://', 'https://'), '', $img_file);
21-
22-
switch($img_target) {
14+
$img_target = isset($_GET['format']) ? strtolower(trim($_GET['format'])) : 'jpg';
15+
$img_file = isset($_GET['imgfile']) ? trim(urldecode($_GET['imgfile'])) : 'img/leer.gif';
16+
$img_width = isset($_GET['w']) ? (int)$_GET['w'] : 0;
17+
$img_height = isset($_GET['h']) ? (int)$_GET['h'] : 0;
18+
$img_quality = isset($_GET['q']) && (int)$_GET['q'] <= 100 && (int)$_GET['q'] ? (int)$_GET['q'] : 75;
19+
$result = false;
20+
21+
// Ensure no protocol handlers (http://…) or something like C:\ or C:/ or ./ or ../ is part of the file name
22+
if (
23+
$img_file
24+
&&
25+
(
26+
$img_file[0] === '.'
27+
||
28+
$img_file[0] === '/'
29+
||
30+
$img_file[0] === '\\'
31+
||
32+
strpos($img_file, ':/') !== false
33+
||
34+
strpos($img_file, './') !== false
35+
||
36+
strpos($img_file, ':\\') !== false
37+
||
38+
strpos($img_file, '.\\') !== false
39+
)
40+
) {
41+
$img_file = '';
42+
} else {
43+
// Absolute path only related to the current directory
44+
$img_file = __DIR__ . '/' . $img_file;
45+
}
2346

47+
switch ($img_target) {
2448
case 'png':
25-
$img_mimetype = 'image/png';
26-
$img_target = 'jpg';
49+
$img_mimetype = 'image/png';
50+
$img_target = 'jpg';
2751
break;
2852

2953
case 'gif':
30-
if(function_exists('imagegif')) {
54+
if (function_exists('imagegif')) {
3155
$img_mimetype = 'image/gif';
32-
$img_target = 'gif';
56+
$img_target = 'gif';
3357
} else {
34-
$img_target = 'png';
58+
$img_target = 'png';
3559
$img_mimetype = 'image/png';
3660
}
3761
break;
3862

3963
case 'webp':
40-
$img_mimetype = 'image/webp';
41-
$img_target = 'webp';
64+
$img_mimetype = 'image/webp';
65+
$img_target = 'webp';
4266
break;
4367

4468
case 'jpeg':
4569
case 'jpg':
4670
default:
47-
$img_mimetype = 'image/jpeg';
48-
$img_target = 'jpg';
49-
71+
$img_mimetype = 'image/jpeg';
72+
$img_target = 'jpg';
5073
}
5174

52-
if(is_file($img_file) && $img_info = getimagesize($img_file)) {
75+
if ($img_file !== '' && is_readable($img_file) && $img_info = getimagesize($img_file)) {
5376

54-
if(!$img_width || $img_width >= $img_info[0]) {
77+
if (!$img_width || $img_width >= $img_info[0]) {
5578
$percent_width = 1;
5679
} else {
5780
$percent_width = $img_width / $img_info[0];
5881
}
5982

60-
if(!$img_height || $img_height >= $img_info[1]) {
83+
if (!$img_height || $img_height >= $img_info[1]) {
6184
$percent_height = 1;
6285
} else {
6386
$percent_height = $img_height / $img_info[1];
6487
}
6588

66-
if($percent_height < $percent_width) {
89+
if ($percent_height < $percent_width) {
6790
$percent = $percent_height;
68-
} elseif($percent_height > $percent_width) {
91+
} elseif ($percent_height > $percent_width) {
6992
$percent = $percent_width;
7093
} else {
7194
$percent = $percent_width;
7295
}
7396

74-
$img_width = $img_info[0] * $percent;
97+
$img_width = $img_info[0] * $percent;
7598
$img_height = $img_info[1] * $percent;
7699

77-
switch($img_target) {
100+
switch ($img_target) {
78101
case 'jpg':
79102
case 'png':
80103
case 'webp':
@@ -86,8 +109,7 @@
86109
break;
87110
}
88111

89-
switch($img_info[2]) {
90-
112+
switch ($img_info[2]) {
91113
case IMAGETYPE_GIF: // GIF
92114
$img_source = imagecreatefromgif($img_file);
93115
break;
@@ -105,41 +127,37 @@
105127
break;
106128
}
107129

108-
imagecopyresized($new_img, $img_source, 0, 0, 0, 0, $img_width, $img_height, $img_info[0], $img_info[1]);
109-
110-
header('Content-type: '.$img_mimetype);
111-
112-
switch($img_target) {
113-
114-
case 'jpg':
115-
imagejpeg($new_img, NULL, $img_quality);
116-
break;
117-
118-
case 'webp':
119-
imagewebp($new_img, NULL, $img_quality);
120-
break;
121-
122-
case 'png':
123-
imagepng($new_img, NULL, 9);
124-
break;
125-
126-
case 'gif':
127-
imagegif($new_img);
128-
break;
129-
130+
$result = imagecopyresized($new_img, $img_source, 0, 0, 0, 0, $img_width, $img_height, $img_info[0], $img_info[1]);
131+
132+
if ($result) {
133+
header('Content-type: ' . $img_mimetype);
134+
135+
switch ($img_target) {
136+
case 'jpg':
137+
$result = imagejpeg($new_img, NULL, $img_quality);
138+
break;
139+
case 'webp':
140+
$result = imagewebp($new_img, NULL, $img_quality);
141+
break;
142+
case 'png':
143+
$result = imagepng($new_img, NULL, 9);
144+
break;
145+
case 'gif':
146+
$result = imagegif($new_img);
147+
break;
148+
}
130149
}
131150

132151
imagedestroy($new_img);
133152
imagedestroy($img_source);
153+
}
134154

135-
} else {
136-
137-
// error / no image
138-
header ('Content-type: image/png');
155+
// Error / no image
156+
if (!$result) {
157+
header('Content-type: image/png');
139158
$new_img = imagecreatetruecolor(75, 20);
140159
$text_color = imagecolorallocate($new_img, 255, 255, 255);
141-
imagestring($new_img, 1, 5, 5, "Image Error", $text_color);
160+
imagestring($new_img, 1, 5, 5, 'Image Error', $text_color);
142161
imagepng($new_img, NULL, 9);
143162
imagedestroy($new_img);
144-
145163
}

0 commit comments

Comments
 (0)