Intro to Security (PHP)

Post all your tuts or request for tuts here.
Post Reply
User avatar
Luke111
Posts: 84
Joined: Fri Aug 17, 2012 7:02 am

Intro to Security (PHP)

Post by Luke111 »

Hi Everyone!
Welcome to my Intro to Security in PHP tutorial.
Today, we will be going over some very common, and easy-to-master tactics that novice to intermediate hackers will learn
once they become serious about learning how to hack.

So, here's the agenda (it is in order from easiest to hardest):

General Tips on writing secure code
What is XSS?
Halting XSS with the "Escape" function
What is SQL Injection?
Stopping SQL Injection with the "mysqli_tgb" mysqli extension class

This is going to be a big tutorial, so get your drink, turn on some tunes and read away!

Alright, first on the agenda:

===
General Tips on Writing Secure Code
===
Here's a list of things to keep in mind when you code:
1. User Input ***CAN NOT BE TRUSTED***
2. It is better to have longer code that you will understand in a year than having code that is short but isn't readable.
3. It is better to comment all over than to not comment at all. Trust me, if you comment, it will save your butt in the future (I know that one very well).
4. Filter in, escape out (you will learn about that one here in a second).

===
What is XSS?
===
XSS is Cross Site Scripting. In easy terms, it is when user x writes Javascript into your website's textbox; then, when user Y sees it, that javascript runs.
This can create all kinds of chaos, like what happened to MySpace in 2005: http://en.wikipedia.org/wiki/Samy_(XSS)
This worm was really nasty! It started on the author's page. When someone viewed his page (Samy Kamkar), then they would automatically send him a friend request,
posts "Samy is my hero" to their wall (or whatever myspace calls it), all without the user knowing. Whenever someone views their wall, they get the same curse.
So, it is a tree: Started on Samy's wall, went to his girlfriend's and other friend's, then his friends of friends viewed his friends' walls, which carried the
same javascript.
Things could have been worse, though. You may know that javascript can redirect users to different pages.
So, the only way to stop it was to do the thing I am about to show you all to the actual PHP script which showed the user's wall.

===
Halting XSS with the "Escape" function
===
XSS is horrible, as described in the last paragraph. I will show you the function to "Escape" the output to make sure this doesn't happen. It is up to you,
however, to use this function whenever you display output. I will also show an example.

Code: Select all

function escape($t) {
    return htmlentities($t,ENT_QUOTES);
}
 
This function simply returns the html with all the "Special Characters" changed to their respective tags (not sure what the right name of them is).
So, & becomes & and < becomes < and > becomes > You get the point.
This also applies to the " quotation marks.

Here's a test example without the escape function, so you can see why it is useful (note that some browsers may detect an XSS attack, and will warn you. At least I know chrome does, sometimes).

Code: Select all

<html>
    <body>
        <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
            <input type="text" name="inp" />
            <input type="submit" value="Attempt XSS!" />
        </form>
        <?php if (isset($_POST['inp'])) {
            echo $_POST['inp'];
        } ?>
    </body>
</html>
Here, give it a go! Put this in the textbox:

Code: Select all

<a href="http://www.google.com/">Login to this Website!</a>
If you click on the link, it takes you to google, not the login page.
This link could take you to any site, but it doesn't have to take you to where it says it's taking you.
So, say I submitted a form with that link, and maybe made it more malicious; say, it takes the user to a fake login page that dumps the user's credentials into a hacker database. (Phishing)
The user clicks on the link, which is supposed to take you to a login page for this site, but instead takes you to the malicious page. THIS IS BAD!
Here's how we fix that (there are other options, like BBCode, but I will get into those in another tutorial):

Code: Select all

<?php
//added this function!
function escape($t) {
    return htmlentities($t,ENT_QUOTES);
}
?>
<html>
    <body>
        <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
            <input type="text" name="inp" />
            <input type="submit" value="Attempt XSS!" />
        </form>
        <?php if (isset($_POST['inp'])) {
            ///Added in here!
            echo escape($_POST['inp']);
        } ?>
    </body>
</html>
Now, this is secure! (against XSS attacks.)
Try entering the same code in, and see what happens!

Thanks For Reading!
Luke
Last edited by Luke111 on Tue Aug 28, 2012 5:17 am, edited 1 time in total.
I don't believe in platform-specific development, but I also don't believe in Apple.
User avatar
Luke111
Posts: 84
Joined: Fri Aug 17, 2012 7:02 am

Re: Intro to Security (PHP)

Post by Luke111 »

Hi!
This is the second part of my tutorial!
Today, we will be learning "What is SQL Injection" and "How do we stop SQL Injection".
I will go over the very basic methods used by most novice to intermediate programmers to stop SQL Injection, and I will touch on the more advanced topic of
Prepared Statements, but that is for another tutorial section.

Don't worry if you don't know what these mean right now. You will once you read through this once or twice.

===
What is SQL Injection?
===
SQL Injection is a common attack to modify database tables, drop database tables, or drop databases altogether.
It is done simply by entering the injection into your textbox on your page, similar to how the XSS works. I am not going to say it is less of a problem, but it
is a different kind of problem, and they are both extremely bad problems (XSS and SQL Injection).
This one is a bit more complicated and involved, and is normally mastered by intermediate-level hackers.
Here's how it works.
Say, we have this code:

Code: Select all

$result = mysql_query("SELECT * FROM `users` WHERE `Username`='$_POST['username']' AND `Password`='$_POST['password']'");
 
First, we enter the desired username into the Username textbox.

Now, we enter the following into the same "Username" textbox, after the username (assuming that this is for a login page):

Code: Select all

' OR '1'='1'#
So, the final query looks like this:

Code: Select all

SELECT * FROM `users` WHERE `Username`='Joe' #' AND `Password`='whatever'
That # is the commonly used Commenting feature in SQL. It makes everything after it a comment. A comment is a piece of code that doesn't run, or do anything.
So, anything can be entered into the Password field, it doesn't matter as it is commented out.

It selected the user with the username "Joe" and it doesn't care what the password is.

Here's a complete example:

Code: Select all

<?php
mysql_connect("localhost","username","password");
mysql_selectdb("mycooldb");
if (isset($_POST['username'],$_POST['password'])) {
    $result = mysql_query("SELECT * FROM `users` WHERE `Username`='" . $_POST['username'] . "' AND `Password`='" . $_POST['password'] . "'");
    while ($row = mysql_fetch_array($result)) {
        echo "ID: " . $row['ID'] . "<br />Username: " . $row['Username'] . "<br />";
    }
} else {
?>
<html>
    <body>
        <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
            Username: <input type="text" name="username" />
            <br />
            Password: <input type="password" name="password" />
            <br />
            <input type="submit" value="Login!" />
        </form>
    </body>
</html>
<?php
}
?>
First, make a database named "mycooldb" and a table in that named "users". The table "users" should contain an ID (primary key/autoincrement), as well as a
Username field, and a Password field. Populate the table with fake data.

Now, try logging in with an invalid username/password. You will see it will redirect you to the login page again. Try again with valid credentials. It will show
you your user data.

Now, try doing the hack described above. It should show you every user's data in one go.

Techie Note: mysql_query doesn't allow multiple queries in one go, so you're safe from table droppers, so long as you write good code.

===
Stopping SQL Injection
===
Simple answer is to just filter the input. This is done with the "mysql_real_escape_string" function.
Here, let's try this:

Code: Select all

$result = mysql_query("SELECT * FROM `users` WHERE `Username`='" . mysql_real_escape_string($_POST['username']) . "' AND `Password`='" . mysql_real_escape_string($_POST['password']) . "'");
 
Now, it should stop your sql injectors!

Just make sure to use mysql_real_escape_string on EVERYTHING going into the query.

===
Prepared What?
===
Prepared Statements are a way to seperate the input from the query. This is kind of hard to understand for some. Think of it like printf in the Standard C Library.
It has a string with placeholders in it, and you put in parameters for the placeholder data. The placeholder data and the string are completely seperate the whole time (I don't know if that's
true for the C Library, but it doesn't matter in that scenario). I will be updating this thread with a link to the "Advanced Security in PHP" topic once finished and released. That topic will go
over prepared statements more in-depth.

Thanks for reading!
-Luke
Last edited by Luke111 on Tue Aug 28, 2012 5:16 am, edited 1 time in total.
I don't believe in platform-specific development, but I also don't believe in Apple.
User avatar
Ark
Posts: 427
Joined: Wed Jun 01, 2011 10:25 pm

Re: Intro to Security (PHP)

Post by Ark »

A very well explained tutorial thanks! looking forward for the next one.
Orgullo Catracho
User avatar
Luke111
Posts: 84
Joined: Fri Aug 17, 2012 7:02 am

Re: Intro to Security (PHP)

Post by Luke111 »

Thanks! I am glad someone reads them!

Off topic:
It's cool to see someone from Honduras, I was once there on a cruise ship!
I don't believe in platform-specific development, but I also don't believe in Apple.
User avatar
Jackolantern
Posts: 10893
Joined: Wed Jul 01, 2009 11:00 pm

Re: Intro to Security (PHP)

Post by Jackolantern »

Very nice stuff! Stickying so we can refer people to it. Security is not an option! If you don't have security, you don't have a web app/game. You just have a hacker sandbox that they haven't found yet :D
The indelible lord of tl;dr
User avatar
Luke111
Posts: 84
Joined: Fri Aug 17, 2012 7:02 am

Re: Intro to Security (PHP)

Post by Luke111 »

Hi Jack!
Thanks for stickying this thread! I hope it helps others as much as it would have when I started in PHP!

Thanks!
-Luke
I don't believe in platform-specific development, but I also don't believe in Apple.
User avatar
Jackolantern
Posts: 10893
Joined: Wed Jul 01, 2009 11:00 pm

Re: Intro to Security (PHP)

Post by Jackolantern »

I am sure it will! I have wanted a good in-community resources to point people to for a long while now :D
The indelible lord of tl;dr
User avatar
Ark
Posts: 427
Joined: Wed Jun 01, 2011 10:25 pm

Re: Intro to Security (PHP)

Post by Ark »

Luke111 wrote:Thanks! I am glad someone reads them!

Off topic:
It's cool to see someone from Honduras, I was once there on a cruise ship!
Haha nice!! I bet you visited Islas de la bahía, really nice beaches. I hope you enjoyed visiting my country :)
Orgullo Catracho
User avatar
Luke111
Posts: 84
Joined: Fri Aug 17, 2012 7:02 am

Re: Intro to Security (PHP)

Post by Luke111 »

I don't remember where I visited, but I do remember a very nice beach! It was a lot of fun!

If you have any questions about the tutorial, please let me know, and I would be happy to help anyone getting the code implemented.

What kind of things would you all like to see in other tutorials?
I don't believe in platform-specific development, but I also don't believe in Apple.
User avatar
Epiales
Posts: 1119
Joined: Thu Aug 15, 2013 1:38 am

Re: Intro to Security (PHP)

Post by Epiales »

Would this be okay for the login?

Code: Select all

<?php
session_start();
include("functions.php");
connect();

if(isset($_POST['login'])){
    if(isset($_SESSION['uid'])){
        echo "You are already logged in!";
    }else{
        $username = protect($_POST['username']);
        $password = protect($_POST['password']);
        
        $login_check = mysql_query("SELECT `id` FROM `user` WHERE `username`='$username' AND `password`='".md5($password)."'") or die(mysql_error());
        if(mysql_num_rows($login_check) == 0){
            echo "Invalid Username/Password Combination!";
        }else{
            $get_id = mysql_fetch_assoc($login_check);
            $_SESSION['uid'] = $get_id['id'];
            header("Location: index.php");
        }
    }
}else{
    echo "You have visited this page incorrectly!";
}

?>
And the protect is a function in my functions.php...

Code: Select all

function protect($string) {
    return mysql_real_escape_string(strip_tags(addslashes($string)));
}
Nothing fancy, but a work in progress!

http://gameplaytoday.net
Post Reply

Return to “Tutorials”