1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Protect AJAX request from abuse

Discussion in 'PHP' started by ycc, Sep 9, 2010.

  1. #1
    I send AJAX requests from web-pages to php pages. The PHP pages read the querystring in the URL (GET-arguments) and change data in databases.
    http://example.com/mypage.php?id=1234&new_value=9876
    
    Code (markup):
    If someone wants to abuse the PHP page they could run it on its own and include random argument values in the querystring.

    I therefore just included the following code. I think it will make it ""impossible"" to run the php-routine in any other way than from my own pages?

    $ref=$_SERVER['HTTP_REFERER'];
    $domain = parse_url($ref, PHP_URL_HOST);
    $domain = strtolower($domain);
    if (($domain=='example.info')||($domain=='www.example.info')) {
    // manipulate database ...
    }
    
    Code (markup):
    It is NOT highly sensitive bank-data or similar I am protecting. (As I think you can understand)

    Maybe someone can "crack" it by going to the Drupal-part of my site, register a blog/forum account, print a link to the PHP page there and click it? But that is maybe not so high risk, at least it would be found out by checking the Drupal site content. This could also be avoided by checking the referring page url in more detail, so that it does not come from the Drupal part of the site.

    So my questions are:

    1. Does the code above give a reasonable "low-level" security to protect the php-program from abuse?

    2. If I would like to make this more strict, how could I do it? I thought of two things:

    2.1
    I do not know if it is possible to send a POSTvariable password? I know they can be sent as "<INPUT Type=hidden ..." in a HTML-form, but I do not know how to "click the submit-button" programmatically from PHP, in order to go to the next ('action') page where the password is evaluated.

    2.2
    Include some kind of password (GET-argument) in the query-string. Maybe the password should be based on the other variable values in the query string, but also other variable factors like time?

    Maybe there is a simpler solution? Grateful for suggestions

    Thanks
     
    Last edited: Sep 10, 2010
    ycc, Sep 9, 2010 IP
  2. viron86

    viron86 Active Member

    Messages:
    426
    Likes Received:
    6
    Best Answers:
    0
    Trophy Points:
    60
    #2
    is your problem related to xss
    you can use strip_tags() function to filter incoming request data
     
    viron86, Sep 10, 2010 IP
  3. ycc

    ycc Peon

    Messages:
    99
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #3
    I don't think you can call it XSS. I just send multiple AJAX requests (maybe every minute) from one web-page and they make calls to PHP pages. (In the most standard and commoon way, as I understand.) The AJAX-page and the PHP page are on the same server.

    The strip-tag is useful, but I don't think it changes the basic problem here. (I do not have incoming data, the PHP routines just manipulate the database)

    The PHP-pages that are called from AJAX should be protected from being invoked from anywhere else but my own AJAX-pages (with the proper querystrings).
     
    Last edited: Sep 10, 2010
    ycc, Sep 10, 2010 IP
  4. viron86

    viron86 Active Member

    Messages:
    426
    Likes Received:
    6
    Best Answers:
    0
    Trophy Points:
    60
    #4
    in that case u can make use of session
    only use in session can make a call to the respective php page
     
    viron86, Sep 10, 2010 IP
    sarahk likes this.
  5. dakshhmehta

    dakshhmehta Active Member

    Messages:
    220
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    85
    #5
    Nice trick,
    I like your trick, but we can improve this system by adding some time restriction..
     
    dakshhmehta, Sep 10, 2010 IP
  6. ycc

    ycc Peon

    Messages:
    99
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #6
    viron86 Thanks for taking your time.

    So what I could do is put this in the beginning of every page that the visitor comes to:
    session_start();  
    $_SESSION['password_for_my_site'] = 'MY_SECRET_PASSWORD';
    
    Code (markup):
    and then let every page check the following when it is called from AJAX:
    if($_SESSION['password_for_my_site'] == 'MY_SECRET_PASSWORD') {
    // manipulate database
    }
    
    Code (markup):
    Is this possible?

    I am new to these session variables, I should have learnt them long ago :eek:


    EDIT:
    To add time restriction, would it also have to be a session variable?

    Thanks for replies.
     
    Last edited: Sep 10, 2010
    ycc, Sep 10, 2010 IP
  7. ycc

    ycc Peon

    Messages:
    99
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #7
    I have not found the solution yet.

    I tried the session variables a little. The "password" I wrote in my last post is not a good idea. If someone just surfs to my site in the normal way he will have the secreet password written as a session variable. After that he can open other tabs in the browser and start abusing the php pages. At least that is my impression?

    If I, on the other hand, send the actual value as a session variable it will become confusing it the visitor opens several of my pages in several tabs? The receiving pages can mix up from where the value is coming. The best thing would be to have "something" that only the sending and receiving page would know.

    I just Googled a little. it seems impossible to send POST-variables without having a visitor clicking a form.

    Thanks for pointing to session variable, but I haven't found a solution yet.
     
    ycc, Sep 10, 2010 IP
  8. viron86

    viron86 Active Member

    Messages:
    426
    Likes Received:
    6
    Best Answers:
    0
    Trophy Points:
    60
    #8
    hmm i think captcha will surely help you

    well i dont know about php but in java servlet we can send parameter without clicking on form using
    request.setAttribute(name,value);

    and i think php might have some similar functions
     
    Last edited: Sep 10, 2010
    viron86, Sep 10, 2010 IP
  9. ycc

    ycc Peon

    Messages:
    99
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #9
    Here is a suggestion, but it seems tricky, it seems to need rewriting the .htaccess file.
    http://www.askapache.com/htaccess/sending-post-form-data-with-php-curl.html
    Sending GET or POST variables invisibly
    
    <?php
     $ch = curl_init('http://mysite.com/index.php');
     curl_setopt ($ch, CURLOPT_POST, 1);
     curl_setopt ($ch, CURLOPT_POSTFIELDS, "option=com_content&task=blogcategory&id=24&Itemid=55");
     curl_exec ($ch);
     curl_close ($ch);
    ?>
    
    Code (markup):
     
    ycc, Sep 10, 2010 IP
  10. danx10

    danx10 Peon

    Messages:
    1,179
    Likes Received:
    44
    Best Answers:
    2
    Trophy Points:
    0
    #10
    Never rely on $_SERVER['HTTP_REFERER'] it can be manipulated to appear as your site when its not, with the use of cURL etc - furthermore can possibly even lead to XSS injections (if not properly sanitized).

    Look into Cross Site Request Forgery prevention using tokens.
     
    Last edited: Sep 10, 2010
    danx10, Sep 10, 2010 IP
  11. ycc

    ycc Peon

    Messages:
    99
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #11
    They also write about fsockopen sending post variables, the same thing as curl does in the last post. But I now realize I cannot use that either. The nature of the AJAX, as I use it, prevents it from sending post variables. Sorry for spamming today.

    I cannot use captcha, the AJAX calls should not be visible to the user.

    The session variables would work in 95% of the cases, thanks for pointing them out, viron86. But since I have a special case where several pages may be open in several tabs, there is a small risk of confusing the arguments, I think?

    I think this is maybe what one needs? There seems to be a special POST-way of sending variables from AJAX to php pages.
    http://www.openjs.com/articles/ajax_xmlhttp_using_post.php
    EDIT/ADDITION: The more I read about this I realize it is not good either. The AJAX-request is JavaScript and will be visible to the user if he wants. I cannot put a password there.

    Poohhh, this was harder than I thought.
     
    Last edited: Sep 10, 2010
    ycc, Sep 10, 2010 IP
  12. ycc

    ycc Peon

    Messages:
    99
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #12
    Thanx danx10, I will look into it.
     
    ycc, Sep 10, 2010 IP
  13. ycc

    ycc Peon

    Messages:
    99
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #13
    It seems to be a common topic/problem in the forums:
    How do you make a unique session for each tab/window of the browser.
    Having the same session id for all tabs sometimes create difficulties.
    I haven't found a solution to that either.
     
    ycc, Sep 10, 2010 IP
  14. ycc

    ycc Peon

    Messages:
    99
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #14
    There doesn't seem to exist an obvious solution to the problem. Here is the first link I find which addreses the very same issue.

    http://webmasters.stackexchange.com...t-a-power-user-from-calling-my-ajax-functions

    They talk about checking $_SERVER['HTTP_X_REQUESTED_WITH'] (which naturally also can be spoofed)
    (EDIT: I tried several rouines reading this variable, none worked with the AJAX-library I use.)

    Very good idea to read on Cross Site Request Foregery, thanks danx10. Much of it is connected to verifying the identity of the browser (by the server). In my case I would like to separate some calls from the browser as legitimate and some as illegal. The question I arise is maybe not quite starightforward, I now realize.

    It seems to be a multi-measure solution. Tightening wherever you can.

    I got into a swamp here, but at least it includes interesting reading about things I know too little about :)
     
    Last edited: Sep 10, 2010
    ycc, Sep 10, 2010 IP
  15. ycc

    ycc Peon

    Messages:
    99
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #15
    Thanks for good advice in this thread. I think I got it as tight as I need.

    If one should make it "absolutely" impossible for anything else than AJAX-requests to be processed maybe one could use a code based on the included arguments?

    mypage.php?time=12.31&id=23&new_value=7654&code=34
    Code (markup):
    And the receiving page would only accept newly sent requests with the correct code.

    In this example the "code" was very simple, it was only the cross-sum of the included arguments:

    1+2+3+1+2+3+7+6+5+4=34
    Code (markup):
     
    Last edited: Sep 16, 2010
    ycc, Sep 16, 2010 IP
  16. Wade C.

    Wade C. Peon

    Messages:
    2
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    3
    #16
    You can use a php script on all of your pages.
    It takes the values of the data you are passing to the php script via ajax, concatenates them adds a "secret" word to the end and then md5 encrypts the string. You then pass the md5 hash as a query paramater through the ajax call. In the receiving php script you receive all the variable values passed concatenate them add the secret word to the end and md5 encode it. Then your script compares this md5 hash with the one passed to it. If they match you execute the php code to update the database. If not, you exit or error out. That way someone hitting the php script directly can only resubmit legitimate data. Since they don't know the secret word they can not recreate a hash that will match. If they change any of the query string values when the receiving php script recreates the md5 hash it will be different than the one passed to it.
     
    Wade C., May 3, 2013 IP
    ThePHPMaster likes this.
  17. ThePHPMaster

    ThePHPMaster Well-Known Member

    Messages:
    737
    Likes Received:
    52
    Best Answers:
    33
    Trophy Points:
    150
    #17
    You can make it harder to make the requests by doing the following:

    - Check for cookies/sessions which are constantly generated based on the IP/Browser Agent and are renewed every request.
    - Check for the HTTP Referral
    - Check for Ajax header
    - Tokens, etc..

    Keep in mind, anyone smart enough to use Curl can bypass all of the above, so you are basically blocking access to those people who don't know better.
     
    ThePHPMaster, May 4, 2013 IP
  18. Wade C.

    Wade C. Peon

    Messages:
    2
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    3
    #18
    There's no full proof way to block someone from executing the script directly but the method described above will prevent someone from passing unauthorized data. The php script, in essence, will only accept data passed to it by an ajax call from a page on your site. it will reject any attempts to manipulate data passed directly to the php script.
     
    Wade C., May 5, 2013 IP
  19. ThePHPMaster

    ThePHPMaster Well-Known Member

    Messages:
    737
    Likes Received:
    52
    Best Answers:
    33
    Trophy Points:
    150
    #19
    Yes, that would work. Good thinking.
     
    ThePHPMaster, May 5, 2013 IP