Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

Php security

mysqli max_file_size

  • Please log in to reply
4 replies to this topic

#1 Vaielab

Vaielab

    Programming God

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1382 posts
  • Location:Quebec City
  • Programming Language:Java, C++, C#, PHP, JavaScript, Visual Basic .NET, Transact-SQL, ActionScript

Posted 12 August 2011 - 04:46 AM

Hello,

In this tutorial (my first tutorial in english) I will try to show you some tricks to secure your php web site.
Security is pretty hard, and it's always evolving, this is why I do not claim that if you follow everything that I say here your website will be 100% protected.
Theses infos are from my personal experiences, and how I manage to secured my websites over the time. I only hope I won't say something false.

Remember, when we are talking about security, one tutorial is good, 2 tutorial is better, 10 turorials is the best.
So before doing anything here, please, look for other sources, first to be sure you understand, second just in case I'm wrong on a point.

Sql injection

Sql injection isn't new, but their a lot of website out there that are still vulnerable against Sql injection.
And by the way, i'm not saying that everything that I do is Sql injection free, but I try to be very carefull for this.

- So what exactly Sql injection can do?
Sql injection can do pretty much anything. It can be used to login to a website without the username/password, it can retreive data directly from your database, or modify data that someone isn't supposed to modify, or it can even delete data/entire database.

I hope I scared you a little bit, and you all will take Sql injection seriously!

Open Sql Query Browser, select a table (for this exemple I will choose the table called "User") and try this
select * from User where username = 'Bob' -- and password = '123'
Even if Bob's password isn't 123, bob will show, since the password part is now only a comment and won't be executed.
And please, I saw a lot of tutorials that was simply saying to remove char like "--" and everything will be correct. Well this is stupid, what if the Bob password contain "--"? And this is even more stupid since it don't help against all type of Sql injection try this one:
select * from User where username = 'a' = 'b'
Well this dosen't make any sens is it?
It's a little bit complex, but 'a' = 'b' = 'c' will always return true, so even if you remove all the "--" char, you will still be subject to sql injection!

- What does it have to do with php?
Well, imagine a login page, where a user enter the username "Bob --", if you don't check for sql injection, this will do pretty much the same thing as my first exemple! And the user will be able to connect as bob.

- So how to prevent Sql injection?
First step is to sanitize your data.
If you are supposed to receive a checkbox answer, but you received a string, their something wrong.
If you are supposed to receive a string with 30char max, but you received something with 200char, you should recheck your data.
So, you need to always validate if you receive the good data for everything, always sanitize your variables ($_POST, $_GET and $_COOKIES, yes even cookies)

Second, you should always know where your data come from.
In this forum, and in a lot of other forums, I seen a lot of person using the variable $_REQUEST, even if a lot of programmer will say there is no problem with using the variable $_REQUEST, I will not suggest it.
Since $_REQUEST can come either from the post, get or cookies (not always cookies depends of your version of php and config) you can't always be sure if the variable isn't overrited by a other variables.
The arguments when someone is telling me that $_REQUEST is as good as post or get is that neither of them are secure and you have simply to sanitize all of them anyway.
That is true, but imagine a that you did a simple mistake and use the same variable in the post and in the get, one of them will be overrited, and it can take some time to understand the problem.

But to sanitize or knowing where the data come from will only help you a little but, it's not all.
First of all, please, please, stop using mysql extension, start using mysqli (PHP: Mysqli - Manual) or even better, use PDO (PHP: PDO - Manual)

The mysql extension is old (very old), slow, and not OOP.
Mysqli and PDO is more secure and are OOP

So if you use mysqli you simply need to sanitize all your data with mysqli_real_escape_string
$mysqli = new mysqli("localhost", "root", "password", "db1");
$username = $mysqli->real_escape_string($username);
$mysqli->query("select * from User where username = '$username'");
$mysqli->close();

If you are using PDO, you either prepare or quote all your data
$dbh = new PDO("mysql:host=$hostname;dbname=$db", $username, $password);
$sth = $dbh->prepare("SELECT * FROM users WHERE id = :id");
$sth->execute(array(':id' => $id));
while ($result = $sth->fetch())
{
//Code here
}


And with this, you should be protected againse sql injection... By the way, I said you SHOULD, not will, so do some backup, and keep a eye on your user.

Html injection

Html injection is a little less problematic than sql injection, but still you should validate against this.
So imagine that you write your own forum, where a user can choose his username. The user bob decide to add a little special code on his username, and his username is "bob</div></div>"
So now everything Bob post something on the forum, there will be 2 end of div that you don't want, and this may break the design, and render everything hard to read.
This is pretty easy to resolv, but you have to think of it.
Insted of doing something like:
echo($username);
you should do
echo(htmlentities($username, ENT_NOQUOTES, 'UTF-8'));
That way the displayed name of bob will be "bob</div></div>" and the 2 end of div will be considerated as normal text and not as html text since both char "<" and ">" will be transformed in their hexadecimal format.
To prevent Html injection isn't hard, but you have to think each time you want to display an user data, you have to sanitize it!


Xss

Xss stand for Cross-site-scripting, is a little bit like html injection, but more serious.
Imagine now that bob decided to have a username like this 'bob<script language="javascript">alert("Hello World!");</script>
Everytime his name will be on the forum, a alert will popup. This ain't too bad, but imagine that this is not an alert, but a redirection, the user will be redirected on a other page without his knowledge, he may than be asked some personal info, and the user thinking he's still on your trusted website will enter them. Or this could be a redirection to download a file that contain a virus, or even simply a ajax call to a other server sending his personal infos. And don't think that because of the same domain policy (Same origin policy - Wikipedia, the free encyclopedia) you are safe, this is pretty easy to by pass. The user will never know, and you as an administrator of the site may take some time to find this (If you ever find it).

So how can we prevent xss?
Xss can be a little more tricky to prevent, but first step is (you guess it) sanitize your data!
A simple xss like my exemple with the alert can by prevent if you pevent against html injection.
But more complex xss attack need more sofisticated prevention.
You will need a script like PHPIDS (https://phpids.org/) or htmlpurifier (HTML Purifier - Filter your HTML the standards-compliant way!).
But even with that, you still might be vulnerable, their no real way to be 100% protected, but find a good script (either phpids or htmlpurifier or a other) and update it as often as you can!


Uploading a file
You wish to give the user the possibility to attach a file on their post (yes still with the forum exemple... their's a lots of security risk in a forum)
First rule, is do not trust the user.
We all used this variable to validate the mime type of a file:
$_FILES["file"]["type"]
Well, sadly this variable can be modifier by the user, so you cannot trust it, insted use mime_content_type wich is deprecated and now you should use a this
//$file = a path to the file
$finfo = finfo_open(FILEINFO_MIME_TYPE);
return finfo_file($finfo, $file);

But since finfo_open isn't installed on all the server, this is a little snippets that could help you
	public static function getFileMime($file)
	{
		if (function_exists('finfo_file'))
		{
			$finfo = finfo_open(FILEINFO_MIME_TYPE);
			return finfo_file($finfo, $file);
		}
		if (function_exists('mime_content_type'))
		{
			return mime_content_type($file);
		}
		return 'application/octet-stream';
	}

And you probably used this to limit the file size:
<input type="hidden" name="MAX_FILE_SIZE" value="500" />
One more time, this is really easy to modify (just take firebug and modify the html)
If you want to set a limite, you have to wait for the file to be completly uploaded than validate his size in php or you can set the limit in the php.ini file like this
    upload_max_filesize = 10M
    post_max_size = 10M


Now you know what is the real mime type of the file and if the file is small enough for you, you have to think where to save this file.
Most common place, is to save it outside the public_html directory, or if you cannot save it outside the public_html directory use a htaccess file to deny the file to everyone
deny from all

Like that, if the user uploaded a php script, or anything that is executable, he won't be able to do it directly.

In this directory, you should randomize the name, a good old
uniqid() 
will do the tricks. Like that, if someone want to execute the file, and you forget to add the htaccess, he won't know where is the file.
If you wish to keep the original name (if the file can be downloaded for exemple) you should think of a sql table with the original name and your unique name.


If you are uploading a image, you should never keep the user original image. Insted you should make a copy of the image using the GD library and save the new image.
Image can contain more than just the image, it is possible to add php code inside a image, so when you display the image, it can inject some php code inside your code, and of course, this could be pretty dangerous.





Well, I think this is pretty complete, if you have any other security tricks, I would love to read them, remember, we are working to make a better internet for tomorow!
Hope this helped some of you.


Ps. Sorry for my english, if there is sentence that are hard to read tell me, I'll try to update them
  • 0

#2 Alexander

Alexander

    YOL9

  • Moderator
  • 3963 posts
  • Location:Vancouver, Eh! Cleverness: 200
  • Programming Language:C, C++, PHP, Assembly

Posted 12 August 2011 - 02:14 PM

Very well written Vaielab, I greatly enjoy the sight of you having recommended both an abstraction such as PDO and MySQL Improved classes, and of course the venerable HTML purifier rather than strip_tags and its insecure allowed tags parameter.

This could serve greatly to inform learners that indeed, no one layer of security is enough, and the client should never be trusted.

In fact, if you do not mind I will link this to the frequently asked questions (FAQ) sheet in the PHP forum.
  • 0

All new problems require investigation, and so if errors are problems, try to learn as much as you can and report back.


#3 Vaielab

Vaielab

    Programming God

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1382 posts
  • Location:Quebec City
  • Programming Language:Java, C++, C#, PHP, JavaScript, Visual Basic .NET, Transact-SQL, ActionScript

Posted 12 August 2011 - 03:21 PM

I do not mind at all.
In fact, I would find this very nice.

I did not know about the strip_tags and its insecure allowed tag, could you give me more info about this?
  • 0

#4 Alexander

Alexander

    YOL9

  • Moderator
  • 3963 posts
  • Location:Vancouver, Eh! Cleverness: 200
  • Programming Language:C, C++, PHP, Assembly

Posted 12 August 2011 - 04:46 PM

I did not know about the strip_tags and its insecure allowed tag, could you give me more info about this?


Of course, there is a function dedicated to removing HTML tags: PHP: strip_tags - Manual

You can either strip everything, or allow its second parameter to allow certain tags. For example, if you wish to make a blog comment form and allow basic HTML, you can use this: strip_tags($contentbody, "<a><b><u><i>");

It does not however guard against those good old XSS style vectors, and ignores attributes all together so a <b> tag can be harmful. HTML Purifier has tried to replace functions like this all together, their comparison states strip_tag's insecurities briefly:
Their comparison: http://htmlpurifier....rison#striptags
  • 0

All new problems require investigation, and so if errors are problems, try to learn as much as you can and report back.


#5 wcypierre

wcypierre

    CC Newcomer

  • Just Joined
  • PipPip
  • 10 posts

Posted 12 November 2011 - 12:01 PM

Of course, there is a function dedicated to removing HTML tags: PHP: strip_tags - Manual

You can either strip everything, or allow its second parameter to allow certain tags. For example, if you wish to make a blog comment form and allow basic HTML, you can use this: strip_tags($contentbody, "<a><b><u><i>");
Their comparison: http://htmlpurifier....rison#striptags

I would prefer using BBcode for that purpose though. or like what you said, limit the user with a very limited set of html codes.
  • 0





Also tagged with one or more of these keywords: mysqli, max_file_size

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download