Web Development for 2010

Alexander Dickson - Web Developer covering PHP, jQuery / Javascript, XHTML, CSS, more

Security issues with PHP's include

Published on Friday, 3rd September 2010.

Pretend that we are writing a web app here, but we are a little naïve. We want to display images that are uploaded from the public on our web app, except for bandwidth conservation we want to add far future expiry headers.

<?php $file = 'image.gif'; $expiry = 12960000; $imageInfo = getimagesize($file); $mime = $imageInfo['mime']; $modified = filemtime($file); $etag = md5_file($file);   if (file_exists($file)) { if (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $modified || $_SERVER['If-None-Match'] == $etag) { header('HTTP/1.1 304 Not Modified'); } $headers = array( 'Content-Type' => $mime, 'Expires' => date(DATE_RFC1123, time() + $expiry ), 'Cache-Control' => "max-age=$expiry, must-revalidate", 'Last-Modified' => date(DATE_RFC1123, $modified), 'Content-Length' => filesize($file), 'Etag' => $etag ); foreach($headers as $type => $value) { header("$type: $value"); } include $file; exit; }

Looks alright, doesn't it? There is one massive security hole there, and it is still present even if we validate the MIME type. The problem is the include, it should be a readfile(). Imagine if a GIF file was uploaded with the following content.

GIF89a<?php file_put_contents('test.txt', 'oh dear');

Yep, you'd have a nasty extra file alongside your script. Of course, the example is trivial. You could do all sorts of nasty things. And getimagesize() still reports the MIME as image/gif, which it is, technically, but checking for it is useless.

I've read some suggestions for combating this on Stack Overflow. Basically, they are...

  • Run images through another image manipulation tool, save that output and throw away the original.
  • Disallow uploading of image files with arbitrary extensions.
  • Place the uploaded images in a directory that can not run PHP.
  • Rename the images uploaded. This will add a little bit more security.

I just ran some tests too, and it seems that exif_imagetype() also won't be able to validate the image, as it is returning the GIF constant always (it doesn't care what the image is, I guess as long as it can read the GIF header).

0 comments

Convert any number to any base in C

Published on Tuesday, 31st August 2010.

I've just had a crack at Exercise 3-5. This is the first time too that I have used exit(). Usually I have been returning -1 for an error, or similar. The problem with that however, is the function's return type must be an int. This means, semantically, it would seem the function may be returning an int as part of its intended use. Because this is not the case, I've decided to use exit().

void itob(int num, char str[], int base) { if (base < 2 || base > 36) { exit(1); } int remainder = num; int i = 0;   while (remainder > 0) { int value = remainder % base; char place; if (value > 9) { place = 'A' + value - 10; } else { place = '0' + value; } str[i++] = place; remainder /= base; } // Our string is in reverse strrev(str); str[i] = '\0'; }
Write the function itob(n,s,b) that converts the integer n into a base b character representation in the string s . In particular, itob(n,s,16) formats n as a hexadecimal integer in s.
0 comments

Some time off to relax and a new C function

Published on Tuesday, 31st August 2010. Coochin Creek

Last Thursday, I got frustrated a lot with web development in general and decided to take a week off to enjoy some time away.

I decided to go camping with Courtnee at Coochin Creek. I spent 4 days there, and had a nice time enjoying the change of pace. No computers and no hustle and bustle, which was enjoyable (I did bring K&R, but I found it annoying to read without the possibility of trying the exercises).

I have a new C function I've been working on tonight. It is Exercise 3-3, to create a function that works very similar to PHP's range(). I tested it with the examples in K&R, and they passed :). As usual, I'm going to show you guys my approach.

void expand(const char str1[], char str2[]) { int i, j; int start = -1; int inRange = 0;   for (i = 0, j = 0 ; str1[i] != '\0'; i++) { if (str1[i] == '-') { // Leading and trailing dashes are taken literally if (i == 0 || i == strlen(str1) - 1) { str2[j++] = str1[i]; } else { inRange = 1; } } else if (inRange) { while(start < str1[i] + 1) { int validChar = (isdigit(start) || (start >= 'a' && start <= 'z') || (start >= 'A' && start <= 'Z'));   if ( ! validChar) continue; str2[j++] = start++; } inRange = 0; } else { start = str1[i]; str2[j++] = start++; } } str2[j] = '\0'; }
Write a function expand(s1,s2) that expands shorthand notations like a-z in the string s1 into the equivalent complete list abc...xyz in s2 . Allow for letters of either case and digits, and be prepared to handle cases like a-b-c and a-z0-9 and -a-z . Arrange that a leading or trailing - is taken literally.

As you can see, I've finally started using some of the functions available such as strlen() and isdigit(). To use these, I've had to include more than just the standard input output library.

0 comments

Get first occurence in a string from characters in a second string in C

Published on Saturday, 21st August 2010.

K&R's Exercise 2-5 looked easy enough, so I gave it a shot and came up with this little beauty.

int any(const char str1[], const char str2[]) { int i = 0; while (str1[i] != '\0') { int j = 0; while (str2[j] != '\0') { if (str1[i] == str2[j]) { return i; } ++j; } ++i; } return -1; }
Write the function any(s1,s2), which returns the first location in the string s1 where any character from the string s2 occurs, or -1 if s1 contains no characters from s2. (The standard library function strpbrk does the same job but returns a pointer to the location.)
0 comments

Remove characters from a C string which occur in a second string

Published on Saturday, 21st August 2010.

This morning's 2AM project is K&R's Exercise 2-4. It takes two arguments, the first, a source string, and the second, a string of characters which should be removed from the first if present.

void squeeze(char str1[], const char str2[]) { int i = 0; int y = 0;   while (str1[i] != '\0') { int j = 0; int found = 0; while (str2[j] != '\0') { if (str1[i] == str2[j]) { found = 1; break; } ++j; } if ( ! found) { str1[y++] = str1[i]; } ++i; } // Trim off any excess string str1[i - (i - y)] = '\0'; }
Write an alternate version of squeeze(s1,s2) that deletes each character in s1 that matches any character in the string s2.
0 comments

Stack Overflow Profile

view full profile »

About

I'm a web developer from the Sunshine Coast, Australia. more »