Web 安全 - XSS/CSRF注入

2017-01-20 Kevin 更多博文 » 博客 » GitHub »

Web安全

原文链接 https://kevindiamen.github.io/web%E5%AE%89%E5%85%A8/2017/01/20/Web-%E5%AE%89%E5%85%A8-XSS%E6%B3%A8%E5%85%A5.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


Web 安全 - XSS / CSRF

介绍

跨站脚本攻击(Cross Site Scripting)。 恶意攻击者往Web页面里插入恶意Script代码,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的特殊目的

XSS注入与防御

注入例子

假如一个用户提交了一段 JavaScript 代码在你的系统中, 如下:

<script>
    alert('I am not sanitized!');
</script>

如果你没有清洗数据就输出到浏览器, 这段 JavaScript 就会正常运行. 这个例子会弹出一个 alert(), 但是真正的黑客绝对不会这么小儿科.

如果你正使用模板引擎或者你使用的框架提供了模板机制,它可能已经自动完成了转义, 或者它会提供一个相关的方法给你。详细的使用和实现你可以查看相关的文档。 这完全取决于你,PHP 内置了很多函数,当你要在浏览器显示数据时都会成为你最好的朋友: htmlentities() 和 htmlspecialchars() 他们都可以转义使得在展示之前就变得更加安全。

防御

  • 不要往HTML页面中插入任何不可信数据

  • 在将不可信数据插入到HTML标签之间时,对这些数据进行HTML Entity编码

CSRF 攻击与防御

Cross Site Request Forgery (CSRF) 是跨站请求伪造. CSRF 可以通过被注入的 XSS 攻击的网站发起, 举个例子, 一个黑客通过发送一个带有删除博客功能的链接,只要拥有操作删除功能的用户点击那么他博客就会被删除, 它不仅仅是一个文字链接 也可能是一个可以点击的按钮或者图片, 当被XSS注入的网站 黑客还用通过 JavaScript 去提交隐藏的表单.

防御

第一步 确定 没有数据修改的 请求 用GET 有数据 修改的请求 POST,PUT,DELETE 请求 如果一个请求是DELETE应该提示用户确认这个操作, 如果你需要用GET请求去修改数据,你需要一个唯一的token,当你提交表单时候也需要增加token, 我们生成一个随机的token 存储在用户的session 然后隐藏这个表单 每一次我们验证这个请求

    staticfunctiongenerateCsrf()
    {
        $token = mcrypt_create_iv(
        16,
        MCRYPT_DEV_URANDOM
        );
        Session::flash(
        'csrfToken',
        $token
        );
        return $token; 
    }

我们刷新 session 后 token 将会存储在 session 中 这样每一次请求 都会验证 token 从来避免 CSRF


    Route::get('/signup',function() 2{
        $data['token'] = Form::generateCsrf(); 
        return View::render('signup.form', $data);
    });

And now for our view, signup/form.php

    <formmethod="POST"action="/signup">
    <label>
    First Name:
    <input type="text" name="first_name" /> </label>
    <label>
    Last Name:
    <input type="text" name="last_name" /> </label> <label>
    Email:
    <input type="text" name="email" /> </label>
    <input type="hidden" name="token" value="<?=$token?>"/> 
    <input type="submit" name="submit" value="Signup"/>
    </form>

当这个表单POST提交我们可以验证token

    Route::post('/signup',function()
    {
        if ($_POST['token'] === Session::get('csrfToken')) {
            //process the form
        }
        die('Invalid Form Data');
    });         

token 会在这个地方检查 , 如果黑客模仿用户提交一个恶意的表单 这个请求会失败,因为他不能匹配用户在session中的token