Jump to content
MakeWebGames

An introduction to security


Guest Anonymous

Recommended Posts

Guest Anonymous

When developing games, it is very common to have a lot of youngsters with a little knowledge "probing" your system looking for the simple exploits. Now personally I run "sentinel" loggers which permit the little blighters to try anything, although my systems are secured against 99.99% of attacks. On a daily basis, I check the logs looking for patterns that may indicate a new trend, and require some extra protection. Any attackers are often (but not always) added to my BLIP (Blocked IP lists).

So just how do we prevent intrusions?

Well the best and most secure web site is:

 

<tt>Site Offline</tt>

 

Although some people will say that even that can be circumvented by social engineering.

Security actually takes a large number of forms so I'll start with the simple ones and work upwards. If you don't follow what I'm trying to demonstrate - then back to school you go. Read the manuals thoroughly until you do.

As a quick side note - for anyone who is curious as to my abilities and knowledge, I've worked for the military, government, police and security services and hold regular discussions with my peers all of whom run large (> 100 public facing machines) networks.

Obtaining your source files

I've seen a lot of illegal copies of software out there - and often it has been badly patched. If you want to run a game, great, but don't steal the software - you will hopefully make some money from it, the original sources are not expensive, so buy a copy.

I have to come clean here and admit to having an illegal copy of some software, however I run it on my local in-house machines for my personal enjoyment only (and gaming is no fun on your own). I would never make it publically facing nor would I attempt to sell it or gain any finances from it by selling extensions for it etc.

One particular case I looked at recently, a game owner "obtained" a copy of xxx code, installed it and called for my help when his entire site was badly hacked. A quick look, and I realized that several files had intentional patches written by somebody else that permitted these exploits. Since the source was illegal and the poor owner couldn't understand what he'd done wrong, I was unable to help.

A little point here also - don't steal modifications - I've had a couple that suddenly appeared on other sites. Now, trust me folks, I recognize my style of programming. If I see my stuff out there that has not been released as open-source, better find yourself a good lawyer.

Installing your files

This is a little harder to explain, but there are certain tricks that can be done to help secure a site.

If you can, find a host that allows you setup out-of-root folders:

 

/path/site         - your site root (NOT the web root)
/path/site/lib     - 3rd party library files
/path/site/include - game specific include files
/path/site/crons   - cron jobs
/path/site/htdocs  - the public facing web root

 

With this system, it becomes almost impossible for users to access information outside of the web root.

Remember however, you will need FTP access - If you allow other developers access to the FTP account, either try and set up limited accounts (i.e. access to only the htdocs folder) or make sure you trust these people 100%.

The older developers amongst us are relativly good at trust - We have been around long enough to know what the possible problems with trusting users is and when we can allow them access to restricted areas. Unfortunately, a lot of younger people think they can make a fast back by nicking the odd bit here and there. Don't - it's not worth it.

A note on passwords here... You will of course have CPanel (or it's equivalent) passwords, passwords for your database, passwords for the FTP server etc. If you can, change these regularly and NEVER give out the database password to anyone. If your data is corrupted, stolen, overwritten etc - You lose everything. Passwords should be very heavy duty for these primary areas - I use 18+ alpha-numeric-punctuation here for example: "DeveloPING_85_bunnieS" is fairly strong whilst "football" is just ridiculous. Don't use the same ones anywhere else, don't write them down, don't store them in text files in your web root (I've seen it done), don't store them on your own personal computer - remember them.

Testing your site

Disable the registrations system. You can normally create users on the fly in the staff/admin pages. This will allow to run with 5 or 6 trusted people who will help you find those bugs and do some basic testing. If your site relies on crons to update various parameters, try scaling these so the game runes effectively a lot faster. This way you can go through each area of the game properly without resorting to editing your stats by hand and check everything out within a couple of weeks rather than possible a few years. (The courses I have for one game would take just under 5 years real time to complete - took me a few days by running everthing in a high speed).

Finding bugs

Turn on all warnings and errors: error_reporting(E_ALL); and fix EVERY warning. Yes, I know it's time consuming, but trust me - It's worth it. I will be releasing some code to help you here soon, but ideally you should be able to track down and fix all those pesky warnings and errors.

Range checking

Okay, hands up... How many of you have seen prices for items in various games at -2,147,483,648 or 2,147,483,647? Range check every number that a user can type in. I always restrict the values that users can type in. Make sure you check that your range checking works properly. PHP has issues with signed and unsigned numbers at 32-bits and 64-bit is not real help. In fact at 64-bit PHP loses accuracy rather quickly as it converts what would appear to be ints into reals.

Cleaning GET and POST data

This is a massive stumbling block for a lot of people but is critical.

You MUST check everything - If you expect a number, make sure it is a number. If you expect a string, make sure you strip slashes, remove quotation marks etc.

See stripslashes(), preg_match(), ctype_xxx(), htmlentities() etc.

Pushing data into the database

Oh lordy - now we have fun...

Too many times, I blow sites up for using:

 

$db->query("UPDATE users SET username='{$_POST['name']}' WHERE userid = {$userid}");

 

No, No, and thrice NO!

 

$sql = sprintf("UPDATE `users` SET `username` = '%s' WHERE (`userid` = %u)", $db->escape($_POST['name']), $userid);
$db->query($sql);

 

Yes, it's longer to write -- It looks possible a little more complex as I have back-quoted field and table names, but trust me - if you don't - your site WILL get damaged.

I'll go into more detail on this one in a future topic...

Transactions

This is probably for the more experienced developers, but it is something worth considering. Transactions are a method of grouping together database queries (during insert/delete/update) and having the facility to "rollback" if something fails.

Why? Well one particular very-well known I site I play on, I accidently double-clicked a particular link which removed a lot of game cash from my account and updated several tables. Unfortunately, because transactions were not in place, the system took twice the amount from me, so I was left in the red for a very long time. I contacted the devlopers and they could not find the problem - pfft, amatuers!

Unfortunately, transactions can be difficult to understand, but a thorough read of the MySQL documentation and some time experimenting on a local machine can pay off here.

Staffing

This can be problematic, I've seen too many games with terrible staff. Get people you know are 100% sound. Create twin accounts for them - a normal account and a staff account. Block any attempts to change their normal account stats, items etc.

You may want to think about a legal agreement preventing them from using anything the see in the staff/admin pages elsewhere. It's not much, but I now require all staff to sign written documents which are basically a form of protection.

A little note here - My in-game mail systems are modified from the norm - I never delete any mails from the servers (okay, I've several Tb of storage per machine), which means I have a full audit trail of any dodgy dealings. I also prevent staff from looking at ANY mails (a simple privacy issue here) unless there has been a reported incident.

--

There's probably a lot more I could go into - so I'll probably add some more notes in the future, but hopefully, these few random thoughts will help give you a better idea of how to protect yourself and your users and give everyone a more enjoyable experience.

Specific inquiries re. this topic should be addressed in the forums for ALL to see, not via PM. I release my source, my thoughts etc as public domain in an attempt to help others - you should help others by being open about what you do. Remember, the game engine you (hopefully) bought, is just that - an engine - not a game. A game has content, looks good, works and is secure. The content is what makes people want to play - not the engine.

Link to comment
Share on other sites

  • 2 weeks later...
Guest Anonymous

Re: An introduction to security

Thank you, and yes I hope to...

I'd like to discuss the design of a simple framework (kernel, configuration and database) that can be used to create or at least help reasonably secure applications with a little careful programming and adherence to standards.

Something that mdshare mentioned in IRC PM they other day was the possibility of CE releasing it's own "toolkit" and perhaps this could be a small contribution towards it. Not sure yet... I don't want to give too many clues away ;)

Link to comment
Share on other sites

  • 1 month later...

Re: An introduction to security

Read through the post...just wanted to try out something. It works perfectly for me, and I'd just like to confirm that it's the safest way possible.

I used this query, is there any way in which it could be improved even more?

 

$nerve=$ir['nerveinc']+1;
$sql = sprintf("UPDATE `users` SET `%s` = `%s` +  %d, `%s` = `%s` - %d, `%s` = `%s` + %d WHERE (`userid` = %u)", $db->escape=maxbrave, maxbrave, 1, merits, merits, $nerve, nerveinc, nerveinc, 1, $userid);
$db->query($sql);
Link to comment
Share on other sites

  • 3 weeks later...

Re: An introduction to security

Why are you escaping the maxbrave and stuff? Is that necessary?

As for:

UPDATE users SET `%s` = `%s`

Does that SQL actually work? As you're not defining which row you're updating..

This should help in some way

 

$nerve=$ir['nerveinc']+1;
$sql = sprintf("UPDATE `users` SET `%s` = `%s` +  %d, `%s` = `%s` - %d, `%s` = `%s` + %d WHERE (`userid` = %u)", $db->escape=maxbrave, maxbrave, 1, merits, merits, $nerve, nerveinc, nerveinc, 1, $userid);
$db->query($sql);

 

Link to comment
Share on other sites

Re: An introduction to security

 

Why are you escaping the maxbrave and stuff? Is that necessary?

As for:

UPDATE users SET `%s` = `%s`

Does that SQL actually work? As you're not defining which row you're updating..

This should help in some way

 

$nerve=$ir['nerveinc']+1;
$sql = sprintf("UPDATE `users` SET `%s` = `%s` +  %d, `%s` = `%s` - %d, `%s` = `%s` + %d WHERE (`userid` = %u)", $db->escape=maxbrave, maxbrave, 1, merits, merits, $nerve, nerveinc, nerveinc, 1, $userid);
$db->query($sql);

 

Oh...I know you're not supposed to escape the maxbrave etc...well I do after I learnt a bit more after posting. I did that because I think I was so used to just escaping everything. Anyway, I have changed my ways, as you will see from my new Lottery Mod [Free] or my new paid 3 in 1 Bank :).

BTW: That query does work...becuase i did define everything in $db->escape...maxbrave, etcetc

And I've also read through things like mysql_real_escape_string and sprintf a bit more...as well as echo sprintf which I learnt through one of Nyna's mods... :-)

Link to comment
Share on other sites

Re: An introduction to security

[note: Akash posted while I was typing mine, I read that post, and am leaving mine as it was originally stated.]

Akash is defining the column names, but is doing so in a roundabout way.

There's nothing more secure than defining a query with a hard coded string.

 

$query = "update table1 set columna = columna +1";

 

However, you can do this:

 

$query = sprintf('update %s ser %s = %s + %d', 'table1', 'columna', 'columna', 1);

 

Both are the same in terms of being hard coded as a string. The difference being there's completely unnecessary formatting happening in the second one.

And if you were to accept a column name from a user as a means to determine which column to update, you better have defined a list of columns they are alowed to update. Accepting a column name from a user would be the only reason I could see passing the column name from the sprintf arguments.

And even in that case, since you should have defined a white list of column names allowed, there would be 0% need for any escaping...

 

$allowed_columns = array('strength', 'defense', 'intel');
if (!in_array($_POST['column_name'], $allowed_columns) ) { die('suckaz'); }
Link to comment
Share on other sites

  • 2 months later...

Re: An introduction to security

If you have alot of spare time it might be fun to try some of the security challenges of my old website http://www.net-force.nl

Yea can learn alot php & javascript in there, might also be worth checking some of the texts (most of them are old but still good info). Also explained how xss works, yes I was one of the first to discover xss, but stopped in 2002 with this website. Currently working on a browser game, much more fun :)

Link to comment
Share on other sites

  • 3 weeks later...

Re: An introduction to security

I haven't had a chance to read all of this yet but i read the first paragraph and to be truthful it done my head in.

I went to read it at 6am so i am going to have a nice read tomorrow and i am sure i will have questions to ask :-D

Thank you for the helpful post!

Link to comment
Share on other sites

Re: An introduction to security

Phew all read :-)

Just a couple of questions...

 

try scaling these so the game runes effectively a lot faster.

"scaling"??? What does that mean make them run faster?

 

Turn on all warnings and errors: error_reporting(E_ALL);

Any idea how i would do this? Do i contact my host?

Link to comment
Share on other sites

Guest Anonymous

Re: An introduction to security

Scaling, in this case refers to scaling the values used in the crons.

For example, assume I update the energy of a player by 10% every 15 minutes -- so a full refill would take 10 x 15 minutes. Now, during testing, were I still using crons, I'd up this to say 40% or higher every 15 minutes. That means I could test a lot more of the project in a shorter space of time.

As for error reporting:

error_reporting(E_ALL); -- or error_reporting(E_ALL | E_STRICT) if you have access to PHP5

should enable all errors and warnings; however you may have to also call

ini_set("display_errors", 1);

If you pop these lines right at the top of a file (after the opening <?php of course), or in a common include file (say header.php) -- you will see a vast number of errors and warnings being reported. You don't want these on for production boxes -- as they give information away that may give people a clue how to subvert your system, however, during development, they are ideal.

 

<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
/* ... rest of code ... */
?>

 

Lookup the error_reporting function in the PHP manual:

http://uk3.php.net/error_reporting

http://uk3.php.net/manual/en/errorfunc. ... lay-errors

Link to comment
Share on other sites

Re: An introduction to security

Right just had a quick flick through the two websites provided. Will read them properly after i have written this :-D

I have now turned the error's on and some error's i have never seen or heard of can you provide me with a site with the common error's?

Link to comment
Share on other sites

Re: An introduction to security

Ok nyna is a good person at redirecting to site's not me but ok say you have a $n that is not being called out for example:

 

if($ir['userid'] == 1)
{
   $n = "BOO";
}

 

By putting error_reporting(E_ALL); on it will say unexpected something some thing $n blah blah. Now you will need to forget about those error's and rather fix the other's.

Thats all i got to say on error_reporting(E_ALL);

Link to comment
Share on other sites

Guest Anonymous

Re: An introduction to security

It's not too hard to get rid of the errors -- Just takes time.

With hand-crafted source from scratch - I get a few I guess, some obvious, some not so, but with something like DBS/MCcodes -- nasty -- There are a lot.

Most can be cured with careful use of isset() -- And that's something that IMO should be done. When you use a real language (compiled rather than interpreted, you quickly find out that uninitialized variables are a sod and can cause all sorts of unexpected issues).

Link to comment
Share on other sites

Re: An introduction to security

Ok i'm sure nyna will be able to find a site that can help me fix it :-)

But that isn't the main error i have just 2 example's are posted below.

 

Notice: Undefined index: HTTP_X_FORWARDED_FOR in /mnt/web6/40/42/51656042/htdocs/hitmanv2/3.php on line 84

Notice: Use of undefined constant ON - assumed 'ON' in /mnt/web6/40/42/51656042/htdocs/hitmanv2/explore.php on line 4

Any sites that might help me with those?

Link to comment
Share on other sites

Guest Anonymous

Re: An introduction to security

 

Ok i'm sure nyna will be able to find a site that can help me fix it :-)

But that isn't the main error i have just 2 example's are posted below.

 

Notice: Undefined index: HTTP_X_FORWARDED_FOR in /mnt/web6/40/42/51656042/htdocs/hitmanv2/3.php on line 84

Notice: Use of undefined constant ON - assumed 'ON' in /mnt/web6/40/42/51656042/htdocs/hitmanv2/explore.php on line 4

Any sites that might help me with those?

The first one is pretty obvious -- second one I don't know (not in my small set of sources anyway)

But.. the first - IIRC: the line is:

 

$ip = ($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];

 

There are a number of problems with this, however to fix your specific issue, I'd use:

 

$ip = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];

 

I do a little more checking, but you should get the gist from this. The error is stating that the key HTTP_X_FORWARDED_FOR does not exist in the $_SERVER array... Therefore the isset() function performs this check.

Link to comment
Share on other sites

Guest Anonymous

Re: An introduction to security

 

if(isset($_GET['donem']))
{
   echo '<script language="javascript">alert("Your email has been changed to '.$_GET['donem'].'");</script>';
}

 

I'd suggest checking the type of $_GET['donem'] as well, but for most people that's probably overkill. - There's also the interesting possibility of injecting nasty data into here, but I'll assume you have cleaned the data up prior to these lines.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...