Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I am aware of nonces to check for intentions but can't make any sense if I can use them to restrict for database reads somehow? I mean, I am fetching records from the database using AJAX but I don't want anyone to have that data by some other means (POST requests to that admin-ajax.php page).

For example, in my AJAX handler I have this much of work (I am sending $myid along with the action in the AJAX call):

$myid = 5575;
$query = "SELECT `id` FROM table WHERE `user_id` = $myid;";
$data = $wpdb->get_col( $query );
echo json_encode($data);
die();

I am calling this much of data through AJAX, how can I protect it from evil users who can try to make direct POST calls to that page?

Edit: @Bainternet Thanks for the detailed explanation, appreciate that but my question is really about what @Milo said and I can see that unless I can create a unique nonce for that request, I can't do anything as per @goldenapples. Right?

I am handling all this stuff with Facebook JS SDK, so everything that has to be done is with AJAX only (without page load), and whatever I can think of making the user sign in wp_signon() or anything, anyone else can do that too without authority. So, I don't have any uniqueness in a user who is actually using the site and the one who is trying to get read some data out other than the site makes the call to fetch the data. And whatever I can do to make it login or anything, that can be replicated by someone else too. Can anyone think of something?

Update: I think I have found a workaround by just calling it with action and get other parameters from Facebook using PHP SDK. But I am still open for suggestions or anything else for that matter.

share|improve this question
    
be sure you're not confusing nonces, which confirm ones intention, with authentication- making sure someone has permission to do something. –  Milo Apr 22 '11 at 0:59
    
No, I think I am not confusing it, I just need a way if I can use it somehow in this case. –  Ashfame Apr 22 '11 at 7:22
add comment

3 Answers

There are a few things you can do to make more secure:

First the Ajax call it self should be made with a WordPress nonce like you said:

<script type="text/javascript" >
    jQuery(document).ready(function($) {
        var data = {
            action: 'ACTION_NAME',
            Whatever_data: 1234,
            _ajax_nonce: <?php echo wp_create_nonce( 'my_ajax_nonce' ); ?>
        };
        $.post(ajaxurl, data, function(response) {
            alert('Got this from the server: ' + response);
        });
    });
</script>

In the above code mind the two attributes action and _ajax_nonce which both are needed to verify the call to admin-ajax.php, in the first few lines of code it check if an action was sent to the server and if not then it die()'s (FIRST CHECK) then using that action you with an action hook you call your own ajax function:

//if you want only logged in users to access this function use this hook
add_action('wp_ajax_ACTION_NAME', 'my_AJAX_processing_function');

//if you want none logged in users to access this function use this hook
add_action('wp_ajax_nopriv_ACTION_NAME', 'my_AJAX_processing_function');

and if you want both logged in users and none logged in visitors to access this function the use both hooks (SECOND CHECK).

then in you ajax function the first thing you should do is check for the ajax referrer (THIRD CHECK):

function my_AJAX_processing_function(){
   check_ajax_referer('my_ajax_nonce');
   //do stuff here
}

next when running queries on database with user input you should use $wpdb->prepare for escaping and validation so instead of:

$query = "SELECT `id` FROM table WHERE `user_id` = $myid;";
$data = $wpdb->get_col( $query )

use:

$data = $wpdb->query( $wpdb->prepare("SELECT `id` FROM table WHERE `user_id` = %d",$myid));
share|improve this answer
1  
the part that confused me about the original question is what is to stop me from changing the user id that's sent and seeing any user's data? –  Milo Apr 22 '11 at 0:53
    
@Milo: that's the down side of ajax nothing will stop you, but you can check the integrity of the posted data an prevent eval stuff like sql injections as much as you can. –  Bainternet Apr 22 '11 at 2:09
    
@Milo if you use dynamic content like the user_id that you're querying about in the "action" string of the nonce, then you can make it very difficult for a user to find data other than what you've authorized them to. For example if they're looking up user 33, make the "action" of the nonce "lookup-user-33" and check for that nonce in your Ajax function. That string will get hashed with a bunch of other data and it will be very difficult for anyone to guess the proper nonce to do an action they're not authorized for. –  goldenapples Apr 22 '11 at 2:52
    
@Milo @Bainternet @goldenapples I have appended my intentions in the question, please take a look. –  Ashfame Apr 22 '11 at 7:20
add comment

I am not entirely sure how secure this is, but WordPress Ajax handlers are user-aware (I guess request is still request so cookies are checked and if user is logged in that is accounted for). So you can make usual current_user_can() check in them.

share|improve this answer
    
I will need to pass an ajax call to WordPress to make a particular user to login by wp_singon() along with ID which someone else can replicate to login by any account. –  Ashfame Apr 22 '11 at 11:56
    
@Ashfame not sure I understand, you want login by Ajax? Then you will need to also send password to authenticate properly, right?.. –  Rarst Apr 22 '11 at 12:05
    
I am using FB connect (no plugin, but custom code), so if I need to make anything unique for which I can use some checks on Nonces, I will need to pass that parameter through Ajax too (like ID). I have updated the question with a workaround, see if you can think of any other ideas. –  Ashfame Apr 22 '11 at 15:45
add comment

presumably one is logged in when making this request? you can hash some data and create a unique per-user nonce on your page, pass it with your ajax request, and check it against the logged in user. or maybe I'm misunderstanding what you're doing here.

share|improve this answer
    
sorta, please take a look at the updated question, your comment on Bainternet's answer is really what I want to do. –  Ashfame Apr 22 '11 at 7:21
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.