Closed ghost closed 6 years ago
Hi @slabber
Thanks for the report.
On 93e18ca5ea18659af58a9f23d057917a01b9867d and 30797a458b1f8e42905538219ea75ddc9c719a76 we have changed the way that the parser understands the element selection while using a regex. That changes may affect the problem that you are correctly facing. Do you mind to update to the most recent version of the code and perform the test again?
On the top of that, if you have the backtrace for the segfault it will be very useful. I did not managed to reproduce your problem. On c4fcb36f4cdd941fca413f85f7ff8603f257a3d9 I've made the debug logs a little bit more verbose about variable exclusion, you may want to share the debug logs as well.
Still the same. CRS 3.0.2 with:
SecRuleUpdateTargetById 942421 "!REQUEST_COOKIES:/Example/"
appended
This is a backtrace from 351beb05676ab5dd5687057f38e7cb6c82f198c0
FYI, this is using https://github.com/kubernetes/ingress-nginx/tree/master/images/nginx-slim
Program terminated with signal SIGSEGV, Segmentation fault.
#0 modsecurity::Rule::getFinalVars (this=this@entry=0x5576e09cb100, trans=trans@entry=0x5576d9a48a10) at rule.cc:465
465 rule.cc: No such file or directory.
[Current thread is 1 (Thread 0x7f3ea6121140 (LWP 1250))]
(gdb) backtrace full
#0 modsecurity::Rule::getFinalVars (this=this@entry=0x5576e09cb100, trans=trans@entry=0x5576d9a48a10) at rule.cc:465
__for_range = <optimized out>
exclusions = {<std::__cxx11::_List_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {
_M_impl = {<std::allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<__gnu_cxx::new_allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<No data fields>}, <No data fields>},
_M_node = {<std::__detail::_List_node_base> = {_M_next = 0x7ffea918bfe0, _M_prev = 0x7ffea918bfe0}, _M_data = 0}}}, <No data fields>}
exclusions_update_by_tag_remove = {<std::__cxx11::_List_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {
_M_impl = {<std::allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<__gnu_cxx::new_allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<No data fields>}, <No data fields>},
_M_node = {<std::__detail::_List_node_base> = {_M_next = 0x7ffea918c000, _M_prev = 0x7ffea918c000}, _M_data = 0}}}, <No data fields>}
exclusions_update_by_id_remove = {<std::__cxx11::_List_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {
_M_impl = {<std::allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<__gnu_cxx::new_allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<No data fields>}, <No data fields>},
_M_node = {<std::__detail::_List_node_base> = {_M_next = 0x7ffea918c020, _M_prev = 0x7ffea918c020}, _M_data = 0}}}, <No data fields>}
variables = std::vector of length 6, capacity 8 = {0x5576e09c8cc0, 0x5576e09c88b0, 0x5576e09c9590, 0x5576e09c98f0, 0x5576e09c9ad0, 0x5576e09c9bf0}
finalVars = std::vector of length 0, capacity 0
#1 0x00007f3e9e30ca2d in modsecurity::Rule::evaluate (this=this@entry=0x5576e09cb100, trans=trans@entry=0x5576d9a48a10,
ruleMessage=std::shared_ptr (count 1, weak 0) 0x5576e0c48eb0) at rule.cc:755
globalRet = false
variables = <optimized out>
recursiveGlobalRet = <optimized out>
containsDisruptive = false
finalVars = std::vector of length 0, capacity 0
eparam = "\"((?:[\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\+\\=\\{\\}\\[\\]\\|\\:\\;\\\"\\'\\\302\264\\\342\200\231\\\342\200\230\\`\\<\\>][^\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\+\\=\\{\\}\\[\\]\\|\\:\\;\\\"\\'\\\302\264\\\342\200\231\\\342\200\230\\`\\<\\>]*?){8})\""
#2 0x00007f3e9e2fede7 in modsecurity::Rules::evaluate (this=0x5576e00b99a0, phase=phase@entry=3, transaction=transaction@entry=0x5576d9a48a10)
at rules.cc:213
rule = 0x5576e09cb100
i = 280
rules = std::vector of length -11746106468198, capacity -11746106468198 = {0x5576dea83000, 0x5576ddf5a730, 0x5576ddf5afc0, 0x5576dfe3ff80,
0x5576e00ded80, 0x5576e00d3490, 0x5576e00d3b20, 0x5576e00e06d0, 0x5576e00e0c80, 0x5576e00e1400, 0x5576e00e1c30, 0x5576e00e21b0, 0x5576e00e3400,
0x5576e00e3870, 0x5576e00e3da0, 0x5576e00e4310, 0x5576e00e4980, 0x5576e00e52a0, 0x5576e00e92f0, 0x5576e00e99d0, 0x5576e00ea190, 0x5576e00ea770,
0x5576e00ead70, 0x5576e00eb350, 0x5576e00eb9e0, 0x5576e00ec040, 0x5576e00ec670, 0x5576e00ecca0, 0x5576e00dffa0, 0x5576e00ee560, 0x5576e00eeaf0,
0x5576e00efbc0, 0x5576e00f0160, 0x5576e00f13a0, 0x5576e00f4930, 0x5576e00f4f20, 0x5576e00f5da0, 0x5576e00f6ee0, 0x5576e00f81b0, 0x5576e00f9290,
0x5576e00fb460, 0x5576e00fb860, 0x5576e00fc8f0, 0x5576e00fdd60, 0x5576e00ff4d0, 0x5576e0102be0, 0x5576e0104c00, 0x5576e0105b30, 0x5576e01069d0,
0x5576e0108910, 0x5576e0108e20, 0x5576e010ac20, 0x5576e010b2d0, 0x5576e010bc00, 0x5576e010cd80, 0x5576e010f620, 0x5576e0110420, 0x5576e0111860,
0x5576e0111ed0, 0x5576e01134d0, 0x5576e0114300, 0x5576e0115680, 0x5576e0116930, 0x5576e0117cb0, 0x5576e0118d90, 0x5576e0119650, 0x5576e0119f80,
0x5576e011ade0, 0x5576e011b980, 0x5576e011c4e0, 0x5576e011cae0, 0x5576e010e850, 0x5576e011eca0, 0x5576e011f640, 0x5576e01201c0, 0x5576e0120da0,
0x5576e0121380, 0x5576e0124200, 0x5576e012a070, 0x5576e012bbf0, 0x5576e012c7b0, 0x5576e012cf80, 0x5576e00e5a20, 0x5576e012eb90, 0x5576e012fcd0,
0x5576e01bc4f0, 0x5576e01c7fd0, 0x5576e01c88f0, 0x5576e01dd520, 0x5576e01fa350, 0x5576e01fac40, 0x5576e0217750, 0x5576e0217d50, 0x5576e011da20,
0x5576e0219cf0, 0x5576e021ab90, 0x5576e021b960, 0x5576e021c920, 0x5576e021e350, 0x5576e021f5d0, 0x5576e0220b10, 0x5576e0222030, 0x5576e02229d0,
0x5576e0223b10, 0x5576e02250e0, 0x5576e02266b0, 0x5576e0227750, 0x5576e0228710, 0x5576e0229580, 0x5576e0229ba0, 0x5576e022a940, 0x5576e022e1e0,
0x5576e022fc00, 0x5576e0230570, 0x5576e0231db0, 0x5576e02327c0, 0x5576e0233a90, 0x5576e0234ce0, 0x5576e0235fa0, 0x5576e0237220, 0x5576e02388d0,
0x5576e0239e30, 0x5576e023b970, 0x5576e023c830, 0x5576e023dfb0, 0x5576e023f120, 0x5576e0240060, 0x5576e0241350, 0x5576e0242900, 0x5576e0243a30,
0x5576e0246450, 0x5576e0247550, 0x5576e02485b0, 0x5576e0248e80, 0x5576e024a120, 0x5576e024aaa0, 0x5576e024b9e0, 0x5576e024d0c0, 0x5576e024e3a0,
0x5576e024f6a0, 0x5576e024fc70, 0x5576e0250a20, 0x5576e0251f30, 0x5576e02531b0, 0x5576e02546c0, 0x5576e0255bf0, 0x5576e0256ce0, 0x5576e0257d40,
0x5576e0259010, 0x5576e0259970, 0x5576e025ad20, 0x5576e025b620, 0x5576e025bff0, 0x5576e025cf50, 0x5576e025e090, 0x5576e02626e0, 0x5576e0263670,
0x5576e0264cc0, 0x5576e0266560, 0x5576e049c5b0, 0x5576e0267600, 0x5576e0267f70, 0x5576e02689f0, 0x5576e054a520, 0x5576e054ab20, 0x5576e0218be0,
0x5576e054cbb0, 0x5576e054de40, 0x5576e054edd0, 0x5576e054f5a0, 0x5576e0550440, 0x5576e05515b0, 0x5576e0552130, 0x5576e0552740, 0x5576e054bb10,
0x5576e0554da0, 0x5576e055b850, 0x5576e0556490, 0x5576e0558f30, 0x5576e055e6d0, 0x5576e055fc20, 0x5576e05de290, 0x5576e05df610, 0x5576e05e0cc0,
0x5576e05e1ea0, 0x5576e05f4ad0, 0x5576e05f5480, 0x5576e05f6020, 0x5576e05f6bc0, 0x5576e05f73c0, 0x5576e05f8410, 0x5576e05f9af0, 0x5576e05fade0,
0x5576e0684600, 0x5576e06aaef0, 0x5576e06b1f70, 0x5576e06b3480, 0x5576e06b3f00, 0x5576e06c9c60, 0x5576e06cb220...}
#3 0x00007f3e9e2e8cb1 in modsecurity::Transaction::processRequestBody (this=0x5576d9a48a10) at transaction.cc:808
a = std::unique_ptr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> containing 0x0
fullRequest = "host: www.example.com\ncache-control: max-age=0\nuser-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36\ndnt: 1\nupgr"...
l = std::vector of length 8, capacity 8 = {0x5576da571630, 0x5576da571590, 0x5576da571460, 0x5576da5713c0, 0x5576d40b5e00, 0x5576d40b5d20,
0x5576e0c487d0, 0x5576e0c48af0}
#4 0x00007f3e9e5fc9dc in ngx_http_modsecurity_pre_access_handler () from /etc/nginx/modules/ngx_http_modsecurity_module.so
No symbol table info available.
#5 0x00005576d2261b83 in ngx_http_core_generic_phase ()
No symbol table info available.
#6 0x00005576d225d855 in ngx_http_core_run_phases ()
No symbol table info available.
#7 0x00005576d2245f4e in ngx_http_process_request ()
No symbol table info available.
#8 0x00005576d220ce48 in ngx_http_v2_state_header_complete.part.18.lto_priv ()
No symbol table info available.
#9 0x00005576d21eded0 in ngx_http_v2_read_handler.lto_priv ()
No symbol table info available.
#10 0x00005576d2256551 in ngx_epoll_process_events.lto_priv ()
No symbol table info available.
#11 0x00005576d22584df in ngx_process_events_and_timers ()
No symbol table info available.
#12 0x00005576d2269915 in ngx_worker_process_cycle ()
No symbol table info available.
#13 0x00005576d22658c9 in ngx_spawn_process ()
No symbol table info available.
#14 0x00005576d226636e in ngx_start_worker_processes ()
No symbol table info available.
#15 0x00005576d2267bb9 in ngx_master_process_cycle ()
No symbol table info available.
#16 0x00005576d21a82c1 in main ()
No symbol table info available.
(gdb)
The last entry in the debug log at level 5 is:
[4] (Rule: 942420) Executing operator "Rx" with param "((?:[\~!\@#\$\%\^\&*()-+\={}[]|\:\;\"\'\´\’\‘`\\>][^\~\!\@\#\$\%\^\&\*\(\)\-\+\=\{\}\[\]\|\:\;\"\'\´\’\‘\`\<\]*?){8})" against REQUEST_COOKIES|REQUEST_COOKIES_NAMES, except for: REQUEST_COOKIES:regex(utm)|REQUEST_COOKIES:regex(_pk_ref)|REQUEST_COOKIES:regex(utm)|REQUEST_COOKIES:regex(_pk_ref).
There is no mention of the exception added with SecRuleUpdateTargetById
In this example, the appended lines were:
SecRuleUpdateTargetById 942420 "!REQUEST_COOKIES:/Example\./"
SecRuleUpdateTargetById 942421 "!REQUEST_COOKIES:/Example\./"
Hi @slabber,
Thank you for the very detailed report. Should be fixed by 371fc03218efc205e8e42935c7d95b82c6047676. It will be great if you can confirm.
Still segfault:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 modsecurity::Rule::getFinalVars (this=this@entry=0x55ab0dc60750, trans=trans@entry=0x55ab0d360c20) at rule.cc:465
465 if (a.second->m_isExclusion) {
[Current thread is 1 (Thread 0x7f7b5ae30140 (LWP 106))]
(gdb) backtrace full
#0 modsecurity::Rule::getFinalVars (this=this@entry=0x55ab0dc60750, trans=trans@entry=0x55ab0d360c20) at rule.cc:465
__for_range = <optimized out>
exclusions = {<std::__cxx11::_List_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {
_M_impl = {<std::allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<__gnu_cxx::new_allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<No data fields>}, <No data fields>},
_M_node = {<std::__detail::_List_node_base> = {_M_next = 0x7fff25d7e4a0, _M_prev = 0x7fff25d7e4a0}, _M_data = 0}}}, <No data fields>}
exclusions_update_by_tag_remove = {<std::__cxx11::_List_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {
_M_impl = {<std::allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<__gnu_cxx::new_allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<No data fields>}, <No data fields>},
_M_node = {<std::__detail::_List_node_base> = {_M_next = 0x7fff25d7e4c0, _M_prev = 0x7fff25d7e4c0}, _M_data = 0}}}, <No data fields>}
exclusions_update_by_id_remove = {<std::__cxx11::_List_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {
_M_impl = {<std::allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<__gnu_cxx::new_allocator<std::_List_node<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {<No data fields>}, <No data fields>},
_M_node = {<std::__detail::_List_node_base> = {_M_next = 0x7fff25d7e4e0, _M_prev = 0x7fff25d7e4e0}, _M_data = 0}}}, <No data fields>}
variables = std::vector of length 6, capacity 8 = {0x55ab0dc5e310, 0x55ab0dc5df00, 0x55ab0dc5ebe0, 0x55ab0dc5ef40, 0x55ab0dc5f120, 0x55ab0dc5f240}
finalVars = std::vector of length 0, capacity 0
#1 0x00007f7b5301cded in modsecurity::Rule::evaluate (this=this@entry=0x55ab0dc60750, trans=trans@entry=0x55ab0d360c20,
ruleMessage=std::shared_ptr (count 1, weak 0) 0x55ab0130bfb0) at rule.cc:755
globalRet = false
variables = <optimized out>
recursiveGlobalRet = <optimized out>
containsDisruptive = false
finalVars = std::vector of length 0, capacity 0
eparam = "\"((?:[\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\+\\=\\{\\}\\[\\]\\|\\:\\;\\\"\\'\\\302\264\\\342\200\231\\\342\200\230\\`\\<\\>][^\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\+\\=\\{\\}\\[\\]\\|\\:\\;\\\"\\'\\\302\264\\\342\200\231\\\342\200\230\\`\\<\\>]*?){8})\""
#2 0x00007f7b5300ede7 in modsecurity::Rules::evaluate (this=0x55ab0d34efb0, phase=phase@entry=3, transaction=transaction@entry=0x55ab0d360c20)
at rules.cc:213
rule = 0x55ab0dc60750
i = 280
rules = std::vector of length -11774130250994, capacity -11774130250994 = {0x55ab0d0d5980, 0x55ab0d0d5dd0, 0x55ab0bd18340, 0x55ab0bd18930,
0x55ab0d374400, 0x55ab0d368aa0, 0x55ab0d369170, 0x55ab0d375d50, 0x55ab0d376300, 0x55ab0d376a80, 0x55ab0d3772b0, 0x55ab0d377830, 0x55ab0d378a80,
0x55ab0d378ef0, 0x55ab0d379420, 0x55ab0d379990, 0x55ab0d37a000, 0x55ab0d37a920, 0x55ab0d37e970, 0x55ab0d37f050, 0x55ab0d37f810, 0x55ab0d37fdf0,
0x55ab0d3803f0, 0x55ab0d3809d0, 0x55ab0d381060, 0x55ab0d3816c0, 0x55ab0d381cf0, 0x55ab0d382320, 0x55ab0d3755f0, 0x55ab0d383b80, 0x55ab0d3840f0,
0x55ab0d385260, 0x55ab0d385780, 0x55ab0d386a40, 0x55ab0d389fd0, 0x55ab0d38a5c0, 0x55ab0d38b440, 0x55ab0d38c580, 0x55ab0d38d850, 0x55ab0d38e930,
0x55ab0d390b00, 0x55ab0d390f00, 0x55ab0d391f90, 0x55ab0d393400, 0x55ab0d394b70, 0x55ab0d398280, 0x55ab0d39a2a0, 0x55ab0d39b1d0, 0x55ab0d39c070,
0x55ab0d39dfb0, 0x55ab0d39e4c0, 0x55ab0d3a02c0, 0x55ab0d3a0970, 0x55ab0d3a12a0, 0x55ab0d3a2430, 0x55ab0d3a4cd0, 0x55ab0d3a5ad0, 0x55ab0d3a6f10,
0x55ab0d3a7580, 0x55ab0d3a8b80, 0x55ab0d3a99b0, 0x55ab0d3aad30, 0x55ab0d3abfe0, 0x55ab0d3ad360, 0x55ab0d3ae440, 0x55ab0d3aed00, 0x55ab0d3af630,
0x55ab0d3b0490, 0x55ab0d3b1030, 0x55ab0d3b1b90, 0x55ab0d3b2190, 0x55ab0d3a3ef0, 0x55ab0d3b4350, 0x55ab0d3b4cf0, 0x55ab0d3b5870, 0x55ab0d3b6450,
0x55ab0d3b6b10, 0x55ab0d3b98b0, 0x55ab0d3bf720, 0x55ab0d3c12a0, 0x55ab0d3c1e60, 0x55ab0d3c2630, 0x55ab0d37b0a0, 0x55ab0d3c4220, 0x55ab0d3c5300,
0x55ab0d451ba0, 0x55ab0d45d670, 0x55ab0d45df90, 0x55ab0d472bc0, 0x55ab0d48f9f0, 0x55ab0d4902e0, 0x55ab0d4acdf0, 0x55ab0d4ad330, 0x55ab0d3b3140,
0x55ab0d4af430, 0x55ab0d4b02a0, 0x55ab0d4b1030, 0x55ab0d4b1ff0, 0x55ab0d4b3a30, 0x55ab0d4b4cb0, 0x55ab0d4b6160, 0x55ab0d4b7680, 0x55ab0d4b8040,
0x55ab0d4b9180, 0x55ab0d4ba750, 0x55ab0d4bbd20, 0x55ab0d4bcdc0, 0x55ab0d4bdd80, 0x55ab0d4bebf0, 0x55ab0d4bf210, 0x55ab0d4bffb0, 0x55ab0d4c3850,
0x55ab0d4c5270, 0x55ab0d4c5be0, 0x55ab0d4c7420, 0x55ab0d4c7e30, 0x55ab0d4c9100, 0x55ab0d4ca350, 0x55ab0d4cb610, 0x55ab0d4cc890, 0x55ab0d4cdf40,
0x55ab0d4cf490, 0x55ab0d4d0fd0, 0x55ab0d4d1e90, 0x55ab0d4d3610, 0x55ab0d4d4780, 0x55ab0d4d56c0, 0x55ab0d4d69b0, 0x55ab0d4d7f60, 0x55ab0d4d9090,
0x55ab0d4dbab0, 0x55ab0d4dcbb0, 0x55ab0d4ddc10, 0x55ab0d4de4e0, 0x55ab0d4df780, 0x55ab0d4e0100, 0x55ab0d4e1040, 0x55ab0d4e2720, 0x55ab0d4e3a00,
0x55ab0d4e4d00, 0x55ab0d4e52d0, 0x55ab0d4e6080, 0x55ab0d4e7590, 0x55ab0d4e8810, 0x55ab0d4e9d20, 0x55ab0d4eb250, 0x55ab0d4ec340, 0x55ab0d4ed3a0,
0x55ab0d4ee670, 0x55ab0d4eefd0, 0x55ab0d4f0380, 0x55ab0d4f0c80, 0x55ab0d4f1650, 0x55ab0d4f65d0, 0x55ab0d4f7740, 0x55ab0d4f7cf0, 0x55ab0d4ae310,
0x55ab0d4fa340, 0x55ab0d4fbbb0, 0x55ab0d731c00, 0x55ab0d4fcc50, 0x55ab0d4fd5c0, 0x55ab0d4fe040, 0x55ab0d7dfb70, 0x55ab0d7e0170, 0x55ab0d4f8bf0,
0x55ab0d7e2260, 0x55ab0d7e34c0, 0x55ab0d7e4480, 0x55ab0d7e4be0, 0x55ab0d7e5b20, 0x55ab0d7e6c20, 0x55ab0d7e77b0, 0x55ab0d7e7dc0, 0x55ab0d7e1170,
0x55ab0d7ea430, 0x55ab0d7f0ed0, 0x55ab0d7ebb20, 0x55ab0d7ee5c0, 0x55ab0d7f3d50, 0x55ab0d7f52a0, 0x55ab0d8738f0, 0x55ab0d874c70, 0x55ab0d876320,
0x55ab0d877500, 0x55ab0d88a130, 0x55ab0d88aae0, 0x55ab0d88b680, 0x55ab0d88c220, 0x55ab0d88ca20, 0x55ab0d88da40, 0x55ab0d88f140, 0x55ab0d890430,
0x55ab0d919c40, 0x55ab0d940530, 0x55ab0d9475b0, 0x55ab0d948ac0, 0x55ab0d949540, 0x55ab0d95f290, 0x55ab0d960850...}
#3 0x00007f7b52ff8cb1 in modsecurity::Transaction::processRequestBody (this=0x55ab0d360c20) at transaction.cc:808
a = std::unique_ptr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> containing 0x0
fullRequest = "host: www.example.com\ncache-control: max-age=0\nuser-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36\ndnt: 1\nupgr"...
l = std::vector of length 8, capacity 8 = {0x55ab0130c3a0, 0x55ab0130c300, 0x55ab0130c1d0, 0x55ab0130c130, 0x55ab0130c0b0, 0x55ab0130bfd0,
0x55ab06cf20d0, 0x55ab06cf2410}
I also still see nothing in the debug log for the exemptions:
[4] (Rule: 942420) Executing operator "Rx" with param "((?:[\~\!\@\#\$\%\^\&\*\(\)\-\+\=\{\}\[\]\|\:\;\"\'\´\�~@~Y\�~@~X\`\<\>][^\~\!\@\#\$\%\^\&\*\(\)\-\+\=\{{
\}\[\]\|\:\;\"\'\´\�~@~Y\�~@~X\`\<\>]*?){8})" against REQUEST_COOKIES|REQUEST_COOKIES_NAMES, except for: REQUEST_COOKIES:regex(__utm)|REQUEST_COOKIES:regex(_pkk
_ref)|REQUEST_COOKIES:regex(__utm)|REQUEST_COOKIES:regex(_pk_ref).
I can also confirm that this is with 371fc03218efc205e8e42935c7d95b82c6047676
@slabber are you using threads on nginx?
Here's the build script from kubernetes ingress:
#!/bin/bash
# Copyright 2015 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
export NGINX_VERSION=1.13.6
export NDK_VERSION=0.3.0
export VTS_VERSION=0.1.15
export SETMISC_VERSION=0.31
export STICKY_SESSIONS_VERSION=08a395c66e42
export MORE_HEADERS_VERSION=0.32
export NGINX_DIGEST_AUTH=7955af9c77598c697ac292811914ce1e2b3b824c
export NGINX_SUBSTITUTIONS=bc58cb11844bc42735bbaef7085ea86ace46d05b
export NGINX_OPENTRACING=5fa9fd9643efed5f638d0e14c63b5da99a89c7fe
export OPENTRACING_CPP=57a523922941be74569e7173c3f90e556177ec3c
export ZIPKIN_CPP=ca9597495b35194e0a7d910f1e0e74844ee26730
export MODSECURITY=a2a5858d249222938c2f5e48087a922c63d7f9d8
export BUILD_PATH=/tmp/build
export NGINX_OPENTRACING_VENDOR="ZIPKIN"
ARCH=$(uname -p)
get_src()
{
hash="$1"
url="$2"
f=$(basename "$url")
curl -sSL "$url" -o "$f"
echo "$hash $f" | sha256sum -c - || exit 10
tar xzf "$f"
rm -rf "$f"
}
mkdir "$BUILD_PATH"
cd "$BUILD_PATH"
if [[ ${ARCH} == "ppc64le" ]]; then
apt-get update && apt-get install --no-install-recommends -y software-properties-common
fi
# install required packages to build
apt-get update && apt-get install --no-install-recommends -y \
bash \
build-essential \
curl ca-certificates \
libgeoip1 \
libgeoip-dev \
patch \
libpcre3 \
libpcre3-dev \
libssl-dev \
zlib1g \
zlib1g-dev \
libaio1 \
libaio-dev \
openssl \
libperl-dev \
cmake \
util-linux \
wget \
libcurl4-openssl-dev \
procps \
git gdb vim g++ pkgconf flex bison doxygen libyajl-dev liblmdb-dev libgeoip-dev libtool dh-autoreconf libxml2 libpcre++-dev libxml2-dev \
linux-headers-generic || exit 1
mkdir -p /etc/nginx
# download GeoIP databases
wget -O /etc/nginx/GeoIP.dat.gz https://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz || { echo 'Could not download GeoLiteCountry, exiting.' ; exit 1; }
wget -O /etc/nginx/GeoLiteCity.dat.gz https://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz || { echo 'Could not download GeoLiteCity, exiting.' ; exit 1; }
gunzip -f /etc/nginx/GeoIP.dat.gz
gunzip -f /etc/nginx/GeoLiteCity.dat.gz
# download, verify and extract the source files
get_src 8512fc6f986a20af293b61f33b0e72f64a72ea5b1acbcc790c4c4e2d6f63f8f8 \
"http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz"
get_src 88e05a99a8a7419066f5ae75966fb1efc409bad4522d14986da074554ae61619 \
"https://github.com/simpl/ngx_devel_kit/archive/v$NDK_VERSION.tar.gz"
get_src 97946a68937b50ab8637e1a90a13198fe376d801dc3e7447052e43c28e9ee7de \
"https://github.com/openresty/set-misc-nginx-module/archive/v$SETMISC_VERSION.tar.gz"
get_src 5112a054b1b1edb4c0042a9a840ef45f22abb3c05c68174e28ebf483164fb7e1 \
"https://github.com/vozlt/nginx-module-vts/archive/v$VTS_VERSION.tar.gz"
get_src c6d9dab8ea1fc997031007e2e8f47cced01417e203cd88d53a9fe9f6ae138720 \
"https://github.com/openresty/headers-more-nginx-module/archive/v$MORE_HEADERS_VERSION.tar.gz"
get_src 53e440737ed1aff1f09fae150219a45f16add0c8d6e84546cb7d80f73ebffd90 \
"https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng/get/$STICKY_SESSIONS_VERSION.tar.gz"
get_src 9b1d0075df787338bb607f14925886249bda60b6b3156713923d5d59e99a708b \
"https://github.com/atomx/nginx-http-auth-digest/archive/$NGINX_DIGEST_AUTH.tar.gz"
get_src 618551948ab14cac51d6e4ad00452312c7b09938f59ebff4f93875013be31f2d \
"https://github.com/yaoweibin/ngx_http_substitutions_filter_module/archive/$NGINX_SUBSTITUTIONS.tar.gz"
get_src 7de6589e0c6e748ae1d1a2667c40224c5a5a14623b98b4103de9ae5313c4f8db \
"https://github.com/opentracing-contrib/nginx-opentracing/archive/$NGINX_OPENTRACING.tar.gz"
get_src 367636ed8211fe5d8a9db56014471923165b907f9338e2b871ed4f3c443d7dfe \
"https://github.com/opentracing/opentracing-cpp/archive/$OPENTRACING_CPP.tar.gz"
get_src cf4ebe742d7fbcc4c2f2510ab03d19f1a765ef764935ce0a53e71e9a0bd7244a \
"https://github.com/rnburn/zipkin-cpp-opentracing/archive/$ZIPKIN_CPP.tar.gz"
get_src 3abdecedb5bf544eeba8c1ce0bef2da6a9f064b216ebbe20b68894afec1d7d80 \
"https://github.com/SpiderLabs/ModSecurity-nginx/archive/$MODSECURITY.tar.gz"
#https://blog.cloudflare.com/optimizing-tls-over-tcp-to-reduce-latency/
curl -sSL -o nginx__dynamic_tls_records.patch https://raw.githubusercontent.com/cloudflare/sslconfig/master/patches/nginx__1.11.5_dynamic_tls_records.patch
# build opentracing lib
cd "$BUILD_PATH/opentracing-cpp-$OPENTRACING_CPP"
mkdir .build
cd .build
cmake -DCMAKE_BUILD_TYPE=Release ..
make
make install
# build zipkin lib
cd "$BUILD_PATH/zipkin-cpp-opentracing-$ZIPKIN_CPP"
mkdir .build
cd .build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 ..
make
make install
cd "$BUILD_PATH"
if [[ ${ARCH} == "x86_64" ]]; then
# build modsecurity library
git clone https://github.com/SpiderLabs/ModSecurity
cd ModSecurity/
git checkout -b v3/master origin/v3/master
sh build.sh
git submodule init
git submodule update
autoreconf -i
automake
autoconf
./configure
make
make install
fi
# build nginx
cd "$BUILD_PATH/nginx-$NGINX_VERSION"
echo "Applying nginx patches..."
patch -p1 < $BUILD_PATH/nginx__dynamic_tls_records.patch
WITH_FLAGS="--with-debug \
--with-pcre-jit \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_auth_request_module \
--with-http_addition_module \
--with-http_dav_module \
--with-http_geoip_module \
--with-http_gzip_static_module \
--with-http_sub_module \
--with-http_v2_module \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-threads"
if [[ ${ARCH} != "armv7l" || ${ARCH} != "aarch64" ]]; then
WITH_FLAGS+=" --with-file-aio"
fi
CC_OPT='-g -O0 -flto -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 --param=ssp-buffer-size=4 -DTCP_FASTOPEN=23 -Wno-error=strict-aliasing -fPIC'
LD_OPT='-Wl,-Bsymbolic-functions -fPIE -fPIC -pie -Wl,-z,relro -Wl,-z,now'
if [[ ${ARCH} == "x86_64" ]]; then
CC_OPT+=' -m64 -mtune=generic'
fi
WITH_MODULES="--add-module=$BUILD_PATH/ngx_devel_kit-$NDK_VERSION \
--add-module=$BUILD_PATH/set-misc-nginx-module-$SETMISC_VERSION \
--add-module=$BUILD_PATH/nginx-module-vts-$VTS_VERSION \
--add-module=$BUILD_PATH/headers-more-nginx-module-$MORE_HEADERS_VERSION \
--add-module=$BUILD_PATH/nginx-goodies-nginx-sticky-module-ng-$STICKY_SESSIONS_VERSION \
--add-module=$BUILD_PATH/nginx-http-auth-digest-$NGINX_DIGEST_AUTH \
--add-module=$BUILD_PATH/ngx_http_substitutions_filter_module-$NGINX_SUBSTITUTIONS \
--add-module=$BUILD_PATH/nginx-opentracing-$NGINX_OPENTRACING/opentracing \
--add-module=$BUILD_PATH/nginx-opentracing-$NGINX_OPENTRACING/zipkin"
if [[ ${ARCH} == "x86_64" ]]; then
WITH_MODULES+=" --add-dynamic-module=$BUILD_PATH/ModSecurity-nginx-$MODSECURITY"
fi
./configure \
--prefix=/usr/share/nginx \
--conf-path=/etc/nginx/nginx.conf \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log \
--lock-path=/var/lock/nginx.lock \
--pid-path=/run/nginx.pid \
--http-client-body-temp-path=/var/lib/nginx/body \
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
--http-proxy-temp-path=/var/lib/nginx/proxy \
--http-scgi-temp-path=/var/lib/nginx/scgi \
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
${WITH_FLAGS} \
--without-mail_pop3_module \
--without-mail_smtp_module \
--without-mail_imap_module \
--without-http_uwsgi_module \
--without-http_scgi_module \
--with-cc-opt="${CC_OPT}" \
--with-ld-opt="${LD_OPT}" \
${WITH_MODULES} \
&& make || exit 1 \
&& make install || exit 1
if [[ ${ARCH} == "x86_64" ]]; then
mkdir -p /etc/nginx/modules/
cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
fi
echo "Cleaning..."
cd /
apt-mark unmarkauto \
bash \
curl ca-certificates \
libgeoip1 \
libpcre3 \
zlib1g \
libaio1 \
xz-utils \
geoip-bin \
libyajl2 liblmdb0 libxml2 libpcre++ \
gzip \
openssl
apt-get remove -y --purge \
build-essential \
gcc-5 \
cpp-5 \
libgeoip-dev \
libpcre3-dev \
libssl-dev \
zlib1g-dev \
libaio-dev \
linux-libc-dev \
perl-modules-5.22 \
cmake \
wget \
git g++ pkgconf flex bison doxygen libyajl-dev liblmdb-dev libgeoip-dev libtool dh-autoreconf libpcre++-dev libxml2-dev \
linux-headers-generic
apt-get autoremove -y
mkdir -p /var/lib/nginx/body /usr/share/nginx/html
mv /usr/share/nginx/sbin/nginx /usr/sbin
#rm -rf "$BUILD_PATH"
rm -Rf /usr/share/man /usr/share/doc
#rm -rf /tmp/* /var/tmp/*
rm -rf /var/lib/apt/lists/*
rm -rf /var/cache/apt/archives/*
rm -rf /usr/local/modsecurity/bin
rm -rf /usr/local/modsecurity/include
rm -rf /usr/local/modsecurity/lib/libmodsecurity.a
# Download owasp modsecurity crs
cd /etc/nginx/
curl -sSL -o master.tgz https://github.com/SpiderLabs/owasp-modsecurity-crs/archive/v3.0.2/master.tar.gz
tar zxpvf master.tgz
mv owasp-modsecurity-crs-3.0.2/ owasp-modsecurity-crs
rm master.tgz
cd owasp-modsecurity-crs
mv crs-setup.conf.example crs-setup.conf
mv rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
mv rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
cd ..
# Download modsecurity.conf
mkdir modsecurity
cd modsecurity
curl -sSL -o modsecurity.conf https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended
# OWASP CRS v3 rules
echo "
Include /etc/nginx/owasp-modsecurity-crs/crs-setup.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-910-IP-REPUTATION.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-912-DOS-PROTECTION.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf
Include /etc/nginx/owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
" > /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf
So, yes. Threading is enabled by the build script from the kubernetes ingress guys.
I have recompiled and retested without threads in nginx with exactly the same results and backtrace.
Hi @slabber
I tried to mimic your scenario with that build script to reproduce the issue and I think I'm pretty close:
root@ubuntu:/usr/share/nginx/logs# nginx -V nginx version: nginx/1.13.6 built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) built with OpenSSL 1.0.2g 1 Mar 2016 TLS SNI support enabled configure arguments: --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_sub_module --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-file-aio --without-mail_pop3_module --without-mail_smtp_module --without-mail_imap_module --without-http_uwsgi_module --without-http_scgi_module --with-cc-opt='-g -O0 -flto -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 --param=ssp-buffer-size=4 -DTCP_FASTOPEN=23 -Wno-error=strict-aliasing -fPIC -m64 -mtune=generic' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -fPIC -pie -Wl,-z,relro -Wl,-z,now' --add-module=/tmp/build/ngx_devel_kit-0.3.0 --add-module=/tmp/build/set-misc-nginx-module-0.31 --add-module=/tmp/build/nginx-module-vts-0.1.15 --add-module=/tmp/build/headers-more-nginx-module-0.32 --add-module=/tmp/build/nginx-goodies-nginx-sticky-module-ng-08a395c66e42 --add-module=/tmp/build/nginx-http-auth-digest-7955af9c77598c697ac292811914ce1e2b3b824c --add-module=/tmp/build/ngx_http_substitutions_filter_module-bc58cb11844bc42735bbaef7085ea86ace46d05b --add-module=/tmp/build/nginx-opentracing-5fa9fd9643efed5f638d0e14c63b5da99a89c7fe/opentracing --add-module=/tmp/build/nginx-opentracing-5fa9fd9643efed5f638d0e14c63b5da99a89c7fe/zipkin --add-dynamic-module=/tmp/build/ModSecurity-nginx-a2a5858d249222938c2f5e48087a922c63d7f9d8
By adding different combinations of the following:
SecRuleUpdateTargetById 942420 "!REQUEST_COOKIES:/Example\./" SecRuleUpdateTargetById 942421 "!REQUEST_COOKIES:/Example\./" SecRuleUpdateTargetById 942420 "!REQUEST_COOKIES:/example/" SecRuleUpdateTargetById 942421 "!REQUEST_COOKIES:/example/" SecRuleUpdateTargetById 942420 "!REQUEST_COOKIES:/Example/" SecRuleUpdateTargetById 942421 "!REQUEST_COOKIES:/Example/"
I still couldn't reproduce this segfault.
But one thing I notice is that on the latest build I can't get SecRuleUpdateTargetById to work properly with regexes. But I could get working properly with
SecRuleUpdateTargetById 942420 "!REQUEST_COOKIES:Example" SecRuleUpdateTargetById 942421 "!REQUEST_COOKIES:Example"
And I can see the following entry in the debug logs:
[9] Variable: REQUEST_COOKIES:Example is part of the exclusion list (from update by ID), skipping...
But do notice that you only get this entry on the debug logs if there's any matching rule ID about to be triggered. This means that, on PL3 or PL4 you would need to send a request like this:
curl -i -s -k -X $'GET' -H $'Content-Type: text/html' -b $'Example=blah*********' $'http://localhost/
It would be helpful if you could share:
a) The actual full HTTP request that triggers the segfault b) Full audit logs & Debug logs c) ModSecurity configuration file d) CRS configuration file (which Paranoia level you're running?) e) Nginx configuration file (which modules you have enabled?)
Thanks for the report.
OK, here is a heavily redacted config and it won't work unless you create the certs needed for SSL. I haven't had a chance to check if this specific redacted version crashes or not but read the next comment for my strange findings:
load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;
daemon off;
worker_processes 2;
pid /run/nginx.pid;
worker_rlimit_nofile 523264;
worker_rlimit_core 600M;
working_directory /tmp/;
worker_shutdown_timeout 10s ;
events {
multi_accept on;
worker_connections 16384;
use epoll;
}
http {
real_ip_header X-Forwarded-For;
real_ip_recursive on;
set_real_ip_from 0.0.0.0/0;
geoip_country /etc/nginx/GeoIP.dat;
geoip_city /etc/nginx/GeoLiteCity.dat;
geoip_proxy_recursive on;
sendfile on;
aio on;
directio 512;
output_buffers 1 128k;
aio_write on;
tcp_nopush on;
tcp_nodelay on;
log_subrequest on;
reset_timedout_connection on;
keepalive_timeout 75s;
keepalive_requests 100;
client_header_buffer_size 1k;
client_header_timeout 60s;
large_client_header_buffers 4 8k;
client_body_buffer_size 8k;
client_body_timeout 60s;
http2_max_field_size 4k;
http2_max_header_size 16k;
types_hash_max_size 2048;
server_names_hash_max_size 1024;
server_names_hash_bucket_size 64;
map_hash_bucket_size 64;
proxy_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 64;
variables_hash_bucket_size 128;
variables_hash_max_size 2048;
underscores_in_headers off;
ignore_invalid_headers on;
include /etc/nginx/mime.types;
default_type text/html;
gzip on;
gzip_comp_level 5;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types application/atom+xml application/javascript application/x-javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component;
gzip_proxied any;
# Custom headers for response
add_header Referrer-Policy "no-referrer";
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Xss-Protection "1; mode=block";
server_tokens off;
# disable warnings
uninitialized_variable_warn off;
# Additional available variables:
# $namespace
# $ingress_name
# $service_name
log_format upstreaminfo '$the_real_ip - [$the_real_ip] - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status';
map $request_uri $loggable {
default 1;
}
access_log /var/log/nginx/access.log upstreaminfo if=$loggable;
error_log /var/log/nginx/error.log notice;
resolver 10.27.240.10 valid=30s;
# Retain the default nginx handling of requests without a "Connection" header
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
map $http_x_forwarded_for $the_real_ip {
default $remote_addr;
}
# trust http_x_forwarded_proto headers correctly indicate ssl offloading
map $http_x_forwarded_proto $pass_access_scheme {
default $http_x_forwarded_proto;
'' $scheme;
}
map $http_x_forwarded_port $pass_server_port {
default $http_x_forwarded_port;
'' $server_port;
}
map $http_x_forwarded_host $best_http_host {
default $http_x_forwarded_host;
'' $this_host;
}
map $pass_server_port $pass_port {
443 443;
default $pass_server_port;
}
geo $the_real_ip $deny_0b1da094ae5f44a69f942a79dad2ba78 {
default 1;
10.0.0.0/8 0;
}
# Obtain best http host
map $http_host $this_host {
default $http_host;
'' $host;
}
server_name_in_redirect off;
port_in_redirect off;
ssl_protocols TLSv1.2;
# turn on session caching to drastically improve performance
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_session_timeout 10m;
# allow configuring ssl session tickets
ssl_session_tickets on;
# slightly reduce the time-to-first-byte
ssl_buffer_size 4k;
# allow configuring custom ssl ciphers
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
# allow custom DH file http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam
ssl_dhparam /ingress-controller/ssl/kube-system-lb-dhparam.pem;
ssl_ecdh_curve auto;
proxy_ssl_session_reuse on;
upstream nonprod-portal-int-9999 {
# Load balance algorithm; empty for round robin, which is the default
least_conn;
keepalive 32;
server 10.24.0.6:9999 max_fails=0 fail_timeout=0;
}
server {
server_name example.com ;
listen 80;
listen [::]:80;
set $proxy_upstream_name "-";
listen 443 ssl http2;
listen [::]:443 ssl http2;
# PEM sha: a426527480e6626d41e8489e598d523c2ad8c862
ssl_certificate /ingress-controller/ssl/example.pem;
ssl_certificate_key /ingress-controller/ssl/example.pem;
ssl_trusted_certificate /ingress-controller/ssl/example-full-chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
more_set_headers "Strict-Transport-Security: max-age=15724800; includeSubDomains;";
location / {
set $proxy_upstream_name "nonprod-portal-int-9999";
set $namespace "nonprod";
set $ingress_name "mvc.int";
set $service_name "";
# enforce ssl on server side
if ($pass_access_scheme = http) {
return 301 https://$best_http_host$request_uri;
}
modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;
if ($deny_0b1da094ae5f44a69f942a79dad2ba78) {
return 403;
}
port_in_redirect off;
client_max_body_size "1m";
proxy_set_header Host $best_http_host;
# Pass the extracted client certificate to the backend
# Allow websocket connections
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Real-IP $the_real_ip;
proxy_set_header X-Forwarded-For $the_real_ip;
proxy_set_header X-Forwarded-Host $best_http_host;
proxy_set_header X-Forwarded-Port $pass_port;
proxy_set_header X-Forwarded-Proto $pass_access_scheme;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Scheme $pass_access_scheme;
# Pass the original X-Forwarded-For
proxy_set_header X-Original-Forwarded-For $http_x_forwarded_for;
# mitigate HTTPoxy Vulnerability
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
proxy_set_header Proxy "";
# Custom headers to proxied server
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_redirect off;
proxy_buffering off;
proxy_buffer_size "4k";
proxy_buffers 4 "4k";
proxy_request_buffering "on";
proxy_http_version 1.1;
proxy_cookie_domain off;
proxy_cookie_path off;
# In case of errors try the next upstream server before returning an error
proxy_next_upstream error timeout invalid_header http_502 http_503 http_504;
proxy_pass http://nonprod-portal-int-9999;
}
}
}
So with the above, the lines that seem to cause the segfault are the "if" sections both before and after the inclusion of the modsecurity configs. i.e.
# enforce ssl on server side
if ($pass_access_scheme = http) {
return 301 https://$best_http_host$request_uri;
}
and
if ($deny_0b1da094ae5f44a69f942a79dad2ba78) {
return 403;
}
If either of these are included then segfault still occurs. With both removed everything works as expected. Here is the curl line which is pretty much as you comment above:
curl -i -s -k -X $'GET' -H $'Content-Type: text/html' -b $'Example=blah*****' -H $'Host: example.com' $'https://localhost:443/'
Thanks @slabber
With this configuration file I can confirm the segfault occurring with the Nginx directive below enabled:
# enforce ssl on server side if ($pass_access_scheme = http) { return 301 https://$best_http_host$request_uri; }
And a SecRuleUpdateTargetByID rule with any existing ID such as:
SecRuleUpdateTargetById 200000 "!ARGS:foo"
In this case any request triggers the segfault.
@victorhora Any update on this? It's highly blocking for us kubernetes users. Even perhaps some update as to when you expect this to be fixed would be useful.
Thanks!
Issue moved to SpiderLabs/ModSecurity-nginx #74 via ZenHub
I updated a rule by appending to the config:
SecRuleUpdateTargetById 942421 "!REQUEST_COOKIES:/example/"
When I hit this rule the worker process dies with signal 11:
This is with core rule set 3.0.2, libmodsec 3.0.0rc1 and nginx compiled with:
nginx version: nginx/1.13.6 built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.5) built with OpenSSL 1.0.2g 1 Mar 2016 TLS SNI support enabled configure arguments: --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/ngi nx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-tem p-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-htt p_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_sub_module --with-http_v2_module --with-stream -- with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-file-aio --without-mail_pop3_module --without-mail_smtp_module --without-mail_imap_module --without-http_uwsgi_m odule --without-http_scgi_module --with-cc-opt='-g -O3 -flto -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 --param=ssp-buffer-size=4 -DTCP_F ASTOPEN=23 -Wno-error=strict-aliasing -fPIC -m64 -mtune=generic' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -fPIC -pie -Wl,-z,relro -Wl,-z,now' --add-module=/tmp/build/ngx_devel_kit-0.3.0 --add-module=/tmp/build/set-misc-nginx-module-0.31 --add-module=/tmp/build/nginx-module-vts-0.1.15 --add-module=/tmp/build/headers-more-nginx-module-0.32 --add-module=/tmp/build/nginx-goodi es-nginx-sticky-module-ng-08a395c66e42 --add-module=/tmp/build/nginx-http-auth-digest-7955af9c77598c697ac292811914ce1e2b3b824c --add-module=/tmp/build/ngx_http_substitutions_filter_module-bc 58cb11844bc42735bbaef7085ea86ace46d05b --add-module=/tmp/build/nginx-opentracing-fcc2e822c6dfc7d1f432c16b07dee9437c24236a --add-dynamic-module=/tmp/build/ModSecurity-nginx-a2a5858d249222938c 2f5e48087a922c63d7f9d8