On my website, I have created a comment section for blog posts. Users can write comments, click a button, and an AJAX request will be sent to PHP containing the data in JSON. The PHP will process & validate the data and then insert it into the database. On success, all comments are retrieved from the database and, using JQuery, all of the page's comments are reloaded.
The problem is that anyone can come along and, using their browser's console, forge an AJAX request, fill in their own JSON, and send the request to PHP. If done like this, all that happens is my client-side validation is useless. The server-side validation would still work. However, there's a bigger problem.
for(var i = 0; i < 10000; i++) {
//ajax request
}
The user can very easily insert thousands and thousands of records into my database instantly.
Does anybody have any suggestions on how I can prevent something like this from happening? It must involve creating something on the server side that can't be guessed by a user, and somehow checking against that during an AJAX request. I'm just not sure how exactly to go about this.
Thanks for the help.
The only way for you to be safe in this respect is to add a CAPTCHA.
This will prevent mass / automated posts. One possible library to use is Securimage . It is simple to use and integrate. You can have it running in 10 minutes with your AJAX stuff.
Relying on other means such as cookies or client side validation of some sort is risky, if possible at all. For instnace KA_lin 's solution can be compromised in 5 minutes: a malicious user can be sending forged cookies that will always have a page count of 0 and thus will always be allowed to post. Or even worse, he could create a small program that will post to your page without sending any cookie at all. The above code will create a new cookie and accept his post, every time ...
I would add a session variable containing the number of posts a user makes, given many pages you can form something like $SESSION['page_id_total_nr_comments'] and track this number, add a config variable that let`s the use to add a maximum of X comments per article for example:
function canUserAddComment($pageId){
$maxAllowed =......;
if(!isset($SESSION[$pageId+'_nr_comments'])){
$SESSION[$pageId+'_nr_comments'] = 0;
}
if($SESSION[$pageId+'_nr_comments']< $maxAllowed){
$SESSION[$pageId+'_nr_comments']++;
return true;
}
return false;
}
OR
On save get the number of comments a use already made on the article and decide if ha can make another(still with a config variable)
Related
I'm making a quiz application, where 4 users join a lobby (finished), and then the leader starts the quiz.
When the quiz is started, questions get randomly selected. Users can answer them, and click submit. Each question is timed, meaning user only has 10 seconds to answer the question.
This is all done through AJAX, since I want the website to be real-time. How exactly would I prevent cheating? User could manually edit the JS file, etc.
I was thinking of getting the exact time when the question gets loaded + the answer time. And if it's not in the span of 10 seconds, he's cheating. Would that work, or is there a better and easier way to do this?
Thank you.
Edit
I thought AntiForgeryToken was right solution to solve your problem. I read a lot of articles to make sure my old answer is correct.
1- Hiding or Encrypting the javascript source code
2- How to Disable HTML view source or Encrypt Html elements programatically?
3- How To Prove That Client Side Javascript Is Secure?
4- ASP.NET MVC - does AntiForgeryToken prevent the user from changing posted form values?
I came to the conclusion:
AntiForgeryToken prevents a malicious site to trick a user to a form that looks the same as the original and post it to the original site. It does not prevent the scenario you are describing.
There's really no way to do this completely client-side. If the person has a valid auth cookie, they can craft any sort of request they want regardless of the code on the page and send it to your server.
You can use HtmlHelper.AntiForgeryToken with salt value.
To use these helpers to protect a particular form, put an Html.AntiForgeryToken() into the BeginForm, e.g.,
#using (Html.BeginForm("Users", "SubmitQuiz"))
{
#Html.AntiForgeryToken()
<!-- rest of form goes here -->
}
This will output something like the following:
<form action="/Users/SubmitQuiz" method="post">
<input name="__RequestVerificationToken" type="hidden" value="saTFWpkKN0BYazFtN6c4YbZAmsEwG0srqlUqqloi/fVgeV2ciIFVmelvzwRZpArs" />
<!-- rest of form goes here -->
</form>
Next, to validate an incoming form post, add the [ValidateAntiForgeryToken] filter to your target action method. For example,
[ValidateAntiForgeryToken]
public ViewResult SubmitQuiz()
{
// ... etc
}
Salt is just an arbitrary string. A different salt value means a
different anti-forgery token will be generated. This means that even
if an attacker manages to get hold of a valid token somehow, they
can’t reuse it in other parts of the application where a different
salt value is required.
You can create different salts for different users like this.
Edit
AntiForgeryToken() prevents tampering with the code using inspection tools like this:
In Client side
1- A new random anti-XSRF token will be generated.
2- An anti-XSRF field token is generated using the security token from step (1).
In Server side (Validating the tokens)
1- The incoming session token and field token are read and the anti-XSRF token extracted from each. The anti-XSRF tokens must be identical per step (2 client side) in the generation routine.
2- If validation succeeds, the request is allowed to proceed. If validation fails, the framework will throw an HttpAntiForgeryException.
For more information this, Please see this article.
Conclusion: Since there's no way to prevent anything on the client side, the only solution that actually sounds okay is having server check everything.
A GET request, which requests the question and logs the time. After that, a JS timer which automatically submits the question if the countdown is finished. The user can also manually submit the answer (obviously). POST of the answer, and the server logs the time of it, compares it to the initial time of the GET request. If it's longer than 10 seconds, it throws and error, and the answer is not counted.
Thank you everyone.
I have a website where you need to create an account and login to play the game. I have PHP that refers to a MySQL database with a column for UserId, Username, firstname, lastname, password and score. The login works fine. Then, you are taken to the html document that contains the game. It is somewhat like cookie clicker, where your objective is to get the highest score possible through interacting with an object.
I have a score variable called "clicks" which increases quite rapidly.
I have some javascript code that reads;
if (clicks%5==0) {
sendScore()
}
What this means is when clicks is divisibly by 5 it activates a function called sendScore. It activates the function every 5 increments because I assume sending data to the table multiple times a second would be demanding too much from the server. This function will write the current players score to the MySQL table column named "score", the row in relation to the players UserID. UserID is a number that is generated when an account is created so that the user's account can be easily referred to.
I know its just me overthinking it, but I cannot seem to write a working piece of PHP code that I can link to the sendScore() function that sends the player's current score ('clicks' javascript variable) to their score column in the MySQL database.
Any help would be appreciated.
Thank you.
NOTE!!!!
The request to send info has to be an AJAX request. Maybe this is why it doesn't work. I am used to writing forms, but forms would refresh the page. Can anyone help write an AJAX request for this situation?
What is your current sendScore function?
It is kind of hard to give a detailed answer without more of your code, but I'll try:
Your sendScore function will need to send a request to the PHP script that will handle this request. You can do that either using pure JavaScript, using XMLHttpRequest. More on that here: http://blog.garstasio.com/you-dont-need-jquery/ajax/. However, you can also use a framework such as jQuery to do some of the heavier lifting. More on jQuery and AJAX functions (specifically post-requests) can be found here: https://api.jquery.com/jQuery.post/.
Then you'll need a PHP function that can handle the request. You have to point your JavaScript function (that performs the POST request) to the URL of this script. Then you can process the information sent by your JavaScript just as you would process a 'normal' form.
To get your values from JavaScript to PHP and vice versa, it's probably easiest to use JSON, as both JavaScript and PHP handle JSON nicely these days, and it's a lot easier than XML.
I'm currently using Classic ASP and youtube javascript API in order to pull information of videos and store them into a database, however I need to know if some of the next steps are possible, or if I would have to convert to another language.
The information I am seeking to download into my SQL 2012 Database currently exceeds the maximum space allowed, meaning I can only send about 50 of my 1700 results (and growing) each time. Prior to the space cap, I would simply keep running the next page function until there is no more pagetokens and simply upload all the data, however, now I must do it in small steps.
My application currently works like this: Javascript creates hidden forms->Forms are submitted->classic ASP queries form and moves information to database
By directly editing the code I can modify which 50 results I send to the classic ASP, but I'd like to be able to do this without modifying code.
So my question is this: Is it possible to send a url query of sorts to javascript so that I know what results I have sent? Or is there a better way to circumvent the space issue aside from rerunning the javascript each time?
The error I get when attempting to spend too much information is:
Request object error 'ASP 0104 : 80004005'
Operation not Allowed
I apologize if this question seems a little vague as I'm not entirely sure how to word this without writing a 5 paragraph essay.
You could add a redirect on the ASP doing the downloading. The redirect can go back to the javascript page and include the number of results processed in the url like so:
Response.Redirect "javascript.asp?numResults=" & numberOfResultsSentSoFar
Then on the javascript page include some ASP to extract the number of results processed
dim resultsProcessed = Request.QueryString("numResults")
Then you can feed it into javascript like so:
var currentResultIndex = <%=resultsProcessed%>;
However, a better way might be to use AJAX to send the first 50 results and wait for a response from the ASP and then send the next 50.
I want to do is when a user fill a valid email in the textbox and click the send button it will send to his email his password directly.
My problem is the result takes 3 secs or more in order the ajax script receives the result specially when the php echo 0 to ajax. Does anyone know how to make my code faster?
Make your connection persistent using mysql_pconnect.
Return only changed data and apply the difference instead of returning whole set of data.
Also, instead of hitting database often, you can cache as much as you can.
Also, refer to PHP micro-optimization tips.
Asynchronous request doesn't mean the request are fast, it means you can continue with your code flow without waiting for the response.
Running a query on your database and sending a mail will take time.
The problem might be not in your ajax code.
Not really know how many records in table tbl_mkash. For a lot number of records (million of records) indexing field elog_email might speed up the query.
First off, let me say that I know this does not seem like an uncommon issue. I do not intend to clutter these forums with questions that have already been answered, but, I have worked through probably about 3 dozen threads with similar issues and have been unable to reach a solution.
The short description of my issue is this: I am trying to redirect after submitting a form using php's header(location:) function, and it's not redirecting. It is a little bit complicated because the form is submitted via AJAX. The steps my code goes through are as follows:
User submits form > form data sent via AJAX > form processing page validates data > if valid, form processing page inserts data into database > if submission is successful, form processing page adds redirect URL to $_SESSION > form processing page returns a 'redirect' variable > javascript/AJAX checks for redirect variable, and refreshes page if found > page header checks $_SESSION for redirect URL, and if found, sets appropriate headers and exits.
I guess the first thing I want to ask is, is this the right way of going about this? It seems to me that there should be a simpler way of doing this. It's obviously much simpler to pass the redirect URL to the javascript and do a window.location redirect, but I read that it's much better/more secure to handle that on the server side, so I'm trying to do that.
Assuming I'm going about this in the right direction, what could be going wrong here? I've checked for leading and trailing whitespace, BOM characters, I've even tried output buffering and I still have the same issue.
What happens on form submission is, the page refreshes, but it returns to the original form page rather than the redirect url. I have turned on the most detailed error reporting and get no errors at all.
One thing that may or may not be of interest, I have an error_log function set up to log all headers to a file right after I set the Location: header. When I redirect outside of AJAX (which works), the accept: header is set to html, but when I try to do it via AJAX, the accept header is set to JSON. Could that cause a problem?
Thank you so much for taking the time, and again, apologies if this is a dumb question. I have used this forum for years and have never once had to post a question on it because it has always solved my problems until now. Thanks in advance!
PHP is too generous to include in your code not only HTML code, but also JavaScript code. I'll explain one thing. When you send data by ajax, it is often difficult return Boolean data (whether true or false, depending on the conditions we work side server with php in some file established in our direction ajax) to give a final answer.
On the other hand, returning to the generosity of PHP, always when we try to validate data server-side and through ajax, we can manipulate the section where work freely to show some response message, a redirect to somewhere on your page or create a session. Anyway, whatever.
What I mean is that in your controller section where you will work with AJAX, you can set different conditions. That is, if the user data are correct, then you could send to call a script from Javascript to redirect him with a location.reload (); and also assign a session automatically. If the user does not have the correct data, then what we should do is return a warning message or alert to the exit AJAX, usually it goes after a:
function (response) {
$ ('.answer').html(response);
}
Note that it is not necessary require, for example, a $ ('.answer').html(response); to return an answer, because ajax only sends data to the server and if there is a reply message well, and if not well. Many times what I do, is to send messages via console, although it is often convenient to do so, because as often work with several conditions and that depends on the result of our request, we will be forced to show some response in some element within our code.
What I advise you is that you work javascript in PHP, and hence redirect to other pages, assign sessions or simply return a message. Remember that an ajax request is not only asynchronous, but repetitive and can send it to call as often as you need. The fact that you sent your ajax call php file and you have returned an answer, does not mean you can go back to work with it once you finish your ajax request.
It is the right way to do what you want, it is often easier to manipulate our server-side code that client side. Greetings.