【知识点】web安全怎么做

服务器

1、更改服务器远程端口

更改默认端口,默认端口相对来说是不安全的,建议修改默认远程端口为随机5位数的端口。

2、设置防火墙并关闭不需要的服务和端口

防火墙是网络安全的一个重要组成部分,通过过滤不安全的服务而降低风险。安装服务器时,要选择绿色安全版的防护软件,以防有被入侵的可能性。对网站提供服务的服务器,软件防火墙的安全设置最高,防火墙只要开放服务器端口,其他的一律都关闭,你要访问网站时防火墙会提示您是否允许访问,在根据实际情况添加允许访问列表。这样至少给系统多一份安全。

3、把密码设置的复杂一点

一但服务器IP被扫描出来默认端口,非法分子就会对服务器进行暴力破解,利用第三方字典生成的密码来尝试破解服务器密码,如果您的密码足够复杂,非法分子就需要大量的时间来进行密码尝试,也许在密码未破解完成,服务器就已经进入保护模式,不允许登陆。

4、修补已知的漏洞

如果网站出现漏洞时不及时处理,网站就会出现一系列的安全隐患,这使得服务器很容易受到病毒入侵,导致网络瘫痪,所以,平时要养成良好的习惯,时刻关注是否有新的需修补的漏洞。

5、定时为数据进行备份

定时为数据做好备份,即使服务器被破解,数据被破坏,或者系统出现故障崩溃,你只需要进行重装系统,还原数据即可,不用担心数据彻底丢失或损坏。

XSS(跨脚本攻击)

XSS 是 Cross Site Scripting 跨站脚本攻击的意思,X是英文Cross的简称
什么叫做跨站,就是非自己网站,如果本网站运行了来自别的网站的东西就叫做XSS,举个例子,如下是前端页面代码

<!-- pug模板引擎语法 -->
if from
    span -- 欢迎来自!{
    
    from}的朋友

下面是后端逻辑代码

// from 来源于get参数
ctx.render('index', {
    
    posts, comments, from:ctx.query.from || ''});

现在,如果我们在页面url上加上如下代码 ?from=<script>alert(1)</script>可以看到页面弹出1,这就是一段XSS攻击代码,为什么是跨站攻击呢?
我们可以做如下变通?from=<script src='其他网站的脚本.js'></script>这种跨站脚本可以执行任何形式的攻击,其攻击原理是:程序+数据=结果
当我们的数据中包含一部分程序的时候,原来我们程序的逻辑就会被改变了

页面中的脚本可以干什么,XSS的脚本就可以看什么,比如

  • 获取页面数据
  • 获取Cookie
  • 劫持前端逻辑
  • 发送请求
  • 偷取网站任意数据资料,密码,登录态
  • 欺骗用户

常见的XSS攻击案例

  • 站酷的搜索框
  • QQ空间的富文本编辑器,script脚本侧漏
  • 电商表单提交脚本,在后台页面运行,获取后台地址和登录态

XSS攻击的分类
XSS攻击的种类很多,尤其是变种很多,我们可以按照攻击代码的来源分为两种

  • 1 ) 反射型:url参数直接注入, 危害略小
    • 攻击者一般会把这种参数变换,比如做一个短网址,在dwz.cn中变换为短网址
    • 一般受害者可能会忽略误点从而导致受害
    • 反射型攻击可以和其他攻击结合进而自动传播
  • 2 ) 存储型:存储到DB后读取时注入,攻击代码来自网站数据,危害较大
    • 一般通过富文本编辑器将脚本注入数据库中
    • 当用户浏览到注入脚本数据的页面时,就会中招

XSS攻击注入点

  • HTML节点内容:如果内容是动态生成了,包含用户输入,那么这个输入中可能包含脚本,进而导致XSS攻击

比如程序是这样的:<div>#{content}</div>, 但是可能会变成这样:<div><script>...</script></div>

主要是存储型XSS攻击,内容提交后注入

  • HTML属性:某个HTML节点的某一个属性是由用户输入构成的,用户输入数据有可能包含脚本或者越出属性本身的范围导致XSS攻击

比如原先是这样的<img src="#{image}" />,结果却成了这样<img src="1" onerror="alert(1)" />

具体程序程序比如前端是这样做的

<!-- pug模板引擎 -->
if avatarId
    <img src="/image/!{avatarId}" />

后端是这样的

// 同样是通过某种参数来引用的
ctx.render('index', {
    
    avatarId:ctx.query.avatarId || ''});

只需要在url中这样访问即可:?avatarId=1" onerror="alert(1) 此时产生一个onerror的新属性

这时候就会执行其中的脚本,这明显是一种反射型攻击,其原理是通过冒号提前关闭原属性,并产生一个新的属性

  • js代码:存在由后台注入的变量,或里面包含用户输入的信息,有可能用户输入信息会改变js代码的逻辑导致XSS攻击

原本逻辑是这样的var data = "#{data}";, 结果却成了 var data = "hello";alert(1);"";

这里的data来自服务器的数据,这个数据很可能是之前用户输入的,也就是用户提前将这个变量进行了关闭

这时候原本的一句代码变成了3句代码,这种可以是反射型攻击,也可能是存储型攻击

  • 富文本:富文本是一大段的HTML标签,我们要保留html格式也要小心其中可能包含XSS攻击的代码

以QQ邮箱为例,可以设置任意的格式,本质上是一段复杂的html

富文本会保留HTML, 但是HTML具有XSS攻击的风险

XSS常见的防御方案

  • 1 ) 浏览器自带防御
    浏览器自带防御:参数出现在HTML内容或属性中,浏览器会自行拦截并提示: ERR_BLOCKED_BY_XSS_AUDITOR

    如果发现谷歌浏览器等现代浏览器没有进行拦截,可能是我们设置了取消拦截
    ctx.set('X-XSS-Protection', 0) 具体有三种参数:

    第一种是 0 是关闭保护
    第二种是 1 是默认开启
    第三种是1后面再加一个url参数,谷歌浏览器会向这个url发送一个通知
    它防御范围非常有限,即反射型XSS攻击,而且只防御HTML相关的注入(内容或属性)
    而在js中注入的参数不会被拦截, 如 url: ?from=";alert(document.cookie);", js脚本:var from = "!{from}";
    而且并不是所有浏览器都支持

  • 2 ) 转义HTML节点内容和属性

    通过程序处理HTML节点内容

    对HTML内容进行转义,只需要转义<&lt;>&gt; 即左右尖括号
    转义的时机可以有几个选择:1 )进入数据库之前; 2 )显示的时候进行转义(简单起见使用这种)
    我们只需要定义这种转义函数, 在输出之前进行转义

var escapeHtml = function(str) {
    
    
    if(!str) return '';
    str = str.replace(/</g, '&lt;');
    str = str.replace(/>/g, '&gt;');
    return str;
}
ctx.render('index', {
    
    from: escapeHtml(ctx.query.from) || ''});

通过程序处理HTML节点属性

对应的策略是转义引号,即:" &quto;也是定义一种转义函数

var escapeHtmlProperty = function(str) {
    
    
    if(!str) return '';
    // 处理单引号和双引号
    str = str.replace(/"/g, '&quto;');
    str = str.replace(/'/g, '&#39;');
    // 属性可以没有引号,处理没有引号的情况,即空格
    str = str.replace(/ /g, '&#32;');
    return str;
}
ctx.render('index', {
    
    avatarId: escapeHtmlProperty(ctx.query.avatarId) || ''});

其实这两种HTML的过滤,过滤内容和属性是没有冲突的,我们可以把两者合并,如下, 有两种方式

方式1

var escapeHtml = function(str) {
    
    
    if(!str) return '';
    str = str.replace(/</g, '&lt;');
    str = str.replace(/>/g, '&gt;');
    str = str.replace(/"/g, '&quto;');
    str = str.replace(/'/g, '&#39;');
    str = str.replace(/ /g, '&#32;');
    return str;
}
ctx.render('index', {
    
    from: escapeHtml(ctx.query.from) || '', avatarId: escapeHtml(ctx.query.avatarId) || ''});

方式2

// type 0 过滤内容,type 1过滤属性
var escapeHtml = function(str, type) {
    
    
    if(!str) return '';
    if(type === 0) {
    
    
        str = str.replace(/</g, '&lt;');
        str = str.replace(/>/g, '&gt;');
    }
    if(type === 1) {
    
    
        str = str.replace(/"/g, '&quto;');
        str = str.replace(/'/g, '&#39;');
        str = str.replace(/ /g, '&#32;');
    }
    return str;
}
ctx.render('index', {
    
    from: escapeHtml(ctx.query.from, 0) || '', avatarId: escapeHtml(ctx.query.avatarId, 1) || ''});

这样其实还是存在问题的

在html中多个连续空格,在渲染时候只会产生一个空格,如果将空格全部转换为html实体的时候,页面上的显示可能会有问题

一般来说,我们对空格不做任何转义,这样的话,我们要约定:属性一定要带上引号,按照html的规范,在html5之前,&也是需要进行转义的,在html5之后不需要了,按照惯例,一般还是会做一下转义,这样我们的转义程序,就变成了

var escapeHtml = function(str) {
    
    
    if(!str) return '';
    str = str.replace(/&/g, '&amp;'); // 这个只能放在最前面,否则会转义下面被转义过的含有&的转义字符
    str = str.replace(/</g, '&lt;');
    str = str.replace(/>/g, '&gt;');
    str = str.replace(/"/g, '&quto;');
    str = str.replace(/'/g, '&#39;');
    return str;
}

  • 3 ) 转义js代码

在js中会插入来自后台或用户直接输入的数据,这个数据可能突破我们的引号边界添加新的脚本语句
就像上面案例url中:?from=sina";alert(1);" 这个alert(1)会被执行

我们初步的解决方案将数据中的引号转义,如果用到上面的escapeHtml方法会有问题,就会把这个变量变成一串含有转义字符的东西,如sina&quto;;alert(1)&quto;

其实这个在js中对变量来说是不对的,即使仅仅是一个字符串,也是很难看的,这里包含html实体,而js并不能解析html实体,其实转义的html实体它不应该出现在js变量中,我们进一步考虑将js用到的变量和html中的变量进行区分处理,如果用处理html的方法来处理一般数据,可能就会在数据中

var escapeJs = function(str) {
    
    
    if(!str) return '';
    str = str.replace(/"/g, '\\"'); // 此处转义: 将 " 转义为 \"
    return str;
}

ctx.render('index', {
    
    from: escapeJs(ctx.query.from) || ''});

通过这种方式,我们就可以得到这样一串js变量sina";alert(1);" 也就是原汁原味的东西,但不会受到攻击
但是,如果访问的url是这样的:?from=sina\";alert(1);" 就会被转义成这样:sina\\";alert(1);\""
此时解析上来说,添加的一个\,会继续转义被转义成的", 其实转义的只是前面的, 此时"还是被添加进去了
这时候sina"其实在变量的概念中就已经闭合了,剩下的;alert(1);"会存在语法错误
报错:Uncaught SyntaxError: Invalid or unexpected token
如果我们输入的url是这样的,?from=sina\";alert(1);//, 后面的//被当成注释,屏蔽了后面默认闭合引号产生语法错误的源头
此时,还是会执行alert(1),依然存在XSS攻击的可能,其原因是输入的\在页面渲染的时候被当成了转义符
这时候,我们可以把\也处理了,如下重写escapeJs函数

var escapeJs = function(str) {
    
    
    if(!str) return '';
    str = str.replace(/\\/g, '\\\\'); // 注意这里的4个\,2个为转义一个,即:\本身是个转义符,表达\本身,需要使用\\
    str = str.replace(/"/g, '\\"'); // 此处转义: 将 " 转义为 \"
    return str;
}

此时就不会报错,或者被攻击了,但是这样也不彻底,因为我们的字符串可能被单引号包裹

var escapeJs = function(str) {
    
    
    if(!str) return '';
    str = str.replace(/\\/g, '\\\\'); // 注意这里的4个\,2个为转义一个,即:\本身是个转义符,表达\本身,需要使用\\
    str = str.replace(/"/g, '\\"'); // 此处转义: 将 " 转义为 \"
    str = str.replace(/'/g, "\\'"); // 此处转义: 将 " 转义为 \"
    return str;
}

如果再处理了单引号,会不会有其他情况呢?也不排除有其他情况,最保险的办法是对我们的数据进行json转义,所以,我们不通过escapeJs这个函数了,而是通过JSON.stringify来处理即可,即
ctx.render('index', {from: JSON.stringify(ctx.query.from) || ''});, 这是最好的处理方式

  • 4 ) 转义富文本

所谓富文本就是一大段的HTML,这段HTML可能会包含非常多的格式,我们需要保留这些格式

没办法把全部HTML转义,同样面临着XSS攻击, 一般的思路是做过滤,过滤又有两种

1 ) 按照黑名单进行过滤,如script标签,onerror属性等去除它们
相对简单,但稍不留神就会留下漏洞

2 ) 按照白名单进行过滤,如只允许部分标签和属性
实现较为麻烦,需要将HTML完全解析成数据结构,对其进行过滤,再重组成HTML

通过使用黑名单来过滤,我们可以提供下面一个过滤函数,针对输入的内容进行过滤

var xssFilter = function(html) {
    
    
    if(!html) return '';
    html = html.replace(/<\s*\/?script\s*>/g, '');
    html = html.replace(/javascript:[^'"]*/g, '');
    html = html.replace(/onerror\s*=\s*['"]?[^'"]*['"]?/g, '');
    // ...继续处理其他 svg, object等可以运行脚本,稍不留神少一个就会造成漏洞隐患
    // 所以并不推荐这种
    return html;
}

通过白名单来过滤,保留部分标签和属性,首先需要把一大段的HTML解析成树状结构,Dom树

这个和浏览器解析HTML过程是类似的,针对这颗树,一个一个的遍历,去除不允许的,保留允许的

我们可以通过一个cheerio库来解析html, 就是爬虫中使用到的,返回出一个类似Dom的结构,其特色是使用JQuery的API,上手很快,可以在npmjs官网找到

一般而言,我们在入库的时候处理富文本,这样比查询渲染页面时性能会更高
具体用法如下,我们提供一个xssFilter函数和白名单,对富文本数据进行过滤

var xssFilter = function(html) {
    
    
    if(!html) return '';
    var cheerio = require('cheerio');
    var $ = cheerio.load(html);
    // 白名单
    var whiteList = {
    
    
        'img': ['src'],
        'font': ['color', 'size'],
        'a': ['href']
    };
    $('*').each(function(index, ele) {
    
    
        if(!whiteList[ele.name]) {
    
    
            // 这里一般直接移除
            $(ele).remove();
            // 如果想要保留script中的内容,也可以在remove之前保留其内容
            return true; // true 相当于 continue,return false 相当于 break;
        }
        // 在白名单中
        for(var attr in ele.attribs) {
    
    
            if(whiteList[ele.name].indexOf(attr) === -1) {
    
    
                $(ele).attr(attr, null); // 过滤其他不允许属性
            }
        }
        return $.html();
    })
    return html;
}

白名单是一个比较好的方案,但是其设计比较复杂,如果定的不好,可能会影响业务,一般推荐白名单库,也就是别人写好的XSS过滤库,比如github上的js-xss库js-xss 地址:https://github.com/leizongmin/js-xss,我们可以直接这样使用

var xssFilter = function(html) {
    
    
    if(!html) return '';
    var xss = require('xss');
    var ret = xss(html, {
    
    
        // 也可以自行指定
        whiteList: {
    
    
            img: ['src'],
            a: ['href'],
            font: ['size'],
        },
        onIgnoreTag() {
    
    
            return '';
        }
    });
    return ret;
}

使用第三方库可能会有一些意料之外的局限,但是安全一般是可以保障的,如果简便开发建议选择第三方库,如果要高度定制,就要自己来写白名单

CSRF(跨站请求伪造)

CSRF(Cross-Site Request Forgery),中文名称:跨站请求伪造,缩写为:CSRF或XSRF,它是一种对网站的恶意利用,和XSS不同的是,XSS是利用站点内的信任用户,而CSRF则是通过伪装来自受信任用户的请求来利用受信任的网站。

可以这么理解:攻击者盗用了你的身份,以你的名义向第三方网站发送恶意请求。

CSRF能做的事情包括利用你的身份发短信、邮件,进行转账交易,甚至盗取你的账号等。
在这里插入图片描述
XSS攻击原理/过程:

假设某银行网站A以GET请求来发起转账握作,转账的地址为www.xxx.com/transfer.do?account={你的账号}&money={转账金额}

而某论坛B上,一个恶意用户上传了一张图片,而图片的地址栏中填的并不是图片的地址,而是上面这个转账地址。

<img src="http://www.xxx.com/transfer.do?accountNum=123&money=100000000">

当你登录网站A后,没有及时登出,这时你访问了论坛B,并点击了这张图片,不幸的事情发生了,你会发现账户里面少了1个小目标……

为什么会这样呢?在你登录银行A时,你的浏览器端会生成银行A的cookie,而当你访问论坛B中这张恶意图片时,页面上的<img>标签需要浏览器发起一个新的HTTP请求,以获得图片资源,当浏览器发起请求时,请求的却是银行A的转账接口,并且会带上银行A的cookie信息,结果银行的服务器收到这个请求后,会认为是你发起的一次转账操作,因此接口请求成功。

当然,绝大多数网站都不会使用GET请求来进行数据更新,因此,攻击者又改进方案:

假设银行将其转账方式改成POST提交,而论坛B恰好又存在一个XSS漏洞,恶意用户在它的页面上植入如下代码:

<form id="aaa" action="http://www.xxx.com/transfer.do" method=POST" display="none">

  <input type="text" name="account" value="123"/>

  <input type="text" name="money" value="100000000"/>

</form>

<script>var form = document.forms['aaa’];   form.submit();</script>

CSRF防御措施:

  1. 将Cookie设置为HttpOnly

response.setHeader(“Set-Cookie”, “cookiename=cookievalue;HttpOnly”);

  1. 使用JWT token进行会话

  2. 通过Refer识别

HTTP请求头中有一个属性叫Refer,记录了该HTTP请求的来源地址。后台获取请求头中的Refer的值,判断是否是本网站域名,如果不是就有可能是CSRF攻击,则拒绝该请求。

SQL注入

原理:

所谓SQL注入,就是通过把SQL命令伪装成正常的HTTP请求参数传递到服务端,款骗服务器最终执行恶意的SQL命令,达到入侵目的。攻击者可以利用SQL注入漏洞,查询非授权信息,修改数据库服务器的数据,改变表结构,甚至是获取服务器root权限。总而言之,SQL注入漏洞的危害极大,攻击者采用的SQL指令决定了攻击的威力。目前涉及的大批量数据泄露的攻击事件,大部分都是通过SQL注入来实施的。

示例:

假设某个存在漏洞的网站登录页需要输入用户名和密码,后台接收到参数后是直接拼接SQL查数据库,如:

String sql = “select * from t_user where username = ‘” + name + ”’ and password = ‘” + pwd + ”’”;

正常情况下,如果密码不正确是查询不到数据的,现在某恶意用户输入的密码为:’ or ‘1’ = ’1

此时拼接的语句就成了:

String sql = “select * from t_user where username = ‘test’ and password = ‘’ or ‘1’ = ‘1’ ”;

显然此时可以查到数据,因为直接可以无需密码这个条件。

这只是最简单的示例,真实情况中黑客会想尽一切办法钻SQL的漏洞。一旦被攻击者找到漏洞,轻则盗取数据、欺骗网站进行登录,重则直接加入drop/delete等语句删库跑。

防御措施:

  1. 使用预编译语句或ORM框架:

感谢现在很多实用的持久层框架,不仅提高编码效率,而且很多问题在框架层面解决了。比如框架一般会使用占位符/变量的方式代替拼接SQL,这样的话引号这种敏感字符会被转义,不会当成SQL来执行。在开发过程中尽量不要随意拼接原生SQL语句。

  1. 避免密码明文存放:

对存储的密码进行单向Hash,如使用MD5对密码进行摘要。不过近年来MD5也可能被彩虹表法进行破解,因此安全起见还可以使用哈希加盐法(Hash + Salt),即给密码末尾加点料(一串私有key)然后再进行Hash,这样就很难破解了。

  1. 处理好异常:
    许多老旧网站,一遇到500异常就直接把错误信息、数据库字段、甚至代码堆栈信息都打印在页面上了,这是非常危险的,一眼就能看出后台使用什么语言、技术、数据库等,所以我们一定要在代码中定义好全局性异常捕捉,不要把服务端信息暴露到前端页面。

劫持攻击

一、怎么防御网页劫持?
1、常规防护措施

使用建站系统的站点,经常会遇到一些大规模爆发式常规漏洞,这类漏洞影响大,修补措施官方更新较快,大小站点都需要及时关注于更新,特别是使用开源程序的站点。

当然了大家都不可能时时刻刻的关注信息,但又拍错失修复机会怎么办?

建议站点使用第三方的安全观测平台,可以非接触式检测,另外还带有短信和邮件通知功能,特别适合站长使用,这里我推荐百度云观测和百度安全指数这2款产品,当然还有其他的检测平台,这里大家自行选择即可。

但是这里要特别注意的是不要使用太多监测平台,监测平台会定期去检测测试会给服务器带去一定的压力。

2、云服务防护

目前较为火的几个云主机平台都提供了一些安全防护软件,毕竟漏洞的爆发肯定是早于修补,而部分厂商也不会一下子就能够出补丁来修复,这时候使用例如安骑士这类产品,通过云服务商的技术团队第一时间无缝或屏蔽漏洞,至少可以支撑到厂商发布漏洞为止。

云服务除了上述安全防护组件外,大家应该还看到过一个叫做安全组的东西,浅易的来说就是防火墙端口策略,可以直接在云面板进行端口控制,比如近期爆出的方程式多个0DAY,如果你只开了必要的端口,实际上都无需修补。一般来说我们打开远程端口、HTTP/HTTPS端口、FTP端口基本上足矣,如无特殊服务可以关闭,可以省事很多。

3、服务器端防护

在服务器端大家可以安装第三方的杀毒、防护软件,这些软件带有大部分常见的防护机制,对付一般小白足矣。

目前市面上安全狗和云盾算是较为优秀的服务器防护软件。

4、网页防护

一般我都建议那些敏感站点,动静态分离、读取存储分离,我们都知道网页被劫持最常见的就是被提权,如果设置好权限可以最大程度上就可以避免被提权。

网页被劫持怎么办?如何处理?

二、网页被劫持怎么办?网页劫持修复思路方法
当你网页遇到劫持时,可以参考以下修复思路进行处理:

1、进行隔离止损。

2、通过日志和行为分析找到漏洞点。

3、通过补丁修复漏洞或临时修补漏洞。

4、 检查系统权限清除后门。

5、 大部分劫持都是带有恶意的,一般都会植入非法违规内容,针对这类内容,我们要第一时间删除,去平台提死链。

6、 观察搜索引擎表现,若有未清数据继续处理。

web安全学习导图

在这里插入图片描述

推荐阅读

多少道防线才能挡住顶尖黑客?

来源

怎么做好web服务器安全措施
Web渗透测试----1、Web安全学习导图
关于XSS攻击及其防御
CSRF攻击原理与防御措施
网页劫持防御方法,网页被劫持怎么办?
SQL注入攻击原理与防御措施

猜你喜欢

转载自blog.csdn.net/weixin_44231544/article/details/126524309