Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

[php+mysql] The MySQLi extension [Rid of Injections 100%]

Joined
Jun 8, 2007
Messages
1,985
Reaction score
490
The MySQLi extension is PHP's MySQL Improved extension.

It's pretty easy to pick up if you know the mysql extension.

The difference is, that there are no more tacky SQL injections. No more tacky escape functions. No more embedding user input directly inside a query, (Yuck!)

How does it work?

Simple, instead of traditional queries, we use prepared statements. Prepared statements, in a nut-shell, are queries separated from dynamic data, (rather then containing the data in each query). This eliminates MySQL injections.

Get it? If not, read on...

In a normal query, the user data is sent to mysql like this:
PHP:
mysql_query('SELECT * FROM `users` WHERE `id` = "'.$_GET['id'].'"') or die(mysql_error());

The above query contains a huge flaw. The MySQL Injection. The variable, $_GET['id'], is provided by user input. Let's say for example, the user puts '1' as the id. When the data gets sent to the MySQL Server, this is the query it gets:
Code:
SELECT * FROM `users` WHERE `id` = "1"
* Notice the '1' gets placed directly in the query.

Now, imagine if the user puts, (instead of [1]), [1" OR rank="admin]

The MySQL server will get this query,
Code:
SELECT * FROM `users` WHERE `id` = "1" OR rank="admin"

This process is called a MySQL Injection. It's when a malicious user puts some code in the query in order to (usually) do malicious things to your site and/or database. It could be considered an attack, in many scenarios. The above attack would grab the data for all of the administrators, or the user with the ID of 1. This outcome would differ from the usual flow of the script, and is a BIG security vulnerability.

Do you know what a SQL injection is now? If not, just consider it an attack on the database.


With the MySQLi extension, when done properly, there ARE NO chances that a SQL injection can pass through.

By done properly, I mean, so long as you don't put ANY dynamic data in your queries, but instead pass the data with prepared statements properly.



Please visit the above link, and put the 5 PHP files on your site in a directory. (you can name the folder 'test', or whatever you wish)

- Create a table named "test_db"
- Now install this database table:
Code:
CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user` varchar(55) NOT NULL,
  `pass` text NOT NULL,
  `email` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
Run this in a query, such as mysql_query(), or in PhpMyAdmin.

Note: Since there's no dynamic data, I don't suggest using mysqli for this query. Only use mysqli extension on queries that DO use embedded variables, or dynamic data.


Now then, you should have a working prototype of a register, login, and update engine running under the mysqli extension.

There are some comments, not much, so it might be a little hard to get used to. I'll go over the basic functions you need for a query.

PHP:
//instantiate the class with the host, db user, db pass, and db name
$mysqli = new mysqli('localhost','user','pass','database_name');
//call the following in an if statement, it returns true on success
//This query selects 4 fields of data where the user and pass match up. Notice the question marks. Always put question marks where the dynamic data would go.
    if($stmt = $mysqli->prepare('SELECT id,user,pass,email FROM users WHERE user=? AND pass=?'))
    {
        //We use bind_param() to add in the dynamic data separate from the query.
        //the 'ss' means, 'string string' (first for user, second for pass; in the order- any order- we put them- depending on the order of the '?' in the query.)
        //Bind user, md5(pass), and email as strings; no escaping needed! =D
        $stmt->bind_param('ss',$_POST['user'],md5($_POST['pass']));

        //execute the query.. Simple enough..
        $stmt->execute();

        //We use bind_result to get the results from the query.
        //Notice I selected 'id, user, pass, email' in the query.
        //the same order I select them, I load them in the result
        //The order of things is VERY important with 'bind' functions.
        $stmt->bind_result($id,$user,$pass,$email);
        
        //Kind of like, while($row=mysql_fetch_assoc($query)), but the large parts of that are done already (bind_result) =D
        while($stmt->fetch())
        {
            ////Assign some session vars from the query result! 
            $_SESSION['id']=$id; 
            $_SESSION['user']=$user;
            $_SESSION['pass']=$pass;
            $_SESSION['email']=$email;
        }
        $stmt->close();
    } else die($mysqli->error());

Hope that helps!! Please check for more help! :thumbup1:
 
Last edited:
ex visor
Loyal Member
Joined
May 17, 2007
Messages
2,741
Reaction score
937
So it is like a class, like what we were discussing on MSN.
It seems more clear now that you're explaining it piece by piece.

Aaron
 
Infraction Baɴɴed
Loyal Member
Joined
Apr 9, 2008
Messages
1,416
Reaction score
169
interesting.

this seems to be a fun learn all though the manuel on php.net is not all that informant as to the function naming like for mysql lol
 
Junior Spellweaver
Joined
Nov 26, 2008
Messages
196
Reaction score
62
Ew, MySqli. Ewewewewew. Only a light weight version of MySQL.

Look into Postgre, it's good for web development AND gaming databases. Open Source FTW?
 
duck you, I'm a dragon
Loyal Member
Joined
Apr 29, 2005
Messages
6,407
Reaction score
130
I usually just check for any non-alphanumeric characters, or escape them. Spares you a lot of the hassle.
 
Joined
Jun 8, 2007
Messages
1,985
Reaction score
490
Ew, MySqli. Ewewewewew. Only a light weight version of MySQL.

Look into Postgre, it's good for web development AND gaming databases. Open Source FTW?
Huh? MySQLi is a PHP extension for a MySQL database. Actually, the MySQL extension is more light-weight, which is why I recommend it instead for queries that don't use dynamic variables.

It has NOTHING to do with switching to a different database, it works with MySQL, not MySQLite (or whatever it is you're thinking of).. So don't think you have to switch databases or any of that- it's for MySQL and PHP, as I stated above. :thumbup1:

No matter what SQL database you have, you should use prepared statements to send dynamic data. It's more secure, and is often more reliable and less computing than escape techniques. The efficiency trade-off is often not met with larger-scale applications. It does use a little more RAM, but as ram size gets bigger, it becomes less and less of a problem.

For PostgreSQL documentation of Prepared Statements, see their docs on "PREPARE":
This tutorial is for , "The world's most popular open source database"

You're certainly welcome to make one for , "The World's Most Advanced Open Source Database"
@Escaping vs Prepared Statements
Even mysql_real_escape_string has flaws under certain conditions. Also preg functions, if you don't know exactly how a given encoding will react to user input, preg_replace won't always solve your problem. Alphanumeric (meaning, no spaces, special characters, dashes, underscores, dollar signs, number signs, punctuation, no mark-up- HTML, BB code- just letters and numbers) is a pretty sure way to escape your data, but how does that suffice for more advanced systems? What if we completely eliminated the possibility of SQL injections, and concentrated ONLY on eliminating XSS injections? Idk, does BBcode sound like a good idea to anyone else? I'm tired of adding and removing slashes, worrying about the encoding of my database, and using a tacky "escape" technique every time I handle my data. The world can be MUCH more easy- much more efficient today- ask Java- Ask Sun Oracle (developers of MySQL and Java- massive supporters of Prepared Statements).

I want to use preg_replace and such escape techniques for covering HTML, and that end of web-applications. I don't want to use them for SQL escape purposes. That often implies (assuming my data needs more than alnum; for example, when it must conform with the RFC standards of an Email Address), I need an escape function on BOTH SIDES of my data. One, to escape quotes in queries (which shouldn't be necessary), and two, to remove the escape characters before sending it to HTML. All that, and ALSO, I need to cover XSS injections before printing anything to HTML. That's if I'm completely covering security using escape functions. What if my database wasn't an issue? The Answer: Things become much more clear in terms of security.

http://www.php.net/manual/en/mysqli.overview.php said:
Note: If you are using MySQL versions 4.1.3 or later it is strongly recommended that you use the mysqli extension instead.

Why would PHP.net recommend such a thing as changing the way we talk to our database? The bigger question, why didn't PHP come out with this extension in previous versions? As Java, C, C++, (now C#), and other languages, developers have been using this technique for years!
 
Newbie Spellweaver
Joined
Nov 2, 2009
Messages
54
Reaction score
21
Note that you can also use PHP's PDO extension with prepare() statements.
PDO is very easy to change as you can use it for just about any type of DB (PostGre, MySQL, SQLServer, Oracle...)

PS: MySQLi can be used as an object or as regular functions (mysqli_*). It's up to you which one to use. PDO on the other hand is only object-oriented.
 
Last edited:
Ginger by design.
Loyal Member
Joined
Feb 15, 2007
Messages
2,340
Reaction score
653
I like to think of mysqli as "MYSQL for Idiots". The base mysql api is not inherently insecure. People failing to validate input correctly is the insecurity.

Good tut though.
 
Elite Diviner
Joined
Jun 14, 2007
Messages
440
Reaction score
10
That happens a lot sadly... People doing half cooked CMS full of holes :)
 
Joined
May 11, 2008
Messages
513
Reaction score
99
I like to think of mysqli as "MYSQL for Idiots". The base mysql api is not inherently insecure. People failing to validate input correctly is the insecurity.

Good tut though.

I kinda agree with you, but I like the fact that I can set what variables I want to go to the mysql server.

I've recently learnt mySQLi, and I've grown quite fond of it.
 
Mother effin' clouds
Loyal Member
Joined
Apr 13, 2008
Messages
1,534
Reaction score
448
I like to think of mysqli as "MYSQL for Idiots". The base mysql api is not inherently insecure. People failing to validate input correctly is the insecurity.

Good tut though.

I beg to differ, as with all extensions, the MySQLi (aka MySQL IMPROVED - take note of the word "IMPROVED") extension was developed for a reason. With that being said, take note of the official MySQL note on this:

The mysqli extension (stands for "MySQL, Improved"; added in PHP 5) is compatible with the improved password hashing employed in MySQL 4.1 and higher, and no special configuration of MySQL need be done to use this MySQL client library.

And also:

MySQL improved extension, was developed to take advantage of new features found in MySQL systems versions 4.1.3 and newer.

Unlike the conventional "MySQL" extension, it was 'designed' for OOP based interfaces with enhanced debugging capabilities and support for multiple as well as prepared statements.
 
Junior Spellweaver
Joined
Jun 23, 2007
Messages
143
Reaction score
0
I like to think of mysqli as "MYSQL for Idiots". The base mysql api is not inherently insecure. People failing to validate input correctly is the insecurity.

Good tut though.

Totally Agree mate,,,, all it takes is abit of logic and a brain and its gonna be secure (not 100% but... secure) !

Nick.

---------- Post added at 12:19 AM ---------- Previous post was at 12:16 AM ----------

Oh and ....
Code:
$stmt->bind_param('ss',$_POST['user'],md5($_POST['pass']));

I could personally exploite that code still lol
 
Newbie Spellweaver
Joined
Nov 2, 2009
Messages
54
Reaction score
21
Totally Agree mate,,,, all it takes is abit of logic and a brain and its gonna be secure (not 100% but... secure) !

Nick.

---------- Post added at 12:19 AM ---------- Previous post was at 12:16 AM ----------

Oh and ....
Code:
$stmt->bind_param('ss',$_POST['user'],md5($_POST['pass']));

I could personally exploite that code still lol

Doubt so.

Anyway yeah, the basic MySQL API is way enough for security as well, though in my opinion (it's personal), using an OO-way to use the connection to your DB keeps your code somewhat organized.

Oh and you shouldn't go crazy over security too, when I see people do
PHP:
$name = htmlentities(preg_replace('#[^a-zA-Z0-9]#', '', htmlspecialchars(nl2br(mysql_real_escape_string(addslashes(str_replace("'", '', $_POST['name'])))))));

It makes me mad, when it most cases, mysql_real_escape_string is way enough.
 
Last edited:

LMC

Experienced Elementalist
Joined
Apr 13, 2009
Messages
247
Reaction score
95
Totally Agree mate,,,, all it takes is abit of logic and a brain and its gonna be secure (not 100% but... secure) !

Nick.

---------- Post added at 12:19 AM ---------- Previous post was at 12:16 AM ----------

Oh and ....
Code:
$stmt->bind_param('ss',$_POST['user'],md5($_POST['pass']));

I could personally exploite that code still lol

Yea, Stop talking out your butt.
 
Mother effin' clouds
Loyal Member
Joined
Apr 13, 2008
Messages
1,534
Reaction score
448
On the topic of 'preventing MySQL injections', I thought I should add to this since I have not covered it on my previous post here. Although relying mainly on 'hardening' your PHP scripts from any sort of vulnerabilities, it is always good to be 'more than certain' you are secure and take note of a few good MySQL practices.

One of these practices includes setting schema/table/column specific permissions for your users. If you are running a site that does not involve a 'drop' or equivalent functions, then it would be advisable to disable this permission for your MySQL user, hence, limiting the hacker's ability.

Rather than running deletes on your news system (or whatever), you can simply create a special column called "DELETE" that is set to either 0 or 1. From there, you can setup a cron task to run a daily or weekly delete on all records with "DELETE" set to 1. Obviously you will have to configure your 'news display' to look for 'non-deleted' records.

Other security best practices would include a SQL Firewall, such as: , Munin IDS - or perhaps a set of mod_security rules on your server to prevent and report any attempts to inject your script. Not sure about most of you here, but I would personally go with PDO given the choice. It is personally a more "OOP" or rather 'framework style' extension and succeeds in both security and performance.

In addition to that, one should make good use of server-side and client-side (JavaScript) validation. Check the regular expression of your data (dates, e-mails, etc), check the data for duplicates (especially for usernames) and add any necessary filters (e.g. Perhaps strip all HTML tags or trim white-spaces, etc).

Binding query statements is an extremely tedious or otherwise repetitive process that I personally feel, limits the ability to form more 'structured' OOP-style MySQL adapters - simple functions, classes, etc. Depending on the type of work you are dealing with, I would most definitely recommend using an ORM. Otherwise, get a simple MySQL class with perhaps a validation module. From there you can administer the 'incoming/user input' data better and perhaps apply any necessary filters and pre- or posts- tasks. This is what most PHP frameworks would do, hence their 'efficiency'.
 
Last edited:

LMC

Experienced Elementalist
Joined
Apr 13, 2009
Messages
247
Reaction score
95
SaintsIan, Thanks for the idea of the delete column, never really thought of that.
 
Last edited:

LMC

Experienced Elementalist
Joined
Apr 13, 2009
Messages
247
Reaction score
95
Does mysqli auto escape characters? As for some reason ",' gets escaped when using mysqli, I dont know if ive not put mysql_real_escape string anywere without knowing, but just wondering.
 
Back
Top