扩展插件

更新时间:
复制 MD 格式

扩展插件功能支持用户编写自定义 Lua 脚本,深度介入 Web 应用的请求处理流程,从而实现 WAF 原生规则之外的个性化安全逻辑。通过灵活配置脚本与参数,可以轻松满足复杂的业务定制需求,极大提升安全防护的适配性与自由度。

开通扩展插件功能

如需使用扩展插件功能,需按以下步骤完成开通:

说明

适用版本:仅包年包月WAF企业版、旗舰版与按量付费版支持开通此功能。

计费说明:该功能为收费服务,具体计费方式如下:

  • 按量付费版:无需预先购买即可直接使用,系统将根据实际使用情况产生额外费用。

  • 包年包月版:需先完成购买方可使用。

  1. 登录Web应用防火墙3.0控制台。在顶部菜单栏,选择WAF实例的资源组和地域(中国内地非中国内地

  2. 在左侧导航栏,选择防护配置 > 全局配置 > 扩展插件

  3. 单击“立即购买”并根据页面指引完成开通。

新建扩展插件

扩展插件页面,单击新建扩展插件,然后完成以下参数配置。

  • 基础信息:填写便于识别的插件名称插件描述

  • 插件代码:在此处编写 Lua 脚本以实现自定义防护逻辑,示例如下。更多API说明,请参见附录:自定义Lua脚本API参考

    -- 自定义 Lua 脚本示例:提取 query 参数与自定义参数比较,不匹配则处置
    
    -- 第一步:提取请求参数
    local token = aliwaf.req.get_arg('token')
    
    -- 第二步:与自定义参数比较
    if token ~= params.token then
        aliwaf.func.punish()
    end 
    重要
    • 为保障WAF系统的稳定性,单条流量Lua脚本的执行时长上限为2毫秒。在调试测试阶段,若执行时长超过该限制,脚本将无法通过测试并导致创建失败;在实际运行阶段,若某条流量的脚本执行时长超过2毫秒,系统将强制跳过本次执行。

    • 请勿在代码中硬编码敏感信息(如密钥),建议使用下方的参数定义功能。

  • 参数定义:将脚本中的“硬编码”值提取为可配置参数,实现逻辑与数据解耦。这有助于在不修改代码的情况下动态调整策略,或安全地管理密钥。单击添加参数。完成以下配置:

    • 参数名称:对应脚本中引用的变量名(如 secret_key)。

    • 参数类型:支持 字符串、数字、布尔值、JSON Object 与 JSON Array。请确保类型与脚本中的处理逻辑一致。

    • 参数描述:说明该参数的用途。

    • 参数值:支持以下两种模式。

      • 手动输入:直接填写具体的值。

      • 使用KMS凭证:引用密钥管理服务中已创建的凭据,以安全存储敏感数据。若要使该凭据能被WAF成功引用,必须为其绑定以下标签:

        • 标签键waf:access:enable

        • 标签值true

  • 调试测试

    • 插件处置参数:当前仅支持拦截模式,表示阻止请求。

    • 流量参数:模拟真实的 HTTP 请求流量。单击添加参数,输入参数名(如 methoduriargs 等)及其对应的参数值

      示例:设置 method 为 POSTuri 为 /login,以测试登录接口的防护逻辑。

  • 执行结果:单击运行调试,系统将根据模拟流量执行脚本,然后查看右侧的执行结果面板。若结果为失败,请根据具体的错误信息提示修正代码。

后续步骤

扩展插件创建完成后,需要在自定义规则防护模板中进行引用,具体信息,请参见自定义规则

日常运维

扩展插件页面,支持进行以下操作:

  • 查看插件列表:页面展示所有扩展插件。可在列表上方的搜索框中输入插件名称,快速检索目标插件。

  • 查看关联防护规则:定位至目标插件,点击关联规则列的image图标,即可展示其关联的防护规则ID。可复制该ID,在Web 核心防护安全报表页面进行精准搜索。

  • 编辑扩展插件:定位至目标插件,点击操作列的编辑,即可对其配置信息进行修改。

  • 删除扩展插件:定位至目标插件,点击操作列的删除,即可移除该扩展插件。

附录:自定义Lua脚本API参考

本附录介绍编写自定义 Lua 脚本时可用的核心接口,包括请求数据读取、加解密运算与请求流程控制。

HTTP请求示例

POST /api/v1/orders?source=web&campaign=spring2024 HTTP/1.1
Host: shop.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
Cookie: session_id=abc123xyz; user_prefs=lang%3Den%26theme%3Ddark
Content-Type: application/json
Content-Length: 68
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx
Accept: application/json

eyJwcm9kdWN0X2lkIjogNzg5LCAicXVhbnRpdHkiOiAyLCAidXJnZW50IjogdHJ1ZX0=

读取请求数据

所有接口返回值为字符串类型,字段不存在时返回空字符串。

读取method

项目

类型

说明

参数

-

-

返回值

string

HTTP 请求方法,如 "GET"、"POST" 等。

-- POST --
local method = aliwaf.req.get_method()

读取uri

项目

类型

说明

参数

-

-

返回值

string

请求的 URI 路径。

-- /api/v1/orders --
local uri = aliwaf.req.get_uri()

读取域名

项目

类型

说明

参数

-

-

返回值

string

请求的 Host 域名。

-- shop.example.com --
local domain = aliwaf.req.get_domain()

读取query

项目

类型

说明

参数

-

-

返回值

string

请求的完整 query 字符串。

-- source=web&campaign=spring2024 --
local query = aliwaf.req.get_query()

读取query parameter

项目

类型

说明

参数

string

query 参数名。

返回值

string

对应参数值;参数不存在时返回空字符串 ""。

-- web --
local source = aliwaf.req.get_arg('source')

读取cookie

项目

类型

说明

参数

string

cookie 名称。

返回值

string

对应 cookie 值;cookie 不存在时返回空字符串 ""。

-- abc123xyz --
local session_id = aliwaf.req.get_cookie('session_id')

读取header

项目

类型

说明

参数

string

HTTP 请求头名称。

返回值

string

对应 header 值;header 不存在时返回空字符串 ""。

-- Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx --
local auth = aliwaf.req.get_header('Authorization')

读取body

判断请求body状态

  • body是否已经收完

    项目

    类型

    说明

    参数

    -

    -

    返回值

    boolean

    true 表示请求 body 已全部收完;false 表示仍有数据未到达。

    local last = aliwaf.func.is_last_fragment_arrived()
  • body是否被截断

    项目

    类型

    说明

    参数

    -

    -

    返回值

    boolean

    true 表示请求体超出限制被截断;false 表示请求体完整保留。

    WAF默认最多保存128K的请求体,超过了会被截断(超过部分丢弃不保存)。

    local discard = aliwaf.func.is_request_body_discarded()

等待body

请求体以流式方式到达 WAF,脚本执行时 body 可能尚未接收完成。如需处理完整 body,需显式通知框架等待 body 接收完毕后再次执行脚本。

项目

类型

说明

参数

-

-

返回值

-

-

aliwaf.func.wait_request_body()

读取请求body案例

-- body未收完, 等待body --
if not aliwaf.func.is_last_fragment_arrived() then
  aliwaf.func.wait_request_body()
  return
end

-- body已经收完, 判断是否被截断 --
if aliwaf.func.is_request_body_discarded() then
  return
end

-- eyJwcm9kdWN0X2lkIjogNzg5LCAicXVhbnRpdHkiOiAyLCAidXJnZW50IjogdHJ1ZX0= --
local body = aliwaf.req.get_body()

-- TODO:对完整body做业务逻辑 --

通用工具函数

基础编解码

url、hex、base64三类编解码接口接收字符串参数并返回处理后的字符串,操作失败时返回空字符串。

url编解码

  • escape_uri

    项目

    类型

    说明

    参数

    string

    待编码的原始字符串。

    返回值

    string

    编码后的字符串。

  • unescape_uri

    项目

    类型

    说明

    参数

    string

    待解码的 URL 编码字符串。

    返回值

    string

    解码后的原始字符串。

-- a%20b --
local data1 = aliwaf.util.escape_uri('a b')

-- a b --
local data2 = aliwaf.util.unescape_uri('a%20b')

hex编解码

  • hex_encode

    项目

    类型

    说明

    参数

    string

    待编码的二进制字符串。

    返回值

    string

    大写十六进制编码字符串。

  • hex_decode

    项目

    类型

    说明

    参数

    string

    待解码的十六进制字符串。

    返回值

    string

    解码后的原始字符串;输入非法时返回空字符串 ""。

-- DEADBEEF --
local data1 = aliwaf.util.hex_encode(string.char(0xDE, 0xAD, 0xBE, 0xEF))

-- \xDE\xAD\xBE\xEF --
local data2 = aliwaf.util.hex_decode('DEADBEEF')

base64编解码

  • base64_encode

    项目

    类型

    说明

    参数

    string

    待编码的原始字符串。

    返回值

    string

    Base64 编码后的字符串。

  • base64_decode

    项目

    类型

    说明

    参数

    string

    待解码的 Base64 字符串。

    返回值

    string

    解码后的原始字符串;输入非法时返回空字符串 ""。

-- aGVsbG8= --
local data1 = aliwaf.util.base64_encode('hello')

-- hello --
local data2 = aliwaf.util.base64_decode('aGVsbG8=')

MD5/CRC/SHA

  • md5

    项目

    类型

    说明

    参数

    string

    待计算的原始字符串。

    返回值

    string

    32 位小写十六进制格式的 MD5 摘要。

  • sha256

    项目

    类型

    说明

    参数

    string

    待计算的原始字符串。

    返回值

    string

    64 位小写十六进制格式的 SHA-256 摘要。

  • crc32

    项目

    类型

    说明

    参数

    string

    待计算的原始字符串。

    返回值

    integer

    CRC32 校验值(无符号 32 位整型)。

-- 5d41402abc4b2a76b9719d911017c592= --
local md5 = aliwaf.util.md5('hello')

-- 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 --
local sha = aliwaf.util.sha256('hello')

-- 3287646509 --
local crc = aliwaf.util.crc32('hello')

加解密(AES/DES)

  • evp_encrypt

    项目

    类型

    说明

    参数1

    string

    加密算法类型,例如 "aes-128-cbc" 等。

    参数2

    string

    加密密钥,二进制安全字符串。

    参数3

    string

    初始化向量,可为空字符串 ""(不使用 IV 时)。

    参数4

    string

    待加密的明文。

    返回值

    string

    加密后的密文;参数非法或加密失败时返回空字符串 ""。

  • evp_decrypt

    项目

    类型

    说明

    参数1

    string

    解密算法类型,需与加密时使用的算法一致,如 "aes-128-cbc"。

    参数2

    string

    解密密钥,需与加密时使用的密钥一致。

    参数3

    string

    初始化向量,需与加密时使用的 IV 一致,可为空字符串 ""。

    参数4

    string

    待解密的密文。

    返回值

    string

    解密后的明文;参数非法或解密失败时返回空字符串 ""。

local data1 = aliwaf.util.evp_encrypt('aes-128-cbc', 'key-12345678-key', 'iv-1234567890-iv', 'hello')

local data2 = aliwaf.util.evp_decrypt('aes-128-cbc', 'key-12345678-key', 'iv-1234567890-iv', data1)

加签验签(ES256)

  • es256_sign

    项目

    类型

    说明

    参数1

    string

    ES256 私钥,PEM 格式。

    参数2

    string

    待签名的原始数据。

    返回值

    string

    签名结果(二进制字符串);参数非法或签名失败时返回空字符串 ""。

  • es256_verify

    项目

    类型

    说明

    参数1

    string

    ES256 公钥,PEM 格式。

    参数2

    string

    签名时使用的原始数据(需与签名时一致)。

    参数3

    string

    待验证的签名值(由 es256_sign 生成)。

    返回值

    boolean

    true 表示签名验证通过;false 表示验证失败或参数非法。

local sign = aliwaf.util.es256_sign('private_key-1234', 'hello')

local result = aliwaf.util.es256_verify('public_key-12345', 'hello', sign)

时间

项目

类型

说明

参数

-

-

返回值

integer

当前毫秒级 UNIX 时间戳。

-- 当前毫秒级时间戳(整型)--
local timestamp = aliwaf.util.get_current_ms()

业务辅助函数

业务辅助函数用于LuaWAF框架进行协作。

处置

项目

类型

说明

参数

-

-

返回值

-

-

-- 根据预先选定的动作处置当前请求 --
aliwaf.func.punish()