Jump to content

HTTPRequest and Databases - Safest Way?


Tommy Rampal
 Share

You are about to reply to a thread that has been inactive for 4782 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hey all,

So pretty much I am developing a stat based game, where levels are sent via. HTTP request to my PHP script, which update the user database occasionally with the latest stats (which are sent via. post data). I'm pretty new to PHP, how the headers work and such. But what lays before me looks pretty clear, that without the correct precaution, some crafty player (unsure why they would go through the efforts, but you never know) could sniff the address/what's being sent, and inject their own data - resulting in cheating when a backup takes place.

Could someone make it clear if this is possible for someone to easily manipulate how Secondlife communicates with HTTP/PHP headers, and if so is there a fool-proof way to prevent this? I use Base64 password encoding (as described by the LSL wiki) for the post data.

I've been awake +24 hours, sorry if I didn't make much sense -_-.

Thanks to those who take the time to help, it's really appreciated!

Link to comment
Share on other sites

Well - the most important thought in that connection you have already mentioned: Why? The next would be: If yes, is it really worth to prevent it? What happens if?

But of course, there are a few things you can do:

  • Use HTTPS - this helps with a range of security issues
  • Encrypt your data
  • send security tokens along

Just a few ideas.

HTTP is one of the savest means of communication in SL.

 

The term 'easy' is can be misleading in this connection. Bulding a bomb is relatively easy: There are plans on the net, the stuff you need is relatively easy to by ... but still that doesn't mean that everybody does it. Actually, to intercept HTTP connections and inject data into it, I would say requires more expertise than a building a bomb. You need to know what you are doing - if you do, it's not very difficult. It requires some time - even more so if you really want to insert data into the HTTP messages that doesn't just cause an error but goes by undetected. If we're talking money transactions this may be worth it - but  in your case?

Link to comment
Share on other sites

two things, one, you'll want to secure your inworld items using it... that pretty means no mod across the board (there a known  security exploit  bug that lets anyone with a script in the object listen to the responses from http.

second, you'll want you use some sort of "auth" which is just a short encrypted string that ensures that only your stuff talks to your sqy server... because even if someone in SL is unlikely to find it, there are zombie machine scanning for servers they can exploit constantly.

Link to comment
Share on other sites

Void has mentioned some of the more pertinent points.

There are a few security best practices (depending a lot on what level of security you want/need):

1. Never, EVER, use the root or admin account to update your DB or script your DB in any way shape or form.
2. If you use MySQL, use something like mysql_real_escape_string. If you use another DB, use the equivalent.
3. Add as many sanity checks to input data as you can. If you expect numeric data, make sure you get numeric data. If you expect string data, add plausibility checks as you see fit.
4. Headers can easily be spoofed. Do not ever trust headers for authentication or verification purposes, maybe with the exception of server vars set by your web server.
5. For any kind of auth mechanism, make sure it's not vulnerable to replay attacks. What that means is that someone replaying the data stream to your server should not succeed. One common approach is to have the server provide a random token on the initial handshake, the LSL script then combines that with its own secret key and sends it back to the server. If the server knows that password, it can then verify that the LSL script also knows it - without ever transmitting the actual password over the wire in any form. One easy way to do so would be llSHA1String(sPassword+sNonceToken), which equates to sha1($sPassword.$sNonceToken) in PHP.

6. There is no good way to encrypt data in LSL. The wiki has a few implementations, though they all have the disadvantage that they are fairly slow. XTEA is about the fastest there I think, but it still ain't fast. Worst thing you can do is create your own :)

And if I haven't mentioned it enough: Add as many plausibility checks as you possibly can. Go overboard if you have to. On the LSL side it's a bit painful to do that, but... still a good idea :) Generally, you don't want your server to get hacked though.

Link to comment
Share on other sites

To be honest, I wouldn't worry about it much, beyond what is necessary to protect your server from random hacking attacks that are nothing to do with its real purpose.

1.  Keep you script no-mod, even if nothing else is.  Then no-one can see the address of your server.  Scripts live and run server-side so the request is going from one of LL's servers (which would be hard for anyone to sniff) to your server (which they don't know).

2.  The response coming back is similarly not likely to be subject to packet-sniffing as it's between your server and LL again.  As Void said, any other script in the object can copy the reply but it doesn't identify the server still and wouldn't give away any of the already-sent data or its format.

Link to comment
Share on other sites

Thanks for the support guys!

So here are some things (web-side) I have done:

  • Moved to mysqli, I never really understood the benefits of using it at first - apart from the syntax is a bit different. I work in object orientated side of things ($mysqli->prepare).
  • As demonstrated above, I use prepared statements - that allows me to use $stmt->bind_param to bind values (set as ? in the query) as string, integer, whatever. So hackers who have field information cannot inject bad data (e.g. 'OR 1').. I don't think?

Some things I am not sure of:

  • So the server script sends a HTTP request on rez to a page, this checks if the owner key of that server object (using the headers) is the admin key (which is a set value in the database). If so, the server key is updated with that object key (just in case of an accidental deletion, or a server update).
  • The client/product sends a request to get the server key, and sends a http request. The web code checks if the owner header is registered with the database.


    So is this bad like Jenni said? If so, what is a better way of going about it following the scenario?

In regards of replay data (I presume it's reusing a command over and over)... The client has client side values which it updates from (like game stats), and sends the update via. a command with a passworded base64 encode. I guess that's a big enough form of 'encryption', there's a new password for different type of commands. Would anyone suggest this is not good enough or there is a better alternative out there?

Link to comment
Share on other sites

Bound parameters should prevent injection attacks :)

As for the owner key in the header... there you'd want one additional check, to validate that the request came from one of the SL servers. That'd be a two-stage check:

First, check if the remote host name gethostbyaddr($_SERVER["REMOTE_ADDR"]) ends with ".agni.lindenlab.com". Notice the dot, it's kinda important, though less so in this specific case.

Second, take the full name you got from the gethostbyaddr call and reverse it, i.e. gethostbyname() and see if the resulting IP matches $_SERVER["REMOTE_ADDR"]. If either of the two don't match, someone is trying to spoof the reply from some offworld site.

As far as I'm aware it should not be possible to spoof the headers (i.e. owner key) from within LSL, though don't quote me on that :)

 

Also, don't use base64 as "encryption", because it's not. It's a transfer encoding to ensure binary data gets passed safely. For your password, use llSHA1String to encrypt it before transmitting it. That way, the password itself never gets transmitted and someone would have to brute force the password. That principle is known as "Pre-Shared Keys", PSK.

 

Preventing replay attacks is a bit more involved. You're right, it means replaying a command (or data stream) over and over. The problem has to do with a relatively simple problem, like this example:
1. Your LSL script sends a "Start Game", hashing the password with SHA1 into something like 2E73318E547AF1B28CC0C96F95DDC9B1EE906B8D
2. The server gets that command, and checks that the SHA1 matches the password it already knows. They match so it starts the game.
...game progresses and ends... and then...
3. Malicious user takes the whole game session and "replays" it against the server, essentially duplicating the game progress. Most often that's used to skew the stats by unfairly replaying a good game over and over.

Now, with the communication between the SL server and your machine, the communication should in theory remain private. Practically, it may or may not be. The trick is to make the replay impossible. One very common way you can do it is by adding a so-called "Nonce" to the password hash. Simply:
1. Your PHP server generates a nonce and sends it to the LSL script
2. The LSL script generates a nonce and sends it to the PHP server
3. The LSL script now "signs" all communication with llSHA1String(sPassword+sNonceFromPHP)
4. The PHP Server now signs all communication with sha1(sPassword.sNonceFromLSL)

II think you're on the right track.

Link to comment
Share on other sites

it all depends on how sure you need/want to be with your communication. Time+Owner is guessable, that's why it's generally frowned upon as auth mechanism.

The principle is that even if a potential miscreant knows _exactly_ how the auth mechanism works, they should be unable to break it. For most SL use where no money changes hands, that's probably overkill.

Link to comment
Share on other sites

Pretty much how I've done it: my game sends a request to make a token that carries the initial command with it, it then repeats that command when the token  has been made in the database and follows the communication with that token (using a select query to see if that token exists with the agent who initiated it), upon the final communication it sends a final request to delete that token and the token is also reset within the game.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 4782 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...