文章目录
ssti漏洞成因
一些框架使用了渲染函数时,由于代码的不规范或者信任了用户输入而导致了服务端模板注入。
模板渲染并没有漏洞,主要是程序员对代码不规范不严谨造成了模板注入漏洞,造成模板可控。
模板引擎
模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,大大提升了开发效率,使代码重用变得更加容易。但是往往新的开发都会导致一些安全问题,虽然模板引擎会提供沙箱机制,但同样存在沙箱逃逸技术来绕过。
模板知识一种提供给程序来解析的一种语法,模板是用于从数据(变量)到实际的视觉表现(HTML代码)这项工作的一种实现手段,这种手段不管在前端还是后端都有应用。
拿到数据——塞进模板——让渲染引擎将数据生成HTML的文本——返回给浏览器
- 后端渲染:浏览器会直接接收到经过服务器计算之后的呈现给用户的最终的HTML字符串,计算就是服务器后端经过解析服务器端的模板来完成的,后端渲染的好吃是对前端浏览器的压力较小,主要任务在服务器端就已经完成。
- 前端渲染:浏览器从服务器得到信息,可能是json等数据包封装的数据,也可能是HTML代码,都是由浏览器前端来解析渲染成HTML的可视化的代码而呈现在用户面前。好处是对于服务器后端压力较小,主要渲染在用户的客户端完成。
例子:
我们想要呈现在每个用户面前自己的名字,用一些url或者cookie包含的信息,渲染到what变量里,呈现给用户。
<html>
<div>{$what}</div>
</html>
服务端模板注入
通过模板,我们可以通过输入转换成特定的HTML文件,比如一些博客页面,登录的时候可能会返回hi!user
。这个user就是通过你的身份信息而渲染成html返回到页面。
$output = $twig->render( $_GET[‘custom_email’] , array(“first_name” => $user.first_name) );
假设URL为xx.xx.xx/?custom_email={{7*7}}
,将会返回49xx.xx.xx/?custom_email={{self}}
返回<templatereference none=""></templatereference>
在{{}}
里,将我们的代码进行了执行,服务器将我们的数据经过引擎解析的时候,进行了执行,模板注入与sql注入的成因有点相似,都是信任了用户的输入,将不可靠的用户输入不经过滤直接进行了执行,用户插入了恶意代码同样也会执行。
flask环境本地搭建
- 安装python 3.x
- 安装pycharm
- 安装flask
创建flask项目
项目自动生成代码
在http://127.0.0.1:5000
中访问
route装饰器路由
@app.route('/')
使用route()
装饰器告诉Flask什么样的URL能触发我们的函数.route()装饰器把一个函数绑定到对应的URL上
@app.route('/test')
def test():
return '123'
访问127.0.0.1:5000/test
@app.route("/hello/<username>")
def hello_user(username):
return "user:%s"%username
或者使用int型
int 接受整数
float 同 int ,但是接受浮点数
path 和默认的相似,但也接受斜线
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
main 入口
当.py文件被直接运行时,if name == ‘main‘
之下的代码块将被运行;当.py文件以模块形式被导入时,if name == ‘main‘
之下的代码块不被运行。如果你经常以cmd方式运行自己写的python小脚本,那么不需要这个东西,但是如果需要做一个稍微大一点的python开发,写if name ==’main__’
是一个良好的习惯,大一点的python脚本要分开几个文件来写,一个文件要使用另一个文件,也就是模块,此时这个if就会起到作用不会运行而是类似于文件包含来使用。
if __name__ == '__main__':
app.debug = True
app.run()
测试的时候,我们可以使用debug,方便调试,增加一句
app.debug = True
或者(效果是一样的)
app.run(debug=True)
这样我们修改代码的时候直接保存,网页刷新就可以了,如果不加debug,那么每次修改代码都要运行一次程序,并且把前一个程序关闭。否则会被前一个程序覆盖。
app.run(host='0.0.0.0')
这会让操作系统监听所有公网 IP,此时便可以在公网上看到自己的web。
模板渲染
你可以使用 render_template() 方法来渲染模板。你需要做的一切就是将模板名和你想作为关键字的参数传入模板的变量。
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)//我们hello.html模板未创建所以这段代码暂时供观赏,不妨往下继续看
首先要搞清楚,模板渲染体系,render_template函数渲染的是templates中的模板,所谓模板是我们自己写的html,里面的参数需要我们根据每个用户需求传入动态变量。
├── app.py
├── static
│ └── style.css
└── templates
└── index.html
我们写一个index.html文件写templates文件夹中。
<!DOCTYPE html>
<html>
<head>
<title>{{title}} - 小猪佩奇</title>
</head>
<body>
<h1>Hello, {{user.name}}!</h1>
</body>
</html>
里面有两个参数需要我们渲染,user.name,以及title
我们在app.py文件里进行渲染。
@app.route('/')
@app.route('/index')#我们访问/或者/index都会跳转
def index():
user = {'name': '小猪佩奇'}#传入一个字典数组
return render_template("index.html",title='Home',user=user)