使用this文章来设置 ModSecurity。但是在使用 XML 和 JSON SecRules 时从 nginx-controller 收到错误。
同时设置
enable-owasp-modsecurity-crs: true
和 enable-modsecurity: true
时,前者会覆盖推荐的 ModSecurity 设置集。这可能会令人惊讶,因为这意味着您不会启用请求正文检查,也不会解析 XML/JSON 请求,这就是我显式添加这两个 SecRules 的原因。当将这两行添加到我的入口时,
# Enable XML and JSON parsing
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\\+|/)|text/)xml" "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/json" "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
nginx-controller pod 出现错误:
one or more objects failed to apply, reason:
admission webhook "validate.nginx.ingress.kubernetes.io" denied the request:
-------------------------------------------------------------------------------
Error: exit status 1 2024/03/04 17:45:48 [emerg] 3741
#3741: unexpected "2" in /tmp/nginx/nginx-cfg4276377893:
132 nginx: [emerg] unexpected "2" in /tmp/nginx/nginx-cfg4276377893:
132 nginx: configuration file /tmp/nginx/nginx-cfg4276377893 test failed
-------------------------------------------------------------------------------
I0304 17:43:00.098748 7 controller.go:190] "Configuration changes detected, backend reload required"
E0304 17:43:00.165306 7 controller.go:205] Unexpected failure reloading the backend:
-------------------------------------------------------------------------------
Error: exit status 1
2024/03/04 17:43:00 [emerg] 3651#3651: unexpected "2" in /tmp/nginx/nginx-cfg2331967383:132
nginx: [emerg] unexpected "2" in /tmp/nginx/nginx-cfg2331967383:132
nginx: configuration file /tmp/nginx/nginx-cfg2331967383 test failed
-------------------------------------------------------------------------------
E0304 17:43:00.165351 7 queue.go:131] "requeuing" err=<
-------------------------------------------------------------------------------
Error: exit status 1
2024/03/04 17:43:00 [emerg] 3651#3651: unexpected "2" in /tmp/nginx/nginx-cfg2331967383:132
nginx: [emerg] unexpected "2" in /tmp/nginx/nginx-cfg2331967383:132
nginx: configuration file /tmp/nginx/nginx-cfg2331967383 test failed
-------------------------------------------------------------------------------
> key="prod-witc-infra/oauth2-proxy-native-redis-replicas-zdl5l"
I0304 17:43:00.165387 7 event.go:298] Event(v1.ObjectReference{Kind:"Pod", Namespace:"kube-system", Name:"rke2-ingress-nginx-controller-qjmwr", UID:"758bc746-af41-4099-9248-d5bdb627d623", APIVersion:"v1", ResourceVersion:"203713628", FieldPath:""}): type: 'Warning' reason: 'RELOAD' Error reloading NGINX:
-------------------------------------------------------------------------------
Error: exit status 1
2024/03/04 17:43:00 [emerg] 3651#3651: unexpected "2" in /tmp/nginx/nginx-cfg2331967383:132
nginx: [emerg] unexpected "2" in /tmp/nginx/nginx-cfg2331967383:132
nginx: configuration file /tmp/nginx/nginx-cfg2331967383 test failed
-------------------------------------------------------------------------------
完整的入口清单:
apiVersion: v1
data:
#https://systemweakness.com/nginx-ingress-waf-with-modsecurity-from-zero-to-hero-fa284cb6f54a
allow-snippet-annotations: "false"
# Enables ModSecurity functionality
enable-modsecurity: "true"
# Enables loading the core rule set (optional, can be enabled on specific ingresses only instead)
enable-owasp-modsecurity-crs: "true"
# Update ModSecurity config and rules
modsecurity-snippet: |
# Enable prevention mode. Can be any of: DetectionOnly,On,Off
# (default is DetectionOnly)
SecRuleEngine On
# Enable scanning of the request body
SecRequestBodyAccess On
# Enable XML and JSON parsing
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\\+|/)|text/)xml" "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/json" "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
# Max request sizes in bytes (with/without files)
# Note NGINX Ingress has its own annotations, keep in sync!
SecRequestBodyLimit 20971520 # 20Mb (default is 12.5Mb)
SecRequestBodyNoFilesLimit 262144 # 250Kb (default is 128Kb)
SecRequestBodyLimitAction Reject # Reject if larger (we could also let it pass with ProcessPartial)
# Update config to include PUT/PATCH/DELETE in the allowed HTTP methods (instead of fully disabling 911100)
SecAction "id:900200,phase:1,nolog,pass,t:none,setvar:tx.allowed_methods=GET HEAD POST OPTIONS PUT PATCH DELETE"
# Send ModSecurity audit logs to the stdout (only for rejected requests)
SecAuditLog /dev/stdout
SecAuditLogFormat JSON
SecAuditEngine RelevantOnly # could be On/Off/RelevantOnly
kind: ConfigMap
metadata:
annotations:
meta.helm.sh/release-name: rke2-ingress-nginx
meta.helm.sh/release-namespace: kube-system
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: rke2-ingress-nginx
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: rke2-ingress-nginx
app.kubernetes.io/part-of: rke2-ingress-nginx
name: rke2-ingress-nginx-controller
namespace: kube-system
调查 nginx 配置文件后:
www-data@rke2-ingress-nginx-controller-qjmwr:/etc/nginx> nginx -c /tmp/nginx/nginx-cfg4276377893
2024/03/04 19:05:48 [emerg] 4242#4242: unexpected "2" in /tmp/nginx/nginx-cfg4276377893:132
nginx: [emerg] unexpected "2" in /tmp/nginx/nginx-cfg4276377893:132
kubectl cp kube-system/rke2-ingress-nginx-controller-qjmwr:/tmp/nginx/nginx-cfg4276377893 nginx-cfg4276377893
nginx配置的第132行和133行是:
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\\+|/)|text/)xml" "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/json" "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
当我删除这两行时,一切都很好。 XML 和 JSON 解析似乎有什么问题?
当前解决方法: 删除 XML 和 JSON 解析。
XML 和 JSON SecRules 格式的固定版本:
# Enable XML and JSON parsing
SecRule REQUEST_HEADERS:Content-Type "(?:text|application(?:/soap\+|/)|application/xml)/" \
"id:200000,phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/json" \
"id:200001,phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
完成固定和工作入口清单:
apiVersion: v1
data:
#https://systemweakness.com/nginx-ingress-waf-with-modsecurity-from-zero-to-hero-fa284cb6f54a
allow-snippet-annotations: "false"
# Enables ModSecurity functionality
enable-modsecurity: "true"
# Enables loading the core rule set (optional, can be enabled on specific ingresses only instead)
enable-owasp-modsecurity-crs: "true"
# Update ModSecurity config and rules
modsecurity-snippet: |
# Enable prevention mode. Can be any of: DetectionOnly,On,Off
# (default is DetectionOnly)
SecRuleEngine On
# Enable scanning of the request body
SecRequestBodyAccess On
#Usefull for testing modsecurity is functioning: block any request containing the word attack in the URI or in the querystring, for example in:
#https://secrule.sample.com/api?task=attack
SecRule REQUEST_URI|ARGS|QUERY_STRING \"@contains attack\" \"id:100001,phase:1,t:lowercase,deny,status:403,msg:\'Attack Detected\'\"
# Enable XML and JSON parsing
SecRule REQUEST_HEADERS:Content-Type "(?:text|application(?:/soap\+|/)|application/xml)/" \
"id:200000,phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/json" \
"id:200001,phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
# Max request sizes in bytes (with/without files)
# Note NGINX Ingress has its own annotations, keep in sync!
SecRequestBodyLimit 20971520 # 20Mb (default is 12.5Mb)
SecRequestBodyNoFilesLimit 262144 # 250Kb (default is 128Kb)
SecRequestBodyLimitAction Reject # Reject if larger (we could also let it pass with ProcessPartial)
# Update config to include PUT/PATCH/DELETE in the allowed HTTP methods (instead of fully disabling 911100)
SecAction "id:900200,phase:1,nolog,pass,t:none,setvar:tx.allowed_methods=GET HEAD POST OPTIONS PUT PATCH DELETE"
# Send ModSecurity audit logs to the stdout (only for rejected requests)
#SecAuditLog /dev/stdout
SecAuditLogFormat JSON
# could be On/Off/RelevantOnly
SecAuditEngine RelevantOnly
kind: ConfigMap
metadata:
annotations:
meta.helm.sh/release-name: rke2-ingress-nginx
meta.helm.sh/release-namespace: kube-system
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: rke2-ingress-nginx
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: rke2-ingress-nginx
app.kubernetes.io/part-of: rke2-ingress-nginx
name: rke2-ingress-nginx-controller
namespace: kube-system