How does facebook server validation work? - php

Considering a simple example:
Login to your fb account
Post a status
Click on the status dropdrown(top-right corner)
Open developer tools in your browser and find the html for the "delete" option
edit a parameter which looks like story_fbid=10202782137141336
Since the wall consists of several statuses and posts each with a different value for story_fbid, facebook should be using these values to update/delete respective posts.However, changing even a single digit of this value(story_fbid) to lets say story_fbid=10202782137141337 throws up a error as shown in the snapshot below.
I am a beginner in php programming and was curious to know how the server side validation of data is done in php...
So, I was looking for a basic explanation of how this client side changed html is detected at the server end.
I came across a similar question here. According to one of the answers, one possible methods would be the server uses UUID associated with an ID of a particular post. If this UUID is manipulated at the client side, the server detects this and does not perform the requested operation(like DB record update/deletion) on that ID.But since a page can contain multiple such posts with different IDs, it could not be possible to have a UUID associated with each one of them.
So. what method does facebook use to detect such changes?

Disclaimer - I have absolutely no idea exactly what validations are made on Facebook's side - this is post consists solely of educated guesses and general web security concepts.
Any data submitted by a user should be treated as if it has been tampered.
I think this is a great motto to go by. The data you send to Facebook when liking/commenting/deleting a post is composed solely of data that was generated by the user submitting the request. Whether that data was generated by the JavaScript that is already on the Facebook page or by a cURL command or even manually compiled by a user makes no difference to the Facebook server responding to that request.
Since there is no way to validate the data before it arrives at a Facebook server, all data should be considered as "possibly manipulated/harmful". For this reason, it's safe to assume that every single request made to a Facebook server passes though multiple levels of validation:
Is this request valid? Does the request pertain to the expected format? Valid endpoint? valid parameters? Valid arguments?
Is there a valid user on the other end of the request? Are they using a valid access_token or similar parameter?
Is that user allowed to make this request? Is the object owned by the user? Does the user have the required permissions to make this request?
etc...
etc...
etc...
Many more etc's...
Probably even more validations...
If anyone of these (assumed) validations fails, an error message is returned to the user. In order to keep the exact validations secret Facebook probably elected to return generic errors to the users as to not let them know exactly which validations are performed.
If a user was to know exactly what validations were performed it might not be too hard to bypass them - hence, as you can see, the error you get mentions an array of possible problems:
"can not be displayed right now" - most generic explanation.
"temporarily unavailable" - huh? like a hard drive failed? power outage? Data center's internet is down?
"link... has expired" - possible manipulation of an access token?
"don't have permissions"
It would be impossible to know exactly what is happening on Facebook's side - and this is their intention.
In a similar manner, sites that give a login error similar to "user name or password invalid" don't give the user any indication as to which parameter is invalid. It could be the username or it could be the password. Saying that only the password is invalid hints to the fact that the supplied username actually is valid and that may be information that the site doesn't want to share.

Related

Should GET requests store to database?

I’ve read that you should not use GET requests if you are modifying the database. How would you record analytics about your website then?
For example, I want to record page views whenever someone visits a page. I would need to update views = views + 1 in the database. Is this OK, despite using a GET request, or is there another technique? Surely, not every request should be a POST request.
The general advice about how to use POST vs. GET shows up in RFC 1945 from 23 years ago:
The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.
 
POST is designed to allow a uniform method to cover the following functions:
Annotation of existing resources;
Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;
Providing a block of data, such as the result of submitting a form [3], to a data-handling process;
Extending a database through an append operation.
These guidelines remain in effect to this day, but they cover the primary purpose of the user's page request.
The act of incrementing a view counter is incidental to the primary purpose of the request, which is to view the page content. Indeed, the user is likely unaware that this database update is occurring.
(Of course, you must expect that you will receive duplicate requests as users move through browser history, caches are populated, or spiders crawl your pages. This wouldn't be the case if a POST request was made.)
It's ok.
When you make POST request, you actually wait for POST params to come and you build your database insert query based on parameters which you've got from browser.
On GET request you actually implement your own business logic, so user won't ever know what is going on the side.
And for the finish, actually sometimes you can do something, what's going against rules, rules are good, but we are able not to follow them, that's what makes us human, if we would strictly follow all the rules, it would be cumbersome.

Qualtrics 3rd Party Add-On Best Practices

I am working with Qualtrics, which is just a web-based survey engine. The request is that, once users finish the survey, they will receive a small prize in the form of a gift code. Since I can't host the prize code data on the Qualtrics platform, my idea was to store the prize codes on a remote server. When the user finishes the survey they will be directed to my server (https), to a PHP script that will give out the prizes. On the surface this is possible, because as one piece of customization they allow to re-direct to a URL upon completion of the survey.
The problems that I am faced with, regarding my PHP script that gives out the prizes are as follows:
1) Make sure visitors have COME FROM the survey and have actually
finished the survey.
2) Only give out 1 prize per participant per survey.
It is difficult to address #1 because it seems like after the survey is complete, you just get a basic re-direct to my site. It would be possible to add GET data to the URL, its very easily readable and doesn't offer security. Even encrypting the GET data doesn't seem feasible because a hacker could just copy the data string once they see it.
The idea I had to address #2 was to check the user's IP address using PHP, and store the address in my DB after a 1-way encryption. This way the IP would be unknown, but I could check for duplicates, only allowing 1 prize per IP.
So the question is, is it even possible to do what I am trying to do with just a simple URL re-direct? Is my idea for addressing #2 acceptable?
Thanks.
There are probably many ways this could be handled. Two that come to mind:
1) At the end of survey, Qualtrics creates an embedded data field called ResponseID which is in the Qualtrics data. You can include the ResponseID in the redirect then have your php script call the Qualtrics REST API, and try to retrieve the response with that ResponseID to make sure it exists.
2) Just before the end of survey, you could do a web service call to a script that creates a unique id, store the id on the server side, and return it to the survey as an embedded data field. Then pass the unique id in your redirect and make sure it matches a unique id you stored.
EDIT based on comment below:
You can add custom parameters to your redirect by piping in parameter values like this:
http://mywebsite.com/myscript.php?rid=${e://Field/ResponseID}
If you are able generate special request parameter for redirect url and make it for every user unique, then you could invent some algorithm, and encrypt user ID with it and pass this ID as parameter in redirect url.

How to stop people from flooding PHP API with requests?

I am using a simple PHP API that takes requests and connects to a MySQL DB to store/retrieve user information. Example: Login is done using a HTTP POST to the API with username and password.
How do I prevent people from flooding my API with requests, potentially making thousands of accounts in a few seconds.
Thanks
You could serve a token generated and remembered on the server side which is rendered with your forms and validated when the form is sent back to your server. That prevents the user from just generating new post requests without actually requesting the according form from your server since they need the according token generated on your server to get it through.
Then there is the mentioned captcha which would be way too much for a login form from my point but when it comes to things like registering a new user the captcha in combination with the token sounds very good to me.
UPDATE
I Just found this article which is about floot protection of script execution in general. I think their approach is good as is the ip tracking provided you have the ability to use memcache or something similar to speed the checks up.
First, when registering a user, also save her IP address at the time of registration in the DB.
If the IP already exists within 45 minutes of previous registration, reject the request.
Another method is the Captcha, I personally prefer a different method that I found to be even more effective against robots.
Instead of asking the user to "type what they see in an image", and verify they are humans (or robots with sophisticated image processing),
Add another field (for example city), and make it hidden with javascript.
The robots would submit that field to the server, and humans would not.
Note that the robots must run the javascript in order to know what fields are hidden, and this is a time consuming process that they usually don't do.
(see turing halting problem)

Passing values through URL or POST variable instead?

I'm implementing a message system (private messaging, if you will) and I'd like to be able to display the list of messages a user has by a text link so I don't need a button to open it. The message_id (unique value in the databse) would be passed through the URL. (something like www.example.com/message/view/16).Assuming I check to make sure the session of the userid matches the userid that the message is sent to, is this OK? To make it safer I could just append a random number and set that as as session, and then just check for that upon viewing.
Should I forget this idea and just stick with a submit button to view the message?
A POST request would not provide any more safety than a GET request: any half-decent web debugging tool can forge POST requests. You should simply never trust user-input data. Always double-check authorizations for safety!
That said, GET request semantics match what you're trying to do here.
The HTTP standard says that a GET request should be repeatable without any non-trivial consequence. For instance, it's adequate to view data with a GET request (and possibly do small things like incrementing a counter, since these are pretty trivial consequences). In fact, GETand HEAD are the two request methods that are considered "safe".
On the other hand, POST requests are expected to have non-trivial consequences, like sending a message or placing an order. Stuff that you don't want to perform twice accidentally. Most browsers these days also respect this by warning users when reloading a page would cause a POST request to be performed again.
Using GET values for viewing messages is much better idea, because assuming a user stays logged in, it would allow them to bookmark messages, etc.

Preventing erroneous AJAX Calls by the user

I have a webpage in which the user is awarded X points on clicking a button. The button sends a AJAX request(JQuery) to a PHP file which then awards the points. It uses POST.
As its client side, the php file, parameters are visible to the user.
Can the user automate this process by making a form with the same fields and sending the request ?
How can I avoid this type of CSRF ? Even session authentication is not useful.
You should handle that on the server-side, If you really want to prevent multi-vote or prevent the same people from voting several time on the same subject.
This is why real votes always use authenticated users and never anonymous votes.
By checking the request is really a XmlHttpRequest (with #Shaun Hare response code or with the linked stackoverflow question in your questions comments) you will eventually block some of the CSRF but you won't prevent a repost from the user, using tools like LiveHttpHeaders 'replay' and such. Everything coming from the client side can be forged, everything.
edit* if it's not a voting system as you commented, the problem is teh same, you nedd 'something' to know if the user is doing this action for the first time, or if he can still do this action. There's a lot of different things available.
You can set a token on your page, use that token in the ajax requests, and invalidate this token for later usage server side. This is one way. the problem is where to store these tokens server-side (sessions, caches, etc)
Another way is to check on the server side the situation is still a valid situation (for example a request asking to update 'something' should maybe handle a hash/marker/timestamp that you can verify with current server side state.
This is a very generic question, solutions depends on the reality of the 'performed action'.
Check it is an ajax call in php by checking
$_SERVER['HTTP_X_REQUESTED_WITH']

Categories