一、复杂的需求

WAF (WEB 应用防火墙) 用来保护 WEB 应用免受来自应用层的攻击。作为防护对象的 WEB 应用,其功能和运行环境往往是复杂且千差万别的,这导致即便防御某个特定的攻击方式时,用户需求也可能是细致而多样的。

以最基本的 SQL 注入 (以下简称注入) 为例。注入攻击当然是要防范的,但用户可能还有以下需求:

  • 某个域名或某些特定的 URL 不需要注入检查
  • 对来自外网的注入访问进行拦截,来自内网的注入访问只记录不拦截
  • 对特定的请求参数名或特定特征的请求参数不进行注入检查
  • 非工作时段不仅拦截还阻止该用户一段时间访问
  • 对 admin 等管理账号登录后的访问不进行注入检查
  • 对于只记录不拦截的请求,附加一个特别的请求头发往应用
  • 对某些 URL 的注入访问记录下 HTTP 请求的全部报文
  • 将 HTTP 响应码为 500 的注入的日志紧急度设为 alert
  • ...

以上需求,用户可能只提出一项,也可能提出多项,还可能是不同的逻辑组合或更多的条件和动作。这还仅仅是防注入这项基本功能,如果有更多的应用防护需求,比如:

一个已登录的非内网用户在 10 秒钟连续访问 POST 方法的页面 (非 AJAX 数据) 达到 5 次,则在 10 秒内延迟这个用户的响应时间 0.5 秒;如果在未来 10 秒内继续访问 POST 方法页面 3 次,则强制用户登出并阻止登录 30 秒;如果一个用户 1 天内这种情形发生 5 次,则产生一条严重级别的告警。

我们该如何描述满足这些需求的功能呢?

WAF是否能够设计得足够灵活,使得实施人员通过现场配置就能实现这个需求?

二、规则的局限性

大部分应用防火墙的配置以规则为核心。

传统意义上的规则,其实质形式是独立的一行行文本,每行文本有固定的结构/字段,可以独立地描述出一个功能。对用户而言,书写规则就是设置其中的参数和选项。这种规则的好处是简单明了,用户甚至可以在图形化界面中完成规则的配置,但其弱点是不足以描述复杂的情形。

以防注入功能为例,如果它只有一个开启或关闭的开关选项,或只能简单地以区分站点来使用不同策略,显然不能满足前述的复杂需求。而企图打造一个预先设定又包罗万象的规则,则完全超出了“规则”的范畴,是不可能完成的任务。

追溯一下,用规则来描述防护功能始自于网络防火墙。网络防火墙的检查对象是 TCP / IP 协议诸元,三/四层网络协议相对来说是简单清晰的,用五元组就可以概括它们,以五元组为对象写一些规则就能够很好地实现防护。

但是,WEB 应用是怎么写成的?WEB 应用是用 Java / PHP / Python 等编程语言写成的。就像不可能用“规则"来书写 WEB 应用一样,试图良好地对应用进行防护,也不可能通过传统的“规则"来实现——无论写多少条规则。

三、大家一起来编程?

既然应用是编程的,那么应用防火墙的配置可否也用编程的方式来实现?

以下是一个通用语言实现的例子,它的主功能是对请求参数进行注入检查,检查时会排除指定名字的参数,而且对不同来源访问者 (外网或内网) 产生不同的日志和动作:

for arg in ARGS:
if arg['name'] in ['__utm', '__token']:
return PASS if detect_sqli(remove_comment(url_decode(arg['value']))):
if is_private_address(REMOTE_ADDRESS):
log('SQLi and PASS')
return PASS
else:
log('SQLi and BLOCK')
return BLOCK
return PASS

功能是实现了,但看上去有点复杂。让非程序员去写这样一段代码难免强人所难 (比如对集合类型数据的遍历获取),而且完全不可能做到可视化。更重要的是,这仅是代码片段 (其实就是函数),真的要整合起来使用,还面临很多编程方面的问题,如:

  • 除错和容错:

    各种语法错误和链接错误,比如使用了不存在的变量或方法。
  • 批量控制:

    怎样实现全局和批量的改变,比如想让 WAF 全局进入只记录模式。
  • 作用域:

    每个代码片段有自己的作用域,如果想影响其他代码片段应该怎么做?如何定义变量作用域?
  • 与预置防护集的关系:

    WAF 必然自带预置的防护集,用户书写的代码与预置防护集的关系。
  • 参数的设置:

    应用相关的可配置参数怎么处理,是作为常量写在程序里 (难以维护) 还是另作一个配置文件 (程序变得更复杂)?

以上问题,如果都通过临时修改代码 (全局替换或加注释) 来实现,则代码将变得不可维护。事实上,由于代码的无限可能性,甲写的代码乙很难理解。为解决上述问题,必须要有一套程序框架,而框架本身的编写、配置和使用又成了问题。

有没有一种方法,不需要使用编程语言,而又能灵活满足复杂的需求呢?

四、类编程的WAF

天存信息的类编程 WAF,用数据结构来表达程序思想,让普通的技术支持人员也能够写出足够复杂和灵活的安全策略。

{
"if": {
"variables": "ARGS",
"transform": "urlDecodeUni",
"operator": "detectSQLi"
},
"then": {
"verdict": {
"action": "block",
"log": true
}
}
}

可见,这时的“规则”已经不是一行文本了,而是具有代码特征的一个函数实现

类编程的 WAF 具有以下与编程语言相似的特性:

  • 无限嵌套的 if / the / else 条件判断
  • 完整的 and / or / not 逻辑运算符
  • 对集合 / 数组成员的遍历运算
  • 变量包含多种数据类型
  • 支持变量的宏扩展引用
  • 用户自定义变量和表达式赋值
  • 预置及可设置不同生命期的全局变量
  • 用户书写任意多样的动作
  • 函数返回值灵活控制流程
  • 运行时改变其他函数行为

而这灵活内涵的表面,却能够用规范的模式 (schema) 来约束,使得写出的类程序易读且统一,甚至做到可视化呈现。

类编程的WAF(上)的更多相关文章

  1. 类编程的WAF(下)

    一.编程语言的要素 天存信息的iWall3应用防火墙是一种创新式的类编程 WAF,它包含了编程语言的一些基本要素. 1. 变量 iWall3 中广义的变量包括报文变量.环境变量和用户变量:报文变量和环 ...

  2. PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(上)

    content: 上: 1.property动态属性 2.__getattr__和__setattr__的区别和在属性查找中的作用 3.属性描述符 和属性查找过程 4.__new__和__init__ ...

  3. Android利用网络编程HttpClient批量上传(两)AsyncTask+HttpClient监测进展情况,并上传

    请尊重别人的劳动.转载请注明出处: Android网络编程之使用HttpClient批量上传文件(二)AsyncTask+HttpClient并实现上传进度监听 执行效果图: 我曾在<Andro ...

  4. Python进阶开发之元类编程

    系列文章 √第一章 元类编程,已完成 ; 本文目录 类是如何产生的如何使用type创建类理解什么是元类使用元类的意义元类实战:ORM . 类是如何产生的 类是如何产生?这个问题肯定很傻.实则不然,很多 ...

  5. js中的行为委托和无类编程

    概述 <你不知道的JavaScript>中有这么一段话:不幸的是,将类和继承的设计模式思维带入Javascript的想法是你所做的最坏的事情,因为语法可能会让你迷惑不已,让你以为真的有类这 ...

  6. 【转】Shell编程基础篇-上

    [转]Shell编程基础篇-上 1.1 前言 1.1.1 为什么学Shell Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具, Linux/UNIX系统的底层及基础应 ...

  7. Python元类编程

    来源:http://python.jobbole.com/88582/ @property装饰器,是将类中的函数当做属性调用 Python类中定义的属性,如果属性名前面只有一个下划线,那么就是一种规范 ...

  8. AOP切面编程在android上的应用

    代码地址如下:http://www.demodashi.com/demo/12563.html 前言 切面编程一直是一个热点的话题,这篇文章讲讲一个第三方aop库在android上的应用.第三方AOP ...

  9. JavaEE-实验一 Java常用工具类编程

    该博客仅专为我的小伙伴提供参考而附加,没空加上代码具体解析,望各位谅解 1.  使用类String类的分割split 将字符串  “Solutions to selected exercises ca ...

随机推荐

  1. MySQL的Double Write并不难理解

    目录 问题引入- 断电了 不一会 - 来电了 Double write工作流程 恢复的过程 配置参数 疑问 推荐阅读 问题引入- 断电了 今天为大家介绍一个新的名词:double write. 相信你 ...

  2. Java对象内存分布

    [deerhang] 创建对象的四种方式:new关键字.反射.Object.clone().unsafe方法 new和反射是通过调用构造器创建对象的,创建对象的时候使用invokespecial指令 ...

  3. Spring Cloud Gateway之全局异常拦截器

    /** * @version 2019/8/14 * @description: 异常拦截器 * @modified: */ @Slf4j public class JsonExceptionHand ...

  4. [Qt] 项处理组件

                             项(Item):一个项存储了文字.文字的格式.自定义数据等. 1.项视图(Item View) 针对一个数据模型,可能有不同的展示需求,如文件夹中图片 ...

  5. 联想ThinkServer服务器安装CentOS7 Redhat7系统 驱动R110i RAID卡

    1.下载对应版本的驱动(因为联想没有CentOS的驱动用redhat的驱动就可以). 2.进入BIOS里,在高级设置里找到SATA设置,把SATA模式改成RAID(重启后配置raid),sSATA模式 ...

  6. Ubuntu 20.04 版本安装

    Ubuntu 20.04 版本安装 安装步骤 首先创建好Ubuntu 20.04虚拟机 等待系统检查完整性 选择语言 选择不更新,回车确定 键盘语言默认即可 网卡IP配置 设置代理服务器 设置源 自定 ...

  7. MegaRAID BIOS设置阵列

    MegaRAID BIOS设置阵列 1.在初始界面可以看到physical View的界面,或者在左侧的菜单栏中点击选中即可,可以看到物理磁盘. 2.点击上一步的配置向导可以进入到配置向导界面 3.选 ...

  8. Mysql数据库-多实例主从复制-主从故障详解

    一.mysql结构 1.实例 1.什么是单实例 一个进程 + 多个线程 + 一个预分配的内存空间 2.多实例 多个进程 + 多个线程 + 多个预分配的内存空间 ](http://shelldon.51 ...

  9. Linux 目录管理

    tree命令的基本使用 tree 查看当前目录的树状结构 -a 查看所有包含隐藏文件 -L 1 查看目录层级 tree /root 指定目录 根目录下的主要文件 /bin 普通用户可以执行的二进制文件 ...

  10. ssh远程主机执行命令或脚本

    1.执行单一命令 [root@vps ~]# ssh user@192.168.9.243 "pwd; ls; rm -f Cent* ;echo --------; ls"/ho ...