codecamp

微信小程序 安全指引·后台

后台(包括云函数与自建后台)

注入漏洞

注入漏洞(SQL、 命令等)通常指用户绕过后台代码限制,直接在数据库、 shell 内执行自定义代码。

常见的注入漏洞有:

SQL 注入

SQL 注入是指 Web 程序代码中对于用户提交的参数未做有效过滤就直接拼接到 SQL 语句中执行,导致参数中的特殊字符打破了 SQL 语句原有逻辑,黑客可以利用该漏洞执行任意 SQL 语句。

开发建议:

  1. 使用数据库提供的参数化查询来进行数据库操作,不允许直接通过拼接字符串的方式来合成 SQL 语句。
  2. 如果存在部分情况需要通过拼接的方式来合成 SQL ,拼接的变量必须要经过处理:对于整数,需要判断变量是否为整数类型。对于字符串,需要对单引号、双引号等做转义处理。
  3. 避免 Web 应用显示 SQL 的报错信息。
  4. 保证 Web 应用里每一数据层的编码统一。

命令注入

命令注入漏洞是指 Web 应用未对用户可控参数进行有效过滤,攻击者可以构造恶意参数拼接到命令上来执行任意命令。

开发建议:

  • 对用户输入的数据(如 ;、|、&等)进行过滤或转义。

弱口令

弱口令指管理后台的用户名密码设置得较为简单或者使用默认帐号。攻击者可以通过登录这些帐号修改后台数据或进行下一步的入侵操作。

开发建议:

  1. 后台服务禁用默认帐号,修改后台弱口令。
  2. 敏感服务增加二次验证机制,如短信验证码、邮箱验证码等。

文件上传漏洞

文件上传漏洞是指 Web 应用允许用户上传指定文件,但未对文件类型、格式等做合法性校验,导致可以上传非预期格式的文件。

开发建议:

  • 正确解析上传文件的文件类型,通过白名单的方式限制可上传的文件类型。

文件下载

文件下载漏洞是指 Web 应用允许用户通过指定路径和文件名的方式来下载对应的文件,但未正确限制可下载文件所在的目录范围,导致预期范围外的文件被下载泄露。

开发建议:

  1. 正确限制可下载文件所在的目录范围
  2. 通过指定文件 id 的方式来查找下载对应的文件

目录遍历

目录遍历是指由后台服务对用户输入验证不足或配置不严谨导致的服务器目录内容泄漏。外部可能通过目录遍历获取系统文件、后台代码等敏感文件。

开发建议:

  1. web 服务配置
    1. 服务端禁止展示目录
    2. 设置目录访问权限
    3. 在每个目录下放置一个空的 index.html 页面
  2. web 应用代码
    1. 严格检查文件路径参数,限定文件的范围

条件竞争

条件竞争比较常见的例子是攻击者通过并发 https 请求而达到多次获奖、多次收获、多次获赠等非正常逻辑所能触发的效果。

  • 漏洞代码示例 
    // 从DB里查询该用户剩余获奖次数,初始值为1
    int remain_times = SelectRemainTimes();
    
    if(remain_times > 0){
        EarnRewards();          // 用户获得奖励
        ClearRemainTimes();     // 在DB里把该用户的剩余获奖次数清零
    }

    开发者的设计本意是只允许用户获得一次奖励,但当出现并发请求时,有可能出现请求 A 和请求 B 都刚好执行完第2行代码的情况,此时两个请求的 remain_times 都为1,也就是可以通过第4行代码的判断,获得两次奖励。

开发建议:

  • 对关键(完整)逻辑加锁操作或把关键逻辑以队列任务的形式去进行处理。


微信小程序 安全指引·通用
微信小程序 性能与体验
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

微信小程序 指南

目录结构

开放能力

微信小程序 调试

微信小程序 实时日志

微信小程序 小程序测速

微信小程序 基础组件

微信小程序 API

媒体

界面

微信小程序API 绘图

微信小程序 服务端

接口调用凭证

统一服务消息

微信小程序 服务市场

微信小程序 生物认证

微信小程序 云开发

服务端

微信小程序云开发服务端API 数据库

SDK文档

微信小程序 扩展能力

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }