服务器
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内容进行转义,只需要转义
<<
和>>
即左右尖括号
转义的时机可以有几个选择:1 )进入数据库之前; 2 )显示的时候进行转义(简单起见使用这种)
我们只需要定义这种转义函数, 在输出之前进行转义
var escapeHtml = function(str) {
if(!str) return '';
str = str.replace(/</g, '<');
str = str.replace(/>/g, '>');
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, ''');
// 属性可以没有引号,处理没有引号的情况,即空格
str = str.replace(/ /g, ' ');
return str;
}
ctx.render('index', {avatarId: escapeHtmlProperty(ctx.query.avatarId) || ''});
其实这两种HTML的过滤,过滤内容和属性是没有冲突的,我们可以把两者合并,如下, 有两种方式
方式1
var escapeHtml = function(str) {
if(!str) return '';
str = str.replace(/</g, '<');
str = str.replace(/>/g, '>');
str = str.replace(/"/g, '&quto;');
str = str.replace(/'/g, ''');
str = str.replace(/ /g, ' ');
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, '<');
str = str.replace(/>/g, '>');
}
if(type === 1) {
str = str.replace(/"/g, '&quto;');
str = str.replace(/'/g, ''');
str = str.replace(/ /g, ' ');
}
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, '&'); // 这个只能放在最前面,否则会转义下面被转义过的含有&的转义字符
str = str.replace(/</g, '<');
str = str.replace(/>/g, '>');
str = str.replace(/"/g, '&quto;');
str = str.replace(/'/g, ''');
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防御措施:
- 将Cookie设置为HttpOnly
response.setHeader(“Set-Cookie”, “cookiename=cookievalue;HttpOnly”);
-
使用JWT token进行会话
-
通过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等语句删库跑。
防御措施:
- 使用预编译语句或ORM框架:
感谢现在很多实用的持久层框架,不仅提高编码效率,而且很多问题在框架层面解决了。比如框架一般会使用占位符/变量的方式代替拼接SQL,这样的话引号这种敏感字符会被转义,不会当成SQL来执行。在开发过程中尽量不要随意拼接原生SQL语句。
- 避免密码明文存放:
对存储的密码进行单向Hash,如使用MD5对密码进行摘要。不过近年来MD5也可能被彩虹表法进行破解,因此安全起见还可以使用哈希加盐法(Hash + Salt),即给密码末尾加点料(一串私有key)然后再进行Hash,这样就很难破解了。
- 处理好异常:
许多老旧网站,一遇到500异常就直接把错误信息、数据库字段、甚至代码堆栈信息都打印在页面上了,这是非常危险的,一眼就能看出后台使用什么语言、技术、数据库等,所以我们一定要在代码中定义好全局性异常捕捉,不要把服务端信息暴露到前端页面。
劫持攻击
一、怎么防御网页劫持?
1、常规防护措施
使用建站系统的站点,经常会遇到一些大规模爆发式常规漏洞,这类漏洞影响大,修补措施官方更新较快,大小站点都需要及时关注于更新,特别是使用开源程序的站点。
当然了大家都不可能时时刻刻的关注信息,但又拍错失修复机会怎么办?
建议站点使用第三方的安全观测平台,可以非接触式检测,另外还带有短信和邮件通知功能,特别适合站长使用,这里我推荐百度云观测和百度安全指数这2款产品,当然还有其他的检测平台,这里大家自行选择即可。
但是这里要特别注意的是不要使用太多监测平台,监测平台会定期去检测测试会给服务器带去一定的压力。
2、云服务防护
目前较为火的几个云主机平台都提供了一些安全防护软件,毕竟漏洞的爆发肯定是早于修补,而部分厂商也不会一下子就能够出补丁来修复,这时候使用例如安骑士这类产品,通过云服务商的技术团队第一时间无缝或屏蔽漏洞,至少可以支撑到厂商发布漏洞为止。
云服务除了上述安全防护组件外,大家应该还看到过一个叫做安全组的东西,浅易的来说就是防火墙端口策略,可以直接在云面板进行端口控制,比如近期爆出的方程式多个0DAY,如果你只开了必要的端口,实际上都无需修补。一般来说我们打开远程端口、HTTP/HTTPS端口、FTP端口基本上足矣,如无特殊服务可以关闭,可以省事很多。
3、服务器端防护
在服务器端大家可以安装第三方的杀毒、防护软件,这些软件带有大部分常见的防护机制,对付一般小白足矣。
目前市面上安全狗和云盾算是较为优秀的服务器防护软件。
4、网页防护
一般我都建议那些敏感站点,动静态分离、读取存储分离,我们都知道网页被劫持最常见的就是被提权,如果设置好权限可以最大程度上就可以避免被提权。
网页被劫持怎么办?如何处理?
二、网页被劫持怎么办?网页劫持修复思路方法
当你网页遇到劫持时,可以参考以下修复思路进行处理:
1、进行隔离止损。
2、通过日志和行为分析找到漏洞点。
3、通过补丁修复漏洞或临时修补漏洞。
4、 检查系统权限清除后门。
5、 大部分劫持都是带有恶意的,一般都会植入非法违规内容,针对这类内容,我们要第一时间删除,去平台提死链。
6、 观察搜索引擎表现,若有未清数据继续处理。
web安全学习导图
推荐阅读
多少道防线才能挡住顶尖黑客?
文章来源:https://www.toymoban.com/news/detail-471984.html
来源
怎么做好web服务器安全措施
Web渗透测试----1、Web安全学习导图
关于XSS攻击及其防御
CSRF攻击原理与防御措施
网页劫持防御方法,网页被劫持怎么办?
SQL注入攻击原理与防御措施文章来源地址https://www.toymoban.com/news/detail-471984.html
到了这里,关于【知识点】web安全怎么做的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!