├── VERSION ├── kong └── plugins │ ├── ssk-allowkey │ ├── daos.lua │ ├── schema.lua │ └── handler.lua │ ├── ssk-libinjection │ ├── daos.lua │ ├── schema.lua │ ├── handler.lua │ └── libinjection.lua │ ├── ssk-saferedirect │ ├── daos.lua │ ├── schema.lua │ └── handler.lua │ ├── ssk-strictparameter │ ├── daos.lua │ ├── schema.lua │ ├── types.lua │ └── handler.lua │ ├── ssk-pm │ ├── daos.lua │ ├── patternmatcher.lua │ ├── schema.lua │ └── handler.lua │ ├── ssk-cors │ ├── daos.lua │ ├── schema.lua │ └── handler.lua │ ├── ssk-safehost │ ├── daos.lua │ ├── schema.lua │ └── handler.lua │ ├── ssk-clickjacking │ ├── daos.lua │ ├── handler.lua │ └── schema.lua │ ├── ssk-std-logger │ ├── daos.lua │ ├── schema.lua │ └── handler.lua │ ├── ssk-telemetry │ ├── daos.lua │ ├── schema.lua │ └── handler.lua │ ├── ssk-ua-filter │ ├── daos.lua │ ├── schema.lua │ └── handler.lua │ ├── ssk-detecthandling │ ├── daos.lua │ ├── schema.lua │ └── handler.lua │ ├── ssk-magika │ ├── schema.lua │ └── handler.lua │ └── ssk-core │ ├── lib │ ├── matcher.lua │ ├── ssk.lua │ └── utils.lua │ ├── response_body.lua │ ├── common.lua │ ├── params.lua │ ├── core.lua │ ├── response.lua │ ├── decoder.lua │ └── request.lua ├── .gitignore ├── img ├── logo.png └── logo_noclear.png ├── rocks ├── ssk-pm-1.1.0-1.all.rock ├── ssk-pm-2.0.0-1.all.rock ├── ssk-cors-1.1.0-1.all.rock ├── ssk-cors-2.0.0-1.all.rock ├── ssk-magika-2.0.0-1.all.rock ├── ssk-allowkey-1.1.0-1.all.rock ├── ssk-allowkey-2.0.0-1.all.rock ├── ssk-safehost-1.1.0-1.all.rock ├── ssk-safehost-2.0.0-1.all.rock ├── ssk-std-logger-1.1.0-1.all.rock ├── ssk-std-logger-2.0.0-1.all.rock ├── ssk-telemetry-1.1.0-1.all.rock ├── ssk-telemetry-2.0.0-1.all.rock ├── ssk-ua-filter-1.1.0-1.all.rock ├── ssk-ua-filter-2.0.0-1.all.rock ├── ssk-clickjacking-1.1.0-1.all.rock ├── ssk-clickjacking-2.0.0-1.all.rock ├── ssk-libinjection-1.1.0-1.all.rock ├── ssk-libinjection-2.0.0-1.all.rock ├── ssk-saferedirect-1.1.0-1.all.rock ├── ssk-saferedirect-2.0.0-1.all.rock ├── ssk-detecthandling-1.1.0-1.all.rock ├── ssk-detecthandling-2.0.0-1.all.rock ├── ssk-strictparameter-1.1.0-1.all.rock └── ssk-strictparameter-2.0.0-1.all.rock ├── install_all.sh ├── install_libinjection.sh ├── specs ├── ssk-cors-1.1.0-1.rockspec ├── ssk-allowkey-1.1.0-1.rockspec ├── ssk-safehost-1.1.0-1.rockspec ├── ssk-telemetry-1.1.0-1.rockspec ├── ssk-ua-filter-1.1.0-1.rockspec ├── ssk-std-logger-1.1.0-1.rockspec ├── ssk-clickjacking-1.1.0-1.rockspec ├── ssk-saferedirect-1.1.0-1.rockspec ├── ssk-pm-1.1.0-1.rockspec ├── ssk-detecthandling-1.1.0-1.rockspec ├── ssk-strictparameter-1.1.0-1.rockspec ├── ssk-cors-2.0.0-1.rockspec ├── ssk-magika-2.0.0-1.rockspec ├── ssk-safehost-2.0.0-1.rockspec ├── ssk-telemetry-2.0.0-1.rockspec ├── ssk-ua-filter-2.0.0-1.rockspec ├── ssk-std-logger-2.0.0-1.rockspec ├── ssk-clickjacking-2.0.0-1.rockspec ├── ssk-saferedirect-2.0.0-1.rockspec ├── ssk-detecthandling-2.0.0-1.rockspec ├── ssk-strictparameter-2.0.0-1.rockspec ├── ssk-pm-2.0.0-1.rockspec ├── ssk-libinjection-1.1.0-1.rockspec ├── ssk-allowkey-2.0.0-1.rockspec └── ssk-libinjection-2.0.0-1.rockspec ├── quickstart.sh ├── tools └── quickstart.py └── LICENSE /VERSION: -------------------------------------------------------------------------------- 1 | 2.0.0 2 | -------------------------------------------------------------------------------- /kong/plugins/ssk-allowkey/daos.lua: -------------------------------------------------------------------------------- 1 | return {} 2 | -------------------------------------------------------------------------------- /kong/plugins/ssk-libinjection/daos.lua: -------------------------------------------------------------------------------- 1 | return {} 2 | -------------------------------------------------------------------------------- /kong/plugins/ssk-saferedirect/daos.lua: -------------------------------------------------------------------------------- 1 | return {} 2 | -------------------------------------------------------------------------------- /kong/plugins/ssk-strictparameter/daos.lua: -------------------------------------------------------------------------------- 1 | return {} 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /coreruleset-*/ 2 | *.gz 3 | /tools/crs_patterns.* -------------------------------------------------------------------------------- /img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/img/logo.png -------------------------------------------------------------------------------- /kong/plugins/ssk-pm/daos.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | return {} 3 | -------------------------------------------------------------------------------- /img/logo_noclear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/img/logo_noclear.png -------------------------------------------------------------------------------- /kong/plugins/ssk-cors/daos.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | return {} 3 | -------------------------------------------------------------------------------- /kong/plugins/ssk-safehost/daos.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | return {} 3 | -------------------------------------------------------------------------------- /kong/plugins/ssk-clickjacking/daos.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | return {} 3 | -------------------------------------------------------------------------------- /kong/plugins/ssk-std-logger/daos.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | return {} 3 | -------------------------------------------------------------------------------- /kong/plugins/ssk-telemetry/daos.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | return {} 3 | -------------------------------------------------------------------------------- /kong/plugins/ssk-ua-filter/daos.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | return {} 3 | -------------------------------------------------------------------------------- /kong/plugins/ssk-detecthandling/daos.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | return {} 3 | -------------------------------------------------------------------------------- /rocks/ssk-pm-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-pm-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-pm-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-pm-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-cors-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-cors-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-cors-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-cors-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-magika-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-magika-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-allowkey-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-allowkey-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-allowkey-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-allowkey-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-safehost-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-safehost-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-safehost-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-safehost-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-std-logger-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-std-logger-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-std-logger-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-std-logger-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-telemetry-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-telemetry-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-telemetry-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-telemetry-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-ua-filter-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-ua-filter-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-ua-filter-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-ua-filter-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-clickjacking-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-clickjacking-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-clickjacking-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-clickjacking-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-libinjection-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-libinjection-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-libinjection-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-libinjection-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-saferedirect-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-saferedirect-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-saferedirect-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-saferedirect-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-detecthandling-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-detecthandling-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-detecthandling-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-detecthandling-2.0.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-strictparameter-1.1.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-strictparameter-1.1.0-1.all.rock -------------------------------------------------------------------------------- /rocks/ssk-strictparameter-2.0.0-1.all.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cybersecuritycloud/sasanka/HEAD/rocks/ssk-strictparameter-2.0.0-1.all.rock -------------------------------------------------------------------------------- /install_all.sh: -------------------------------------------------------------------------------- 1 | dir="rocks" 2 | subdirs=$(ls -d "$dir"/* ) 3 | PLUGINS_str=$(echo "${subdirs//$dir\//}" | tr '\n' ' ') 4 | PLUGINS_str="${PLUGINS_str//\//}" 5 | PLUGINS_str="${PLUGINS_str/ssk-core/}" 6 | IFS=" " read -r -a PLUGINS < <(echo "$PLUGINS_str") 7 | 8 | for PLG in "${PLUGINS[@]}"; do 9 | sudo luarocks install $dir/$PLG 10 | done -------------------------------------------------------------------------------- /kong/plugins/ssk-clickjacking/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | 3 | local function add_header( k, subj ) 4 | if subj then 5 | kong.response.set_header(k, subj) 6 | end 7 | end 8 | 9 | local function h_res_header( params, config ) 10 | add_header( "X-Frame-Options", config["policy"] ) 11 | end 12 | 13 | 14 | local _M = core:extend() 15 | _M.PRIORITY = 100 16 | 17 | function _M:init_handler( config ) 18 | self:add_handler( "res_header", h_res_header, config) 19 | end 20 | 21 | 22 | return _M 23 | -------------------------------------------------------------------------------- /kong/plugins/ssk-clickjacking/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-clickjacking" 4 | 5 | local schema = { 6 | name = PLUGIN_NAME, 7 | fields = { 8 | -- the 'fields' array is the top-level entry with fields defined by Kong 9 | { consumer = typedefs.no_consumer }, -- this plugin cannot be configured on a consumer (typical for auth plugins) 10 | { protocols = typedefs.protocols_http }, 11 | { config = { 12 | -- The 'config' record is the custom part of the plugin schema 13 | type = "record", 14 | fields = { 15 | { policy = {type = "string", default = "DENY", 16 | one_of = { "DENY","SAMEORIGIN"}, }}, 17 | }, 18 | entity_checks = { 19 | -- add some validation rules across fields 20 | }, 21 | }, 22 | }, 23 | }, 24 | } 25 | 26 | return schema 27 | -------------------------------------------------------------------------------- /kong/plugins/ssk-telemetry/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-telemetry" 4 | 5 | local schema = { 6 | name = PLUGIN_NAME, 7 | fields = { 8 | -- global plugin only 9 | { consumer = typedefs.no_consumer }, 10 | { service = typedefs.no_service }, 11 | { route = typedefs.no_route }, 12 | { protocols = typedefs.protocols_http }, 13 | { config = { 14 | -- The 'config' record is the custom part of the plugin schema 15 | type = "record", 16 | fields = { 17 | { std = { type = "string", one_of = { "out", "err" }, default = "out" }}, 18 | { tag = { type = "string" }}, 19 | { header = { type = "string" }}, 20 | }, 21 | entity_checks = { 22 | -- add some validation rules across fields 23 | }, 24 | }, 25 | }, 26 | }, 27 | } 28 | 29 | return schema 30 | -------------------------------------------------------------------------------- /install_libinjection.sh: -------------------------------------------------------------------------------- 1 | GIT_DIR=$(cd $(dirname $0); pwd) 2 | # prepare 3 | sudo apt install -y autoconf luajit=2.1.* libluajit-5.1 4 | sudo apt install -y swig 5 | git clone https://github.com/libinjection/libinjection ${GIT_DIR}/libinjection 6 | 7 | # version of Mar 30, 2023 8 | cd ${GIT_DIR}/libinjection/ 9 | git checkout c1831ca56351c351744acdff6bf3cca250ae1df7 10 | 11 | # build 12 | autoconf 13 | ./autogen.sh 14 | ./configure 15 | make 16 | 17 | # build .so for lua 18 | sed -i "s/luajit-2\.0/luajit-2\.1/g" ./lua/Makefile 19 | cp ./src/version.h ./lua/version.h 20 | make -C lua 21 | 22 | ### If you failed to make and saw below error message, 23 | ### /usr/bin/ld: cannot find -lluajit-5.1 24 | ### confirm ldconfig 25 | ### ldconfig -p | grep luajit 26 | ### and create symbolic link from luajit-*.so.?.? to luajit-*.so, refer to the following 27 | ### sudo ln -s /usr/lib/x86_64-linux-gnu/libluajit-5.1.so.2.1.0 /usr/lib/x86_64-linux-gnu/libluajit-5.1.so 28 | 29 | # copy .so 30 | sudo cp ./lua/libinjection.so /usr/local/kong/lib/ 31 | -------------------------------------------------------------------------------- /kong/plugins/ssk-safehost/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-safehost" 4 | 5 | local type_string = { type = "string" } 6 | 7 | local type_string_array = { 8 | type = "array", 9 | elements = { type = "string" } 10 | } 11 | 12 | local schema = { 13 | name = PLUGIN_NAME, 14 | fields = { 15 | -- the 'fields' array is the top-level entry with fields defined by Kong 16 | { consumer = typedefs.no_consumer }, -- this plugin cannot be configured on a consumer (typical for auth plugins) 17 | { protocols = typedefs.protocols_http }, 18 | { config = { 19 | -- The 'config' record is the custom part of the plugin schema 20 | type = "record", 21 | fields = { 22 | { ["tags"] = type_string_array }, 23 | { host_check = type_string }, 24 | }, 25 | entity_checks = { 26 | -- add some validation rules across fields 27 | }, 28 | }, 29 | }, 30 | }, 31 | } 32 | 33 | return schema 34 | -------------------------------------------------------------------------------- /kong/plugins/ssk-ua-filter/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-ua-filter" 4 | 5 | local type_string_array = { 6 | type = "array", 7 | elements = { type = "string" } 8 | } 9 | 10 | local schema = { 11 | name = PLUGIN_NAME, 12 | fields = { 13 | -- the 'fields' array is the top-level entry with fields defined by Kong 14 | { consumer = typedefs.no_consumer }, -- this plugin cannot be configured on a consumer (typical for auth plugins) 15 | { protocols = typedefs.protocols_http }, 16 | { config = { 17 | -- The 'config' record is the custom part of the plugin schema 18 | type = "record", 19 | fields = { 20 | { ["tags"] = type_string_array }, 21 | { block_useragents = type_string_array }, 22 | { block_no_useragent = { type = "boolean" } }, 23 | }, 24 | entity_checks = { 25 | -- add some validation rules across fields 26 | }, 27 | }, 28 | }, 29 | }, 30 | } 31 | 32 | return schema 33 | -------------------------------------------------------------------------------- /kong/plugins/ssk-allowkey/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-allowkey" 4 | 5 | 6 | local type_string_array = { 7 | type = "array", 8 | elements = { type = "string" }, 9 | } 10 | 11 | local schema = { 12 | name = PLUGIN_NAME, 13 | fields = { 14 | -- the 'fields' array is the top-level entry with fields defined by Kong 15 | { consumer = typedefs.no_consumer }, -- this plugin cannot be configured on a consumer (typical for auth plugins) 16 | { protocols = typedefs.protocols_http }, 17 | { config = { 18 | -- The 'config' record is the custom part of the plugin schema 19 | type = "record", 20 | fields = { 21 | { ["tags"] = type_string_array }, 22 | { ["query"] = type_string_array }, 23 | { ["body"] = type_string_array }, 24 | { ["cookie"] = type_string_array }, 25 | { ["header"] = type_string_array }, 26 | }, 27 | entity_checks = { 28 | -- add some validation rules across fields 29 | }, 30 | }, 31 | }, 32 | }, 33 | } 34 | 35 | return schema 36 | -------------------------------------------------------------------------------- /kong/plugins/ssk-magika/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-magika" 4 | 5 | local type_string_array = { 6 | type = "array", 7 | elements = { type = "string" }, 8 | } 9 | 10 | local type_param_info = { 11 | type = "record", 12 | fields = { 13 | { ["in"] = { type = "string", default = "param_req_*", }}, 14 | { ["key"] = { type = "string", default = "*", }}, 15 | } 16 | } 17 | local type_param_info_array = { 18 | type = "array", 19 | elements = type_param_info, 20 | } 21 | 22 | local schema = { 23 | name = PLUGIN_NAME, 24 | fields = { 25 | { protocols = typedefs.protocols_http }, 26 | { config = { 27 | type = "record", 28 | fields = { 29 | { ["tags"] = type_string_array }, 30 | { ["allows"] = type_string_array }, 31 | { ["denys"] = type_string_array }, 32 | { ["params"] = type_param_info_array }, 33 | }, 34 | entity_checks = { 35 | }, 36 | }, 37 | }, 38 | }, 39 | } 40 | 41 | return schema 42 | -------------------------------------------------------------------------------- /kong/plugins/ssk-std-logger/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-std-logger" 4 | 5 | local schema = { 6 | name = PLUGIN_NAME, 7 | fields = { 8 | -- the 'fields' array is the top-level entry with fields defined by Kong 9 | { consumer = typedefs.no_consumer }, -- this plugin cannot be configured on a consumer (typical for auth plugins) 10 | { protocols = typedefs.protocols_http }, 11 | { config = { 12 | -- The 'config' record is the custom part of the plugin schema 13 | type = "record", 14 | fields = { 15 | { std = { type = "string", one_of = { "out", "err" }, default = "out" }}, 16 | { header = { type = "string", default = "[ssk-detect]" }}, 17 | { encode = { type = "string", 18 | one_of = { "none", "url", "url_ctrl", "base64", "escape_ctrl" }, default = "none" }}, 19 | }, 20 | entity_checks = { 21 | -- add some validation rules across fields 22 | }, 23 | }, 24 | }, 25 | }, 26 | } 27 | 28 | return schema 29 | -------------------------------------------------------------------------------- /kong/plugins/ssk-safehost/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | local util = require "kong.plugins.ssk-core.lib.utils" 3 | 4 | -- luacheck: no unused 5 | local DETECT_CODE_SAFEHOST_BASE = 300 6 | -- luacheck: unused 7 | local DETECT_CODE_SAFEHOST_NO_HOST = 301 8 | local DETECT_CODE_SAFEHOST_NOT_MATCHED = 302 9 | 10 | local function h( params, config ) 11 | local host_check = config.host_check 12 | local host = util.get_safe(params, "host") 13 | if host == nil then 14 | return { detect_code = DETECT_CODE_SAFEHOST_NO_HOST, tags = config.tags, 15 | details = {["expected"]=host_check}} 16 | end 17 | if host ~= host_check then 18 | return { detect_code = DETECT_CODE_SAFEHOST_NOT_MATCHED, tags = config.tags, 19 | details = {["expected"]=host_check, ["input"]=host}} 20 | end 21 | end 22 | 23 | local _M = core:extend() 24 | 25 | _M.PRIORITY = 100 26 | 27 | function _M:init_handler( config ) 28 | self:add_handler( "req_header", h, config) 29 | end 30 | 31 | 32 | return _M 33 | -------------------------------------------------------------------------------- /specs/ssk-cors-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-cors" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 17 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 18 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 19 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 20 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 21 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 22 | ["kong.plugins.ssk-cors.daos"] = "kong/plugins/ssk-cors/daos.lua", 23 | ["kong.plugins.ssk-cors.handler"] = "kong/plugins/ssk-cors/handler.lua", 24 | ["kong.plugins.ssk-cors.schema"] = "kong/plugins/ssk-cors/schema.lua" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /specs/ssk-allowkey-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-allowkey" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-allowkey.daos"] = "kong/plugins/ssk-allowkey/daos.lua", 15 | ["kong.plugins.ssk-allowkey.handler"] = "kong/plugins/ssk-allowkey/handler.lua", 16 | ["kong.plugins.ssk-allowkey.schema"] = "kong/plugins/ssk-allowkey/schema.lua", 17 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 18 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 19 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 20 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 21 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 22 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 23 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 24 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /specs/ssk-safehost-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-safehost" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 17 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 18 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 19 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 20 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 21 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 22 | ["kong.plugins.ssk-safehost.daos"] = "kong/plugins/ssk-safehost/daos.lua", 23 | ["kong.plugins.ssk-safehost.handler"] = "kong/plugins/ssk-safehost/handler.lua", 24 | ["kong.plugins.ssk-safehost.schema"] = "kong/plugins/ssk-safehost/schema.lua" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /specs/ssk-telemetry-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-telemetry" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 17 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 18 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 19 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 20 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 21 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 22 | ["kong.plugins.ssk-telemetry.daos"] = "kong/plugins/ssk-telemetry/daos.lua", 23 | ["kong.plugins.ssk-telemetry.handler"] = "kong/plugins/ssk-telemetry/handler.lua", 24 | ["kong.plugins.ssk-telemetry.schema"] = "kong/plugins/ssk-telemetry/schema.lua" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /specs/ssk-ua-filter-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-ua-filter" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 17 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 18 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 19 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 20 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 21 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 22 | ["kong.plugins.ssk-ua-filter.daos"] = "kong/plugins/ssk-ua-filter/daos.lua", 23 | ["kong.plugins.ssk-ua-filter.handler"] = "kong/plugins/ssk-ua-filter/handler.lua", 24 | ["kong.plugins.ssk-ua-filter.schema"] = "kong/plugins/ssk-ua-filter/schema.lua" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /specs/ssk-std-logger-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-std-logger" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 17 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 18 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 19 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 20 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 21 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 22 | ["kong.plugins.ssk-std-logger.daos"] = "kong/plugins/ssk-std-logger/daos.lua", 23 | ["kong.plugins.ssk-std-logger.handler"] = "kong/plugins/ssk-std-logger/handler.lua", 24 | ["kong.plugins.ssk-std-logger.schema"] = "kong/plugins/ssk-std-logger/schema.lua" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /specs/ssk-clickjacking-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-clickjacking" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-clickjacking.daos"] = "kong/plugins/ssk-clickjacking/daos.lua", 15 | ["kong.plugins.ssk-clickjacking.handler"] = "kong/plugins/ssk-clickjacking/handler.lua", 16 | ["kong.plugins.ssk-clickjacking.schema"] = "kong/plugins/ssk-clickjacking/schema.lua", 17 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 18 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 19 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 20 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 21 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 22 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 23 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 24 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /specs/ssk-saferedirect-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-saferedirect" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 17 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 18 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 19 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 20 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 21 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 22 | ["kong.plugins.ssk-saferedirect.daos"] = "kong/plugins/ssk-saferedirect/daos.lua", 23 | ["kong.plugins.ssk-saferedirect.handler"] = "kong/plugins/ssk-saferedirect/handler.lua", 24 | ["kong.plugins.ssk-saferedirect.schema"] = "kong/plugins/ssk-saferedirect/schema.lua" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /specs/ssk-pm-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-pm" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 17 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 18 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 19 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 20 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 21 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 22 | ["kong.plugins.ssk-pm.daos"] = "kong/plugins/ssk-pm/daos.lua", 23 | ["kong.plugins.ssk-pm.handler"] = "kong/plugins/ssk-pm/handler.lua", 24 | ["kong.plugins.ssk-pm.patternmatcher"] = "kong/plugins/ssk-pm/patternmatcher.lua", 25 | ["kong.plugins.ssk-pm.schema"] = "kong/plugins/ssk-pm/schema.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /specs/ssk-detecthandling-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-detecthandling" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 17 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 18 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 19 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 20 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 21 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 22 | ["kong.plugins.ssk-detecthandling.daos"] = "kong/plugins/ssk-detecthandling/daos.lua", 23 | ["kong.plugins.ssk-detecthandling.handler"] = "kong/plugins/ssk-detecthandling/handler.lua", 24 | ["kong.plugins.ssk-detecthandling.schema"] = "kong/plugins/ssk-detecthandling/schema.lua" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /specs/ssk-strictparameter-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-strictparameter" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 17 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 18 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 19 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 20 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 21 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 22 | ["kong.plugins.ssk-strictparameter.daos"] = "kong/plugins/ssk-strictparameter/daos.lua", 23 | ["kong.plugins.ssk-strictparameter.handler"] = "kong/plugins/ssk-strictparameter/handler.lua", 24 | ["kong.plugins.ssk-strictparameter.schema"] = "kong/plugins/ssk-strictparameter/schema.lua" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /specs/ssk-cors-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-cors" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 17 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 18 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 19 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 20 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 21 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 22 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 23 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 24 | ["kong.plugins.ssk-cors.handler"] = "kong/plugins/ssk-cors/handler.lua", 25 | ["kong.plugins.ssk-cors.schema"] = "kong/plugins/ssk-cors/schema.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /specs/ssk-magika-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-magika" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 17 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 18 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 19 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 20 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 21 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 22 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 23 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 24 | ["kong.plugins.ssk-magika.handler"] = "kong/plugins/ssk-magika/handler.lua", 25 | ["kong.plugins.ssk-magika.schema"] = "kong/plugins/ssk-magika/schema.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /kong/plugins/ssk-saferedirect/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-saferedirect" 4 | 5 | local type_string_array = { 6 | type = "array", 7 | elements = { type = "string" } 8 | } 9 | 10 | local type_param_info = { 11 | type = "record", 12 | fields = { 13 | { ["in"] = { type = "string", default = "param_req_*", }}, 14 | { key = { type = "string", default = "*", }}, 15 | { prefix = { type = "string" }}, 16 | } 17 | } 18 | local type_param_info_array = { 19 | type = "array", 20 | elements = type_param_info, 21 | } 22 | 23 | local schema = { 24 | name = PLUGIN_NAME, 25 | fields = { 26 | -- the 'fields' array is the top-level entry with fields defined by Kong 27 | { consumer = typedefs.no_consumer }, -- this plugin cannot be configured on a consumer (typical for auth plugins) 28 | { protocols = typedefs.protocols_http }, 29 | { config = { 30 | -- The 'config' record is the custom part of the plugin schema 31 | type = "record", 32 | fields = { 33 | { ["tags"] = type_string_array }, 34 | { params = type_param_info_array }, 35 | }, 36 | entity_checks = { 37 | -- add some validation rules across fields 38 | }, 39 | }, 40 | }, 41 | }, 42 | } 43 | 44 | return schema 45 | -------------------------------------------------------------------------------- /kong/plugins/ssk-cors/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-cors" 4 | local type_string = { type = "string" } 5 | local type_string_array = { 6 | type = "array", 7 | elements = type_string 8 | } 9 | 10 | local schema = { 11 | name = PLUGIN_NAME, 12 | fields = { 13 | -- the 'fields' array is the top-level entry with fields defined by Kong 14 | { consumer = typedefs.no_consumer }, -- this plugin cannot be configured on a consumer (typical for auth plugins) 15 | { protocols = typedefs.protocols_http }, 16 | { config = { 17 | -- The 'config' record is the custom part of the plugin schema 18 | type = "record", 19 | fields = { 20 | { ["tags"] = type_string_array }, 21 | { block = {type = "boolean"}}, 22 | { modify_response_header = {type = "boolean"}}, 23 | { allow_origins = type_string_array }, 24 | { allow_methods = type_string_array }, 25 | { allow_headers = type_string_array }, 26 | { expose_headers = type_string_array }, 27 | { allow_credentials = {type = "boolean"}}, 28 | { max_age = {type = "integer"}}, 29 | }, 30 | entity_checks = { 31 | -- add some validation rules across fields 32 | }, 33 | }, 34 | }, 35 | }, 36 | } 37 | 38 | return schema 39 | -------------------------------------------------------------------------------- /specs/ssk-safehost-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-safehost" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 17 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 18 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 19 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 20 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 21 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 22 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 23 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 24 | ["kong.plugins.ssk-safehost.handler"] = "kong/plugins/ssk-safehost/handler.lua", 25 | ["kong.plugins.ssk-safehost.schema"] = "kong/plugins/ssk-safehost/schema.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /specs/ssk-telemetry-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-telemetry" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 17 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 18 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 19 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 20 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 21 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 22 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 23 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 24 | ["kong.plugins.ssk-telemetry.handler"] = "kong/plugins/ssk-telemetry/handler.lua", 25 | ["kong.plugins.ssk-telemetry.schema"] = "kong/plugins/ssk-telemetry/schema.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /specs/ssk-ua-filter-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-ua-filter" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 17 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 18 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 19 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 20 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 21 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 22 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 23 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 24 | ["kong.plugins.ssk-ua-filter.handler"] = "kong/plugins/ssk-ua-filter/handler.lua", 25 | ["kong.plugins.ssk-ua-filter.schema"] = "kong/plugins/ssk-ua-filter/schema.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /specs/ssk-std-logger-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-std-logger" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 17 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 18 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 19 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 20 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 21 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 22 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 23 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 24 | ["kong.plugins.ssk-std-logger.handler"] = "kong/plugins/ssk-std-logger/handler.lua", 25 | ["kong.plugins.ssk-std-logger.schema"] = "kong/plugins/ssk-std-logger/schema.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /specs/ssk-clickjacking-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-clickjacking" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-clickjacking.handler"] = "kong/plugins/ssk-clickjacking/handler.lua", 15 | ["kong.plugins.ssk-clickjacking.schema"] = "kong/plugins/ssk-clickjacking/schema.lua", 16 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 17 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 18 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 19 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 20 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 21 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 22 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 23 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 24 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 25 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /specs/ssk-saferedirect-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-saferedirect" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 17 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 18 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 19 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 20 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 21 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 22 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 23 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 24 | ["kong.plugins.ssk-saferedirect.handler"] = "kong/plugins/ssk-saferedirect/handler.lua", 25 | ["kong.plugins.ssk-saferedirect.schema"] = "kong/plugins/ssk-saferedirect/schema.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /specs/ssk-detecthandling-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-detecthandling" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 17 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 18 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 19 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 20 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 21 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 22 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 23 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 24 | ["kong.plugins.ssk-detecthandling.handler"] = "kong/plugins/ssk-detecthandling/handler.lua", 25 | ["kong.plugins.ssk-detecthandling.schema"] = "kong/plugins/ssk-detecthandling/schema.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /specs/ssk-strictparameter-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-strictparameter" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 17 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 18 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 19 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 20 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 21 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 22 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 23 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 24 | ["kong.plugins.ssk-strictparameter.handler"] = "kong/plugins/ssk-strictparameter/handler.lua", 25 | ["kong.plugins.ssk-strictparameter.schema"] = "kong/plugins/ssk-strictparameter/schema.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /kong/plugins/ssk-ua-filter/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | local util = require "kong.plugins.ssk-core.lib.utils" 3 | local matcher = require "kong.plugins.ssk-core.lib.matcher" 4 | 5 | -- luacheck: no unused 6 | local DETECT_CODE_USERAGENT_BASE = 700 7 | -- luacheck: unused 8 | local DETECT_CODE_USERAGENT_NO_UA = 701 9 | local DETECT_CODE_USERAGENT_UA_MATCHED = 702 10 | 11 | local function match( ua, config, key ) 12 | for _, pat in ipairs( util.get_safe_d({}, config, key) ) do 13 | local a, _ = matcher.match(ua, pat, 1 ) 14 | if a then return true end 15 | end 16 | return false 17 | end 18 | 19 | local function h( params, config ) 20 | local ua = util.get_safe( params, "user-agent" ) 21 | 22 | if type(ua) ~= "string" then 23 | if util.get_safe( config, "block_no_useragent" ) then 24 | return { detect_code = DETECT_CODE_USERAGENT_NO_UA, tags = config.tags } 25 | end 26 | return -- ignore useragent 27 | end 28 | if match( ua, config, "block_useragents" ) then 29 | return { detect_code = DETECT_CODE_USERAGENT_UA_MATCHED, tags = config.tags, 30 | details = { ["ua"]=ua } } 31 | end 32 | end 33 | 34 | local _M = core:extend() 35 | 36 | function _M:init_handler( config ) 37 | self:add_handler( "req_header", h, config) 38 | end 39 | 40 | 41 | return _M 42 | -------------------------------------------------------------------------------- /specs/ssk-pm-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-pm" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 17 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 18 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 19 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 20 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 21 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 22 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 23 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 24 | ["kong.plugins.ssk-pm.handler"] = "kong/plugins/ssk-pm/handler.lua", 25 | ["kong.plugins.ssk-pm.patternmatcher"] = "kong/plugins/ssk-pm/patternmatcher.lua", 26 | ["kong.plugins.ssk-pm.schema"] = "kong/plugins/ssk-pm/schema.lua" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /specs/ssk-libinjection-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-libinjection" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 17 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 18 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 19 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 20 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 21 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 22 | ["kong.plugins.ssk-libinjection.daos"] = "kong/plugins/ssk-libinjection/daos.lua", 23 | ["kong.plugins.ssk-libinjection.handler"] = "kong/plugins/ssk-libinjection/handler.lua", 24 | ["kong.plugins.ssk-libinjection.libinjection"] = "kong/plugins/ssk-libinjection/libinjection.lua", 25 | ["kong.plugins.ssk-libinjection.schema"] = "kong/plugins/ssk-libinjection/schema.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /kong/plugins/ssk-libinjection/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-libinjection" 4 | 5 | local type_tag_array = { 6 | type = "array", 7 | elements = { type = "string" } 8 | } 9 | 10 | local type_param_info = { 11 | type = "record", 12 | fields = { 13 | { ["in"] = { type = "string", default = "param_req_*", }}, 14 | { key = { type = "string", default = "*", }}, 15 | { sql = { type = "boolean", default = true, }}, 16 | { xss = { type = "boolean", default = true, }}, 17 | } 18 | } 19 | local type_param_info_array = { 20 | type = "array", 21 | elements = type_param_info, 22 | } 23 | 24 | local schema = { 25 | name = PLUGIN_NAME, 26 | fields = { 27 | -- the 'fields' array is the top-level entry with fields defined by Kong 28 | { consumer = typedefs.no_consumer }, -- this plugin cannot be configured on a consumer (typical for auth plugins) 29 | { protocols = typedefs.protocols_http }, 30 | { config = { 31 | -- The 'config' record is the custom part of the plugin schema 32 | type = "record", 33 | fields = { 34 | { tags = type_tag_array }, 35 | { params = type_param_info_array }, 36 | }, 37 | entity_checks = { 38 | -- add some validation rules across fields 39 | }, 40 | }, 41 | }, 42 | }, 43 | } 44 | 45 | return schema 46 | -------------------------------------------------------------------------------- /specs/ssk-allowkey-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-allowkey" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-allowkey.daos"] = "kong/plugins/ssk-allowkey/daos.lua", 15 | ["kong.plugins.ssk-allowkey.handler"] = "kong/plugins/ssk-allowkey/handler.lua", 16 | ["kong.plugins.ssk-allowkey.schema"] = "kong/plugins/ssk-allowkey/schema.lua", 17 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 18 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 19 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 20 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 21 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 22 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 23 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 24 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 25 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 26 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /kong/plugins/ssk-core/lib/matcher.lua: -------------------------------------------------------------------------------- 1 | local util = require "kong.plugins.ssk-core.lib.utils" 2 | 3 | local MODE_RE = 1 4 | local MODE_PCRE2 = 2 5 | local mode = MODE_RE 6 | 7 | 8 | local function check_pcre() 9 | if util.check_module( 'rex_pcre2' ) then 10 | mode = MODE_PCRE2 11 | end 12 | end 13 | 14 | check_pcre() 15 | 16 | local function validate( p ) 17 | local _, _, err = ngx.re.find( "s", p, "jo" ) 18 | if err then 19 | kong.log.err( "pattern validate fail : ", err ) 20 | return false 21 | end 22 | return true 23 | end 24 | 25 | local function build( p ) 26 | if mode == MODE_PCRE2 then 27 | if not validate( p ) then 28 | return p 29 | end 30 | 31 | local rp = require ('rex_pcre2') 32 | local userdata = rp.new( p ) 33 | return userdata 34 | else 35 | return p 36 | end 37 | end 38 | 39 | local function match( subj, p, from, cf) 40 | if mode == MODE_PCRE2 then 41 | local rp = require ('rex_pcre2') 42 | local from, to = rp.find (subj, p, from, cf ) 43 | return from, to 44 | else 45 | local from, to, err = ngx.re.find( subj, p, "jo" ) 46 | if err then kong.log.err( err ) end 47 | return from, to 48 | end 49 | end 50 | 51 | return { 52 | match = match, 53 | build = build, 54 | } 55 | -------------------------------------------------------------------------------- /specs/ssk-libinjection-2.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "ssk-libinjection" 2 | version = "2.0.0-1" 3 | source = { 4 | url = "https://github.com/cybersecuritycloud/sasanka.git" 5 | } 6 | description = { 7 | summary = "Kong plugins for API security developed by CyberSecurityCloud", 8 | homepage = "https:///www.cscloud.co.jp/", 9 | license = "Apache2.0" 10 | } 11 | build = { 12 | type = "builtin", 13 | modules = { 14 | ["kong.plugins.ssk-core.common"] = "kong/plugins/ssk-core/common.lua", 15 | ["kong.plugins.ssk-core.core"] = "kong/plugins/ssk-core/core.lua", 16 | ["kong.plugins.ssk-core.decoder"] = "kong/plugins/ssk-core/decoder.lua", 17 | ["kong.plugins.ssk-core.lib.matcher"] = "kong/plugins/ssk-core/lib/matcher.lua", 18 | ["kong.plugins.ssk-core.lib.ssk"] = "kong/plugins/ssk-core/lib/ssk.lua", 19 | ["kong.plugins.ssk-core.lib.utils"] = "kong/plugins/ssk-core/lib/utils.lua", 20 | ["kong.plugins.ssk-core.params"] = "kong/plugins/ssk-core/params.lua", 21 | ["kong.plugins.ssk-core.request"] = "kong/plugins/ssk-core/request.lua", 22 | ["kong.plugins.ssk-core.response"] = "kong/plugins/ssk-core/response.lua", 23 | ["kong.plugins.ssk-core.response_body"] = "kong/plugins/ssk-core/response_body.lua", 24 | ["kong.plugins.ssk-libinjection.handler"] = "kong/plugins/ssk-libinjection/handler.lua", 25 | ["kong.plugins.ssk-libinjection.libinjection"] = "kong/plugins/ssk-libinjection/libinjection.lua", 26 | ["kong.plugins.ssk-libinjection.schema"] = "kong/plugins/ssk-libinjection/schema.lua" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /kong/plugins/ssk-strictparameter/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-strictparameter" 4 | 5 | local type_string_array = { 6 | type = "array", 7 | elements = { type = "string" }, 8 | } 9 | 10 | local type_param_info = { 11 | type = "record", 12 | fields = { 13 | { ["in"] = { type = "string", default = "param_req_*", }}, 14 | { key = { type = "string", default = "*", }}, 15 | { ["type"] = { type = "string" }}, 16 | { pattern = { type = "string" }}, 17 | { required = { type = "boolean" }}, 18 | { min = { type = "integer" }}, 19 | { max = { type = "integer" }}, 20 | 21 | } 22 | } 23 | local type_param_info_array = { 24 | type = "array", 25 | elements = type_param_info, 26 | } 27 | 28 | local schema = { 29 | name = PLUGIN_NAME, 30 | fields = { 31 | -- the 'fields' array is the top-level entry with fields defined by Kong 32 | { consumer = typedefs.no_consumer }, -- this plugin cannot be configured on a consumer (typical for auth plugins) 33 | { protocols = typedefs.protocols_http }, 34 | { config = { 35 | -- The 'config' record is the custom part of the plugin schema 36 | type = "record", 37 | fields = { 38 | { ["tags"] = type_string_array }, 39 | { params = type_param_info_array }, 40 | }, 41 | entity_checks = { 42 | -- add some validation rules across fields 43 | }, 44 | }, 45 | }, 46 | }, 47 | } 48 | 49 | return schema 50 | -------------------------------------------------------------------------------- /kong/plugins/ssk-detecthandling/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-detecthandling" 4 | 5 | local type_header = { 6 | type = "record", 7 | fields = { 8 | { key = { type = "string", required = true }}, 9 | { value = { type = "string", required = true }}, 10 | } 11 | } 12 | 13 | local type_header_array = { 14 | type = "array", 15 | elements = type_header, 16 | } 17 | 18 | local type_filter = { 19 | type = "record", 20 | fields = { 21 | { default = { type = "boolean" }}, 22 | { tag = { type = "string" }}, 23 | { status = { type = "number" }}, 24 | { headers = type_header_array }, 25 | { body = { type = "string" }}, 26 | { delay = { type = "number", default = 0, between = {0, 60} }}, 27 | } 28 | } 29 | 30 | local type_filter_array = { 31 | type = "array", 32 | elements = type_filter, 33 | } 34 | 35 | local schema = { 36 | name = PLUGIN_NAME, 37 | fields = { 38 | -- the 'fields' array is the top-level entry with fields defined by Kong 39 | { consumer = typedefs.no_consumer }, -- this plugin cannot be configured on a consumer (typical for auth plugins) 40 | { protocols = typedefs.protocols_http }, 41 | { config = { 42 | -- The 'config' record is the custom part of the plugin schema 43 | type = "record", 44 | fields = { 45 | { filters = type_filter_array }, 46 | }, 47 | entity_checks = { 48 | -- add some validation rules across fields 49 | }, 50 | }, 51 | }, 52 | }, 53 | } 54 | 55 | return schema 56 | -------------------------------------------------------------------------------- /kong/plugins/ssk-pm/patternmatcher.lua: -------------------------------------------------------------------------------- 1 | local matcher = require "kong.plugins.ssk-core.lib.matcher" 2 | 3 | local function build( patt ) 4 | return matcher.build( patt ) 5 | end 6 | 7 | -- for all match 8 | -- rp.gmatch (subj, patt) 9 | 10 | -- for single find 11 | -- rp.find(subj, patt) 12 | 13 | 14 | 15 | local function detect_tbl( subj, patt_tbl, ignorecase ) 16 | if patt_tbl == nil then 17 | return nil, nil 18 | end 19 | 20 | -- for lua5.2 21 | -- local ft = rp.flags() 22 | -- ft["CASELESS"] = 8 23 | local cf = 0 24 | if ignorecase then 25 | cf = 8 26 | end 27 | 28 | for i=1, #patt_tbl do 29 | local a, b = matcher.match( subj, patt_tbl[i], 1, cf) 30 | if a ~= nil then 31 | return a, b 32 | end 33 | end 34 | 35 | return nil, nil 36 | end 37 | 38 | local function append_patterns(patterns) 39 | local appended = "" 40 | for i = 1, #patterns do 41 | appended = appended .. "(" .. patterns[i] .. ")" 42 | if i ~= #patterns then 43 | appended = appended .. "|" 44 | end 45 | end 46 | return appended 47 | end 48 | 49 | 50 | local function optimize(patterns, opt) 51 | local out = {} 52 | local buffer = {} 53 | for i = 1, #patterns do 54 | table.insert( buffer, patterns[i] ) 55 | 56 | if #buffer % opt == 0 then 57 | table.insert( out, build( append_patterns(buffer)) ) 58 | buffer = {} 59 | end 60 | end 61 | if #buffer ~= 0 then 62 | table.insert( out, build( append_patterns(buffer)) ) 63 | end 64 | return out 65 | end 66 | 67 | return { 68 | optimize = optimize, 69 | append_patterns = append_patterns, 70 | detect = nil, 71 | detect_tbl = detect_tbl, 72 | } 73 | -------------------------------------------------------------------------------- /kong/plugins/ssk-core/lib/ssk.lua: -------------------------------------------------------------------------------- 1 | local util = require "kong.plugins.ssk-core.lib.utils" 2 | 3 | -- kong.request.get_path 4 | --- on kong 2.0: unnormalized path 5 | --- on kong 3.0: normalized path 6 | local function get_raw_path() 7 | if kong.request.get_raw_path then 8 | -- on kong3.0 9 | return kong.request.get_raw_path() 10 | else 11 | -- on kong2.0 12 | return kong.request.get_path() 13 | end 14 | end 15 | 16 | -- on kong, ngx: get_query will return value which url decoded once 17 | local function get_query() 18 | local q = kong.request.get_raw_query() 19 | return util.parse_urlencoded_kv( q ) 20 | end 21 | 22 | 23 | local function get_ip_bin() 24 | local ip_bin = ngx.var.binary_remote_addr 25 | if kong.ctx.shared.cap.ip_bin then 26 | ip_bin = kong.ctx.shared.cap.ip_bin 27 | end 28 | return ip_bin 29 | end 30 | 31 | local function get_ip() 32 | local ip = ngx.var.remote_addr 33 | if kong.ctx.shared.cap.ip then 34 | ip = kong.ctx.shared.cap.ip 35 | end 36 | return ip 37 | end 38 | 39 | local function get_id() 40 | return get_ip_bin() 41 | end 42 | 43 | -- plugin_ctx 44 | -- in case of optimization, use shared.ctx 45 | local function get_ctx( key ) 46 | if kong.ctx.shared.cap.optimize then 47 | if kong.ctx.shared.cap.plugin[key] == nil then 48 | kong.ctx.shared.cap.plugin[key] = {} 49 | end 50 | return kong.ctx.shared.cap.plugin[key] 51 | else 52 | return kong.ctx.plugin 53 | end 54 | end 55 | 56 | -- shared_ctx 57 | local function get_shared_ctx() 58 | return kong.ctx.shared.cap 59 | end 60 | 61 | return { 62 | get_raw_path = get_raw_path, 63 | get_query = get_query, 64 | get_ip = get_ip, 65 | get_ip_bin = get_ip_bin, 66 | get_id = get_id, 67 | get_ctx = get_ctx, 68 | get_shared_ctx = get_shared_ctx, 69 | } 70 | -------------------------------------------------------------------------------- /kong/plugins/ssk-core/response_body.lua: -------------------------------------------------------------------------------- 1 | local zlib = require "zlib" 2 | 3 | local function get_body_part() 4 | if kong.ctx.shared.cap.body_part then 5 | return kong.ctx.shared.cap.body_part 6 | end 7 | 8 | -- set body_part 9 | local enc = kong.response.get_header("content_encoding") 10 | if enc == nil or string.find(enc, "gzip") == nil then 11 | kong.ctx.shared.cap.body_part = ngx.arg[1] 12 | return kong.ctx.shared.cap.body_part 13 | end 14 | 15 | -- gzip 16 | if kong.ctx.shared.cap.inflate == nil then 17 | kong.ctx.shared.cap.inflate = zlib.inflate() 18 | end 19 | 20 | local decompressed, _, _, _ = kong.ctx.shared.cap.inflate(ngx.arg[1]) 21 | kong.ctx.shared.cap.body_part = decompressed 22 | return kong.ctx.shared.cap.body_part 23 | end 24 | 25 | local function set_body_part( in_body ) 26 | kong.ctx.shared.cap.body_part = in_body 27 | end 28 | 29 | local function get_deflated_body_part() 30 | if kong.ctx.shared.cap.body_part == nil then 31 | kong.ctx.shared.cap.body_part = get_body_part() 32 | end 33 | local opt = nil 34 | if ngx.arg[2] then 35 | opt = "finish" 36 | end 37 | local compressed, _, _, len_out = kong.ctx.shared.cap.deflate( kong.ctx.shared.cap.body_part , opt) 38 | 39 | return compressed, len_out 40 | end 41 | 42 | local function get_encoded_body() 43 | -- gzip 44 | if kong.ctx.shared.cap.deflate then 45 | return get_deflated_body_part() 46 | end 47 | 48 | -- normal 49 | local enc = kong.response.get_header("content_encoding") 50 | if enc == nil or string.find(enc, "gzip") == nil then 51 | return get_body_part(), #get_body_part() 52 | end 53 | 54 | -- gzip 55 | 56 | kong.ctx.shared.cap.deflate = zlib.deflate(6,31) 57 | return get_deflated_body_part() 58 | 59 | end 60 | 61 | 62 | return { 63 | get_body_part = get_body_part, 64 | set_body_part = set_body_part, 65 | get_encoded_body = get_encoded_body, 66 | } 67 | -------------------------------------------------------------------------------- /kong/plugins/ssk-allowkey/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | local util = require "kong.plugins.ssk-core.lib.utils" 3 | 4 | -- luacheck: no unused 5 | local DETECT_CODE_ALLOWKEY_BASE = 2500 6 | -- luacheck: unused 7 | local DETECT_CODE_ALLOWKEY_NOT_ALLOWED = 2501 8 | 9 | local function h( _, k, _, _, allowed, tags ) 10 | if not allowed[k] then 11 | return { detect_code = DETECT_CODE_ALLOWKEY_NOT_ALLOWED, tags = tags, 12 | details = { ["input"]=k } } 13 | end 14 | end 15 | 16 | 17 | local function listtodict( l ) 18 | local d = {} 19 | for _, v in ipairs(l) do 20 | d[v] = true 21 | end 22 | return d 23 | end 24 | 25 | 26 | local function initialize( config ) 27 | if config.inited then 28 | return 29 | end 30 | 31 | config.inited = true 32 | config.dict = {} 33 | 34 | if util.get_safe_d( false, config, "query" ) then 35 | config.dict.query = listtodict( config.query ) 36 | end 37 | if util.get_safe_d( false, config, "cookie" ) then 38 | config.dict.cookie = listtodict( config.cookie ) 39 | end 40 | if util.get_safe_d( false, config, "header" ) then 41 | config.dict.header = listtodict( config.header ) 42 | end 43 | if util.get_safe_d( false, config, "body" ) then 44 | config.dict.body = listtodict( config.body ) 45 | end 46 | end 47 | 48 | 49 | local _M = core:extend() 50 | 51 | function _M:init_handler( config ) 52 | initialize(config) 53 | 54 | if config.dict.query then 55 | self:add_param_handler( "param_req_query", config, h, config.dict.query, config.tags ) 56 | end 57 | if config.dict.cookie then 58 | self:add_param_handler( "param_req_cookie", config, h, config.dict.cookie, config.tags ) 59 | end 60 | if config.dict.header then 61 | self:add_param_handler( "param_req_header", config, h, config.dict.header, config.tags ) 62 | end 63 | if config.dict.body then 64 | self:add_param_handler( "param_req_body", config, h, config.dict.body, config.tags ) 65 | end 66 | 67 | end 68 | 69 | 70 | return _M 71 | -------------------------------------------------------------------------------- /kong/plugins/ssk-saferedirect/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | 3 | -- luacheck: no unused 4 | local DETECT_CODE_SAFEREDIRECT_BASE = 1500 5 | -- luacheck: unused 6 | local DETECT_CODE_SAFEREDIRECT_NOT_MATCHED = 1501 7 | 8 | local function make_dict_by_in( params ) 9 | local ret = {} 10 | if params then 11 | for i = 1, #params do 12 | local cat = params[i]["in"] 13 | if cat then 14 | if not ret[cat] then 15 | ret[cat] = {} 16 | end 17 | table.insert( ret[cat], params[i] ) 18 | end 19 | end 20 | end 21 | 22 | return ret 23 | end 24 | 25 | local function initialize(config) 26 | if config["params_in"] then return end 27 | 28 | config["params_in"] = make_dict_by_in( config["params"] ) 29 | end 30 | 31 | -- luacheck: no unused args 32 | local function h( _, k, v, v_list, params, tags, ...) 33 | -- luacheck: unused args 34 | for i = 1, #params do 35 | if params[i]["key"] == k then 36 | -- check if one of v_list matched at least 37 | local found = false; 38 | for ii = 1, #v_list do 39 | local v_decoded = v_list[ii] 40 | local v_shorted = string.sub( v_decoded, 1, #params[i]["prefix"] ) 41 | if v_shorted == params[i]["prefix"] then 42 | found = true; 43 | end 44 | end 45 | if not found then 46 | return { detect_code = DETECT_CODE_SAFEREDIRECT_NOT_MATCHED, tags = tags, 47 | details = { ["key"]=k, ["value"]=v, ["expected"]=params[i]["prefix"] } } 48 | end 49 | end 50 | end 51 | end 52 | 53 | local _M = core:extend() 54 | 55 | function _M:init_handler( config ) 56 | initialize(config) 57 | 58 | for cat, params in pairs( config["params_in"] ) do 59 | self:add_param_handler( cat, config, h, params, config.tags ) 60 | end 61 | end 62 | 63 | 64 | return _M 65 | -------------------------------------------------------------------------------- /kong/plugins/ssk-pm/schema.lua: -------------------------------------------------------------------------------- 1 | local typedefs = require "kong.db.schema.typedefs" 2 | 3 | local PLUGIN_NAME = "ssk-pm" 4 | 5 | local type_pattern = { type = "string" } 6 | local type_pattern_name = { type = "string" } 7 | 8 | local type_pattern_name_array = { 9 | type = "array", 10 | elements = type_pattern_name 11 | } 12 | 13 | local type_string_array = { 14 | type = "array", 15 | elements = { type = "string" }, 16 | } 17 | 18 | local type_pattern_array = { 19 | type = "array", 20 | elements = type_pattern 21 | } 22 | 23 | local type_customize_info = { 24 | type = "record", 25 | fields = { 26 | { ["in"] = type_string_array }, 27 | { ["key"] = type_string_array }, 28 | { ["tags"] = type_string_array }, 29 | } 30 | } 31 | 32 | local type_pattern_info = { 33 | type = "record", 34 | fields = { 35 | { name = { type = "string" }}, 36 | { patterns = type_pattern_array }, 37 | { ["in"] = type_string_array }, 38 | { ["key"] = type_string_array }, 39 | { ["tags"] = type_string_array }, 40 | } 41 | } 42 | 43 | local type_pattern_info_array = { 44 | type = "array", 45 | elements = type_pattern_info, 46 | } 47 | 48 | local type_param_info = { 49 | type = "record", 50 | fields = { 51 | { ["in"] = { type = "string" }}, -- deprecated 52 | { key = { type = "string" }}, -- deprecated 53 | { ["patterns"] = type_pattern_name_array }, 54 | { ["customize"] = type_customize_info }, 55 | } 56 | } 57 | local type_param_info_array = { 58 | type = "array", 59 | elements = type_param_info, 60 | } 61 | 62 | local schema = { 63 | name = PLUGIN_NAME, 64 | fields = { 65 | -- the 'fields' array is the top-level entry with fields defined by Kong 66 | { consumer = typedefs.no_consumer }, -- this plugin cannot be configured on a consumer (typical for auth plugins) 67 | { protocols = typedefs.protocols_http }, 68 | { config = { 69 | -- The 'config' record is the custom part of the plugin schema 70 | type = "record", 71 | fields = { 72 | { patterns = type_pattern_info_array }, 73 | { params = type_param_info_array }, 74 | }, 75 | entity_checks = { 76 | -- add some validation rules across fields 77 | }, 78 | }, 79 | }, 80 | }, 81 | } 82 | 83 | return schema 84 | -------------------------------------------------------------------------------- /kong/plugins/ssk-detecthandling/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | local util = require "kong.plugins.ssk-core.lib.utils" 3 | 4 | local function h( detect_info, config ) 5 | -- Do not try to exit on phase RES 6 | -- 512 == header_filter 7 | -- 1024 == body_filter 8 | 9 | if ngx.ctx.KONG_PHASE >= 512 then 10 | return 11 | end 12 | 13 | local filter = config.default_filter 14 | 15 | if util.get_safe_d( false, detect_info, "tags" ) then 16 | for i = 1, #detect_info["tags"] do 17 | local found = util.get_safe_d( nil, config.filters_tbl, detect_info["tags"][i] ) 18 | if found ~= nil then 19 | filter = found 20 | break 21 | end 22 | end 23 | end 24 | 25 | 26 | local ondetect_status = util.get_safe_d( nil, filter, "status" ) 27 | local ondetect_headers = util.get_safe_d( {}, filter, "headers_tbl" ) 28 | local ondetect_body = util.get_safe_d( "", filter, "body" ) 29 | local ondetect_delay = util.get_safe_d( 0, filter, "delay" ) 30 | 31 | return ondetect_status, ondetect_body, ondetect_headers, ondetect_delay 32 | end 33 | 34 | local function optimize_filter( filter ) 35 | filter.headers_tbl = {} 36 | if filter.headers then 37 | for i = 1, #filter.headers do 38 | if filter.headers[i].key and filter.headers[i].value then 39 | filter.headers_tbl[ filter.headers[i].key ] = filter.headers[i].value 40 | end 41 | end 42 | end 43 | 44 | end 45 | 46 | local function optimize(config) 47 | if config.optimized then return true end 48 | 49 | config.filters_tbl = {} 50 | config.default_filter = nil 51 | if config.filters then 52 | for i = 1, #config.filters do 53 | config.filters_tbl[ config.filters[i].tag ] = config.filters[i] 54 | optimize_filter( config.filters[i] ) 55 | if config.default_filter == nil then 56 | config.default_filter = config.filters[i] 57 | end 58 | if config.filters[i].default then 59 | config.default_filter = config.filters[i] 60 | end 61 | end 62 | end 63 | 64 | config.optimized = true 65 | end 66 | 67 | local _M = core:extend() 68 | 69 | _M.PRIORITY = 100 + 2 70 | 71 | function _M:init_handler( config ) 72 | optimize(config) 73 | self:add_global_handler( "ondetect", h, config) 74 | end 75 | 76 | 77 | return _M 78 | -------------------------------------------------------------------------------- /kong/plugins/ssk-core/lib/utils.lua: -------------------------------------------------------------------------------- 1 | local function check_module( k ) 2 | if package.loaded[k] then 3 | return true 4 | else 5 | for _, loader in ipairs(package.loaders) do 6 | local f = loader( k ) 7 | if type(f) == "function" then 8 | package.preload[k] = f 9 | return true 10 | end 11 | end 12 | return false 13 | end 14 | end 15 | 16 | local function get_safe( tbl, ... ) 17 | local ret = tbl 18 | local arg = {...} 19 | for i,v in ipairs(arg) do 20 | if ret == nil or v == nil then return nil end 21 | ret = ret[v] 22 | end 23 | return ret 24 | end 25 | 26 | local function get_safe_d( default, tbl, ... ) 27 | local ret = tbl 28 | local arg = {...} 29 | for i,v in ipairs(arg) do 30 | if ret == nil or v == nil then return default end 31 | ret = ret[v] 32 | end 33 | if ret == nil then return default end 34 | return ret 35 | end 36 | 37 | local function keys( tbl ) 38 | local i = 0 39 | local ret = {} 40 | for k,v in pairs(tbl) do 41 | i = i + 1 42 | ret[i] = k 43 | end 44 | return ret 45 | end 46 | 47 | local function merge(tbl_l, tbl_r) 48 | for k, v in pairs(tbl_r) do 49 | if tbl_l[k] == nil then 50 | tbl_l[k] = tbl_r[k] 51 | else 52 | if type(tbl_l[k])=="table" then 53 | merge(tbl_l[k], tbl_r[k]) 54 | end 55 | end 56 | end 57 | return tbl_l 58 | end 59 | local function isempty( tbl ) 60 | local next = next 61 | if tbl == nil or next(tbl) == nil then 62 | return true 63 | end 64 | return false 65 | end 66 | 67 | local function split( str, delim ) 68 | if not delim then return {str} end 69 | local ret= {}; 70 | 71 | local i = 1 72 | for s in string.gmatch(str, "([^"..delim.."]+)") do 73 | ret[i] = s 74 | i = i + 1 75 | end 76 | 77 | return ret 78 | end 79 | 80 | local function split_once( str, delim ) 81 | if not delim then return str, nil end 82 | 83 | local p = string.find( str, delim ) 84 | if not p then 85 | return str, nil 86 | else 87 | local head = string.sub( str, 1, p - 1) 88 | local tail = string.sub( str, p + #delim ) 89 | return head, tail 90 | 91 | end 92 | end 93 | 94 | local function parse_urlencoded_kv(target) 95 | local ret = {} 96 | local ql = split( target, "&") 97 | for i = 1, #ql do 98 | local k, v = split_once(ql[i], "=") 99 | if ret[k] then 100 | if type( ret[k] ) == "table" then 101 | table.insert(ret[k], v) 102 | else 103 | local v_list = { ret[k] } 104 | table.insert( v_list, v ) 105 | ret[k] = v_list 106 | end 107 | else 108 | ret[k] = v 109 | end 110 | end 111 | return ret 112 | 113 | end 114 | 115 | 116 | 117 | return { 118 | check_module = check_module, 119 | 120 | get_safe = get_safe, 121 | get_safe_d = get_safe_d, 122 | 123 | keys = keys, 124 | merge = merge, 125 | isempty = isempty, 126 | 127 | split = split, 128 | split_once = split_once, 129 | parse_urlencoded_kv = parse_urlencoded_kv, 130 | } 131 | -------------------------------------------------------------------------------- /kong/plugins/ssk-core/common.lua: -------------------------------------------------------------------------------- 1 | local util = require "kong.plugins.ssk-core.lib.utils" 2 | local ssk = require "kong.plugins.ssk-core.lib.ssk" 3 | 4 | local function on_detect_list(e_list) 5 | local on_s, on_t, on_h, on_d = nil 6 | 7 | -- run handler 8 | local max_delay = 0 9 | for i, e in ipairs( e_list["list"] ) do 10 | kong.log.inspect("detected", e) 11 | -- add common info 12 | e[ "route_id" ] = util.get_safe( ngx.ctx, "route", "id" ) 13 | e[ "host" ] = util.get_safe( kong.ctx.shared, "cap", "req_params", "header", "host" ) 14 | e[ "remote" ] = ssk.get_ip() 15 | -- Nginx cached time (no syscall ) 16 | e[ "time" ] = ngx.utctime() 17 | 18 | for i = 1, #util.get_safe_d({}, kong.ctx.shared.cap.handlers, "ondetect" ) do 19 | local handler_info = kong.ctx.shared.cap.handlers.ondetect[i] 20 | local s,t,h,d = handler_info["h"]( e, unpack( handler_info["args"]) ) 21 | if s then 22 | if not (on_s and s < on_s) then 23 | kong.ctx.shared.cap.blocked = true 24 | on_s, on_t, on_h, on_d = s,t,h,d 25 | end 26 | end 27 | 28 | if d and max_delay < d then 29 | max_delay = d 30 | end 31 | end 32 | end 33 | 34 | 35 | 36 | if on_s then 37 | if on_d and on_d > 0 then 38 | ngx.sleep( on_d ) 39 | end 40 | 41 | return kong.response.exit( on_s, on_t, on_h ) 42 | end 43 | 44 | if max_delay > 0 then 45 | ngx.sleep( max_delay ) 46 | end 47 | 48 | return kong.ctx.shared.cap.blocked 49 | end 50 | 51 | 52 | local function on_detect(e) 53 | local on_s, on_t, on_h, on_d = nil 54 | kong.log.inspect("detected", e) 55 | -- add common info 56 | e[ "route_id" ] = util.get_safe( ngx.ctx, "route", "id" ) 57 | e[ "host" ] = util.get_safe( kong.ctx.shared, "cap", "req_params", "header", "host" ) 58 | e[ "remote" ] = ssk.get_ip() 59 | 60 | -- run handler 61 | local max_delay = 0 62 | for i = 1, #util.get_safe_d({}, kong.ctx.shared.cap.handlers, "ondetect" ) do 63 | local handler_info = kong.ctx.shared.cap.handlers.ondetect[i] 64 | local s,t,h,d = handler_info["h"]( e, unpack( handler_info["args"]) ) 65 | if s then 66 | kong.ctx.shared.cap.blocked = true 67 | on_s, on_t, on_h, on_d = s,t,h,d 68 | end 69 | 70 | if d and max_delay < d then 71 | max_delay = d 72 | end 73 | end 74 | 75 | if on_s then 76 | if on_d and on_d > 0 then 77 | ngx.sleep( on_d ) 78 | end 79 | 80 | return kong.response.exit( on_s, on_t, on_h ) 81 | end 82 | 83 | if max_delay > 0 then 84 | ngx.sleep( max_delay ) 85 | end 86 | 87 | return kong.ctx.shared.cap.blocked 88 | end 89 | 90 | local function store_detected( e_new ) 91 | if e_new then 92 | if not kong.ctx.shared.detected_info then 93 | kong.ctx.shared.detected_info = { ["list"] = {} } 94 | end 95 | 96 | if e_new["list"] then 97 | for i, v in ipairs( e_new["list"] ) do 98 | table.insert( kong.ctx.shared.detected_info["list"], v ) 99 | end 100 | else 101 | table.insert( kong.ctx.shared.detected_info["list"], e_new ) 102 | end 103 | end 104 | end 105 | 106 | 107 | return { 108 | on_detect = on_detect, 109 | on_detect_list = on_detect_list, 110 | store_detected = store_detected, 111 | } 112 | -------------------------------------------------------------------------------- /kong/plugins/ssk-strictparameter/types.lua: -------------------------------------------------------------------------------- 1 | -- https://swagger.io/specification/#dataTypeFormat 2 | local function match_type(t, p, target) 3 | local pm = require "kong.plugins.cscapisec.lib.patternmatcher" 4 | 5 | if t == 'integer' or t == 'int' then 6 | return pm.detect(target, "^([+-]?\\d+)$") 7 | end 8 | 9 | if t == 'number' then 10 | return pm.detect(target, "^[+-]?\\d+([.]\\d+([Ee][+-]\\d+)?)?$") 11 | end 12 | 13 | if t == 'string' then 14 | local full_date = '\\d{4}-\\d{2}-\\d{2}' 15 | local time_delta = '(Z|[+-]\\d{2}:\\d{2})' 16 | local full_time = '\\d{2}:\\d{2}:\\d{2}([.]\\d+)?' .. time_delta 17 | local date_time = full_date .. "T" .. full_time 18 | 19 | if p == 'date' then 20 | return pm.detect(target, "^".. full_date .. "$") 21 | end 22 | if p == 'date-time' then 23 | return pm.detect(target, "^".. date_time .. "$") 24 | end 25 | return true 26 | end 27 | 28 | if t == 'boolean' then 29 | return pm.detect(target, "^(true|false)$", true) 30 | end 31 | 32 | return true 33 | end 34 | 35 | local function check_type(t, p, target) 36 | local from, to = match_type(t, p, target) 37 | if from == nil then 38 | return false 39 | end 40 | return true 41 | end 42 | 43 | 44 | 45 | local function test(expect, t, p, target) 46 | local result = check_type(t, p, target) 47 | if result == expect then 48 | print(t, p, target, " => ", result) 49 | else 50 | print(t, p, target, " => ", result, " (( expected" , expect, "))") 51 | end 52 | end 53 | 54 | local function testcase() 55 | print('===== integer ===') 56 | test(true, 'integer', '', 0) 57 | test(true, 'integer', '', '0') 58 | test(false, 'integer', '', 'some string') 59 | test(true, 'integer', '', 42) 60 | test(true, 'integer', '', '42') 61 | test(true, 'integer', '', '56237842') 62 | test(true, 'integer', '', '+43422') 63 | test(false, 'integer', '', '5623.7842') 64 | test(false, 'integer', '', '+43.422') 65 | test(true, 'int', '', '+43422') 66 | test(true, 'int', '', '-43422') 67 | test(false, 'int', '', '434-22') 68 | print('===== number ===') 69 | test(true, 'number', '', '42') 70 | test(true, 'number', '', '56237842') 71 | test(true, 'number', '', '43422') 72 | test(true, 'number', '', '+43422') 73 | test(true, 'number', '', '-43422') 74 | test(true, 'number', '', '42.24352') 75 | test(true, 'number', '', '56237842.111') 76 | test(true, 'number', '', '43422.1') 77 | test(true, 'number', '', '+43422.88853') 78 | test(true, 'number', '', '-43422.2') 79 | test(false, 'number', '', '+43422.88.853') 80 | test(false, 'number', '', '-43422.2d') 81 | print('===== string ===') 82 | test(true, 'string', '', '42') 83 | test(true, 'string', '', '+43422.88853') 84 | test(true, 'string', '', 'AAckvie(()33$df') 85 | print('===== date ===') 86 | test(false, 'string', 'date', '4') 87 | test(false, 'string', 'date', '421') 88 | test(false, 'string', 'date', '12-08') 89 | test(false, 'string', 'date', '19221208') 90 | test(true, 'string', 'date', '1922-12-08') 91 | test(true, 'string', 'date', '7292-42-99') 92 | print('===== date-time ===') 93 | test(false, 'string', 'date-time', '12-08') 94 | test(false, 'string', 'date-time', '19221208') 95 | test(false, 'string', 'date-time', '1922-12-08') 96 | test(false, 'string', 'date-time', '1922-12-02T14:12:53.+05:308') 97 | test(true, 'string', 'date-time', '1922-12-02T14:12:53Z') 98 | test(false, 'string', 'date-time', '1922-12-02T14:12:53D') 99 | test(false, 'string', 'date-time', '1922-12-02T14:12:53') 100 | test(true, 'string', 'date-time', '1922-12-02T14:12:53+05:30') 101 | test(true, 'string', 'date-time', '2006-04-13T14:12:53.4242+05:30') 102 | test(false, 'string', 'date-time', '2006-04-13T14:12:53:4242+05:30') 103 | 104 | print('===== boolean ===') 105 | -- test(true, 'boolean', '', true) 106 | test(true, 'boolean', '', 'true') 107 | test(true, 'boolean', '', 'True') 108 | test(true, 'boolean', '', 'false') 109 | test(false, 'boolean', '', 'Trues') 110 | end 111 | 112 | return { 113 | check_type = check_type, 114 | test = test, 115 | } 116 | 117 | -------------------------------------------------------------------------------- /kong/plugins/ssk-core/params.lua: -------------------------------------------------------------------------------- 1 | local common = require "kong.plugins.ssk-core.common" 2 | local util = require "kong.plugins.ssk-core.lib.utils" 3 | local decoder = require "kong.plugins.ssk-core.decoder" 4 | 5 | local function handle_param_list( cat, k, v_list ) 6 | local options = kong.ctx.shared.cap.options[cat] 7 | local handlers = util.get_safe_d({}, kong.ctx.plugin.handlers, cat ) 8 | for _, subv in ipairs(v_list) do 9 | local decoded_list = decoder.build_decoded_list(subv, options) 10 | for i = 1, #handlers do 11 | local handler_info = handlers[i] 12 | local e_new = handler_info.h( cat, k, nil, decoded_list, unpack(handler_info.args) ) 13 | common.store_detected( e_new ) 14 | end 15 | end 16 | end 17 | local function handle_param( cat, k, v ) 18 | local options = kong.ctx.shared.cap.options[cat] 19 | local handlers = util.get_safe_d({}, kong.ctx.plugin.handlers, cat ) 20 | local decoded_list = decoder.build_decoded_list(v, options) 21 | for i = 1, #handlers do 22 | local handler_info = handlers[i] 23 | local e_new = handler_info.h( cat, k, v, decoded_list, unpack(handler_info.args) ) 24 | common.store_detected( e_new ) 25 | end 26 | end 27 | 28 | -- reference each other 29 | local detect_param_record, detect_param_list 30 | function detect_param_list( cat, prefix, params ) 31 | for i = 1, #params do 32 | local v = params[i] 33 | if type(v) == "table" then 34 | if util.get_safe(v,1) then --list 35 | detect_param_list( cat, prefix .. "[]", v ) 36 | else 37 | detect_param_record( cat, prefix .. ".", v ) 38 | end 39 | else 40 | handle_param( cat, prefix, v ) 41 | end 42 | end 43 | end 44 | 45 | function detect_param_record( cat, prefix, params ) 46 | for k, v in pairs(params) do 47 | if type(v) == "table" then 48 | if util.get_safe(v,1) then --list 49 | detect_param_list( cat, prefix .. k .. "[]", v ) 50 | else 51 | detect_param_record( cat, prefix .. k .. ".", v ) 52 | end 53 | else 54 | handle_param( cat, prefix .. k, v ) 55 | end 56 | end 57 | end 58 | 59 | local function detect_param_urlencoded(cat, params ) 60 | for k, v in pairs(params) do 61 | if type(v) == "table" then 62 | if util.get_safe(v,1) then --list 63 | local v_merged = "" 64 | for _, subv in ipairs(v) do 65 | if type(subv) == "string" then 66 | v_merged = v_merged .. subv 67 | -- else 68 | -- not allowed 69 | end 70 | end 71 | table.insert( v, v_merged ) 72 | handle_param_list( cat, k, v ) 73 | -- else 74 | -- not allowed 75 | end 76 | 77 | else 78 | handle_param( cat, k, v ) 79 | end 80 | end 81 | end 82 | 83 | 84 | local function detect_param_main( cat, v ) 85 | if type(v) == "table" then 86 | if util.get_safe(v,1) then --list 87 | detect_param_list( cat, "[]", v ) 88 | else 89 | detect_param_record( cat, "", v ) 90 | end 91 | else 92 | handle_param( cat, "", v) 93 | end 94 | end 95 | 96 | return { 97 | detect_param_urlencoded = detect_param_urlencoded, 98 | detect_param_main = detect_param_main, 99 | } 100 | -------------------------------------------------------------------------------- /kong/plugins/ssk-telemetry/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | local util = require "kong.plugins.ssk-core.lib.utils" 3 | 4 | local EMITTER_INTERVAL_TIME = 5 5 | 6 | local function inspect( t ) 7 | local ret = "" 8 | local is_first = true 9 | local is_array = false 10 | for k, v in pairs (t) do 11 | if not is_first then 12 | ret = ret .. ", " 13 | end 14 | is_first = false 15 | 16 | if type( k ) == "string" then 17 | ret = ret .. '"' .. k ..'" = ' 18 | else 19 | is_array = true 20 | end 21 | 22 | if type( v ) == "table" then 23 | ret = ret .. inspect( v ) 24 | elseif type ( v ) == "string" then 25 | ret = ret .. '"' .. tostring( v ) ..'"' 26 | else 27 | ret = ret .. tostring( v ) 28 | end 29 | end 30 | 31 | if is_array then 32 | return "[" .. ret .. "]" 33 | else 34 | return "{" .. ret .. "}" 35 | end 36 | end 37 | 38 | 39 | 40 | local telemetry_map = {} 41 | 42 | local function new_telemetry( name ) 43 | local ret = {} 44 | ret.transaction_time = 0 45 | ret.kong_request_delay = 0 46 | ret.kong_request_time = 0 47 | ret.endpoint_latency = 0 48 | ret.kong_response_time = 0 49 | ret.count = 0 50 | ret.route_name = name 51 | 52 | return ret 53 | end 54 | 55 | -- as global plugin 56 | local _M = core:extend() 57 | _M.header = "" 58 | _M.tag = nil 59 | _M.std = "out" 60 | _M.exist = false 61 | 62 | _M.PRIORITY = 100 63 | 64 | 65 | local function h( config ) 66 | local name = util.get_safe_d(nil, ngx.ctx, "route", "name" ) 67 | if not name then 68 | name = "extra" 69 | end 70 | 71 | if not telemetry_map[ name ] then 72 | telemetry_map[ name ] = new_telemetry( name ) 73 | end 74 | 75 | -- consider use below 76 | -- KONG_ACCESS_TIME 77 | -- KONG_RESPONSE_LATENCY 78 | 79 | telemetry_map[name].transaction_time = telemetry_map[name].transaction_time + 80 | ( ngx.ctx.KONG_LOG_START - ngx.ctx.KONG_PROCESSING_START ) 81 | telemetry_map[name].kong_request_delay = telemetry_map[name].kong_request_delay + 82 | ( ngx.ctx.KONG_ACCESS_ENDED_AT - ngx.ctx.KONG_ACCESS_START ) 83 | telemetry_map[name].kong_request_time = telemetry_map[name].kong_request_time + 84 | ( ngx.ctx.KONG_LOG_START - ngx.ctx.KONG_PROCESSING_START ) 85 | telemetry_map[name].endpoint_latency = telemetry_map[name].endpoint_latency + 86 | ( ngx.ctx.KONG_HEADER_FILTER_START - ngx.ctx.KONG_ACCESS_ENDED_AT ) 87 | telemetry_map[name].kong_response_time = telemetry_map[name].kong_response_time + 88 | ( ngx.ctx.KONG_BODY_FILTER_ENDED_AT - ngx.ctx.KONG_HEADER_FILTER_START ) 89 | telemetry_map[name].count = telemetry_map[name].count + 1 90 | 91 | _M.exist = true 92 | end 93 | 94 | 95 | local function async_emitter() 96 | if not _M.exist then return end 97 | 98 | local t_map = {} 99 | t_map.duration = EMITTER_INTERVAL_TIME 100 | t_map.data = telemetry_map 101 | if _M.tag then 102 | t_map.tag = _M.tag 103 | end 104 | 105 | telemetry_map = {} 106 | 107 | if _M.std == "err" then 108 | io.stderr:write( _M.header .. inspect(t_map) .. "\n") 109 | io.stderr:flush() 110 | elseif _M.std == "out" then 111 | io.stdout:write( _M.header .. inspect(t_map) .. "\n") 112 | io.stdout:flush() 113 | end 114 | 115 | _M.exist = false 116 | end 117 | 118 | -- ngx.timer.every will create 'fake' connection every that time. 119 | -- it will release its thread memory by intervaltime (maybe) 120 | local function start_emitter() 121 | ngx.timer.every( EMITTER_INTERVAL_TIME, async_emitter ) 122 | end 123 | 124 | 125 | function _M:init_worker() 126 | _M.super.init_worker(self) 127 | -- init send pool 128 | start_emitter() 129 | 130 | end 131 | 132 | function _M:init_handler( config ) 133 | if config.tag then _M.tag = config.tag end 134 | if config.std then _M.std = config.std end 135 | if config.header then _M.header = config.header end 136 | 137 | self:add_handler( "log", h, config) 138 | end 139 | 140 | 141 | return _M 142 | -------------------------------------------------------------------------------- /kong/plugins/ssk-cors/handler.lua: -------------------------------------------------------------------------------- 1 | local table = require "table" 2 | local core = require "kong.plugins.ssk-core.core" 3 | local util = require "kong.plugins.ssk-core.lib.utils" 4 | 5 | -- luacheck: no unused 6 | local DETECT_CODE_CORS_BASE = 400 7 | -- luacheck: unused 8 | local DETECT_CODE_CORS_ORIGIN_NOT_ALLOWED = 401 9 | local DETECT_CODE_CORS_METHOD_NOT_ALLOWED = 402 10 | local DETECT_CODE_CORS_HEADER_NOT_ALLOWED = 403 11 | 12 | 13 | local function isInclude(needle, stack) 14 | for i = 1, #stack do 15 | if stack[i] == "*" then return true end 16 | if stack[i] == needle then return true end 17 | end 18 | return false 19 | end 20 | 21 | local function h_req_header( params, config ) 22 | if config.block then 23 | -- origin 24 | if util.get_safe( config.allow_origins ) then 25 | local subj = util.get_safe( params, "origin" ) 26 | if subj ~= nil and 27 | not isInclude( subj, config.allow_origins ) then 28 | return { detect_code = DETECT_CODE_CORS_ORIGIN_NOT_ALLOWED, tags = config.tags, 29 | details = { ["input"]=subj } } 30 | end 31 | else 32 | local subj = util.get_safe( params, "origin" ) 33 | if subj then 34 | return { detect_code = DETECT_CODE_CORS_ORIGIN_NOT_ALLOWED, tags = config.tags, 35 | details = { ["input"]=subj } } 36 | end 37 | end 38 | 39 | -- allow_methods 40 | if util.get_safe( config.allow_methods ) then 41 | local subj = kong.request.get_method() 42 | if not isInclude( subj, config.allow_methods ) then 43 | return { detect_code = DETECT_CODE_CORS_METHOD_NOT_ALLOWED, tags = config.tags, 44 | details = { ["input"]=subj } } 45 | end 46 | end 47 | 48 | -- allow_headers 49 | 50 | if util.get_safe( config.allow_headers ) then 51 | for subj, _ in pairs(params) do 52 | if not isInclude( subj, config.optimized_config.allow_headers ) then 53 | return { detect_code = DETECT_CODE_CORS_HEADER_NOT_ALLOWED, tags = config.tags, 54 | details = { ["input"]=subj } } 55 | end 56 | end 57 | end 58 | end 59 | end 60 | 61 | local function add_header_a( k, array ) 62 | if array then 63 | if #array > 0 then 64 | kong.response.set_header(k, table.concat(array, ", ")) 65 | end 66 | end 67 | end 68 | 69 | local function add_header( k, subj ) 70 | if subj then 71 | kong.response.set_header(k, subj) 72 | end 73 | end 74 | 75 | local function h_res_header( _, config ) 76 | if config.modify_response_header then 77 | add_header_a( "Access-Control-Allow-Origin", config.allow_origins ) 78 | add_header_a( "Access-Control-Allow-Methods", config.allow_methods ) 79 | add_header_a( "Access-Control-Allow-Headers", config.allow_headers ) 80 | add_header_a( "Access-Control-Expose-Headers", config.expose_headers ) 81 | add_header( "Access-Control-Max-Age", config.max_age ) 82 | add_header( "Access-Control-Allow-Credentials", config.allow_credentials ) 83 | end 84 | end 85 | 86 | 87 | local _M = core:extend() 88 | _M.PRIORITY = 100 89 | 90 | local function make_lower( l ) 91 | local ret = {} 92 | if not l then return ret end 93 | 94 | for i = 1, #l do 95 | table.insert(ret, l[i]:lower() ) 96 | end 97 | return ret 98 | end 99 | 100 | local function optimize(config) 101 | if not config.optimized_config then 102 | config.optimized_config = {} 103 | config.optimized_config.allow_headers = make_lower( config.allow_headers ) 104 | end 105 | end 106 | 107 | function _M:init_handler( config ) 108 | optimize(config) 109 | self:add_handler( "req_header", h_req_header, config) 110 | self:add_handler( "res_header", h_res_header, config) 111 | end 112 | 113 | 114 | return _M 115 | -------------------------------------------------------------------------------- /kong/plugins/ssk-magika/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | local util = require "kong.plugins.ssk-core.lib.utils" 3 | 4 | -- luacheck: no unused 5 | local DETECT_CODE_MAGIKA_BASE = 3600 6 | local DETECT_CODE_MAGIKA_NOT_ALLOWED = 3601 7 | local DETECT_CODE_MAGIKA_DENY = 3602 8 | -- luacheck: unused 9 | 10 | local lumagika = nil 11 | local function check_lumagika() 12 | if util.check_module( "liblumagika" ) then 13 | lumagika = require "liblumagika" 14 | end 15 | end 16 | 17 | check_lumagika() 18 | 19 | local function magika( body ) 20 | if not lumagika then 21 | kong.log.err( "!! magika not loaded !!") 22 | return "Unknown" 23 | end 24 | 25 | return lumagika.identify_content_label(body) 26 | end 27 | 28 | 29 | local function make_dict_by_in( params ) 30 | local ret = {} 31 | if params then 32 | for i = 1, #params do 33 | local cat = params[i]["in"] 34 | if not cat then cat = "req_body" end 35 | 36 | if not ret[cat] then 37 | ret[cat] = {} 38 | end 39 | table.insert( ret[cat], params[i] ) 40 | end 41 | end 42 | 43 | return ret 44 | end 45 | 46 | local function check_same( p1, p2 ) 47 | if p2 == nil then return true end 48 | if p2 == "*" then return true end 49 | if p1 == p2 then return true end 50 | return false 51 | end 52 | 53 | local function match( tbl, needle, default ) 54 | if util.isempty( tbl ) then 55 | return default 56 | end 57 | 58 | return tbl[needle] == true 59 | end 60 | 61 | local function h_main( v, config ) 62 | if type(v) ~= "string" then return end 63 | 64 | local label = magika(v) 65 | local matched = match( config.denys_tbl, label, false ) 66 | if matched then 67 | return { detect_code = DETECT_CODE_MAGIKA_DENY, tags = config.tags, 68 | details = { ["determined"]=label, ["value"]=v } } 69 | end 70 | 71 | matched = match( config.allows_tbl, label, true ) 72 | if not matched then 73 | return { detect_code = DETECT_CODE_MAGIKA_NOT_ALLOWED, tags = config.tags, 74 | details = { ["determined"]=label, ["value"]=v } } 75 | end 76 | 77 | return 78 | end 79 | 80 | local function h_req_body( v, _, config ) 81 | return h_main(v, config) 82 | end 83 | 84 | local function h_req_param(_, k, v, _, params, config ) 85 | for i = 1, #params do 86 | if check_same( k, params[i]["key"] ) then 87 | local ret = h_main(v, config) 88 | if ret then 89 | return ret 90 | end 91 | end 92 | end 93 | end 94 | 95 | local function h_res_body( body, config ) 96 | return h_main(body, config) 97 | end 98 | 99 | 100 | local function initialize( config ) 101 | if config["allows_tbl"] then return end 102 | 103 | config["allows_tbl"] = {} 104 | config["denys_tbl"] = {} 105 | if config["allows"] then 106 | for _, item in ipairs(config["allows"]) do 107 | config["allows_tbl"][item] = true 108 | end 109 | end 110 | if config["denys"] then 111 | for _, item in ipairs(config["denys"]) do 112 | config["denys_tbl"][item] = true 113 | end 114 | end 115 | config["params_in"] = make_dict_by_in( config["params"] ) 116 | 117 | end 118 | 119 | 120 | local _M = core:extend() 121 | _M.PRIORITY = 100 122 | 123 | function _M:init_handler( config ) 124 | initialize( config ) 125 | 126 | if not config["params_in"] then 127 | self:add_handler( "req_body", h_req_body, config ) 128 | else 129 | for cat, params in pairs( config["params_in"] ) do 130 | if cat == "req_body" then 131 | self:add_handler( cat, h_req_body, config ) 132 | elseif cat == "param_req_body" then 133 | self:add_param_handler( cat, config, h_req_param, params, config ) 134 | elseif cat == "res_body" then 135 | self:add_handler( cat, h_res_body, config ) 136 | end 137 | end 138 | end 139 | end 140 | 141 | return _M 142 | -------------------------------------------------------------------------------- /kong/plugins/ssk-libinjection/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | local util = require "kong.plugins.ssk-core.lib.utils" 3 | 4 | -- luacheck: no unused 5 | local CODE_LIBINJECTION_BASE = 1300 6 | local DETECT_CODE_LIBINJECTION_BASE = CODE_LIBINJECTION_BASE 7 | -- luacheck: unused 8 | local DETECT_CODE_LIBINJECTION_SQL = 1301 9 | local DETECT_CODE_LIBINJECTION_XSS = 1302 10 | 11 | 12 | local function make_dict_by_in( params ) 13 | local ret = {} 14 | if params then 15 | for i = 1, #params do 16 | local cat = params[i]["in"] 17 | if not cat then cat = "param_req_*" end 18 | 19 | if not ret[cat] then 20 | ret[cat] = {} 21 | end 22 | table.insert( ret[cat], params[i] ) 23 | end 24 | end 25 | 26 | return ret 27 | end 28 | 29 | 30 | local function initialize( config ) 31 | if not config["params_in"] then 32 | config["params_in"] = make_dict_by_in( config["params"] ) 33 | end 34 | end 35 | 36 | 37 | local function check_same( p1, p2 ) 38 | if p2 == nil then return true end 39 | if p2 == "*" then return true end 40 | if p1 == p2 then return true end 41 | return false 42 | end 43 | 44 | local function run_match( subj, param_config ) 45 | local libinjection = require "kong.plugins.ssk-libinjection.libinjection" 46 | if not libinjection.try_load() then 47 | kong.log.err( "!! libinjection not loaded !!") 48 | return 49 | end 50 | 51 | if param_config.sql then 52 | local d, fingerprint = libinjection.sqli(subj) 53 | if d then 54 | return { detect_code = DETECT_CODE_LIBINJECTION_SQL, details={ ["fingerprint"]=fingerprint } } 55 | end 56 | end 57 | 58 | if param_config.xss then 59 | local d, fingerprint = libinjection.xss(subj) 60 | if d then 61 | return { detect_code = DETECT_CODE_LIBINJECTION_XSS, details={ ["fingerprint"]=fingerprint } } 62 | end 63 | end 64 | 65 | return nil 66 | end 67 | 68 | -- luacheck: no unused args 69 | local function h_param(_, k, v, v_list, params, config, ...) 70 | -- luacheck: unused args 71 | if type(v) ~= "string" then return end 72 | local e_list = {} 73 | for i = 1, #params do 74 | if check_same( k, params[i]["key"] ) then 75 | 76 | for _, decoded in ipairs( v_list ) do 77 | local e = run_match( decoded, params[i] ) 78 | if e then 79 | e.details["key"] = k 80 | e.details["value"] = v 81 | e.details["decoded"] = decoded 82 | e.tags = util.get_safe_d( {}, config, "tags" ) 83 | table.insert(e_list, e) 84 | end 85 | end 86 | end 87 | end 88 | if #e_list > 0 then 89 | return { ["list"] = e_list } 90 | end 91 | 92 | end 93 | 94 | local function h_raw( v, v_list, params, config ) 95 | if type(v) ~= "string" then return end 96 | local e_list = {} 97 | for i = 1, #params do 98 | for _, decoded in ipairs( v_list ) do 99 | local e = run_match( decoded, params[i] ) 100 | if e then 101 | e.details["value"] = v 102 | e.details["decoded"] = decoded 103 | e.tags = util.get_safe_d( {}, config, "tags" ) 104 | table.insert(e_list, e) 105 | end 106 | end 107 | end 108 | 109 | if #e_list > 0 then 110 | return { ["list"] = e_list } 111 | end 112 | end 113 | 114 | local _M = core:extend() 115 | function _M:init_handler( config ) 116 | initialize( config ) 117 | 118 | for cat, params in pairs( config["params_in"] ) do 119 | if cat == "req_path" or 120 | cat == "req_query" or 121 | cat == "req_body" then 122 | self:add_handler( cat, h_raw, params, config ) 123 | else 124 | self:add_param_handler( cat, config, h_param, params, config ) 125 | end 126 | end 127 | end 128 | 129 | 130 | return _M 131 | -------------------------------------------------------------------------------- /quickstart.sh: -------------------------------------------------------------------------------- 1 | # Prerequirements: 2 | # Kong has been installed 3 | # Service has been initialized 4 | # Kong restarted after modified kong.conf rewrite plugins 5 | 6 | 7 | SERVICENAME=$1 8 | 9 | if test ${#SERVICENAME} -eq 0 ; then 10 | echo "input YOUR_SERVICE_NAME_OR_ID in arg1" 11 | fi 12 | 13 | 14 | # config module 15 | echo -e "\n\nConfigure ssk-pm\n" 16 | curl -i -X POST http://localhost:8001/services/${SERVICENAME}/plugins \ 17 | -H "Content-Type: application/json" \ 18 | -d '{"name": "ssk-pm", "config": { "patterns" : [] } }' 19 | 20 | 21 | # config module 22 | # You should set manually your host(FQDN) on ssk-safehost. 23 | # echo -e "\n\nConfigure ssk-safehost\n" 24 | # curl -i -X POST http://localhost:8001/services/${SERVICENAME}/plugins \ 25 | # -d "name=ssk-safehost" 26 | 27 | 28 | # config module 29 | echo -e "\n\nConfigure ssk-cors\n" 30 | curl -i -X POST http://localhost:8001/services/${SERVICENAME}/plugins \ 31 | -d name=ssk-cors \ 32 | -d config.block=false \ 33 | -d config.modify_response_header=true \ 34 | -d config.allow_origins=["*"] \ 35 | -d config.allow_methods=["*"] \ 36 | -d config.allow_headers=["*"] \ 37 | -d config.expose_headers=["*"] \ 38 | -d config.allow_credentials=false \ 39 | -d config.max_age=3600 40 | 41 | # config module 42 | echo -e "\n\nConfigure ssk-detecthandling\n" 43 | curl -i -X POST http://localhost:8001/services/${SERVICENAME}/plugins \ 44 | -H "Content-Type: application/json" 45 | -d '{"name": "ssk-detecthandling", 46 | "config": {"filters" : 47 | [{"tag" : "status_401","status" : 401,"headers" : [ {"key": "CustomHeader", "value": "CustomValue" },{"key": "CustomHeader2", "value" : "CustomValue2" }],"body" : "blocked","default" : true}, 48 | {"tag" : "status409","status" : 409}, 49 | {"tag" : "log"}] 50 | } 51 | }' 52 | 53 | # config module 54 | # you can check the detected log in error.log 55 | echo -e "\n\nConfigure ssk-std-logger\n" 56 | curl -i -X POST http://localhost:8001/services/${SERVICENAME}/plugins \ 57 | -d "name=ssk-std-logger" \ 58 | -d "config.std=err" 59 | 60 | 61 | # config module 62 | echo -e "\n\nConfigure ssk-ua-filter\n" 63 | curl -i -X POST http://localhost:8001/services/${SERVICENAME}/plugins \ 64 | -d "name=ssk-ua-filter" \ 65 | -d "config.block_no_useragent=true" 66 | 67 | 68 | # config module 69 | # ./install_libinjection.sh 70 | # echo -e "\n\nConfigure ssk-libinjection\n" 71 | # curl -i -X POST http://localhost:8001/services/${SERVICENAME}/plugins \ 72 | # -H "Content-Type: application/json" \ 73 | # -d '{"name": "ssk-libinjection", "config": { "params" : [{"in": "param_req_body"}] } }' 74 | 75 | 76 | # config module 77 | echo -e "\n\nConfigure ssk-click-jacking\n" 78 | curl -i -X POST http://localhost:8001/services/${SERVICENAME}/plugins \ 79 | -d "name=ssk-clickjacking" \ 80 | -d "config.policy=DENY" 81 | 82 | 83 | # config module 84 | # You should set config of ssk-strictparameter manually. 85 | # echo -e "\n\nConfigure ssk-strictparameter\n" 86 | # curl -i -X POST http://localhost:8001/services/${SERVICENAME}/plugins \ 87 | # -H "Content-Type: application/json" \ 88 | # -d '{"name": "ssk-strictparameter", "config": { "params" : [{"in": "param_req_body", "key": "", "type": "", "min": 0, "max": 18}] } }' 89 | 90 | 91 | # config module 92 | 93 | 94 | 95 | echo "start to build CoreRuleSet" 96 | 97 | wget https://github.com/coreruleset/coreruleset/archive/v3.3.4.tar.gz 98 | tar -xvzf v3.3.4.tar.gz 99 | 100 | sudo apt-get update -y 101 | sudo apt-get install -y libregexp-assemble-perl 102 | 103 | pushd coreruleset-3.3.4/util/regexp-assemble 104 | mkdir build 105 | 106 | files=(regexp-932100.txt regexp-932105.txt regexp-932106.txt regexp-932110.txt regexp-932115.txt regexp-932150.txt regexp-934100.txt) 107 | for f in ${files[@]} 108 | do 109 | echo "loading $f" 110 | cat $f| python3 regexp-cmdline.py unix | ./regexp-assemble.pl > build/${f} 111 | echo "saved build/$f" 112 | done 113 | 114 | bfiles=(933131 941130 941160 942120 942130 942140 942150 942170 942180 942190 942200 942210 942240 942280 942300 942310 942320 942330 942340 942350 942360 942370 942380 942390 942400 942410 942470 942480) 115 | for bf in ${bfiles[@]} 116 | do 117 | bfile="regexp-$bf.data" 118 | echo "loading $bfile" 119 | ./regexp-assemble.pl $bfile > build/$bfile 120 | echo "saved build/$bfile" 121 | done 122 | 123 | bv2files=(942260) 124 | for bf in ${bv2files[@]} 125 | do 126 | bfile="regexp-$bf.data" 127 | echo "loading $bfile" 128 | ./regexp-assemble-v2.pl $bfile > build/$bfile 129 | echo "saved build/$bfile" 130 | done 131 | 132 | echo "finished to build CoreRuleSet" 133 | popd 134 | 135 | python3 tools/quickstart.py --service $SERVICENAME 136 | 137 | 138 | echo " 139 | ==================== 140 | Finished QuickStart 141 | 142 | You can start sasanka Plugin by quickstart settings 143 | ==================== 144 | " 145 | 146 | -------------------------------------------------------------------------------- /kong/plugins/ssk-pm/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | local ssk = require "kong.plugins.ssk-core.lib.ssk" 3 | local util = require "kong.plugins.ssk-core.lib.utils" 4 | local pm = require "kong.plugins.ssk-pm.patternmatcher" 5 | 6 | -- luacheck: no unused 7 | local DETECT_CODE_PATTERNMATCH_BASE = 200 8 | -- luacheck: unused 9 | local DETECT_CODE_PATTERNMATCH_MATCHED = 201 10 | 11 | local function get_overwritten( param, dict, v ) 12 | local ret = util.get_safe_d( {}, param, "customize", v ) 13 | if util.isempty( ret ) then 14 | ret = util.get_safe_d( {}, dict, v ) 15 | end 16 | return ret 17 | end 18 | 19 | local function merge_dict_by_in( config, pattern_dict ) 20 | 21 | local ret = {} 22 | 23 | local params = config["params"] 24 | if params then 25 | for i = 1, #params do 26 | local p = params[i]["patterns"] 27 | 28 | for ii = 1, #p do 29 | 30 | local obj = {} 31 | local cache_key = p[ii] 32 | local found = pattern_dict[cache_key] 33 | -- TODO: fix me : array to single 34 | obj["patterns"] = { cache_key } 35 | 36 | obj["key"] = get_overwritten(params[i], found, "key") 37 | obj["in"] = get_overwritten(params[i], found, "in") 38 | obj["tags"] = get_overwritten(params[i], found, "tags") 39 | 40 | if util.isempty(obj["in"]) then 41 | local cat = "param_req_*" 42 | if not ret[cat] then 43 | ret[cat] = {} 44 | end 45 | 46 | table.insert( ret[cat], obj ) 47 | end 48 | 49 | for iii = 1, #obj["in"] do 50 | local cat = obj["in"][iii] 51 | if not ret[cat] then 52 | ret[cat] = {} 53 | end 54 | 55 | table.insert( ret[cat], obj ) 56 | end 57 | end 58 | 59 | end 60 | end 61 | 62 | return ret 63 | end 64 | 65 | 66 | local function initialize( config, pattern_dict) 67 | if config["pattern_dict"] then return end 68 | 69 | if pattern_dict then 70 | config["pattern_dict"] = pattern_dict 71 | else 72 | config["pattern_dict"] = {} 73 | if config["patterns"] then 74 | for i = 1, #config["patterns"] do 75 | local opt = 10 76 | local cache_key = config["patterns"][i]["name"] 77 | config["pattern_dict"][cache_key] = config["patterns"][i] 78 | config["pattern_dict"][cache_key]["ud_list"] = pm.optimize( config["patterns"][i]["patterns"], opt ) 79 | end 80 | end 81 | end 82 | 83 | config["params_in"] = merge_dict_by_in( config, config["pattern_dict"] ) 84 | 85 | end 86 | 87 | 88 | local function check_include( stack, needle) 89 | if util.isempty(stack) then return true end 90 | for i = 1, #stack do 91 | if stack[i] == "*" then return true end 92 | if stack[i] == needle then return true end 93 | end 94 | return false 95 | end 96 | 97 | local function run_match( subj, pattern_dict, keys ) 98 | for i = 1, #keys do 99 | local ud = util.get_safe( pattern_dict, keys[i], "ud_list" ) 100 | if ud then 101 | local a, _ = pm.detect_tbl(tostring(subj), ud) 102 | if a then 103 | local tags = util.get_safe( pattern_dict, keys[i], "tags" ) 104 | return {detect_code = DETECT_CODE_PATTERNMATCH_MATCHED, tags = tags, 105 | details = {["pattern"]=keys[i], ["key"]="", ["value"]=subj}} 106 | end 107 | end 108 | end 109 | end 110 | 111 | local function h(_, k, _, v_list, params, pattern_dict ) 112 | for i = 1, #params do 113 | if check_include( params[i]["key"], k ) then 114 | for _, decoded in ipairs( v_list ) do 115 | local e = run_match( decoded, pattern_dict, params[i]["patterns"] ) 116 | if e then 117 | e.details["key"] = k 118 | return e 119 | end 120 | end 121 | end 122 | end 123 | 124 | end 125 | 126 | local _M = core:extend() 127 | function _M:init_handler( config ) 128 | 129 | local pattern_dict = nil 130 | if ssk.get_shared_ctx().pattern_dict then 131 | pattern_dict = ssk.get_shared_ctx().pattern_dict 132 | end 133 | 134 | initialize( config, pattern_dict ) 135 | 136 | for cat, params in pairs( config["params_in"] ) do 137 | self:add_param_handler( cat, config, h, params, config["pattern_dict"] ) 138 | end 139 | end 140 | 141 | 142 | return _M 143 | -------------------------------------------------------------------------------- /kong/plugins/ssk-core/core.lua: -------------------------------------------------------------------------------- 1 | local util = require "kong.plugins.ssk-core.lib.utils" 2 | local request = require "kong.plugins.ssk-core.request" 3 | local response = require "kong.plugins.ssk-core.response" 4 | local common = require "kong.plugins.ssk-core.common" 5 | 6 | local _M = { 7 | VERSION = "0.0.1", 8 | PRIORITY = 100 9 | } 10 | 11 | function _M:extend() 12 | self.__index = self 13 | local o = {} 14 | for k, v in pairs(self) do 15 | if k:find("__") == 1 then 16 | o[k] = v 17 | end 18 | end 19 | o.__index = o 20 | o.super = self 21 | setmetatable(o, self) 22 | return o 23 | end 24 | 25 | function _M:hasoptimize() 26 | return kong.ctx.shared.cap.optimize 27 | end 28 | 29 | local function initialize( config ) 30 | if not kong.ctx.shared.cap then 31 | --initialize 32 | kong.ctx.shared.cap = {} 33 | kong.ctx.shared.cap.id = {} 34 | kong.ctx.shared.cap.handlers = {} 35 | kong.ctx.shared.cap.options = {} 36 | kong.ctx.shared.cap.plugin = {} 37 | kong.ctx.shared.cap.optimize = false 38 | end 39 | 40 | -- already intted 41 | if not util.get_safe(kong.ctx.plugin, "handlers") then 42 | -- init objects 43 | kong.ctx.plugin.handlers = {} 44 | end 45 | kong.ctx.plugin.config = config 46 | 47 | end 48 | 49 | function _M:new( name ) 50 | end 51 | 52 | function _M:add_param_handler( cat, config, h, ...) 53 | if not cat or cat == "param_req_*" then 54 | self:add_handler( "param_req_path", h, ... ) 55 | self:add_handler( "param_req_query", h, ... ) 56 | self:add_handler( "param_req_header", h, ...) 57 | self:add_handler( "param_req_body", h, ...) 58 | self:add_handler( "param_req_cookie", h, ...) 59 | elseif cat == "param_req_path" then 60 | self:add_handler( "param_req_path", h, ...) 61 | elseif cat == "param_req_query" then 62 | self:add_handler( "param_req_query", h, ...) 63 | elseif cat == "param_req_header" then 64 | self:add_handler( "param_req_header", h, ...) 65 | elseif cat == "param_req_cookie" then 66 | self:add_handler( "param_req_cookie", h, ...) 67 | elseif cat == "param_req_body" then 68 | self:add_handler( "param_req_body", h, ...) 69 | -- response 70 | elseif cat == "param_res_header" then 71 | self:add_handler( "param_res_header", h, ...) 72 | elseif cat == "param_res_body" then 73 | self:add_handler( "param_res_body", h, ...) 74 | end 75 | end 76 | 77 | -- as global plugin handler 78 | function _M:add_global_handler( cat, h, ... ) 79 | local p = util.get_safe( kong.ctx.shared.cap.handlers, cat ) 80 | if p == nil then 81 | kong.ctx.shared.cap.handlers[cat] = {} 82 | p = kong.ctx.shared.cap.handlers[cat] 83 | end 84 | 85 | table.insert( p, { args = {...}, h= h } ) 86 | end 87 | 88 | 89 | -- as local plugin handler 90 | function _M:add_handler( cat, h, ...) 91 | 92 | if self:hasoptimize() then 93 | return self:add_global_handler( cat, h, ... ) 94 | end 95 | 96 | local p = util.get_safe( kong.ctx.plugin.handlers, cat ) 97 | if p == nil then 98 | kong.ctx.plugin.handlers[cat] = {} 99 | p = kong.ctx.plugin.handlers[cat] 100 | end 101 | table.insert( p, { args = {...}, h= h } ) 102 | end 103 | 104 | -- run at init worker phase 105 | -- it runs when enabled in kong.conf 106 | -- ( even not plugin created ) 107 | function _M:init_worker() 108 | end 109 | 110 | -- call once on access 111 | -- it used on child plugin 112 | function _M:init_handler( config ) 113 | -- empty 114 | end 115 | 116 | function _M:preprocess( config ) 117 | initialize(config) 118 | if not kong.ctx.plugin.inited then 119 | self:init_handler( config ) 120 | kong.ctx.plugin.inited = true 121 | end 122 | 123 | if kong.ctx.shared.cap.blocked then 124 | return false 125 | end 126 | 127 | if kong.ctx.plugin.done then 128 | return false 129 | end 130 | 131 | -- check whether run on local plugin or global plugin 132 | if self:hasoptimize() then return false end 133 | 134 | return true 135 | end 136 | 137 | -- every time from client until send to upstream 138 | function _M:access(config) 139 | if not self:preprocess( config ) then return end 140 | 141 | local handlers = kong.ctx.plugin.handlers 142 | 143 | local cont, err = request.phase_access( handlers ) 144 | if err then 145 | local blocked = common.on_detect( err ) 146 | if blocked then return end 147 | end 148 | if not cont then return end 149 | 150 | return request.run_access_handler() 151 | end 152 | 153 | function _M:header_filter(config) 154 | if not self:preprocess( config ) then return end 155 | 156 | return response.run_header_handler() 157 | end 158 | 159 | -- every time when received from upstrem, until sent to client 160 | function _M:body_filter(config) 161 | if not self:preprocess( config ) then return end 162 | 163 | return response.phase_body() 164 | end 165 | 166 | -- last time of transaction 167 | function _M:log(config) 168 | if not self:preprocess( config ) then return end 169 | 170 | return response.run_log_handler() 171 | end 172 | 173 | return _M 174 | -------------------------------------------------------------------------------- /kong/plugins/ssk-core/response.lua: -------------------------------------------------------------------------------- 1 | local common = require "kong.plugins.ssk-core.common" 2 | local util = require "kong.plugins.ssk-core.lib.utils" 3 | local response_body = require "kong.plugins.ssk-core.response_body" 4 | 5 | local function enable_body_write() 6 | kong.ctx.shared.cap.response_body_write_enabled = true 7 | 8 | if ngx.header.content_length then 9 | ngx.header.content_length = nil 10 | end 11 | end 12 | 13 | local function rewrite_body() 14 | if kong.ctx.shared.cap.response_body_write_enabled ~= true then 15 | -- disabled 16 | return 17 | end 18 | 19 | local encoded_body, _ = response_body.get_encoded_body() 20 | ngx.arg[1] = encoded_body 21 | end 22 | 23 | local function run_header_handler() 24 | local handlers = kong.ctx.plugin.handlers 25 | local res_params = kong.response.get_headers() 26 | -- run handler 27 | for i = 1, #util.get_safe_d({}, handlers, "res_header" ) do 28 | local handler_info = handlers.res_header[i] 29 | local err = handler_info.h( res_params, unpack( handler_info.args ) ) 30 | if err then 31 | local blocked = common.on_detect( err ) 32 | if blocked then return end 33 | end 34 | end 35 | 36 | -- run header param 37 | if util.get_safe(handlers, "param_res_header") then 38 | local params = require "kong.plugins.ssk-core.params" 39 | params.detect_param_main( "param_res_header", res_params ) 40 | end 41 | 42 | -- check detected list 43 | local ret = kong.ctx.shared.detected_info 44 | kong.ctx.shared.detected_info = nil 45 | if ret then 46 | local blocked = common.on_detect_list( ret ) 47 | if blocked then return end 48 | end 49 | 50 | end 51 | 52 | 53 | -- luacheck: no unused 54 | local BUFFERING_LIMIT = 8192 55 | local BODYDETECT_LIMIT = 81920 56 | -- luacheck: unused 57 | 58 | local function run_body_handler() 59 | local params = require "kong.plugins.ssk-core.params" 60 | local handlers = kong.ctx.plugin.handlers 61 | 62 | -- run handler 63 | for i = 1, #util.get_safe_d({}, handlers, "res_body" ) do 64 | local handler_info = handlers.res_body[i] 65 | local err = handler_info.h( kong.ctx.shared.cap.res_body, unpack( handler_info.args ) ) 66 | if err then 67 | local blocked = common.on_detect( err ) 68 | if blocked then return end 69 | end 70 | end 71 | 72 | -- run body param 73 | if util.get_safe( handlers, "param_res_body" ) then 74 | local bodyparam = kong.ctx.shared.cap.res_bodyparam 75 | params.detect_param_main( "param_res_body", bodyparam ) 76 | end 77 | 78 | -- check detected list 79 | local ret = kong.ctx.shared.detected_info 80 | kong.ctx.shared.detected_info = nil 81 | if ret then 82 | local blocked = common.on_detect_list( ret ) 83 | if blocked then return end 84 | end 85 | end 86 | 87 | local function check_duty() 88 | if kong.ctx.shared.cap.res_body_ongoing then 89 | return kong.ctx.plugin.res_duty 90 | end 91 | 92 | kong.ctx.shared.cap.res_body_ongoing = true 93 | kong.ctx.plugin.res_duty = true 94 | return kong.ctx.plugin.res_duty 95 | end 96 | 97 | local function phase_body() 98 | local handlers = kong.ctx.plugin.handlers 99 | if (not util.get_safe( handlers, "res_body" )) and 100 | (not util.get_safe( handlers, "param_res_body" )) then 101 | return false 102 | end 103 | 104 | -- do below on duty plugin only 105 | if check_duty() then 106 | kong.ctx.shared.cap.body_part = nil 107 | local parsers = util.get_safe_d({}, kong.ctx.shared.cap.handlers, "parse_res_body" ) 108 | if #parsers > 0 then 109 | -- if have custom parser 110 | for i = 1, #parsers do 111 | local handler_info = parsers[i] 112 | local err = handler_info.h( "param_res_body", unpack(handler_info.args) ) 113 | if err then return err end 114 | end 115 | else 116 | -- else just call raw_body 117 | local body = kong.response.get_raw_body() 118 | if body then 119 | kong.ctx.shared.cap.res_body_finished = nil 120 | local cjson = require("cjson.safe") 121 | local bodyparam, _ = cjson.decode(body) 122 | kong.ctx.shared.cap.res_body = body 123 | kong.ctx.shared.cap.res_bodyparam = bodyparam 124 | 125 | end 126 | end 127 | end 128 | 129 | run_body_handler() 130 | rewrite_body() 131 | end 132 | 133 | local function run_log_handler() 134 | local handlers = kong.ctx.plugin.handlers 135 | 136 | -- run handler 137 | for i = 1, #util.get_safe_d({}, handlers, "log" ) do 138 | local handler_info = handlers.log[i] 139 | local err = handler_info.h( {}, unpack( handler_info.args ) ) 140 | if err then 141 | local blocked = common.on_detect( err ) 142 | if blocked then return end 143 | end 144 | end 145 | 146 | end 147 | 148 | return { 149 | enable_body_write = enable_body_write, 150 | get_body_part = response_body.get_body_part, 151 | set_body_part = response_body.set_body_part, 152 | run_header_handler = run_header_handler, 153 | phase_body = phase_body, 154 | run_log_handler = run_log_handler, 155 | } 156 | -------------------------------------------------------------------------------- /kong/plugins/ssk-std-logger/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | local util = require "kong.plugins.ssk-core.lib.utils" 3 | 4 | local escape_control_map = { 5 | ["\b"] = "\\b", -- 8, backspace 6 | ["\t"] = "\\t", -- 9, horizontal tab 7 | ["\n"] = "\\n", -- 10, line feed 8 | ["\v"] = "\\v", -- 11, vertical tab 9 | ["\f"] = "\\f", -- 12, form feed 10 | ["\r"] = "\\r", -- 13, carriage return 11 | ["\""] = "\\\"", -- 34, double quote 12 | ["\'"] = "\\\'", -- 39, single quote 13 | ["\\"] = "\\\\", -- 92, backslash 14 | } 15 | local urlencode_control_map = { 16 | ["\b"] = "%08", -- 8, backspace 17 | ["\t"] = "%09", -- 9, horizontal tab 18 | ["\n"] = "%0A", -- 10, line feed 19 | ["\v"] = "%0B", -- 11, vertical tab 20 | ["\f"] = "%0C", -- 12, form feed 21 | ["\r"] = "%0D", -- 13, carriage return 22 | ["\""] = "%22", -- 34, double quote 23 | ["\'"] = "%27", -- 39, single quote 24 | ["\\"] = "%5C", -- 92, backslash 25 | } 26 | 27 | local CONTROL_CHAR_RANGE = 32 28 | local LOG_LEN = 8192 29 | 30 | local function encode_escape_ctrl( v ) 31 | local result = {} 32 | local result_idx = 1 33 | for i = 1, #v do 34 | local c = v:sub(i, i) 35 | if escape_control_map[c] then 36 | result[result_idx] = escape_control_map[c] 37 | result_idx = result_idx + 1 38 | elseif string.byte(c) < CONTROL_CHAR_RANGE then 39 | result[result_idx] = " " 40 | result_idx = result_idx + 1 41 | else 42 | result[result_idx] = c 43 | result_idx = result_idx + 1 44 | end 45 | end 46 | 47 | return table.concat(result) 48 | end 49 | 50 | local function encode_url_ctrl( v ) 51 | local result = {} 52 | local result_idx = 1 53 | for i = 1, #v do 54 | local c = v:sub(i, i) 55 | if urlencode_control_map[c] then 56 | result[result_idx] = urlencode_control_map[c] 57 | result_idx = result_idx + 1 58 | elseif string.byte(c) < CONTROL_CHAR_RANGE then 59 | result[result_idx] = " " 60 | result_idx = result_idx + 1 61 | else 62 | result[result_idx] = c 63 | result_idx = result_idx + 1 64 | end 65 | end 66 | 67 | return table.concat(result) 68 | end 69 | 70 | local function encode( v, enc ) 71 | if enc == "url" then 72 | return ngx.escape_uri( v ) 73 | elseif enc == "url_ctrl" then 74 | return encode_url_ctrl( v ) 75 | elseif enc == "base64" then 76 | return ngx.encode_base64( v ) 77 | elseif enc == "escape_ctrl" then 78 | return encode_escape_ctrl( v ) 79 | end 80 | --else enc == "none" 81 | return v 82 | end 83 | 84 | local function inspect( t, config ) 85 | local ret = "" 86 | local is_first = true 87 | local is_array = false 88 | for k, v in pairs (t) do 89 | if not is_first then 90 | ret = ret .. ", " 91 | end 92 | is_first = false 93 | 94 | if type( k ) == "string" then 95 | ret = ret .. '"' .. k ..'" : ' 96 | else 97 | is_array = true 98 | end 99 | 100 | if type( v ) == "table" then 101 | ret = ret .. inspect( v, config ) 102 | elseif type ( v ) == "string" then 103 | ret = ret .. '"' .. encode( v, config.encode ) ..'"' 104 | else 105 | ret = ret .. tostring( v ) 106 | end 107 | end 108 | 109 | if is_array then 110 | return "[" .. ret .. "]" 111 | else 112 | return "{" .. ret .. "}" 113 | end 114 | 115 | end 116 | 117 | local function filter( detect_info ) 118 | if detect_info.details then 119 | for k, v in pairs( detect_info.details ) do 120 | if type ( v ) == "string" then 121 | detect_info.details[k] = v:sub(1,LOG_LEN) 122 | end 123 | end 124 | end 125 | end 126 | 127 | local function h( detect_info, config ) 128 | local header = util.get_safe_d( "", config, "header" ) 129 | config.handler( header, detect_info ) 130 | return 131 | end 132 | 133 | 134 | local function init( config ) 135 | if not config.inited then 136 | config.inited = true 137 | if config.std == "out" then 138 | config.handler = function ( header, detect_info) 139 | if not detect_info.silence then 140 | filter(detect_info) 141 | io.stdout:write( header .. inspect(detect_info, config) .. "\n" ) 142 | end 143 | end 144 | end 145 | if config.std == "err" then 146 | config.handler = function ( header, detect_info) 147 | if not detect_info.silence then 148 | filter(detect_info) 149 | io.stderr:write( header .. inspect(detect_info, config) .. "\n") 150 | end 151 | end 152 | end 153 | end 154 | end 155 | 156 | local _M = core:extend() 157 | _M.PRIORITY = 100 + 2 158 | 159 | function _M:init_handler( config ) 160 | init( config ) 161 | 162 | self:add_global_handler( "ondetect", h, config) 163 | end 164 | 165 | 166 | return _M 167 | -------------------------------------------------------------------------------- /kong/plugins/ssk-core/decoder.lua: -------------------------------------------------------------------------------- 1 | local util = require "kong.plugins.ssk-core.lib.utils" 2 | 3 | local decoder = nil 4 | local function check_shydecoder() 5 | if util.check_module( "shydecoder" ) then 6 | decoder = require "shydecoder" 7 | end 8 | end 9 | 10 | check_shydecoder() 11 | 12 | 13 | -- reference each other 14 | local decode_list, decode_record 15 | function decode_list( params, option ) 16 | for i = 1, #params do 17 | local v = params[i] 18 | if type(v) == "table" then 19 | if util.get_safe(v,1) then --list 20 | decode_list( params[i], option) 21 | else 22 | decode_record( params[i], option) 23 | end 24 | else 25 | if util.get_safe( option, "urldecode" )then 26 | params[i] = ngx.unescape_uri(params[i]) 27 | end 28 | end 29 | end 30 | end 31 | 32 | function decode_record( params, option ) 33 | for k, v in pairs(params) do 34 | if type(v) == "table" then 35 | if util.get_safe(v,1) then --list 36 | decode_list( params[k], option) 37 | else 38 | decode_record( params[k], option) 39 | end 40 | else 41 | if util.get_safe( option, "urldecode" )then 42 | params[k] = ngx.unescape_uri(params[k]) 43 | end 44 | end 45 | end 46 | end 47 | 48 | local function decode_body( params, option ) 49 | if type(params) == "table" then 50 | if util.get_safe(params,1) then --list 51 | decode_list( params, option) 52 | else 53 | decode_record( params, option) 54 | end 55 | end 56 | end 57 | 58 | local function build_decoded_list( v, option ) 59 | local ret = { v } 60 | if type ( v ) ~= "string" then return ret end 61 | 62 | local max = util.get_safe_d(2, option, "decodemax" ) 63 | local cur = v 64 | 65 | if util.get_safe( option, "unifydecode" ) and 66 | decoder then 67 | for i = 1, max do 68 | -- 1. unifydecode 69 | local result, suc = decoder.unify_decode( cur, 2 ) 70 | if suc and #cur ~= #result then 71 | table.insert( ret, result ) 72 | cur = result 73 | end 74 | 75 | -- 2. base64decode 76 | if util.get_safe( option, "base64decode" ) then 77 | local result, suc = decoder.base64_decode( cur ) 78 | if suc and #cur ~= #result then 79 | local ret_inner = build_decoded_list( result, option ) 80 | for _, v in ipairs( ret_inner ) do 81 | table.insert( ret, v ) 82 | end 83 | end 84 | end 85 | end 86 | elseif decoder then 87 | for i = 1, max do 88 | local more = false 89 | -- 1. urldecode 90 | if util.get_safe( option, "urldecode" ) then 91 | local result = decoder.url_decode( cur ) 92 | if #cur ~= #result then 93 | table.insert( ret, result ) 94 | more = true 95 | cur = result 96 | end 97 | end 98 | 99 | -- 2. htmldecode 100 | if util.get_safe( option, "htmldecode" ) and 101 | decoder then 102 | local result, suc = decoder.html_decode( cur, 2 ) 103 | if suc and #cur ~= #result then 104 | table.insert( ret, result ) 105 | more = true 106 | cur = result 107 | end 108 | end 109 | 110 | -- 3. escapedecode 111 | if util.get_safe( option, "escapedecode" ) and 112 | decoder then 113 | local result, suc = decoder.escape_decode( cur, 2 ) 114 | if suc and #cur ~= #result then 115 | table.insert( ret, result ) 116 | more = true 117 | cur = result 118 | end 119 | end 120 | 121 | -- 4. base64decode 122 | if util.get_safe( option, "base64decode" ) then 123 | local result, _ = decoder.base64_decode( cur ) 124 | if result and #cur ~= #result then 125 | local ret_inner = build_decoded_list( result, option ) 126 | for _, v in ipairs( ret_inner ) do 127 | table.insert( ret, v ) 128 | end 129 | end 130 | end 131 | 132 | if more ~= true then 133 | break 134 | end 135 | end 136 | else 137 | for i = 1, max do 138 | local more = false 139 | -- 1. urldecode 140 | if util.get_safe( option, "urldecode" ) then 141 | local result = ngx.unescape_uri( cur ) 142 | if #cur ~= #result then 143 | table.insert( ret, result ) 144 | more = true 145 | cur = result 146 | end 147 | end 148 | 149 | -- 2. base64decode 150 | if util.get_safe( option, "base64decode" ) then 151 | local result = ngx.decode_base64( cur ) 152 | if result and #cur ~= #result then 153 | local ret_inner = build_decoded_list( result, option ) 154 | for _, v in ipairs( ret_inner ) do 155 | table.insert( ret, v ) 156 | end 157 | end 158 | end 159 | 160 | if more ~= true then 161 | break 162 | end 163 | end 164 | end 165 | 166 | return ret 167 | 168 | end 169 | 170 | return { 171 | decode_body = decode_body, 172 | build_decoded_list = build_decoded_list, 173 | } 174 | -------------------------------------------------------------------------------- /tools/quickstart.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import argparse 3 | import re 4 | import sys 5 | import glob 6 | import json 7 | import os 8 | 9 | 10 | 11 | parser = argparse.ArgumentParser() 12 | parser.add_argument("--dir", "-d", type=str, default='coreruleset-3.3.4') 13 | parser.add_argument("--out", "-o", type=str, help="output pattern json path", default="tools/crs_patterns.json") 14 | parser.add_argument("--yml", "-y", type=str, help="output pattern yaml path", default="tools/crs_patterns.yml") 15 | parser.add_argument("--service", "-s", type=str, help="SERVICE NAME OR ID", required=True) 16 | parser.add_argument("--adminhost", "-ah", type=str, help="Admin host", default="localhost") 17 | parser.add_argument("--adminport", "-ap", type=str, help="Admin Port", default="8001") 18 | parser.add_argument("--mode", "-m", type=str, help="Admin Port", default="") 19 | args = parser.parse_args() 20 | 21 | 22 | yaml_cnv = True 23 | try: 24 | import yaml 25 | except ImportError: 26 | print("you need to install pyyaml refer below or manually convert json to yaml") 27 | print('\n pip install pyyaml \n') 28 | yaml_cnv = False 29 | 30 | def out_plugins_format(patterns:dict, outpath:str, outyaml:str) -> None: 31 | 32 | patterns.pop("all") 33 | json.dump(patterns, open(outpath, "w", encoding="utf-8"), ensure_ascii=False, indent=2) 34 | print(f"saved {outpath}") 35 | if yaml_cnv: 36 | yaml.dump(patterns, open(outyaml, "w", encoding="utf-8"), default_flow_style=False) 37 | print(f"saved {outyaml}") 38 | return 39 | 40 | 41 | def read_core_rule_set(crsdir, id_rules) -> dict: 42 | patterns, rule_patterns = load_regex_assembly(crsdir, id_rules) 43 | summerized = { 44 | "all": patterns 45 | } 46 | summerized.update(rule_patterns) 47 | return summerized 48 | 49 | def is_regex_line(line) -> bool: 50 | if line.startswith("#") or len(line) == 0 or re.search("##!", line): 51 | return False 52 | return True 53 | 54 | def load_regex_assembly(crsdir, id_rules): 55 | patter_list = list() 56 | rule_patterns = dict() 57 | build_dir = crsdir + "/util/regexp-assemble/build/" 58 | regex_dir = crsdir + "/util/regexp-assemble/" 59 | loaded = set() 60 | 61 | def match_rules(baseid:str, id_rules:dict) -> str: 62 | if baseid in id_rules: 63 | return id_rules[baseid] 64 | for i in range(1, len(baseid)): 65 | mid = baseid[:-i] 66 | for rl, rid in id_rules.items(): 67 | mir = rid[:-i] 68 | if mid == mir: 69 | return rid 70 | 71 | 72 | def load_dir(_dir_path): 73 | if is_debug(): 74 | print(f"{_dir_path} path exist", os.path.exists(_dir_path)) 75 | for df in glob.glob(_dir_path+"*.data"): 76 | basename = os.path.basename(df) 77 | baseid = re.search("[0-9]+", basename).group() 78 | if not re.search("[0-9]+.data", basename) or basename in loaded: 79 | continue 80 | loaded.add(basename) 81 | rule_name = match_rules(baseid, id_rules) 82 | if rule_name not in rule_patterns: 83 | rule_patterns[rule_name] = list() 84 | with open(df, 'r', encoding='utf-8') as f: 85 | _read = f.read() 86 | for l in _read.split('\n'): 87 | if is_regex_line(l): 88 | patter_list.append(l) 89 | rule_patterns[rule_name].append(l) 90 | return 91 | load_dir(build_dir) 92 | load_dir(regex_dir) 93 | 94 | return patter_list, rule_patterns 95 | 96 | 97 | def get_secrule(line) -> str or None: 98 | secrule = None 99 | if re.search("SecRule", line): 100 | secrule = re.sub("SecRule ", "", line) 101 | secrule = re.sub('".+', '', secrule) 102 | secrule = secrule.strip() 103 | return secrule 104 | 105 | def get_secid(line) -> str or None: 106 | secid = None 107 | line = line.strip() 108 | if re.match('"id:[0-9]+', line): 109 | secid = re.search("[0-9]+", line).group() 110 | return secid 111 | 112 | 113 | def need_build(line) -> bool: 114 | return bool(re.search("\./regexp-assemble(-v2)?\.pl", line)) 115 | 116 | 117 | 118 | def load_rules_conf(crsdir) -> dict: 119 | id_rules = dict() 120 | nbuild = list() 121 | for conf in glob.glob(crsdir+"/rules/*.conf"): 122 | with open(conf, 'r', encoding='utf-8') as f: 123 | _read = f.read() 124 | current_rule = str() 125 | for l in _read.split('\n'): 126 | if get_secrule(l): 127 | current_rule = get_secrule(l) 128 | if get_secid(l): 129 | id_rules[current_rule] = get_secid(l) 130 | _id = get_secid(l) 131 | if need_build(l): 132 | nfile = re.sub("\./regexp-assemble(-v2)?\.pl (<)?", "", l) 133 | nfile = re.sub("#", "", nfile) 134 | nfile = nfile.strip() 135 | if re.search("\.txt", nfile): 136 | continue 137 | if nfile in nbuild: 138 | continue 139 | nbuild.append(nfile) 140 | 141 | file_nums = [re.search("[0-9]+", f).group() for f in nbuild] 142 | file_nums.sort() 143 | return id_rules 144 | 145 | def is_debug(): 146 | return bool(args.mode == "debug") 147 | 148 | 149 | 150 | def get_plugin_id(plugin_name): 151 | r = requests.request("GET", "http://"+args.adminhost+":"+args.adminport+"/services/"+args.service+"/plugins/") 152 | parsed = json.loads(r.text) 153 | for conf in parsed["data"]: 154 | if conf["name"] == plugin_name: 155 | return conf["id"] 156 | return None 157 | 158 | 159 | def put_config(plugin_name, pl_config): 160 | header = {"Content-Type": "application/json"} 161 | data = { 162 | "name": plugin_name, 163 | "config": pl_config 164 | } 165 | plugin_id = get_plugin_id(plugin_name) 166 | r = requests.request("PUT", "http://"+args.adminhost+":"+args.adminport+"/services/"+args.service+"/plugins/"+plugin_id, headers=header, data=json.dumps(data)) 167 | parsed = json.loads( r.text ) 168 | 169 | if is_debug(): 170 | print("\033[91mdata: \033[0m", data) 171 | print("\033[91mresponse: \033[0m", r.text) 172 | 173 | if "name" in parsed and parsed["name"] in ["schema violation"]: 174 | raise NotImplementedError("Configure error.\nPlease Check your config file.") 175 | return 176 | 177 | 178 | def set_safehost_default_settings(): 179 | # get service host 180 | r = requests.request("GET", "http://"+args.adminhost+":"+args.adminport+"/services/"+args.service) 181 | parsed = json.loads(r.text) 182 | tgt_host = parsed["host"] 183 | port = parsed["port"] 184 | if port not in ["80"]: 185 | tgt_host = tgt_host+":"+str(port) 186 | tgt_host = parsed['protocol'] + "://" + tgt_host 187 | config = {"host_check": tgt_host} 188 | plugin_id = get_plugin_id("ssk-safehost") 189 | if plugin_id is not None: 190 | put_config("ssk-safehost", config) 191 | else: 192 | print("ssk-safehost is not configured.You have to set manuallly.") 193 | 194 | return 195 | 196 | 197 | def set_patterns_default_settings(patterns): 198 | 199 | confing_patterns = [{"name": name, "patterns": pat} for name, pat in patterns.items()] 200 | patterkeys = [name for name in patterns.keys()] 201 | config = { 202 | "patterns": confing_patterns, 203 | "params": [ 204 | {"in": "*", "key": "*", "patterns": patterkeys} 205 | ] 206 | } 207 | put_config("ssk-pm", config) 208 | return 209 | 210 | 211 | 212 | 213 | def main(): 214 | 215 | id_rules = load_rules_conf(args.dir) 216 | sumpatterns = read_core_rule_set(args.dir, id_rules) 217 | allpatter = sumpatterns["all"] 218 | out_plugins_format(sumpatterns, args.out, args.yml) 219 | 220 | set_safehost_default_settings() 221 | set_patterns_default_settings(sumpatterns) 222 | 223 | 224 | 225 | # 226 | 227 | 228 | if __name__ == "__main__": 229 | main() 230 | 231 | -------------------------------------------------------------------------------- /kong/plugins/ssk-core/request.lua: -------------------------------------------------------------------------------- 1 | local common = require "kong.plugins.ssk-core.common" 2 | local util = require "kong.plugins.ssk-core.lib.utils" 3 | local ssk = require "kong.plugins.ssk-core.lib.ssk" 4 | local decoder = require "kong.plugins.ssk-core.decoder" 5 | 6 | 7 | local function preserve_exit(s, b, h) 8 | kong.ctx.shared.cap.preserve_exit = { 9 | status = s, 10 | body = b, 11 | headers = h, 12 | } 13 | end 14 | 15 | local function call_preserved_exit() 16 | local preserved = kong.ctx.shared.cap.preserve_exit 17 | if preserved then 18 | kong.response.exit( preserved.status, preserved.body, preserved.headers ) 19 | end 20 | end 21 | 22 | local function parse_body_cb( bodyparam, body, body_mime) 23 | local params = require "kong.plugins.ssk-core.params" 24 | local handlers = kong.ctx.plugin.handlers 25 | 26 | --- run body param 27 | if bodyparam and util.get_safe(handlers, "param_req_body") then 28 | if body_mime and string.find(body_mime, "urlencoded") ~= nil then 29 | params.detect_param_urlencoded( "param_req_body", bodyparam ) 30 | else 31 | params.detect_param_main( "param_req_body", bodyparam ) 32 | end 33 | 34 | end 35 | 36 | --- run body raw 37 | local req_body_n = #util.get_safe_d({}, handlers, "req_body" ) 38 | if req_body_n > 0 then 39 | local v = body 40 | local v_list = decoder.build_decoded_list( v, kong.ctx.shared.cap.options["req_body"]) 41 | for i = 1, #util.get_safe_d({}, handlers, "req_body" ) do 42 | local handler_info = handlers.req_body[i] 43 | local err = handler_info.h( v, v_list, unpack( handler_info.args ) ) 44 | common.store_detected( err ) 45 | end 46 | end 47 | end 48 | 49 | local function get_body_by_memory() 50 | -- CAUTION : DO NOT CALL get_raw_body several time! 51 | -- NOTE : In kong, phase_access will called once. 52 | return kong.request.get_raw_body() 53 | end 54 | 55 | local function parse_body( h_req_body, h_param_req_body) 56 | 57 | -- NOTE: In Kong, access phase will be called end of request body 58 | -- if body is nil, it means need to read file 59 | -- if body is "", it means no body 60 | local body = get_body_by_memory() 61 | if body ~= nil then 62 | -- by memory 63 | -- use native kong parser 64 | local body_param, _, reqbody_mimetype = kong.request.get_body() 65 | 66 | parse_body_cb( body_param, body, reqbody_mimetype ) 67 | 68 | else 69 | local parsers = util.get_safe_d({}, kong.ctx.shared.cap.handlers, "parse_req_body" ) 70 | for i = 1, #parsers do 71 | local handler_info = parsers[i] 72 | handler_info.h( "parse_req_body", parse_body_cb, unpack(handler_info.args) ) 73 | end 74 | end 75 | end 76 | 77 | local function detect_request_body( handlers ) 78 | 79 | if not util.get_safe(kong.ctx.shared.cap, "req_body") and 80 | (util.get_safe(handlers, "req_body") or 81 | util.get_safe(handlers, "param_req_body")) then 82 | 83 | parse_body( util.get_safe(handlers, "req_body") , util.get_safe(handlers, "param_req_body") ) 84 | end 85 | 86 | end 87 | 88 | local function detect_request( handlers, req_params ) 89 | local params = require "kong.plugins.ssk-core.params" 90 | 91 | -- run handler 92 | --- run path 93 | local req_path_n = #util.get_safe_d({}, handlers, "req_path" ) 94 | if req_path_n > 0 then 95 | local v = ssk.get_raw_path() 96 | local v_list = decoder.build_decoded_list( v, kong.ctx.shared.cap.options["req_path"]) 97 | for i = 1, #util.get_safe_d({}, handlers, "req_path" ) do 98 | local handler_info = handlers.req_path[i] 99 | local err = handler_info.h( v, v_list, unpack( handler_info.args ) ) 100 | common.store_detected( err ) 101 | end 102 | end 103 | 104 | --- run query 105 | local req_path_n = #util.get_safe_d({}, handlers, "req_query" ) 106 | if req_path_n > 0 then 107 | local v = kong.request.get_raw_query() 108 | local v_list = decoder.build_decoded_list( v, kong.ctx.shared.cap.options["req_query"]) 109 | for i = 1, #util.get_safe_d({}, handlers, "req_query" ) do 110 | local handler_info = handlers.req_query[i] 111 | local err = handler_info.h( v, v_list, unpack( handler_info.args ) ) 112 | common.store_detected( err ) 113 | end 114 | end 115 | --- run header 116 | for i = 1, #util.get_safe_d({}, handlers, "req_header" ) do 117 | local handler_info = handlers.req_header[i] 118 | local err = handler_info.h( req_params.header, unpack( handler_info.args ) ) 119 | common.store_detected( err ) 120 | end 121 | 122 | 123 | --- run params 124 | if util.get_safe(handlers, "param_req_query") then 125 | params.detect_param_urlencoded( "param_req_query", req_params.queryparam ) 126 | end 127 | if util.get_safe(handlers, "param_req_path") then 128 | params.detect_param_main( "param_req_path", req_params.pathparam ) 129 | end 130 | if util.get_safe(handlers, "param_req_cookie") then 131 | params.detect_param_main( "param_req_cookie", req_params.cookieparam ) 132 | end 133 | if util.get_safe(handlers, "param_req_header") then 134 | params.detect_param_main( "param_req_header", req_params.header ) 135 | end 136 | 137 | detect_request_body( handlers ) 138 | 139 | 140 | --- run after access 141 | for i = 1, #util.get_safe_d({}, handlers, "after_access" ) do 142 | local handler_info = handlers.after_access[i] 143 | local err = handler_info.h( params.header, unpack( handler_info.args ) ) 144 | common.store_detected( err ) 145 | end 146 | 147 | local ret = kong.ctx.shared.detected_info 148 | kong.ctx.shared.detected_info = nil 149 | return ret 150 | end 151 | 152 | local function parse_cookie() 153 | local ck = require "resty.cookie" 154 | local cookie, err = ck:new() 155 | if err then return {} end 156 | local fields, err = cookie:get_all() 157 | if err then return {} end 158 | return fields 159 | end 160 | 161 | local function make_path_param( pathsplit, matcher) 162 | local ret = {} 163 | if #pathsplit < #matcher then return nil end 164 | 165 | for ii = 1, #matcher do 166 | local frag = util.get_safe( matcher, ii ) 167 | local key = util.get_safe( frag, "key" ) 168 | 169 | if key then 170 | ret[key] = pathsplit[ii] 171 | elseif util.get_safe( frag, "splited" ) ~= pathsplit[ii] then 172 | return nil 173 | --elseif util.get_safe( frag, "splited" ) == pathsplit[ii] 174 | -- continue 175 | end 176 | end 177 | return ret 178 | end 179 | 180 | local function match_path_param( pathsplit, matchlist ) 181 | if not matchlist then return {} end 182 | for i = 1, #matchlist do 183 | local ret = make_path_param( pathsplit, matchlist[i] ) 184 | if ret ~= nil then 185 | return ret 186 | end 187 | end 188 | return {} 189 | end 190 | 191 | local function phase_access( handlers ) 192 | if not kong.ctx.shared.cap.req_params then kong.ctx.shared.cap.req_params = {} end 193 | local params = kong.ctx.shared.cap.req_params 194 | 195 | if not util.get_safe(params, "pathparam") and 196 | util.get_safe(handlers, "param_req_path") then 197 | 198 | local pathsplit = util.split( ssk.get_raw_path(), "/") 199 | params["pathparam"] = match_path_param( pathsplit, kong.ctx.shared.cap.options["path_split"]) 200 | end 201 | 202 | if not util.get_safe(params, "queryparam") and 203 | (util.get_safe(handlers, "req_query") or 204 | util.get_safe(handlers, "param_req_query")) then 205 | 206 | params["queryparam"] = ssk.get_query() 207 | end 208 | 209 | if not util.get_safe(params, "cookieparam") and 210 | util.get_safe(handlers, "param_req_cookie") then 211 | params["cookieparam"] = parse_cookie() 212 | end 213 | 214 | if not util.get_safe(params, "header") and 215 | ( util.get_safe(handlers, "req_header") or 216 | util.get_safe(handlers, "param_req_header"))then 217 | params["header"] = kong.request.get_headers() 218 | end 219 | 220 | return true 221 | end 222 | 223 | local function run_access_handler() 224 | local handlers = kong.ctx.plugin.handlers 225 | local params = kong.ctx.shared.cap.req_params 226 | 227 | --- run params 228 | local detected = detect_request( handlers, params ) 229 | if detected then 230 | local blocked = common.on_detect_list( detected ) 231 | if blocked then return end 232 | end 233 | 234 | --- if have preserved exit 235 | call_preserved_exit() 236 | 237 | return 238 | end 239 | 240 | return { 241 | preserve_exit = preserve_exit, 242 | run_access_handler = run_access_handler, 243 | phase_access = phase_access, 244 | } 245 | -------------------------------------------------------------------------------- /kong/plugins/ssk-strictparameter/handler.lua: -------------------------------------------------------------------------------- 1 | local core = require "kong.plugins.ssk-core.core" 2 | local ssk = require "kong.plugins.ssk-core.lib.ssk" 3 | local matcher = require "kong.plugins.ssk-core.lib.matcher" 4 | 5 | -- luacheck: no unused 6 | local CODE_STRICTPARAM = 1800 7 | local DETECT_CODE_STRICTPARAM_BASE = CODE_STRICTPARAM 8 | -- luacheck: unused 9 | local DETECT_CODE_STRICTPARAM_TYPE = 1801 10 | local DETECT_CODE_STRICTPARAM_REQUIRED = 1802 11 | local DETECT_CODE_STRICTPARAM_MIN = 1803 12 | local DETECT_CODE_STRICTPARAM_MAX = 1804 13 | 14 | 15 | -- https://swagger.io/specification/#dataTypeFormat 16 | local function build() 17 | local ret = {} 18 | 19 | ret["boolean"] = matcher.build( "^(true|false)$" ) 20 | ret["int"] = matcher.build( "^[0-9]+$" ) 21 | ret["integer"] = matcher.build( "^[0-9]+$" ) 22 | ret["number"] = matcher.build( "^[+-]?\\d+([.]\\d+([Ee][+-]\\d+)?)?$" ) 23 | ret["uuid"] = matcher.build( "^[0-9a-fA-F-]+$" ) 24 | local full_date = '\\d{4}-\\d{2}-\\d{2}' 25 | local time_delta = '(Z|[+-]\\d{2}:\\d{2})' 26 | local full_time = '\\d{2}:\\d{2}:\\d{2}([.]\\d+)?' .. time_delta 27 | local date_time = full_date .. "T" .. full_time 28 | 29 | ret["date"] = matcher.build( "^".. full_date .. "$" ) 30 | ret["date-time"] = matcher.build( "^".. date_time .. "$" ) 31 | 32 | return ret 33 | end 34 | 35 | 36 | local function make_param_map( params ) 37 | local ret = {} 38 | if params then 39 | for i = 1, #params do 40 | local cat = params[i]["in"] 41 | local key = params[i]["key"] 42 | if not cat then cat = "param_req_*" end 43 | 44 | if not ret[cat] then 45 | ret[cat] = {} 46 | end 47 | 48 | if params[i]["type"] == "regex" and params[i]["pattern"] then 49 | params[i]["pattern_ud"] = matcher.build(params[i]["pattern"]) 50 | end 51 | 52 | ret[cat][key] = params[i] 53 | end 54 | end 55 | 56 | return ret 57 | end 58 | 59 | local function make_req_map( params ) 60 | local ret = {} 61 | if params then 62 | for i = 1, #params do 63 | if params[i]["required"] then 64 | local cat = params[i]["in"] 65 | if not ret[cat] then 66 | ret[cat] = {} 67 | end 68 | local key = params[i]["key"] 69 | ret[cat][key] = false 70 | end 71 | end 72 | end 73 | 74 | return ret 75 | end 76 | 77 | 78 | local _M = core:extend() 79 | 80 | function _M:initialize_global() 81 | if not self.type_tbl then 82 | self.type_tbl = build() 83 | end 84 | end 85 | 86 | local function initialize( config ) 87 | 88 | if config["param_map"] == nil then 89 | config["param_map"] = make_param_map( config["params"] ) 90 | end 91 | 92 | ssk.get_ctx(CODE_STRICTPARAM).required_map = make_req_map( config["params"] ) 93 | end 94 | 95 | 96 | 97 | local function check_regex( pattern_ud, target ) 98 | local a, _ = matcher.match( target, pattern_ud, 1, 0 ) 99 | if a ~= nil then return true end 100 | return false 101 | end 102 | 103 | local function check_type( t, target ) 104 | -- if not defined type, allow 105 | if not _M.type_tbl[t] then 106 | return true 107 | end 108 | 109 | local a, _ = matcher.match( target, _M.type_tbl[t], 1, 0 ) 110 | 111 | if a ~= nil then return true end 112 | return false 113 | end 114 | 115 | local function h( cat, k, v, _, params, tags ) 116 | 117 | local param = params[k] 118 | 119 | if param then 120 | if param["required"] then 121 | ssk.get_ctx(CODE_STRICTPARAM).required_map[cat][k] = true 122 | end 123 | 124 | if param["type"] ~= nil then 125 | if param["type"] == "regex" and param["pattern_ud"] then 126 | if not check_regex( param["pattern_ud"], v ) then 127 | return { detect_code = DETECT_CODE_STRICTPARAM_TYPE, tags = tags, 128 | details = { 129 | ["key"] = param["key"], 130 | ["value"] = v, 131 | ["type"] = param["type"], 132 | ["pattern"] = param["pattern"] 133 | }} 134 | end 135 | else 136 | if not check_type( param["type"], v) then 137 | return { detect_code = DETECT_CODE_STRICTPARAM_TYPE, tags = tags, 138 | details = { 139 | ["key"] = param["key"], 140 | ["value"] = v, 141 | ["type"] = param["type"] 142 | }} 143 | end 144 | end 145 | end 146 | if param["min"] ~= nil then 147 | if param["type"] == "int" or 148 | param["type"] == "integer" or 149 | param["type"] == "number" then 150 | local num = tonumber( v ) 151 | if num == nil then 152 | return { detect_code = DETECT_CODE_STRICTPARAM_TYPE, tags = tags, 153 | details = { 154 | ["key"] = param["key"], 155 | ["value"] = v, 156 | ["type"] = param["type"] 157 | }} 158 | end 159 | if num < param["min"] then 160 | return { detect_code = DETECT_CODE_STRICTPARAM_MIN, tags = tags, 161 | details = { 162 | ["key"] = param["key"], 163 | ["value"] = v, 164 | ["min"] = param["min"] 165 | }} 166 | end 167 | else 168 | if string.len(v) < param["min"] then 169 | return { detect_code = DETECT_CODE_STRICTPARAM_MIN, tags = tags, 170 | details = { 171 | ["key"] = param["key"], 172 | ["value"] = v, 173 | ["min"] = param["min"] 174 | }} 175 | end 176 | end 177 | end 178 | 179 | if param["max"] ~= nil then 180 | if param["type"] == "int" or 181 | param["type"] == "integer" or 182 | param["type"] == "number" then 183 | local num = tonumber( v ) 184 | if num == nil then 185 | return { detect_code = DETECT_CODE_STRICTPARAM_TYPE, tags = tags, 186 | details = { 187 | ["key"] = param["key"], 188 | ["value"] = v, 189 | ["type"] = param["type"] 190 | }} 191 | end 192 | if num > param["max"] then 193 | return { detect_code = DETECT_CODE_STRICTPARAM_MAX, tags = tags, 194 | details = { 195 | ["key"] = param["key"], 196 | ["value"] = v, 197 | ["max"] = param["max"] 198 | }} 199 | end 200 | else 201 | if string.len(v) > param["max"] then 202 | return { detect_code = DETECT_CODE_STRICTPARAM_MAX, tags = tags, 203 | details = { 204 | ["key"] = param["key"], 205 | ["value"] = v, 206 | ["max"] = param["max"] 207 | }} 208 | end 209 | end 210 | end 211 | end 212 | end 213 | 214 | local function after_access( tags ) 215 | for _, params in pairs( ssk.get_ctx(CODE_STRICTPARAM).required_map ) do 216 | for k,v in pairs( params ) do 217 | if not v then 218 | return { detect_code = DETECT_CODE_STRICTPARAM_REQUIRED, tags = tags, 219 | details = { 220 | ["key"] = k 221 | }} 222 | end 223 | end 224 | end 225 | end 226 | 227 | 228 | function _M:init_handler( config ) 229 | self:initialize_global() 230 | initialize(config) 231 | 232 | for cat, params in pairs( config["param_map"] ) do 233 | self:add_param_handler( cat, config, h, params, config.tags ) 234 | end 235 | 236 | self:add_handler( "after_access", after_access, config.tags ) 237 | end 238 | 239 | 240 | return _M 241 | -------------------------------------------------------------------------------- /kong/plugins/ssk-libinjection/libinjection.lua: -------------------------------------------------------------------------------- 1 | -- Copyright 2017 Robert Paprocki BSD-3 2 | -- https://github.com/p0pr0ck5/lua-ffi-libinjection 3 | -- bdbff0fc5ac5b50e7e010d8e7184eb66122a7668 4 | 5 | local _M = {} 6 | 7 | local bit = require "bit" 8 | local ffi = require "ffi" 9 | 10 | local ffi_new = ffi.new 11 | local ffi_string = ffi.string 12 | 13 | -- enum sqli_flags 14 | local FLAG_NONE = 0 15 | local FLAG_QUOTE_NONE = 1 16 | local FLAG_QUOTE_SINGLE = 2 17 | local FLAG_QUOTE_DOUBLE = 4 18 | local FLAG_SQL_ANSI = 8 19 | local FLAG_SQL_MYSQL = 16 20 | 21 | -- enum lookup_type 22 | local LOOKUP_FINGERPRINT = 4 23 | 24 | -- enum html5_flags 25 | local DATA_STATE = 0 26 | local VALUE_NO_QUOTE = 1 27 | local VALUE_SINGLE_QUOTE = 2 28 | local VALUE_DOUBLE_QUOTE = 3 29 | local VALUE_BACK_QUOTE = 4 30 | 31 | -- cached ORs 32 | local QUOTE_NONE_SQL_ANSI = bit.bor(FLAG_QUOTE_NONE, FLAG_SQL_ANSI) 33 | local QUOTE_NONE_SQL_MYSQL = bit.bor(FLAG_QUOTE_NONE, FLAG_SQL_MYSQL) 34 | local QUOTE_SINGLE_SQL_ANSI = bit.bor(FLAG_QUOTE_SINGLE, FLAG_SQL_ANSI) 35 | local QUOTE_SINGLE_SQL_MYSQL = bit.bor(FLAG_QUOTE_SINGLE, FLAG_SQL_MYSQL) 36 | local QUOTE_DOUBLE_SQL_MYSQL = bit.bor(FLAG_QUOTE_DOUBLE, FLAG_SQL_MYSQL) 37 | 38 | -- libibjection.so 39 | ffi.cdef[[ 40 | const char* libinjection_sqli_fingerprint(struct libinjection_sqli_state* sql_state, int flags); 41 | 42 | struct libinjection_sqli_token { 43 | char type; 44 | char str_open; 45 | char str_close; 46 | size_t pos; 47 | size_t len; 48 | int count; 49 | char val[32]; 50 | }; 51 | 52 | typedef char (*ptr_lookup_fn)(struct libinjection_sqli_state*, int lookuptype, const char* word, size_t len); 53 | 54 | struct libinjection_sqli_state { 55 | const char *s; 56 | size_t slen; 57 | ptr_lookup_fn lookup; 58 | void* userdata; 59 | int flags; 60 | size_t pos; 61 | struct libinjection_sqli_token tokenvec[8]; 62 | struct libinjection_sqli_token *current; 63 | char fingerprint[8]; 64 | int reason; 65 | int stats_comment_ddw; 66 | int stats_comment_ddx; 67 | int stats_comment_c; 68 | int stats_comment_hash; 69 | int stats_folds; 70 | int stats_tokens; 71 | }; 72 | 73 | void libinjection_sqli_init(struct libinjection_sqli_state * sf, const char *s, size_t len, int flags); 74 | int libinjection_is_sqli(struct libinjection_sqli_state* sql_state); 75 | 76 | int libinjection_sqli(const char* s, size_t slen, char fingerprint[]); 77 | 78 | int libinjection_is_xss(const char* s, size_t len, int flags); 79 | int libinjection_xss(const char* s, size_t slen); 80 | ]] 81 | 82 | _M.version = "0.1.1" 83 | 84 | local state_type = ffi.typeof("struct libinjection_sqli_state[1]") 85 | local lib, loaded 86 | 87 | -- "borrowed" from CF aho-corasick lib 88 | local function _loadlib() 89 | if (not loaded) then 90 | local path, so_path 91 | local libname = "libinjection.so" 92 | 93 | for k, v in string.gmatch(package.cpath, "[^;]+") do 94 | so_path = string.match(k, "(.*/)") 95 | if so_path then 96 | -- "so_path" could be nil. e.g, the dir path component is "." 97 | so_path = so_path .. libname 98 | 99 | -- Don't get me wrong, the only way to know if a file exist is 100 | -- trying to open it. 101 | local f = io.open(so_path) 102 | if f ~= nil then 103 | io.close(f) 104 | path = so_path 105 | break 106 | end 107 | end 108 | end 109 | 110 | if not path then 111 | return false 112 | end 113 | 114 | lib = ffi.load(path) 115 | 116 | if (lib) then 117 | loaded = true 118 | return true 119 | else 120 | return false 121 | end 122 | else 123 | return true 124 | end 125 | end 126 | 127 | -- this function is not publicly exposed so we need to emulate it here. not great but not a measurable perf hit 128 | local function _reparse_as_mysql(sqli_state) 129 | return sqli_state[0].stats_comment_ddx ~= 0 or sqli_state[0].stats_comment_hash ~= 0 130 | end 131 | 132 | --[[ 133 | Secondary API: detects SQLi in a string, given a context. Given a string, returns a list of 134 | 135 | * boolean indicating a match 136 | * SQLi fingerprint 137 | --]] 138 | local function _sqli_contextwrapper(string, char, flag1, flag2) 139 | if (char and not string.find(string, char, 1, true)) then 140 | return false, nil 141 | end 142 | 143 | if (not loaded) then 144 | if (not _loadlib()) then 145 | return false, nil 146 | end 147 | end 148 | 149 | local lookup, sqli_state 150 | 151 | -- allocate a new libinjection_sqli_state struct 152 | sqli_state = ffi_new(state_type) 153 | 154 | -- init the state 155 | lib.libinjection_sqli_init( 156 | sqli_state, 157 | string, 158 | #string, 159 | FLAG_NONE 160 | ) 161 | 162 | -- initial fingerprint 163 | lib.libinjection_sqli_fingerprint( 164 | sqli_state, 165 | flag1 166 | ) 167 | 168 | -- lookup 169 | lookup = sqli_state[0].lookup( 170 | sqli_state, 171 | LOOKUP_FINGERPRINT, 172 | sqli_state[0].fingerprint, 173 | #ffi.string(sqli_state[0].fingerprint) 174 | ) 175 | 176 | -- match? great, we're done 177 | if (lookup > 0) then 178 | return true, ffi_string(sqli_state[0].fingerprint) 179 | end 180 | 181 | -- no? reparse, fingerprint and lookup again 182 | if (flag2 and _reparse_as_mysql(sqli_state)) then 183 | lib.libinjection_sqli_fingerprint( 184 | sqli_state, 185 | flag2 186 | ) 187 | 188 | lookup = sqli_state[0].lookup( 189 | sqli_state, 190 | LOOKUP_FINGERPRINT, 191 | sqli_state[0].fingerprint, 192 | #ffi.string(sqli_state[0].fingerprint) 193 | ) 194 | 195 | if (lookup > 0) then 196 | return true, ffi_string(sqli_state[0].fingerprint) 197 | end 198 | end 199 | 200 | return false, nil 201 | end 202 | 203 | --[[ 204 | Wrapper for second-level API with no char context 205 | --]] 206 | function _M.sqli_noquote(string) 207 | return _sqli_contextwrapper( 208 | string, 209 | nil, 210 | QUOTE_NONE_SQL_ANSI, 211 | QUOTE_NONE_SQL_MYSQL 212 | ) 213 | end 214 | 215 | --[[ 216 | Wrapper for second-level API with CHAR_SINGLE context 217 | --]] 218 | function _M.sqli_singlequote(string) 219 | return _sqli_contextwrapper( 220 | string, 221 | "'", 222 | QUOTE_SINGLE_SQL_ANSI, 223 | QUOTE_SINGLE_SQL_MYSQL 224 | ) 225 | end 226 | 227 | --[[ 228 | Wrapper for second-level API with CHAR_DOUBLE context 229 | --]] 230 | function _M.sqli_doublequote(string) 231 | return _sqli_contextwrapper( 232 | string, 233 | '"', 234 | QUOTE_DOUBLE_SQL_MYSQL 235 | ) 236 | end 237 | 238 | --[[ 239 | Simple API. Given a string, returns a list of 240 | 241 | * boolean indicating a match 242 | * SQLi fingerprint 243 | --]] 244 | function _M.sqli(string) 245 | if (not loaded) then 246 | if (not _loadlib()) then 247 | return false, nil 248 | end 249 | end 250 | 251 | local fingerprint = ffi_new("char [8]") 252 | 253 | return lib.libinjection_sqli(string, #string, fingerprint) == 1, ffi_string(fingerprint) 254 | end 255 | 256 | --[[ 257 | Secondary API: detects XSS in a string, given a context. Given a string, returns a boolean denoting if XSS was detected 258 | --]] 259 | local function _xss_contextwrapper(string, flag) 260 | if (not loaded) then 261 | if (not _loadlib()) then 262 | return false 263 | end 264 | end 265 | 266 | return lib.libinjection_is_xss(string, #string, flag) == 1 267 | end 268 | 269 | --[[ 270 | Wrapper for second-level API with DATA_STATE flag 271 | --]] 272 | function _M.xss_data_state(string) 273 | return _xss_contextwrapper( 274 | string, 275 | DATA_STATE 276 | ) 277 | end 278 | 279 | --[[ 280 | Wrapper for second-level API with VALUE_NO_QUOTE flag 281 | --]] 282 | function _M.xss_noquote(string) 283 | return _xss_contextwrapper( 284 | string, 285 | VALUE_NO_QUOTE 286 | ) 287 | end 288 | 289 | --[[ 290 | Wrapper for second-level API with VALUE_SINGLE_QUOTE flag 291 | --]] 292 | function _M.xss_singlequote(string) 293 | return _xss_contextwrapper( 294 | string, 295 | VALUE_SINGLE_QUOTE 296 | ) 297 | end 298 | 299 | --[[ 300 | Wrapper for second-level API with VALUE_DOUBLE_QUOTE flag 301 | --]] 302 | function _M.xss_doublequote(string) 303 | return _xss_contextwrapper( 304 | string, 305 | VALUE_DOUBLE_QUOTE 306 | ) 307 | end 308 | 309 | --[[ 310 | Wrapper for second-level API with VALUE_BACK_QUOTE flag 311 | --]] 312 | function _M.xss_backquote(string) 313 | return _xss_contextwrapper( 314 | string, 315 | VALUE_BACK_QUOTE 316 | ) 317 | end 318 | 319 | --[[ 320 | ALPHA version of XSS detector. Given a string, returns a boolean denoting if XSS was detected 321 | --]] 322 | function _M.xss(string) 323 | if (not loaded) then 324 | if (not _loadlib()) then 325 | return false 326 | end 327 | end 328 | 329 | return lib.libinjection_xss(string, #string) == 1 330 | end 331 | 332 | 333 | -------------------------- 334 | -- additional code 335 | -------------------------- 336 | 337 | function _M.try_load() 338 | if (not loaded) then 339 | if (not _loadlib()) then 340 | return false 341 | end 342 | end 343 | return true 344 | end 345 | 346 | return _M 347 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | ```markdown 3 | Apache License 4 | Version 2.0, January 2004 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, 12 | and distribution as defined by Sections 1 through 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by 15 | the copyright owner that is granting the License. 16 | 17 | "Legal Entity" shall mean the union of the acting entity and all 18 | other entities that control, are controlled by, or are under common 19 | control with that entity. For the purposes of this definition, 20 | "control" means (i) the power, direct or indirect, to cause the 21 | direction or management of such entity, whether by contract or 22 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | outstanding shares, or (iii) beneficial ownership of such entity. 24 | 25 | "You" (or "Your") shall mean an individual or Legal Entity 26 | exercising permissions granted by this License. 27 | 28 | "Source" form shall mean the preferred form for making modifications, 29 | including but not limited to software source code, documentation 30 | source, and configuration files. 31 | 32 | "Object" form shall mean any form resulting from mechanical 33 | transformation or translation of a Source form, including but 34 | not limited to compiled object code, generated documentation, 35 | and conversions to other media types. 36 | 37 | "Work" shall mean the work of authorship, whether in Source or 38 | Object form, made available under the License, as indicated by a 39 | copyright notice that is included in or attached to the work 40 | (an example is provided in the Appendix below). 41 | 42 | "Derivative Works" shall mean any work, whether in Source or Object 43 | form, that is based on (or derived from) the Work and for which the 44 | editorial revisions, annotations, elaborations, or other modifications 45 | represent, as a whole, an original work of authorship. For the purposes 46 | of this License, Derivative Works shall not include works that remain 47 | separable from, or merely link (or bind by name) to the interfaces of, 48 | the Work and Derivative Works thereof. 49 | 50 | "Contribution" shall mean any work of authorship, including 51 | the original version of the Work and any modifications or additions 52 | to that Work or Derivative Works thereof, that is intentionally 53 | submitted to Licensor for inclusion in the Work by the copyright owner 54 | or by an individual or Legal Entity authorized to submit on behalf of 55 | the copyright owner. For the purposes of this definition, "submitted" 56 | means any form of electronic, verbal, or written communication sent 57 | to the Licensor or its representatives, including but not limited to 58 | communication on electronic mailing lists, source code control systems, 59 | and issue tracking systems that are managed by, or on behalf of, the 60 | Licensor for the purpose of discussing and improving the Work, but 61 | excluding communication that is conspicuously marked or otherwise 62 | designated in writing by the copyright owner as "Not a Contribution." 63 | 64 | "Contributor" shall mean Licensor and any individual or Legal Entity 65 | on behalf of whom a Contribution has been received by Licensor and 66 | subsequently incorporated within the Work. 67 | 68 | 2. Grant of Copyright License. Subject to the terms and conditions of 69 | this License, each Contributor hereby grants to You a perpetual, 70 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | copyright license to reproduce, prepare Derivative Works of, 72 | publicly display, publicly perform, sublicense, and distribute the 73 | Work and such Derivative Works in Source or Object form. 74 | 75 | 3. Grant of Patent License. Subject to the terms and conditions of 76 | this License, each Contributor hereby grants to You a perpetual, 77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | (except as stated in this section) patent license to make, have made, 79 | use, offer to sell, sell, import, and otherwise transfer the Work, 80 | where such license applies only to those patent claims licensable 81 | by such Contributor that are necessarily infringed by their 82 | Contribution(s) alone or by combination of their Contribution(s) 83 | with the Work to which such Contribution(s) was submitted. If You 84 | institute patent litigation against any entity (including a 85 | cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | or a Contribution incorporated within the Work constitutes direct 87 | or contributory patent infringement, then any patent licenses 88 | granted to You under this License for that Work shall terminate 89 | as of the date such litigation is filed. 90 | 91 | 4. Redistribution. You may reproduce and distribute copies of the 92 | Work or Derivative Works thereof in any medium, with or without 93 | modifications, and in Source or Object form, provided that You 94 | meet the following conditions: 95 | 96 | (a) You must give any other recipients of the Work or 97 | Derivative Works a copy of this License; and 98 | 99 | (b) You must cause any modified files to carry prominent notices 100 | stating that You changed the files; and 101 | 102 | (c) You must retain, in the Source form of any Derivative Works 103 | that You distribute, all copyright, patent, trademark, and 104 | attribution notices from the Source form of the Work, 105 | excluding those notices that do not pertain to any part of 106 | the Derivative Works; and 107 | 108 | (d) If the Work includes a "NOTICE" text file as part of its 109 | distribution, then any Derivative Works that You distribute must 110 | include a readable copy of the attribution notices contained 111 | within such NOTICE file, excluding those notices that do not 112 | pertain to any part of the Derivative Works, in at least one 113 | of the following places: within a NOTICE text file distributed 114 | as part of the Derivative Works; within the Source form or 115 | documentation, if provided along with the Derivative Works; or, 116 | within a display generated by the Derivative Works, if and 117 | wherever such third-party notices normally appear. The contents 118 | of the NOTICE file are for informational purposes only and 119 | do not modify the License. You may add Your own attribution 120 | notices within Derivative Works that You distribute, alongside 121 | or as an addendum to the NOTICE text from the Work, provided 122 | that such additional attribution notices cannot be construed 123 | as modifying the License. 124 | 125 | You may add Your own copyright statement to Your modifications and 126 | may provide additional or different license terms and conditions 127 | for use, reproduction, or distribution of Your modifications, or 128 | for any such Derivative Works as a whole, provided Your use, 129 | reproduction, and distribution of the Work otherwise complies with 130 | the conditions stated in this License. 131 | 132 | 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | any Contribution intentionally submitted for inclusion in the Work 134 | by You to the Licensor shall be under the terms and conditions of 135 | this License, without any additional terms or conditions. 136 | Notwithstanding the above, nothing herein shall supersede or modify 137 | the terms of any separate license agreement you may have executed 138 | with Licensor regarding such Contributions. 139 | 140 | 6. Trademarks. This License does not grant permission to use the trade 141 | names, trademarks, service marks, or product names of the Licensor, 142 | except as required for reasonable and customary use in describing the 143 | origin of the Work and reproducing the content of the NOTICE file. 144 | 145 | 7. Disclaimer of Warranty. Unless required by applicable law or 146 | agreed to in writing, Licensor provides the Work (and each 147 | Contributor provides its Contributions) on an "AS IS" BASIS, 148 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | implied, including, without limitation, any warranties or conditions 150 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any 153 | risks associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, 156 | whether in tort (including negligence), contract, or otherwise, 157 | unless required by applicable law (such as deliberate and grossly 158 | negligent acts) or agreed to in writing, shall any Contributor be 159 | liable to You for damages, including any direct, indirect, special, 160 | incidental, or consequential damages of any character arising as a 161 | result of this License or out of the use or inability to use the 162 | Work (including but not limited to damages for loss of goodwill, 163 | work stoppage, computer failure or malfunction, or any and all 164 | other commercial damages or losses), even if such Contributor 165 | has been advised of the possibility of such damages. 166 | 167 | 9. Accepting Warranty or Additional Liability. While redistributing 168 | the Work or Derivative Works thereof, You may choose to offer, 169 | and charge a fee for, acceptance of support, warranty, indemnity, 170 | or other liability obligations and/or rights consistent with this 171 | License. However, in accepting such obligations, You may act only 172 | on Your own behalf and on Your sole responsibility, not on behalf 173 | of any other Contributor, and only if You agree to indemnify, 174 | defend, and hold each Contributor harmless for any liability 175 | incurred by, or claims asserted against, such Contributor by reason 176 | of your accepting any such warranty or additional liability. 177 | 178 | END OF TERMS AND CONDITIONS 179 | 180 | APPENDIX: How to apply the Apache License to your work. 181 | 182 | To apply the Apache License to your work, attach the following 183 | boilerplate notice, with the fields enclosed by brackets "[]" 184 | replaced with your own identifying information. (Don't include 185 | the brackets!) The text should be enclosed in the appropriate 186 | comment syntax for the file format. We also recommend that a 187 | file or class name and description of purpose be included on the 188 | same "printed page" as the copyright notice for easier 189 | identification within third-party archives. 190 | 191 | Copyright 2023 CyberSecurityCloud Inc. 192 | 193 | Licensed under the Apache License, Version 2.0 (the "License"); 194 | you may not use this file except in compliance with the License. 195 | You may obtain a copy of the License at 196 | 197 | http://www.apache.org/licenses/LICENSE-2.0 198 | 199 | Unless required by applicable law or agreed to in writing, software 200 | distributed under the License is distributed on an "AS IS" BASIS, 201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | See the License for the specific language governing permissions and 203 | limitations under the License. 204 | ``` --------------------------------------------------------------------------------