How do I provide more security for checking source of the request

前端 未结 3 1832
甜味超标
甜味超标 2020-12-10 15:25

I am developing one PHP web application, I want to provide more security to application so that no one can easily break the functionality.

Brief explanation about my

相关标签:
3条回答
  • 2020-12-10 16:05

    Checking the HTTP_REFERRER for CSRF is a valid form of protection. Although it is trivial to spoof this HTTP header on your OWN BROWSER it is impossilbe to spoof it on another persons browser using CSRF because it breaks the rules.

    According to the Department of Homeland Security I have found the most dangerous CSRF vulnerability ever found and is in the top 1,000 most dangerous vulnerabilities of all time. Motorola patched this flaw using a referer check, and its common to see this protection method on embedded network hardware because memory is scarce.

    A more common and more secure method is to store a Cryptographic nonce inside a $_SESSION variable and check this for each sensitive request. An easy approach is to use POST for all sensitive requests (like changing your password) and make sure this Cryptographic nonce is valid for all posts in a php header file, if it isn't valid then unset($_POST);. This method works because although an attacker can force your browser into SENDING GET/POST requests he cannot view the RESPONSE, and there for cannot read this token needed to forge the request. This token can be obtained with XSS, so make sure you test your site for xss.

    A good method for generating a csrf token is md5(uniqid(mt_rand(),true)); This should be enough entropy to stop CSRF. md5() is used to obscure how the salt is generated. Keep in mind that the current time is not a secret, the attacker knows exactly what time the CSRF request is produced and can narrow down when the session was created. You must assume that the attacker can make many guesses, and in practice this is simple to accomplish by writing a bunch of iframes to the page.

    0 讨论(0)
  • 2020-12-10 16:12

    Lesson #1 in web security: NEVER trust user input. And when I say never, I mean never. ;) Including the HTTP_REFER var in PHP which is easily compromised with an http header (source: http://www.mustap.com/phpzone_post_62_how-to-bypass-the-referer-se)

    A possible solution in checking the source is the using a form token (csrf protection): http://www.thespanner.co.uk/2007/04/12/one-time-form-tokens/ but isn't that safe either and is only possible with your own source.

    A simple CSRF (cross-site request forgery) protection example: (Hence the simple. For a more safe/robust solution, refer to the answer of The Rook)

    1) In your form page, create some kind of token and put in your session and in a hidden form field:

    <?php
        session_start();
        $csrfToken = md5(uniqid(mt_rand(),true)); // Token generation updated, as suggested by The Rook. Thanks!
    
        $_SESSION['csrfToken'] = $token;
    ?>
    <form action="formHandler.php">
       <input type="hidden" name="csrfKey" value="<?php echo $csrfToken ?>" />
    </form>
    

    2) In your form handler check if the token is valid.

    <?php
       session_start();
       if($_POST['csrfKey'] != $_SESSION['csrfKey']) {
          die("Unauthorized source!");
       }
    ?>
    
    0 讨论(0)
  • 2020-12-10 16:13

    Treur got it right, but I still want to clarify a few things and provide you with some sources for reference material. As Treur said, NEVER ever trust user input data, that includes all headers sent by the browser.

    What you are describing, is a typical Cross-Site Request Forgery attack. Checking the referrer header is not a valid protection against CSRF attacks, since according to the RFC2616 (Hyper Text Transfer Protocol 1.1), the referer header is optional and thus may be omitted by the browser at any time. If you are using SSL, then the referer header is always omitted by browsers. Secondly, it is a user defined value, and thus should not be trusted.

    The recommended protection against CSRF attacks is to use the synchronized token pattern. This means that you should create a secret token which is embedded as a hidden field in your form. When the form is posted, you verify that the secret token is present and that it is valid. There are multiple strategies for creating security tokens. I'll describe one way for creating the tokens:

    For each action in your application, create a unique action name for them. For example, "delete_user", "add_user" or "save_user_profile". Let's say that the form you described has the action name "foobar". Concatenate the action name with the user's session id and a secret value.

    $stringValue = "foobar" . "secret value" . session_id();

    To create the security token, create a hash of the concatenated string, you can use sha1 to create the hash. To decrease the risk of brute force attacks, use a larger key in the hash, for example, sha 512.

    $secretToken = hash("sha5125", $stringValue);

    Set this token in your form's hidden field. When the form is submitted, recreate the token and verify that it matches the one submitted in the form. This token is valid for one user session. One may argue, that there is a window of opportunity where an attacker can reuse the token as it is not regenerated at every request. However, with proper session management strategies, this shouldn't really be a concern.

    Like I said, proper session management is necessary. This means that you shouldn't keep the sessions alive to long. Especially session fixation vulnerabilities will undo any CSRF protection measures, as the attacker is then in control of the user session and hence can "predict" the secret tokens.

    Here are a couple of links that I recommend you read through:

    • OWASP: Cross-Site Request Forgery
    • OWASP: Cross-Site Request Forgery Prevention Cheat Sheet
    0 讨论(0)
提交回复
热议问题