From fa96c349e5b54324a46a4907465043a0363e703b Mon Sep 17 00:00:00 2001 From: b1v1r Date: Thu, 5 Mar 2009 21:50:55 +0000 Subject: [PATCH] Merge 2.5 changes. --- .cdtproject | 1192 ---- .jupiter | 200 - .project | 85 - .settings/org.eclipse.cdt.core.prefs | 3 - CHANGES | 7 +- apache2/apache2_util.c | 2 +- apache2/mlogc-src/mlogc-batch-load.pl.in | 2 +- apache2/pdf_protect.c | 7 +- apache2/t/action/.empty | 0 apache2/t/regression/server_root/data/.empty | 0 .../t/regression/server_root/htdocs/test.pdf | Bin 0 -> 15406 bytes .../regression/server_root/logs/audit/.empty | 0 .../regression/server_root/logs/subdir/.empty | 0 apache2/t/regression/server_root/tmp/.empty | 0 .../t/regression/server_root/upload/.empty | 0 doc/modsecurity2-apache-reference.xml | 5759 +++++++++++------ doc/modsecurity2-data-formats.xml | 2 +- review/pre-2.5-brian.review | 3436 ---------- review/pre-2.5-brian.txt | 982 --- review/review-summary.pl | 50 - 20 files changed, 3910 insertions(+), 7817 deletions(-) delete mode 100644 .cdtproject delete mode 100644 .jupiter delete mode 100644 .project delete mode 100644 .settings/org.eclipse.cdt.core.prefs create mode 100644 apache2/t/action/.empty create mode 100644 apache2/t/regression/server_root/data/.empty create mode 100644 apache2/t/regression/server_root/htdocs/test.pdf create mode 100644 apache2/t/regression/server_root/logs/audit/.empty create mode 100644 apache2/t/regression/server_root/logs/subdir/.empty create mode 100644 apache2/t/regression/server_root/tmp/.empty create mode 100644 apache2/t/regression/server_root/upload/.empty delete mode 100644 review/pre-2.5-brian.review delete mode 100644 review/pre-2.5-brian.txt delete mode 100755 review/review-summary.pl diff --git a/.cdtproject b/.cdtproject deleted file mode 100644 index 93d4fd4b..00000000 --- a/.cdtproject +++ /dev/null @@ -1,1192 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - - all - false - true - - - make - - test - false - true - - - gksudo - make - install - false - false - - - make - - clean - false - true - - - make - - dist-clean - false - true - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.jupiter b/.jupiter deleted file mode 100644 index 4bd771a5..00000000 --- a/.jupiter +++ /dev/null @@ -1,200 +0,0 @@ - - - - property.default.description - - 1970-01-01 :: 00:00:00:000 GMT-10:00 - review - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Pre 2.5 Review - brian - 2008-01-04 :: 10:09:23:000 GMT-08:00 - review - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.project b/.project deleted file mode 100644 index 6f0bc9dc..00000000 --- a/.project +++ /dev/null @@ -1,85 +0,0 @@ - - - ModSecurity - - - - - - org.eclipse.cdt.make.core.makeBuilder - clean,full,incremental, - - - org.eclipse.cdt.make.core.append_environment - true - - - org.eclipse.cdt.make.core.enableCleanBuild - true - - - org.eclipse.cdt.make.core.build.command - make - - - org.eclipse.cdt.make.core.useDefaultBuildCmd - true - - - org.eclipse.cdt.make.core.build.target.auto - all - - - org.eclipse.cdt.make.core.stopOnError - false - - - org.eclipse.cdt.make.core.build.location - - - - org.eclipse.cdt.make.core.build.target.inc - all - - - org.eclipse.cdt.make.core.build.arguments - - - - org.eclipse.cdt.core.errorOutputParser - org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.VCErrorParser; - - - org.eclipse.cdt.make.core.enableAutoBuild - false - - - org.eclipse.cdt.make.core.environment - - - - org.eclipse.cdt.make.core.enabledIncrementalBuild - true - - - org.eclipse.cdt.make.core.build.target.clean - clean - - - org.eclipse.cdt.make.core.enableFullBuild - true - - - - - org.eclipse.cdt.make.core.ScannerConfigBuilder - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.make.core.makeNature - org.eclipse.cdt.make.core.ScannerConfigNature - - diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs deleted file mode 100644 index 2222ff26..00000000 --- a/.settings/org.eclipse.cdt.core.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#Fri Jan 04 09:57:26 GMT-08:00 2008 -eclipse.preferences.version=1 -indexerId=org.eclipse.cdt.core.fastIndexer diff --git a/CHANGES b/CHANGES index cda4a90c..ea8a1e9b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,12 +1,13 @@ -07 Oct 2008 - trunk +21 Nov 2008 - 2.5.8 ------------------- + * Fixed PDF XSS issue where a non-GET request for a PDF file would crash the + Apache httpd process. Discovered by Steve Grubb at Red Hat. + * Removed an invalid "Internal error: Issuing "%s" for unspecified error." message that was logged when denying with nolog/noauditlog set and causing the request to be audited. - * Persistent counter updates are now atomic. - 24 Sep 2008 - 2.5.7 ------------------- diff --git a/apache2/apache2_util.c b/apache2/apache2_util.c index 353c76f4..34fa0c3f 100644 --- a/apache2/apache2_util.c +++ b/apache2/apache2_util.c @@ -240,7 +240,7 @@ void internal_log(request_rec *r, directory_config *dcfg, modsec_rec *msr, char str1[1024] = ""; char str2[1256] = ""; - /* Find the logging FD and look up the logging level in the configuration. */ + /* Find the logging FD and determine the logging level from configuration. */ if (dcfg != NULL) { if ((dcfg->debuglog_fd != NULL)&&(dcfg->debuglog_fd != NOT_SET_P)) { debuglog_fd = dcfg->debuglog_fd; diff --git a/apache2/mlogc-src/mlogc-batch-load.pl.in b/apache2/mlogc-src/mlogc-batch-load.pl.in index a32f57fa..75d43ba5 100755 --- a/apache2/mlogc-src/mlogc-batch-load.pl.in +++ b/apache2/mlogc-src/mlogc-batch-load.pl.in @@ -1,7 +1,7 @@ #!@PERL@ # # ModSecurity for Apache 2.x, http://www.modsecurity.org/ -# Copyright (c) 2004-2009 Breach Security, Inc. (http://www.breach.com/) +# Copyright (c) 2004-2008 Breach Security, Inc. (http://www.breach.com/) # # This product is released under the terms of the General Public Licence, # version 2 (GPLv2). Please refer to the file LICENSE (included with this diff --git a/apache2/pdf_protect.c b/apache2/pdf_protect.c index d5c26482..0c708955 100644 --- a/apache2/pdf_protect.c +++ b/apache2/pdf_protect.c @@ -365,7 +365,6 @@ apr_status_t pdfp_output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) { */ int pdfp_check(modsec_rec *msr) { const char *token = NULL; - directory_config *cfg = NULL; char *uri = NULL; char *p = NULL; @@ -426,10 +425,12 @@ int pdfp_check(modsec_rec *msr) { /* Ignore request methods other than GET and HEAD if * configured to do so. + * + * TODO: Code here is only GET, not GET|HEAD as comment states */ - if ((msr->r->method_number != M_GET)&&(cfg->pdfp_only_get != 0)) { + if ((msr->r->method_number != M_GET)&&(msr->txcfg->pdfp_only_get != 0)) { if (msr->txcfg->debuglog_level >= 4) { - msr_log(msr, 4, "PdfProtect: Not intercepting a GET/HEAD request " + msr_log(msr, 4, "PdfProtect: Not intercepting request " "(method=%s/%d).", log_escape_nq(msr->mp, msr->r->method), msr->r->method_number); } diff --git a/apache2/t/action/.empty b/apache2/t/action/.empty new file mode 100644 index 00000000..e69de29b diff --git a/apache2/t/regression/server_root/data/.empty b/apache2/t/regression/server_root/data/.empty new file mode 100644 index 00000000..e69de29b diff --git a/apache2/t/regression/server_root/htdocs/test.pdf b/apache2/t/regression/server_root/htdocs/test.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a6ec2d04c7ff2428885770f29ac8164264ab53c7 GIT binary patch literal 15406 zcmaib1yr2PmM!k?PUBAF?rtGSaF@p2-5r8^2u^T!2=1;ygL|;xP9FUC&b66&^DXGA zI(4MZsa>^N)}~UDkYZwG=0Kq8EA0E;*VLDTzy@Fe*c)3R2nYZbKz8OX76A4)i3(84 z(#8ek1eCHdasf$zOzcfTLP7}6E>0jLTLh0RL4^r~UKXUz13D)hz9bu4Zd&N#t4&*_ z-+=Y!R`|2+<5g1@hz)xTD?I<-l48p?^}i(e_X4m2*f_aZIQ})=Qy*_# z-GSxbZSJZbF=dG;Qzu7jNKUpoEXYj&8u-@2ioImY6y>y;z zWq6wHXJnXXua5JEuSwW&gnY6fs->OgCyK#2Fm;5>OGE2zTR(+A+cIeS1tuIBe+~OG z6S$?*)q2GZH_{av&m+XbvCy^0c}pZl04b*B8=PlIs?o@gOm@J@GMFz~vc$qp9eRnW z>)#GKP*^7(%pJ&K&c9_m$2z@h$#HyJIo$e zh)=R!ssqSk=)m?*FR4Y z_K=#N8NsM;6-^~*ZT>D^qwu@zz4KTHuck8aI%3L{^EgUVFP>v?{TC5gr?6 zQDaGJ4d*<9&6-{B%`4}sye~daw!~aaoGluu1ktE;T3#b9T&018{Wg;B zD2xhpX;JBm(i6)g!;YC>zg!?Hw{~RPbmgI6{NV8+)*~E)Bh@R65Y!^W{l-9l@0S_c zHUghxLO@6OjL9J_^FWaTR}%8TA`rtzAFs=R}uaLMsH_XmV z^$d-4H!{EOx}%Y_lsManY^Bf}h)+c}pelvp`~qHsgpGDZ9_kLmx6232Rholsu4Ys= zJD^Jz`#<&!KBsuqn>j?#nGKJ7Gm5R-I2{nqn9=!)DhrHn~g9(+#tPzS8*LTAE= zR^?<-!C~wB?$!X090XGZZMlJR>SL+WiLSuOr2E@MD}LKl?<$ZlWHUH2rB z6J?*t%X?Lv@lnM)9;?EJci0F^5JBaheG-BM;R1(fs0(tECY@%9Lw#&zS*|JD)`Wiv zSnpmZY~;@z6^RnLj!}&TI}l#jlaY|2p)yfQh!%-~u~`o0sRUgH@pJ@hy@K#8xfPXX zJ?(0N+J=0x=jMV&9OOzW4a_yj-^fQ5g@n@yJYX3YLQ;39=tQo1xo3SQdL{D%?}`?t z#x)5Z8(=j4l@4Qu&))qLZt?3l{J!hH??V4=UHg(_%b7`z@dg%If=n_-T2G_cca7(o zUCC1UHn9~7@1wc7gQ!W@EN^d^iQP#bqy4Ik1GCrom2?8g*RR9TKHWzX-FtpDJ+NC| zSd15R*Ax+JUHRW%vDr0|aO}I?YG6<;Dp7z#3|rd4z;J6w-7mk*T7p_&QF|K^<92{s z#}~-=>d$IkYmnC7X#Rx4(2IA!SzG)fH+s&ugtxoc4EvD~7fwtO(v1gE8Eg$x*_p=q zT42)Qbd{+GZD5fF$BB$$*{bXDE0S*NMBND6b6%LA1fB?%82(XpegBnc%U^N%Hg z(fa5eWRDUy=-iR819y=*X?RrFiO7jeiQbfP^6P0n^eHkrMS`=|h1IgEY%~((qnJVY}0=h5*x2p zLaxXB$S!PJZC?FRFxsmBZp*#@jC$d+lP|>pu z90TY}{azn@+}i5MGx09-)A5bp_&&H2pL4d<$YGtSc806Ku&&=1(XevW1tan(%8DAuIli6`Gfw-LOZ zOFed)YJ3g|5(gSpFxE=={E_k&B>d?$wDYM+0dexCd*loKn))X#RPAs%C7LVpGVqOi zLEY0s>Q7;@fyjRNDJ*xn)+#$KsN1gu5jjYiy*f&)>S7J!FzaqTehC9h035fTia+2N ze~Qs=zFc$_5T`>;!hXG{Q=?sW#)w()nP)^bR9;pQ>Y#Sdb16_BLcqx(?cJ^Z=GHnJmIct9!Jv% z@3!Pe4NYf2Z)v+Sfn&@n?zQYYs zJBB68PeS#nyjj|VQbyrkuzJ~EJfI!~j&y>c;U^?7CHk->_So@lSja$;wZt(i+{OFy zavU}FUnA zuDNV#9rt^_;0O%=Fwv1+dNXT=?+snw136NawMCbwUwOjXoGF}hVT<|Hgzn|$-szQ2 zCFSX10Bd55v({ZUh~Nm$;uObV$61FPm+}E z7b!%}Ro--jXVUNzTrEy76fD~VKwjjj$J^Eve8UT|Z^XDc`-+fDLQ6RWv_BXl`o*f4 zFH+l1G2)VxdbEu50yE1dw92;Fv5MmM4Ant6Lj!tn_9w7amzp#DfMM>d=p12huWxVP z>Eq15*ift!Z|l4ogt4J7xJYf7ZVwhnBdHiaFUOz0-ZpVs2=UrK3A+8}aEIW)xyhO_ zGd)R=fkI*u!$^#9au?N_Ae*NrIf%haHUIkbt&okyP&>F4Bx`$zAatsvS^3AbxO5(W zHrni<9o|}Qp#?V;7f1^<{MZ-{9VYpp;Jmso=#7QAk}6uWQg5E|Ri~-g`=bLr=eo&3 z!>yq7vRjky$A(gG^%vDr6YtL>pk|kDau~Bz%Zg@cXyLD2H?|QieAd{B*sm+$wKvPBWbwOHdq6i{q11 zHRmdi6lGXWB66Hgu8YB0AE6Wx=M2&04gKX4`MIvea$!)+$M?Ta>{og))N|UGYpL5* z);DRMqi@*yNIb_Yk8TP$rw)`fuI%Cz3|gfToDBC`aIzg^u@eu+_q}`q@K-7p2X1L^ zdC-cf#vFUIwKDOKZF7Ar`UYuPh@a88&wM3XKkO6Z*h3=d8*+S1d6IK#V<8+hUV0=8 zq9V)rWJUk;4CRiFsUnyIW|ua%0xG@IA9X=i{g<1`DdGyQoV)|guYUa7=b&ewc0oaQ z{_^j-_LYpl;IE8pc1d!SD&Ap-ejhs7`q-x3ex`4z_?)#SevYkxZPUdrFMQCx_?2<6 zO2ny_leK0^=fua*k}i{y%IX5GFE)8$r8Kp%N#c(FSS{k{np>ixyjFRpTj*$YIaE$l zCOPu!=ojXX3Y{RG^7itALVBgoycv1ZSwaI=5Jz10d98*iACxT?s_JwQCmvL7w7bo# z8GrxKNM|5q)u@5X6Nr;RcrGrs#^!|y_Yn(BLa0!dz=p*FGDt+x?Joz+MOUEY46Ob- zy_M?7cRUYCll5Y~wCb2!$J9?~ZvU01CsFwI>#A`-#^eQWggm0g+ELqzOV^)*xt#5| zpTFstEb$Oc_cQz1BInZWF%HseKBY2Dup7lQz%BZ&xq9dzQLeTkQ-1BVQ1;YPcT3G4 z=8jG~Cnw)TKx_Lz{$Xm@TJ*3!Wfp=)AM-)wWu=6b;)60qx>i1FGM%QpiR@9Tn%AGY zjLfl<44BVU8U|TmuG_1VH@a&L7g5~>>{B+|NYvp40E2cM?sZp?qvTl3kzCHe*09ni zdsE=kV3cm9AcCI~A~PlQ1nt(z)v?HA2&6lIek}Zu=n#H*x^n|xI+!exp_=sQD7}Tg zUf;nwhEOxVCCTr-UG;!LHudHCP&4AgQb2JwyAGimZ&?gHeCj=VU1=dc-#`e_*b5`; ze3)D!G>2=-iF%6M*8(>@2)nMp`90>c(sY(hb;vU=31rN$;4pTWTBBK^2e2PgP3fz? znY4S1yR24|uEi!td|m3(C`%m5352E_ktQvS@;P+1tCtK6IG}O(%+Xdu_32Q_Xk1+E zAIzOx#SMPn@_NjZF-p;7rJJX^r}k+3Xf^%! zQD@Z^irb;F4f755QUp+u*)^ldAdW85U9ReqU}W~qhpnF?UI{%}R~0i^)*}Ney3A=K zRG)dL%o3!&C?3?5r;vXDpXfJxHrZuhrVnK~VNBfD|B_^qZkz_qRv$H?_%+c}HoW!> zbj-gXtfO^|^#xx^inB!r^M`_k<^+~L)-c`h#D$ir=02}dKs#bS^bRzmhLTD*7E$oi zXSQ)-JFXTozTm;dtk|zb%$_L5E2g7S{QS=YHU1yIvE&vjuN|pQ`?bZc4A7k(x#%^K zCP9(s_8K+w&yOlJYI{0oPJL}seF{c_ob~g#bumY>{+J^;v4d4)XX}Km&12gpVI|v~ zSyQNFCYH5eBc_tJ6oS5lePQ?8oazNRIb`=p!yb`uj7_-ww_aziKabJf-MZgy1!m?Up!?pvqsW#y zSWLef)~oI|4lhC%YMB7mu3ySRMY;Tr41~^g;mpT+B4M80rzCto{+v>PH+|nZtLbl( zqx)J8zH~8I)x&2JMd`;Zcnc1ZZx{92oZ|)5kXi7D^DJ=$7GOw6Sn*F+LVzzQ5ne}b z1WVUwXLa?Se;5FrW*>pDu#CZ93VkA!HWT(h%Z0iF3Yu5$y0tbG=0|NW1Lo4JVHJ-y zjX$i~s*5dE9rkUj@796L+N#-AKT4N|%>A5(Qq|V2H1g~{&$->txEY)-E_LkMe{Q(! zNqqL7Yx1t+w1k1PvjF|#XeSh?N75U#fs;u7Cb$=4_d;H=!}xm9CcXQSPV=iyGv+B{ z7yPN(S!MF>QJqzT>y9gVt7W4{V_~FqU1b&g{OM#8-E1LIU1k47RLW>d%7hv+Cj)S` zkVt8rwoBA8SYvfKy^&QC>P?9v{WA<=j4ZTMBCv5D!k2~PIB8us>>=SWWI0r4xy>tjXQ#=`tG;Tr@9No&Y zsAh&2$Hl)zx@{P5)8rs6{S;T|iPP$|>4Yc-DpeS5HD_7aj(u3~2po{P*U;BYt#_;A z_>G(eyw5%r-(GXUbx;3Nyqh~bVTOUd?#sz}oVy$ypl;_WDDzV0q(~UUVv{m%bmWp! zDZO^46$JK$xZo2+uY}m%4j6aAtBuj~=xXK7XEab}nFSY0saTVT!CnPLii+JX<>!-c zhp{@8*t*n*PAe4$dj#;W(Zal5OVBY+aHsI`mKH6mTE5bw;K=KWOV%ZUQ$blO9!J!0op(BqC^$1?!Z#F_uZYz2Sir&94V5A~rke3)h$8K@Ih-H6CRPtzVsv`=Q6U=5jw8f4Fn52l87x z3#`3j>+M3NW;`OQGI*ij&m2o9@ZI?3>hGQR>LID7H4FRtPddI_RFr1jITylS{yx+F znQx`+UfMQKir`(x5cTyB<+;YT|p_$xnCwRID~Hud#No3{h)! z4@n_U@+LmlD7`6aW$IBA0tntVW^r>x?q8EWU$GAysB18jgc%Gkbt2dq2-MYv8IfzE zleW>*%7fJX^M*Byl6Qw!*{jBXjjr3=i&bIOJ4JqCR*k%2plZ+1q2w;VwXh%e4&XKQ zVB6u`|1hDmQa`@2ghcF7tibSNw5@2Zj+STF?!kFB$6``Ojhs1)04j?Se$-8a*Zqe)Su?EZ#|Ws~%5Aeurv*^e^#ihN{( zv>)UoXTRnvd`c{$`EGXj+{XOE`~t3&BU8=YN#C1aIv+Wr&=s*EEJ4XwIsG76B)5kx zW#jTqz6dx{rz_P(jVN8`209%xuAekBiyd=_v=JLj9=;t}PpH+_5`mGArvlM{FqR7} zz0g-aWOLVL2UJlq#V=$I=5yE*qzz`v_F0Bt^1`uK_WbO&f3S<-v!1jq(D9=&EhcNR z7~vu<=SQx>mA}Kqw2wRNS+$fQcO3m_Z&p?wY01$bOeUIc)Z{uHAR)v-NhGO~u3&jr z4x!&gAR^@^nPxC*j**D}keFbPDTmNmxGC?XjZir9;$<5v94>!X&fCV>i@X+umq504 z*KA{)t^f)}IfJ}bWawC}lU?ui_2stjoUxwybDa(Q=Q^#p^R~d5dq=u|C2L*sxY``2 zD_Q1RKc)3aFJ|KzGqv;H;zN4@p9Asm49s1wofqn_9_u)A(i$h}51?B6`FIv;g~gWq z&g#rUldyB%*j7K==f)$ZaLQtlW9Pl6udhJ^RTvxlK@Otx+-It+3rr;3${~A-YqVUe=**B#b@CuFu|;t{}4Zi=$FWGv605igZX*4LTs;1QqR#S zaC{Otgn~&4%`3ULWZ95*MZ@W&F3zwz2%%j+VO0ynSswpsY`Vt?m!t{#D~PaBv4JV< zXpKN3DYUuUA<3{=Lwl?)q&*^N`3e#K_Fm`PGbi>zHuJ{eI0sGz-H^ZMFI>#7S6R!7 zPA9$f%{2x)3kG{oCl5QH-38CrAE{9M5;glH<)nNGO}cq4{@-8D_K~KGiDRcta;F$g zC4sP=xg7LYcC&tJPx6%>?QY)t6D!_qx5ox7o$+^>>Si*Fp#2Q3Qj(3VClLEiqAa77 zX`?KYRO63q+lkti+1Yso6bq;kg+?a67#D5gVul%L7vnX#_T0n(VrMs^M$(3yhI%(^ zt`nWR9j>cp%&1 zOc?8G$6!D!qgXg+U4&r`9)VtDjn0deYVTs2A>tE*n6^2V?S0akF=KGPaxcXE<>4V? z!qGg1a}worTVPU`ytdXRNeZz<}da5s<|78QLJD^Bg7-;#H zt^qk26y!tAprgL&CK!gmO3z4#ge8S28H$M!DH)|xc+Znn{q1)WIJ8`S#?{%?L=r!| z$*yVR=})@#!#^FW-c>j!B*sMkg+c8E!k%uF1;Q1(f)M`Ry`vB9}3*lwsRq?KiMb zkzLfi1M7MV@FOAD0Ve^^LZ`k*vemi_GjbVK`OMrViA91&scUw9AJdCeD;N!Hzo4ea zeZhBb>&y7OR_TDoOh-RoBrl?)y%h27cN@ji=5PK1AA!i|pQ@UKO6>@>ib+)+dIdcw zb)`f{XH~hLACPkve_XT{B<}|@CN&z9BPUgsFfe6ueRU)MkeIr|J1D0~w;k8@d{zr% z$2c|HC(C4d?wY-w!#}@}9sOhBYp{uZ?Ir=Axu}_Xr)tjmxKoCb=(k`2v~5z@0l+xe zI4a97T}VeA(PY$h&9F3HJ_R8W`pur#bNooF=}YSdPFw1}f?|_!E7MPXRijB}15oYm z6T~;vkcH^`4TaXXkNTUgZ-h3tKTUvw@3gRbU;uFwJ5F7q&8SXD{m# zw=TCCHe6pujkTahAUR(Luz9>y)|yK=31RDW>f7rJmNA!M1C`3?Ipj5#9rCnP45t{C z7R}Sy32)$JsSrYltx{N!{LNKcTa3j*b<|pPu+=`4pp;FP^p}lPc%s_g7hAeE9+1v; zqsKMWRbwUIMNZU$_i(r9=ved{SvamCR0Nz!XLC<$h=wr8UJ9t5M_y zByxof(24O2L}fuHuasfv6jz~KqeB$!eyZI@DU#5VGM~$(ipXIZJHzkBPC0)@4wZgoX#EPO}8At5O15cR(5A1;l>b(3EE+>B0far>L~Jld0}9fg&+32l^E2`RKPaF^(jON5Z1 z@SXrmlmZMsFiIR*DGFS17BC-92Mx<9KD_~}Nl}UVN*en~;O!fi1@SR7g0BUUbAN{M z(DxZ6{aWPWHM&PFYz43Jf_#Xt@xe$i8W#ERfGB9HrNY`{FXoat1!W- z53qCUfus^J!a4o=u;Z6z_4%+6btR1MTqiHq;YN6o2DVXxz$l$ll$Yl6AXmWxqql@G zKpf?s@@2$dG4WwRWCgE0={e5J_?5(1v^jrZX(TQ|GIG!Fh{trk_LOS1|1!oJ+6w-uUI6chT8K<%$(Us`5 zv5Ms2lJMB^2}k#JAUr86yLZAg!^!Zz#BeISP>{u}$Wvj4m*;rlbAK%E_{7%Z$r^lMt4{uX0j4A? zsKI^%Vr}T?=Xa3fCt+VK!Xgz!vXIM4BE=mxk&zUD=vIx}trzRgn)PzkOI>HJ*9 zd6mvw?s@(fPWJ~sF$QZYR=nT!r1$R+P7~AmBG9IA<+7Svh01)_+oVfF9ulOERvvhD zjxoA&WC?(f4V9_ zd=7Vz7qCl}Hby3Dl+!0QUF+ajK%TJlkclV|1QSngXEhoq;8?h%IL&1Wc4>gq^%+0G zc40^I_0Y11XcOY=O9vD@Toi`iuF?M|JPIb?|2m-(Bg$_+bB4eFZeo60+I=W*W?# zFsNCC=^`7%;T8W#U803b$NRz)^NXaDu|FBg_NDk$|R)n~>c1 zw@VYOF0aW2tv8t!Y~VF6F7tXHxx-E7AnZ#oYx#Nj6J$4sLzi;@PUR$zAt}@iIm{l_ z!K=MOG2+_(x*B@FAzt9Fxzu{^`I=yAHf72mLY#K5;-Qa}MY`wt@fU8zp7CWA+%Y)@ zB2z?Rz0lM0!()gHMnSePA1|A-H+{R$;0 zN2NGOnx%s}wdiw9f|E}P^j|N}5Aw~5`-W(Hc%|;LE~Gx&=&$Zv?@i`k7d@qe+%k88@vR4DJ0CMWe}3R_ZZRpWnfg*X|84JU$7wSZ?o+AE<=F%71sdzi6UG&nn zP^`Orb268}Nz&bGm1b{|YB69ee0$S|U%jC&+_*m@L)B2=O*a@F)~k_5gqJVOxP>YRGea$!tQj zAl+Iq?&+L%U};K;zV<)kYt^&>5Pb|W&J$u5=%os9>GP`MOy9h0ZQ|6G_wR~BjJnS;OF_U(!Wj1)ZZ18Sp)KMep25W-#djJhg{A4_z{Mhk4hDp4@{r(PI1u)A zM9ReI5XanvN?`yNF6)|l9Ed!~7-7A`#B`0-(_XeT1$v+hW|ZE(hm23kVvIK6sc>{P zEksr4z*s?#gDJ>M4?hmacS8#EhHZ5ST1Ag>_RaI~Fr=J6*l9_Dw?nhqE)cw!Zc^Sf zvWPi`zmW;f)yL;RZ8wP$eavMYiQ>y(APZ!hr}mVqiO15 zh<4o@S|t}EwY_yprfC{sfn8(4D5eRGZX1VWOOts>`dRcGPitD8yj9B=92Iv4PobFu z4^~Th_#Pm?X#{nmYe+=7ICK-#BJGVS!a+bIs3Tr$LCZ=|*fh(BMI;*{I%T9kZkS-A zYg!T)O*1Ic*b&^LiT2oQ5$Rx`b&S7vgL#4|H4+gC$1Spe-d4uV!6AVo0L8U}NrFH# zXt+Idh=z6wM+4IuCnvpgcS z8xlh);y2C;?h)}`noLBn_yru*G2&2xcn@o5oxL}0DqK?IBMfGw#RtcWSYm#kz94|F zA>Tl78 z?xkwu#l&j#e zW1+qC5S~e}R5!tzlULBQiV`ql-xDwwJa*u@p}dWhBgm+%FyWRRWyY@To1EiF?jJ2@_1K3@o!#ed9EEr=pm4QGT}^Jc>z{$}BE~7#!_fN$%uHgqeRygs zxSp_^o0`&=GKMmQ*0NbEds#`@NZrmne0q5~c?NnwC4KdF8IIZ`!;95`@b9)MS1A>G zoTUOkIPNiYuP?H8h{GSY@zncfOc04gg>qrjmYbHt{e7Q<`ERXHjBd4VdAgNv@t&57 za2e9{D|EeTosI?&+OCcFW}{Q&f$Gd1nyvrq;KBcLU^J+h^xy(e)TO!Fj(ZKyQx4W}N5OpP)(y>^cW9y|FHTDImGt2?LU~!NU@h~cgBCH~arADZ=;Q>>yBVBdk+DK^NORxYj z+miyNu9U(PiW3~u;Lhe6cXGj9?`3|ASEgZSvOm=GU&y*hM=6B?$>*V24gMcWHcESoHjC#EOClfh~N*5H@E0^0Z^gUAL> zZcfm?9(T*PtQ^Xm0 zS{IUIG2oNj63;j;jR7d&6Jj@b4d9Mv`0G3k*;g1I(PR4n7l=&&T`j*zY-slnJGZgI zF$gIxhkjDpa_`JjSY_CyR|;NF(9>kvE`o7Hd@+1$*mRhM^%sYb6N-3O?qt*Y1=Q?IL{ zDwHQsqCj7qLX*5*XsYcb=A_~zMZQl-l^9T{Hp>(#H%Nt<7>vRDAcr$o8ACsmQlUOV zC!Y)sDp#>d*bctot`poXM~b%s&j-TWqdcfkD7aIj{fT(FWqXg4LF08ku67%K`2x-d6z8xh%YgOCKqod1&8ujbMb&^kGEjZuU zyS9Ew?KyYYxS5BEc`P{Jx17|#*XL%eTvD%`qTIdGtbF*clzNQ{#L>(v`?_nYXs4C( z?UilcQBx7O5Eg75+%Vy9a3&Uk5*ZgzwC;jz+z4Db&&3H~24lT`M1g0G*AC%Q@egQ1 zk7-~>T+z~eHc8^#W4b9PJ8=Ui0y8u^8OnWOm76e$n|q`zq_Omk7V(c?z@$g)wh_jF z;+}J8#{cQSUIuvx5dje~Gj>9KjRF>fQVI<~_{|d#v4*rr?S^?p+(KePVj>9cTDl%o zS7-P%T{PBkqb&v9lsgzVeNB>i_RW&`194!3+OIf`(ylH!-#L0$a6k+q7Z+z|(zk_x zI{g=kj>1!FEmFodm*@-);iC=&I(%Lrxt7{YxkXHhg$BGr7?0CGqp`968if530~a7 zJ0XcIs{+SN7n}lBv@`4cC&v+42f+xGYKzgVK7tnb)+N4;bfpX5Sm9S@Hq_-KG-}gg z1;T`+eM?R83=Imx2~g7Qu_4w7=A>$B*P_q|oLHgW%#kO?E^nBHX7s2(h}BsFrk;DW z=!=DWpeZajA<#qXi{%(9v8u;TA!vo2DmZK>n+`_Uk{3x#5rQc=r%vDuzs6@sQHQia zoT21Vq;k=z+P5Cmg*lp(dMq%7#x>1S;X%RS?vbjgzDQEX=&WdDfimA~3LaWCNK${F z*XD&#E#Ne)@++OZBDotcJi897C+5LzbTq8YM1d-CdnQ0SGyYbFTMn4UoSG`%p`w^c z!zs%S;>%D^rB)rmV#`n<#~i`KPXs0A2s_Rhz$I85ePoW7q0etgC8HDX(htXDH0gFv z#J6Fe`|d}l_$yP{d3Dw_rQK65Q#-A~jhhBkX<#87b74!YB*$iu-CI&gjFkLo&4N<6 z$rH;+*Jr0vD$&4sr;?bsg_n0NI@7ylcj(xNIBJZWX5h96Cb_X=QmI%c@yuYsBcV`7 z=HO*8$f&2f4(~G2owM5hqfq8z0waYCeRTnEYu2;EfwCDPrlpm@sD$joj31W4gpIYf z^skE_pNXAKhX*ABk$xn`#1o5hiG|tR!%^vc80l89{qQ;5mMip$hn>F=O zT%>#(Htv@vE&!UZLy`Q40(d#aju#w;&=ANJkeO32dd2=XnA(p(v>l3`jq964Qu)&+ z?ohC{B=2Tag2Wv`BKMYa?%wK>efPU-ltckMxz|AwD}~!-!q&c?^=OW}#Qofk3zlED zR@TBl3E?;uVIX^`y=!WBhQ-?nGI7Tnz3r;P^lj;k<*>V z?U@;rk_F=C4jYp;8}wD?RiRbz)g3N)%a;6?Qjt^e)g0RsT1`yF?&8vfNnQlr=LBP8 z4n-k2>Ilf+bFI>A$fq}4^N7XzNHi|MQLq}wWXK9wv;zO&Yqfw4@MmO^kgD)&lmJ+; z*m#14F|RL3TW>#2hkt=0hSYH@EUc^WLbx;(&Z*uQKlot%@V%*X9PGhVuQgx4FVX%Z zY4CM1m_7J2`eqkczYV^Q6fEgpWfMj0wjI(*l7WwGJms0<^oDhn(G`5V=Tm51veWFPK-l6^jT zI)H#u_I553AZHUNO9vPGH#XDTP|?U11QZi}e;7Vl+Jc-FLGCK{wnlbJsvkZfyc3?x zodFzgoi|-EF?$akCQdFM024b47l4h0jT^wq!osBolyxz(u{062Gq(W&SP+1s&L$u` z7XS}0D+2I6-ur-wjg<=lC~o8+1F|%?aQVv+0jTN%vQ-E0yxF`5cwbBi-#J-qJly{WBTFw~!Y%}W6?!KCJ$7VF&c`Pl$(q5(9vS^w*o2zv&`605 zx82(e)cs~V3%%RE?p);{^J{;W_9#)K+!HYtMFk$QUY`+mrH>X{mYtr`{SLuh$Tf^| zeYL7SxKufqSw8Xm!}`gI9JhI%w+CP(8r!gl;Ap?V&UcM@(5DA#R9UJl3IXpqt9Vkt z9h35Kg{!x@NT+%IlE%XTc^c`MgCx`%y#9!1N%6CY+#tR7x*aw+)$7fyfc9gczuSVm zDiBmL%rJ$2`HJU(`}U?qTId7dt4^RZ!#-~Nmf4~M9#L)d`^P%ynxg?Y*hit z14b)~&*wjF+mdHAC>jVEetlQ&i#;2kU~2>*hfw^09}^hvP--V^=zdDefKf6MI+n187Nm7MHNR6#B} zz&Dm4@Ds?xMepC-{?qEO(kL03gMdm#PVZ3Xcy|C)0Xf^dI+=i+0j%#KRDd5qrj|zU zN9a8O7b_cpo0m-wDD7nL>hMN4RDCP6k)5-{y9*Ofpt$PW$#JtZ0jWrf0c8O$Z(ATF z1QdT;;9CS|z&lUzU(d*U$oKRA=I9^GaYp!WYe4wtBHj$%Hi4HDz{A1zURZfcQ)eB( zUn_kdirc%s*WzCb`7hkazha0Ry`6e{^S7+c-;(?*X$0U$2auhpiHoJZozCBU0X4O> z0d}r7Hh+6zdGoDcWM@tbvSU(HrTe#%{uf{IEeY{AX64%zB_Jg!CB?$R$<4yT&GvTF z@V>PiZ|xg+xY>jd-uKAV)dcikdK_=MZ>oRIb4jwWypOrK{{H`F%f4?oUBYN+%zmKG<5$`8xJRt z83GI74d!p2{{8^CI62ul0cL=|$yhnqdEaj7_XlA2ciCH?^$n2!A!B2EtL4ARSUEV^ z{|7ye|E9;z$@+GC{<|$ZC;Qte`41WQ+sgh!#=*k-wqyUU$HC6>pK;&v;P~%)T}t+EryGe(c9(j^bSx}OE1t{semf>_HPLL3&{vTSvxa(0PA05+qZ!PKnEbeDE!6hmx z!Og=hDkUx|Df+hMtP)&2;-V}P;#?A}JW}s~bapXva`|gZSvh#w*bu0wBtJ?a{6Avz B`Q`us literal 0 HcmV?d00001 diff --git a/apache2/t/regression/server_root/logs/audit/.empty b/apache2/t/regression/server_root/logs/audit/.empty new file mode 100644 index 00000000..e69de29b diff --git a/apache2/t/regression/server_root/logs/subdir/.empty b/apache2/t/regression/server_root/logs/subdir/.empty new file mode 100644 index 00000000..e69de29b diff --git a/apache2/t/regression/server_root/tmp/.empty b/apache2/t/regression/server_root/tmp/.empty new file mode 100644 index 00000000..e69de29b diff --git a/apache2/t/regression/server_root/upload/.empty b/apache2/t/regression/server_root/upload/.empty new file mode 100644 index 00000000..e69de29b diff --git a/doc/modsecurity2-apache-reference.xml b/doc/modsecurity2-apache-reference.xml index 76cda13a..a3bf4940 100644 --- a/doc/modsecurity2-apache-reference.xml +++ b/doc/modsecurity2-apache-reference.xml @@ -2,845 +2,1338 @@
- <trademark class="registered">ModSecurity</trademark> Reference Manual + <trademark class="registered">ModSecurity</trademark> Reference + Manual + - Version 2.6.0-trunk (September 5, 2008) + Version 2.6.0-trunk (March 5, 2009) + 2004-2008 - Breach Security, Inc. (http://www.breach.com) + + Breach Security, Inc. (http://www.breach.com) +
Introduction - ModSecurity is a web application firewall (WAF). With over 70% of attacks now carried out - over the web application level, organisations need all the help they can get in making their - systems secure. WAFs are deployed to establish an increased external security layer to detect - and/or prevent attacks before they reach web applications. ModSecurity provides protection - from a range of attacks against web applications and allows for HTTP traffic monitoring and - real-time analysis with little or no changes to existing infrastructure. + + ModSecurity is a web application firewall (WAF). With over 70% of + attacks now carried out over the web application level, organisations need + all the help they can get in making their systems secure. WAFs are + deployed to establish an increased external security layer to detect + and/or prevent attacks before they reach web applications. ModSecurity + provides protection from a range of attacks against web applications and + allows for HTTP traffic monitoring and real-time analysis with little or + no changes to existing infrastructure. +
HTTP Traffic Logging - Web servers are typically well-equipped to log traffic in a form useful for marketing - analyses, but fall short logging traffic to web applications. In particular, most are not - capable of logging the request bodies. Your adversaries know this, and that is why most - attacks are now carried out via POST requests, rendering your systems blind. ModSecurity - makes full HTTP transaction logging possible, allowing complete requests and responses to be - logged. Its logging facilities also allow fine-grained decisions to be made about exactly - what is logged and when, ensuring only the relevant data is recorded. As some of the request - and/or response may contain sensitive data in certain fields, ModSecurity can be configured - to mask these fields before they are written to the audit log. + + Web servers are typically well-equipped to log traffic in a form + useful for marketing analyses, but fall short logging traffic to web + applications. In particular, most are not capable of logging the request + bodies. Your adversaries know this, and that is why most attacks are now + carried out via POST requests, rendering your systems blind. ModSecurity + makes full HTTP transaction logging possible, allowing complete requests + and responses to be logged. Its logging facilities also allow + fine-grained decisions to be made about exactly what is logged and when, + ensuring only the relevant data is recorded. As some of the request + and/or response may contain sensitive data in certain fields, + ModSecurity can be configured to mask these fields before they are + written to the audit log.
+
Real-Time Monitoring and Attack Detection - In addition to providing logging facilities, ModSecurity can monitor the HTTP traffic in - real time in order to detect attacks. In this case, ModSecurity operates as a web intrusion - detection tool, allowing you to react to suspicious events that take place at your web - systems. + + In addition to providing logging facilities, ModSecurity can + monitor the HTTP traffic in real time in order to detect attacks. In + this case, ModSecurity operates as a web intrusion detection tool, + allowing you to react to suspicious events that take place at your web + systems.
+
Attack Prevention and Just-in-time Patching - ModSecurity can also act immediately to prevent attacks from reaching your web - applications. There are three commonly used approaches: + + ModSecurity can also act immediately to prevent attacks from + reaching your web applications. There are three commonly used + approaches: + - Negative security model. A negative security model monitors requests for anomalies, - unusual behaviour, and common web application attacks. It keeps anomaly scores for each - request, IP addresses, application sessions, and user accounts. Requests with high - anomaly scores are either logged or rejected altogether. + Negative security model. A negative security model monitors + requests for anomalies, unusual behaviour, and common web + application attacks. It keeps anomaly scores for each request, IP + addresses, application sessions, and user accounts. Requests with + high anomaly scores are either logged or rejected altogether. + - Positive security model. When a positive security model is deployed, only requests - that are known to be valid are accepted, with everything else rejected. This model - requires knownledge of the web applications you are protecting. Therefore a positive - security model works best with applications that are heavily used but rarely updated so - that maintenance of the model is minimized. + Positive security model. When a positive security model is + deployed, only requests that are known to be valid are accepted, + with everything else rejected. This model requires knownledge of the + web applications you are protecting. Therefore a positive security + model works best with applications that are heavily used but rarely + updated so that maintenance of the model is minimized. + - Known weaknesses and vulnerabilities. Its rule language makes ModSecurity an ideal - external patching tool. External patching (sometimes referred to as Virtual Patching) is - about reducing the window of opportunity. Time needed to patch application - vulnerabilities often runs to weeks in many organisations. With ModSecurity, - applications can be patched from the outside, without touching the application source - code (and even without any access to it), making your systems secure until a proper - patch is applied to the application. + Known weaknesses and vulnerabilities. Its rule language makes + ModSecurity an ideal external patching tool. External patching + (sometimes referred to as Virtual Patching) is about reducing the + window of opportunity. Time needed to patch application + vulnerabilities often runs to weeks in many organisations. With + ModSecurity, applications can be patched from the outside, without + touching the application source code (and even without any access to + it), making your systems secure until a proper patch is applied to + the application.
+
Flexible Rule Engine - A flexible rule engine sits in the heart of ModSecurity. It implements the ModSecurity - Rule Language, which is a specialised programming language designed to work with HTTP - transaction data. The ModSecurity Rule Language is designed to be easy to use, yet flexible: - common operations are simple while complex operations are possible. Certified ModSecurity - Rules, included with ModSecurity, contain a comprehensive set of rules that implement - general-purpose hardening, protocol validation and detection of common web application - security issues. Heavily commented, these rules can be used as a learning tool. + + A flexible rule engine sits in the heart of ModSecurity. It + implements the ModSecurity Rule Language, which is a specialised + programming language designed to work with HTTP transaction data. The + ModSecurity Rule Language is designed to be easy to use, yet flexible: + common operations are simple while complex operations are possible. + Certified ModSecurity Rules, included with ModSecurity, contain a + comprehensive set of rules that implement general-purpose hardening, + protocol validation and detection of common web application security + issues. Heavily commented, these rules can be used as a learning + tool.
+
Embedded-mode Deployment - ModSecurity is an embeddable web application firewall, which means it can be deployed as - part of your existing web server infrastructure provided your web servers are Apache-based. - This deployment method has certain advantages: + + ModSecurity is an embeddable web application firewall, which means + it can be deployed as part of your existing web server infrastructure + provided your web servers are Apache-based. This deployment method has + certain advantages: + - No changes to existing network. It only takes a few minutes to add ModSecurity to - your existing web servers. And because it was designed to be completely passive by - default, you are free to deploy it incrementally and only use the features you need. It - is equally easy to remove or deactivate it if required. + No changes to existing network. It only takes a few minutes to + add ModSecurity to your existing web servers. And because it was + designed to be completely passive by default, you are free to deploy + it incrementally and only use the features you need. It is equally + easy to remove or deactivate it if required. + - No single point of failure. Unlike with network-based deployments, you will not be - introducing a new point of failure to your system. + No single point of failure. Unlike with network-based + deployments, you will not be introducing a new point of failure to + your system. + - Implicit load balancing and scaling. Because it works embedded in web servers, - ModSecurity will automatically take advantage of the additional load balancing and - scalability features. You will not need to think of load balancing and scaling unless - your existing system needs them. + Implicit load balancing and scaling. Because it works embedded + in web servers, ModSecurity will automatically take advantage of the + additional load balancing and scalability features. You will not + need to think of load balancing and scaling unless your existing + system needs them. + - Minimal overhead. Because it works from inside the web server process there is no - overhead for network communication and minimal overhead in parsing and data - exchange. + Minimal overhead. Because it works from inside the web server + process there is no overhead for network communication and minimal + overhead in parsing and data exchange. + - No problem with encrypted or compressed content. Many IDS systems have difficulties - analysing SSL traffic. This is not a problem for ModSecurity because it is positioned to - work when the traffic is decrypted and decompressed. + No problem with encrypted or compressed content. Many IDS + systems have difficulties analysing SSL traffic. This is not a + problem for ModSecurity because it is positioned to work when the + traffic is decrypted and decompressed.
+
Network-based Deployment - ModSecurity works equally well when deployed as part of an Apache-based reverse proxy - server, and many of our customers choose to do so. In this scenario, one installation of - ModSecurity can protect any number of web servers (even the non-Apache ones). + + ModSecurity works equally well when deployed as part of an + Apache-based reverse proxy server, and many of our customers choose to + do so. In this scenario, one installation of ModSecurity can protect any + number of web servers (even the non-Apache ones).
+
Portability - ModSecurity is known to work well on a wide range of operating systems. Our customers - are successfully running it on Linux, Windows, Solaris, FreeBSD, OpenBSD, NetBSD, AIX, Mac - OS X, and HP-UX. + + ModSecurity is known to work well on a wide range of operating + systems. Our customers are successfully running it on Linux, Windows, + Solaris, FreeBSD, OpenBSD, NetBSD, AIX, Mac OS X, and HP-UX.
+
Licensing - ModSecurity is available under two licenses. Users can choose to use the software under - the terms of the GNU General Public License version 2 (licence text is included with the - distribution), as an Open Source / Free Software product. A range of commercial licenses is - also available, together with a range of commercial support contracts. For more information - on commercial licensing please contact Breach Security. + + ModSecurity is available under two licenses. Users can choose to + use the software under the terms of the GNU General Public License + version 2 (licence text is included with the distribution), as an Open + Source / Free Software product. A range of commercial licenses is also + available, together with a range of commercial support contracts. For + more information on commercial licensing please contact Breach + Security. + - ModSecurity, mod_security, ModSecurity Pro, and ModSecurity Core Rules are trademarks - or registered trademarks of Breach Security, Inc. + ModSecurity, mod_security, ModSecurity Pro, and ModSecurity Core + Rules are trademarks or registered trademarks of Breach Security, + Inc.
+
<trademark>ModSecurity Core Rules</trademark> +
Overview - ModSecurity is a web application firewall engine that provides very little protection on - its own. In order to become useful, ModSecurity must be configured with rules. In order to - enable users to take full advantage of ModSecurity out of the box, Breach Security, Inc. is - providing a free certified rule set for ModSecurity 2.x. Unlike intrusion detection and - prevention systems, which rely on signatures specific to known vulnerabilities, the Core - Rules provide generic protection from unknown vulnerabilities often found in web - applications, which are in most cases custom coded. The Core Rules are heavily commented to - allow it to be used as a step-by-step deployment guide for ModSecurity. The latest Core - Rules can be found at the ModSecurity website - http://www.modsecurity.org/projects/rules/. + + ModSecurity is a web application firewall engine that provides + very little protection on its own. In order to become useful, + ModSecurity must be configured with rules. In order to enable users to + take full advantage of ModSecurity out of the box, Breach Security, Inc. + is providing a free certified rule set for ModSecurity 2.x. Unlike + intrusion detection and prevention systems, which rely on signatures + specific to known vulnerabilities, the Core Rules provide generic + protection from unknown vulnerabilities often found in web applications, + which are in most cases custom coded. The Core Rules are heavily + commented to allow it to be used as a step-by-step deployment guide for + ModSecurity. The latest Core Rules can be found at the ModSecurity + website - http://www.modsecurity.org/projects/rules/.
+
Core Rules Content - In order to provide generic web applications protection, the Core Rules use the - following techniques: + + In order to provide generic web applications protection, the Core + Rules use the following techniques: + - HTTP protection - detecting violations of the HTTP protocol and a locally defined - usage policy. + HTTP protection - detecting violations of the HTTP protocol + and a locally defined usage policy. + - Common Web Attacks Protection - detecting common web application security - attack. + Common Web Attacks Protection - detecting common web + application security attack. + - Automation detection - Detecting bots, crawlers, scanners and other surface - malicious activity. + Automation detection - Detecting bots, crawlers, scanners and + other surface malicious activity. + Trojan Protection - Detecting access to Trojans horses. + - Error Hiding - Disguising error messages sent by the server. + Error Hiding - Disguising error messages sent by the + server.
+
Installation + ModSecurity installation consists of the following steps: + ModSecurity 2.x works with Apache 2.0.x or better. + - Make sure you have mod_unique_id installed. + Make sure you have mod_unique_id installed. + mod_unique_id is packaged with Apache httpd. + - Install the latest version of libxml2, if it isn't already installed on the - server. - http://xmlsoft.org/downloads.html + Install the latest version of libxml2, if it isn't already + installed on the server. + + http://xmlsoft.org/downloads.html + - Optionally install the latest version of Lua in the 5.1.x branch, if it isn't already - installed on the server and you will be using the new Lua engine. - http://www.lua.org/download.html - Note that ModSecurity requires the dynamic libraries. These are not built by default - in the source distribution, so the binary distribution is recommended. + Optionally install the latest version of Lua in the 5.1.x + branch, if it isn't already installed on the server and you will be + using the new Lua engine. + + http://www.lua.org/download.html + + Note that ModSecurity requires the dynamic libraries. These are + not built by default in the source distribution, so the binary + distribution is recommended. + Stop Apache httpd + Unpack the ModSecurity archive + - Building differs for UNIX (or UNIX-like) operating systems and Windows. + Building differs for UNIX (or UNIX-like) operating systems and + Windows. + UNIX + - Run the configure script to generate a Makefile. Typically no options are - needed. + Run the configure script to generate a Makefile. + Typically no options are needed. + ./configure - Options are available for more customization (use ./configure - --help for a full list), but typically you will only need to specify - the location of the apxs command installed by Apache httpd with - the --with-apxs option. + + Options are available for more customization (use + ./configure --help for a full list), but + typically you will only need to specify the location of the + apxs command installed by Apache httpd with + the --with-apxs option. + ./configure - --with-apxs=/path/to/httpd-2.x.y/bin/apxs + --with-apxs=/path/to/httpd-2.x.y/bin/apxs + - There are certain configure options that are meant for debugging an other - development use. If enabled, these options can substantially impact performance. - These options include all --debug-* options as well as the - --enable-performance-measurements options. + There are certain configure options that are meant for + debugging an other development use. If enabled, these + options can substantially impact performance. These options + include all --debug-* options as well as + the --enable-performance-measurements + options. + Compile with: make + - Optionally test with: make test + Optionally test with: make + test + - This is step is still a bit experimental. If you have problems, please send - the full output and error from the build to the support list. Most common issues - are related to not finding the required headers and/or libraries. + This is step is still a bit experimental. If you have + problems, please send the full output and error from the + build to the support list. Most common issues are related to + not finding the required headers and/or libraries. + - Optionally build the ModSecurity Log Collector with: make - mlogc + Optionally build the ModSecurity Log Collector with: + make mlogc + - Optionally install mlogc: Review the INSTALL file included in the apache2/mlogc-src directory in the - distribution. + Optionally install mlogc: Review the + INSTALL file included in the + apache2/mlogc-src directory in the distribution. + - Install the ModSecurity module with: make install + Install the ModSecurity module with: make + install + Windows (MS VC++ 8) + - Edit Makefile.win to configure the Apache base and library - paths. + Edit Makefile.win to configure the + Apache base and library paths. + - Compile with: nmake -f Makefile.win + Compile with: nmake -f + Makefile.win + - Install the ModSecurity module with: nmake -f Makefile.win - install + Install the ModSecurity module with: nmake -f + Makefile.win install + - Copy the libxml2.dll and lua5.1.dll to - the Apache bin directory. Alternatively you can follow the step - below for using LoadFile to load these libraries. + Copy the libxml2.dll and + lua5.1.dll to the Apache + bin directory. Alternatively you can follow + the step below for using LoadFile to load these + libraries. + - Edit the main Apache httpd config file (usually httpd.conf) - On UNIX (and Windows if you did not copy the DLLs as stated above) you must load - libxml2 and lua5.1 before ModSecurity with something like this: - - LoadFile /usr/lib/libxml2.so -LoadFile /usr/lib/liblua5.1.so - - Load the ModSecurity module - with:LoadModule security2_module modules/mod_security2.so + Edit the main Apache httpd config file (usually + httpd.conf) + + On UNIX (and Windows if you did not copy the DLLs as stated + above) you must load libxml2 and lua5.1 before ModSecurity with + something like this: + + LoadFile /usr/lib/libxml2.so +LoadFile /usr/lib/liblua5.1.so + + Load the ModSecurity module with:LoadModule security2_module modules/mod_security2.so + Configure ModSecurity + Start Apache httpd + You should now have ModSecurity 2.x up and running. + - If you have compiled Apache yourself you might experience problems compiling ModSecurity - against PCRE. This is because Apache bundles PCRE but this library is also typically - provided by the operating system. I would expect most (all) vendor-packaged Apache - distributions to be configured to use an external PCRE library (so this should not be a - problem). - You want to avoid Apache using the bundled PCRE library and ModSecurity linking against - the one provided by the operating system. The easiest way to do this is to compile Apache - against the PCRE library provided by the operating system (or you can compile it against the - latest PCRE version you downloaded from the main PCRE distribution site). You can do this at - configure time using the --with-pcre switch. If you are - not in a position to recompile Apache, then, to compile ModSecurity successfully, you'd - still need to have access to the bundled PCRE headers (they are available only in the Apache - source code) and change the include path for ModSecurity (as you did in step 7 above) to - point to them (via the --with-pcre ModSecurity configure option). - Do note that if your Apache is using an external PCRE library you can compile - ModSecurity with WITH_PCRE_STUDY defined,which would - possibly give you a slight performance edge in regular expression processing. + If you have compiled Apache yourself you might experience problems + compiling ModSecurity against PCRE. This is because Apache bundles PCRE + but this library is also typically provided by the operating system. I + would expect most (all) vendor-packaged Apache distributions to be + configured to use an external PCRE library (so this should not be a + problem). + + You want to avoid Apache using the bundled PCRE library and + ModSecurity linking against the one provided by the operating system. + The easiest way to do this is to compile Apache against the PCRE library + provided by the operating system (or you can compile it against the + latest PCRE version you downloaded from the main PCRE distribution + site). You can do this at configure time using the --with-pcre switch. If you are not in a + position to recompile Apache, then, to compile ModSecurity successfully, + you'd still need to have access to the bundled PCRE headers (they are + available only in the Apache source code) and change the include path + for ModSecurity (as you did in step 7 above) to point to them (via the + --with-pcre ModSecurity configure option). + + Do note that if your Apache is using an external PCRE library you + can compile ModSecurity with WITH_PCRE_STUDY defined,which would possibly + give you a slight performance edge in regular expression + processing.
+
Configuration Directives - The following section outlines all of the ModSecurity directives. Most of the ModSecurity - directives can be used inside the various Apache Scope Directives such as VirtualHost, Location, LocationMatch, - Directory, etc... There are others, however, that can only be used once - in the main configuration file. This information is specified in the Scope sections below. The - first version to use a given directive is given in the Version sections below. - These rules, along with the Core rules files, should be contained is files outside of the - httpd.conf file and called up with Apache "Include" directives. This allows for easier - updating/migration of the rules. If you create your own custom rules that you would like to - use with the Core rules, you should create a file called - modsecurity_crs_15_customrules.conf and place it in the same directory as the - Core rules files. By using this file name, your custom rules will be called up after the - standard ModSecurity Core rules configuration file but before the other Core rules. This - allows your rules to be evaluated first which can be useful if you need to implement specific - "allow" rules or to correct any false positives in the Core rules as they are applied to your - site. + + The following section outlines all of the ModSecurity directives. + Most of the ModSecurity directives can be used inside the various Apache + Scope Directives such as VirtualHost, + Location, LocationMatch, + Directory, etc... There are others, however, that can + only be used once in the main configuration file. This information is + specified in the Scope sections below. The first version to use a given + directive is given in the Version sections below. + + These rules, along with the Core rules files, should be contained is + files outside of the httpd.conf file and called up with Apache "Include" + directives. This allows for easier updating/migration of the rules. If you + create your own custom rules that you would like to use with the Core + rules, you should create a file called - + modsecurity_crs_15_customrules.conf and place it in + the same directory as the Core rules files. By using this file name, your + custom rules will be called up after the standard ModSecurity Core rules + configuration file but before the other Core rules. This allows your rules + to be evaluated first which can be useful if you need to implement + specific "allow" rules or to correct any false positives in the Core rules + as they are applied to your site. + - It is highly encouraged that you do not edit the Core rules files themselves but rather - place all changes (such as SecRuleRemoveByID, etc...) in your custom - rules file. This will allow for easier upgrading as newer Core rules are released by Breach - Security on the ModSecurity website. + It is highly encouraged that you do not edit the Core rules files + themselves but rather place all changes (such as + SecRuleRemoveByID, etc...) in your custom rules file. + This will allow for easier upgrading as newer Core rules are released by + Breach Security on the ModSecurity website. +
<literal>SecAction</literal> - Description: Unconditionally processes the action list it receives - as the first and only parameter. It accepts one parameter, the syntax of which is identical - to the third parameter of SecRule. - Syntax: - SecAction action1,action2,action3 - Example Usage: - SecAction - nolog,initcol:RESOURCE=%{REQUEST_FILENAME} + + Description: Unconditionally processes the + action list it receives as the first and only parameter. It accepts one + parameter, the syntax of which is identical to the third parameter + of SecRule. + + Syntax: SecAction + action1,action2,action3 + + Example Usage: SecAction + nolog,initcol:RESOURCE=%{REQUEST_FILENAME} + Processing Phase: Any + Scope: Any + Version: 2.0.0 + Dependencies/Notes: None - SecAction is best used when you unconditionally execute an action. This is explicit - triggering whereas the normal Actions are conditional based on data inspection of the - request/response. This is a useful directive when you want to run certain actions such as - initcol to initialize collections. + + SecAction is best used when you unconditionally execute an action. + This is explicit triggering whereas the normal Actions are conditional + based on data inspection of the request/response. This is a useful + directive when you want to run certain actions such as + initcol to initialize collections.
+
<literal>SecArgumentSeparator</literal> - Description: Specifies which character to use as separator - for application/x-www-form-urlencoded content. Defaults - to &. Applications are sometimes (very rarely) - written to use a semicolon (;). - Syntax: - SecArgumentSeparator character - Example Usage: - SecArgumentSeparator ; + + Description: Specifies which character to use + as separator for + application/x-www-form-urlencoded content. Defaults to + &. Applications are sometimes + (very rarely) written to use a semicolon (;). + + Syntax: SecArgumentSeparator character + + Example Usage: SecArgumentSeparator ; + Processing Phase: Any + Scope: Main + Version: 2.0.0 + Dependencies/Notes: None - This directive is needed if a backend web application is using a non-standard argument - separator. If this directive is not set properly for each web application, then ModSecurity - will not be able to parse the arguments appropriately and the effectiveness of the rule - matching will be significantly decreased. + + This directive is needed if a backend web application is using a + non-standard argument separator. If this directive is not set properly + for each web application, then ModSecurity will not be able to parse the + arguments appropriately and the effectiveness of the rule matching will + be significantly decreased.
+
<literal>SecAuditEngine</literal> - Description: Configures the audit logging engine. - Syntax: - SecAuditEngine On|Off|RelevantOnly - Example Usage: - SecAuditEngine On + + Description: Configures the audit logging + engine. + + Syntax: SecAuditEngine On|Off|RelevantOnly + + Example Usage: SecAuditEngine On + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: Can be set/changed with the "ctl" action for the current transaction. - Example: The following example shows the various audit directives used together. + + Dependencies/Notes: Can be set/changed with + the "ctl" action for the current transaction. + + Example: The following example shows the various audit directives + used together. + SecAuditEngine RelevantOnly SecAuditLog logs/audit/audit.log SecAuditLogParts ABCFHZ SecAuditLogType concurrent SecAuditLogStorageDir logs/audit SecAuditLogRelevantStatus ^(?:5|4\d[^4]) + Possible values are: + - On - log all transactions by default. + On - log all transactions + by default. + - Off - do not log transactions by default. + Off - do not log + transactions by default. + - RelevantOnly - by default only log transactions - that have triggered a warning or an error, or have a status code that is considered to - be relevant (see SecAuditLogRelevantStatus). + RelevantOnly - by default + only log transactions that have triggered a warning or an error, or + have a status code that is considered to be relevant (see SecAuditLogRelevantStatus).
+
<literal>SecAuditLog</literal> - Description: Defines the path to the main audit log file. - Syntax: - SecAuditLog /path/to/auditlog - Example Usage: - SecAuditLog /usr/local/apache/logs/audit.log + + Description: Defines the path to the main + audit log file. + + Syntax: SecAuditLog + /path/to/auditlog + + Example Usage: SecAuditLog + /usr/local/apache/logs/audit.log + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: This file is open on startup when the server - typically still runs as root. You should not allow non-root users to - have write privileges for this file or for the directory it is stored in.. - This file will be used to store the audit log entries if serial audit logging format is - used. If concurrent audit logging format is used this file will be used as an index, and - contain a record of all audit log files created. If you are planning to use Concurrent audit - logging and sending your audit log data off to a remote Console host or commercial - ModSecurity Management Appliance, then you will need to configure and use the ModSecurity - Log Collector (mlogc) and use the following format for the audit log: - - SecAuditLog "|/path/to/mlogc /path/to/mlogc.conf" - + + Dependencies/Notes: This file is open on + startup when the server typically still runs as + root. You should not allow non-root users to have write + privileges for this file or for the directory it is stored in.. + + This file will be used to store the audit log entries if serial + audit logging format is used. If concurrent audit logging format is used + this file will be used as an index, and contain a record of all audit + log files created. If you are planning to use Concurrent audit logging + and sending your audit log data off to a remote Console host or + commercial ModSecurity Management Appliance, then you will need to + configure and use the ModSecurity Log Collector (mlogc) and use the + following format for the audit log: + + SecAuditLog "|/path/to/mlogc /path/to/mlogc.conf"
+
<literal>SecAuditLog2</literal> - Description: Defines the path to the secondary audit log index file - when concurrent logging is enabled. See SecAuditLog2 for - more details. - Syntax: - SecAuditLog2 /path/to/auditlog2 - Example Usage: - SecAuditLog2 /usr/local/apache/logs/audit2.log + + Description: Defines the path to the + secondary audit log index file when concurrent logging is enabled. See + SecAuditLog2 for more details. + + Syntax: SecAuditLog2 + /path/to/auditlog2 + + Example Usage: SecAuditLog2 + /usr/local/apache/logs/audit2.log + Processing Phase: N/A + Scope: Any + Version: 2.1.2 - Dependencies/Notes: A main audit log must be defined via SecAuditLog before this directive may be used. Additionally, - this log is only used for replicating the main audit log index file when concurrent audit - logging is used. It will not be used for non-concurrent audit - logging. + + Dependencies/Notes: A main audit log must be + defined via SecAuditLog before this + directive may be used. Additionally, this log is only used for + replicating the main audit log index file when concurrent audit logging + is used. It will not be used for non-concurrent + audit logging.
+
<literal>SecAuditLogParts</literal> - Description: Defines which part of each transaction are going to be - recorded in audit log. Each part is assigned a single letter. If a letter appears in the - list then the equivalent part of each transactions will be recorded. See below for the list - of all parts. - Syntax: - SecAuditLogParts PARTS - Example Usage: - SecAuditLogParts ABCFHZ + + Description: Defines which part of each + transaction are going to be recorded in audit log. Each part is assigned + a single letter. If a letter appears in the list then the equivalent + part of each transactions will be recorded. See below for the list of + all parts. + + Syntax: SecAuditLogParts PARTS + + Example Usage: SecAuditLogParts ABCFHZ + Processing Phase: N/A + Scope: Any + Version: 2.0.0 + + Dependencies/Notes: At this time ModSecurity + does not log response bodies of stock Apache responses (e.g. 404), or the Server and Date response headers. + Default: ABCFHZ. - Please refer to the ModSecurity Data Formats document for a detailed description of - every available part. + + + Please refer to the ModSecurity Data Formats document for a + detailed description of every available part. + + + Available audit log parts: + + + + A - audit log header + (mandatory) + + + + B - request headers + + + + C - request body (present + only if the request body exists and ModSecurity is configured to + intercept it) + + + + D - RESERVED for + intermediary response headers, not implemented yet. + + + + E - intermediary response + body (present only if ModSecurity is configured to intercept + response bodies, and if the audit log engine is configured to record + it). Intermediary response body is the same as the actual response + body unless ModSecurity intercepts the intermediary response body, + in which case the actual response body will contain the error + message (either the Apache default error message, or the + ErrorDocument page). + + + + F - final response headers + (excluding the Date and Server headers, which are always added by + Apache in the late stage of content delivery). + + + + G - RESERVED for the actual + response body, not implemented yet. + + + + H - audit log + trailer + + + + I - This part is a + replacement for part C. It will log the same data as C in all cases + except when multipart/form-data + encoding in used. In this case it will log a fake application/x-www-form-urlencoded body + that contains the information about parameters but not about the + files. This is handy if you don't want to have (often large) files + stored in your audit logs. + + + + J - RESERVED. This part, + when implemented, will contain information about the files uploaded + using multipart/form-data encoding. + + + + K - This part contains a + full list of every rule that matched (one per line) in the order + they were matched. The rules are fully qualified and will thus show + inherited actions and default operators. Supported as of + v2.5.0 + + + + Z - final boundary, + signifies the end of the entry (mandatory) + +
+
<literal>SecAuditLogRelevantStatus</literal> - Description: Configures which response status code is to be - considered relevant for the purpose of audit logging. - Syntax: - SecAuditLogRelevantStatus REGEX - Example Usage: - SecAuditLogRelevantStatus ^(?:5|4\d[^4]) + + Description: Configures which response status + code is to be considered relevant for the purpose of audit + logging. + + Syntax: SecAuditLogRelevantStatus REGEX + + Example Usage: SecAuditLogRelevantStatus + ^(?:5|4\d[^4]) + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: Must have the SecAuditEngine - set to RelevantOnly. The parameter is a regular expression. - The main purpose of this directive is to allow you to configure audit logging for only - transactions that generate the specified HTTP Response Status Code. This directive is often - used to the decrease the total size of the audit log file. Keep in mind that if this - parameter is used, then successful attacks that result in a 200 OK status code will not be - logged. + + Dependencies/Notes: Must have the + SecAuditEngine set to + RelevantOnly. The parameter is a regular + expression. + + The main purpose of this directive is to allow you to configure + audit logging for only transactions that generate the specified HTTP + Response Status Code. This directive is often used to the decrease the + total size of the audit log file. Keep in mind that if this parameter is + used, then successful attacks that result in a 200 OK status code will + not be logged.
+
<literal>SecAuditLogStorageDir</literal> - Description: Configures the storage directory where concurrent - audit log entries are to be stored. - Syntax: - SecAuditLogStorageDir /path/to/storage/dir - Example Usage: - SecAuditLogStorageDir /usr/local/apache/logs/audit + + Description: Configures the storage directory + where concurrent audit log entries are to be stored. + + Syntax: SecAuditLogStorageDir + /path/to/storage/dir + + Example Usage: SecAuditLogStorageDir + /usr/local/apache/logs/audit + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: SecAuditLogType must be set to Concurrent. The - directory must already be created before starting Apache and it must be writable by the web - server user as new files are generated at runtime. - As with all logging mechanisms, ensure that you specify a file system location that has - adequate disk space and is not on the root partition. + + Dependencies/Notes: SecAuditLogType must be + set to Concurrent. The directory must already be created before starting + Apache and it must be writable by the web server user as new files are + generated at runtime. + + As with all logging mechanisms, ensure that you specify a file + system location that has adequate disk space and is not on the root + partition.
+
<literal>SecAuditLogType</literal> - Description: Configures the type of audit logging mechanism to be - used. - Syntax: - SecAuditLogType Serial|Concurrent - Example Usage: - SecAuditLogType Serial + + Description: Configures the type of audit + logging mechanism to be used. + + Syntax: SecAuditLogType Serial|Concurrent + + Example Usage: SecAuditLogType Serial + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: Must specify SecAuditLogStorageDir if you use concurrent logging. + + Dependencies/Notes: Must specify + SecAuditLogStorageDir if you use concurrent + logging. + Possible values are: + - Serial - all audit log entries will be stored in - the main audit logging file. This is more convenient for casual use but it is slower as - only one audit log entry can be written to the file at any one file. + Serial - all audit log + entries will be stored in the main audit logging file. This is more + convenient for casual use but it is slower as only one audit log + entry can be written to the file at any one file. + - Concurrent - audit log entries will be stored in - separate files, one for each transaction. Concurrent logging is the mode to use if you - are going to send the audit log data off to a remote ModSecurity Console host. + Concurrent - audit log + entries will be stored in separate files, one for each transaction. + Concurrent logging is the mode to use if you are going to send the + audit log data off to a remote ModSecurity Console host.
+
- <literal>SecCacheTransformations</literal> (Deprecated/Experimental) - Description: Controls caching of transformations. Caching is off by - default starting with 2.5.6, when it was deprecated and downgraded back to - experimental. - Syntax: - SecCacheTransformations On|Off [options] - Example Usage: - SecCacheTransformations On "minlen:64,maxlen:0" + <literal>SecCacheTransformations</literal> + (Deprecated/Experimental) + + Description: Controls caching of + transformations. Caching is off by default starting with 2.5.6, when it + was deprecated and downgraded back to experimental. + + Syntax: SecCacheTransformations On|Off + [options] + + Example Usage: SecCacheTransformations On + "minlen:64,maxlen:0" + Processing Phase: N/A + Scope: Any + Version: 2.5.0 + Dependencies/Notes: N/A + First parameter: + - On - cache transformations (per transaction, per - phase) allowing identical transformations to be performed only once. (default) + On - cache transformations + (per transaction, per phase) allowing identical transformations to + be performed only once. (default) + - Off - do not cache any transformations, forcing - all transformations to be performed for each rule executed. + Off - do not cache any + transformations, forcing all transformations to be performed for + each rule executed. + The following options are allowed (comma separated): + - incremental:on|off - enabling this option will - cache every transformation instead of just the final transformation. (default: - off) + incremental:on|off - + enabling this option will cache every transformation instead of just + the final transformation. (default: off) + - maxitems:N - do not allow more than N - transformations to be cached. The cache will then be disabled. A zero value is - interpreted as "unlimited". This option may be useful to limit caching for a form with a - large number of ARGS. (default: 512) + maxitems:N - do not allow + more than N transformations to be cached. The cache will then be + disabled. A zero value is interpreted as "unlimited". This option + may be useful to limit caching for a form with a large number of + ARGS. (default: 512) + - minlen:N - do not cache the transformation if the - value's length is less than N bytes. (default: 32) + minlen:N - do not cache the + transformation if the value's length is less than N bytes. (default: + 32) + - maxlen:N - do not cache the transformation if the - value's length is more than N bytes. A zero value is interpreted as "unlimited". - (default: 1024) + maxlen:N - do not cache the + transformation if the value's length is more than N bytes. A zero + value is interpreted as "unlimited". (default: 1024)
+
<literal>SecChrootDir</literal> - Description: Configures the directory path that will be used to - jail the web server process. - Syntax: - SecChrootDir /path/to/chroot/dir - Example Usage: - SecChrootDir /chroot + + Description: Configures the directory path + that will be used to jail the web server process. + + Syntax: SecChrootDir + /path/to/chroot/dir + + Example Usage: SecChrootDir /chroot + Processing Phase: N/A + Scope: Main + Version: 2.0.0 - Dependencies/Notes: This feature is not available on Windows - builds. The internal chroot functionality provided by ModSecurity works great for simple - setups. One example of a simple setup is Apache serving static files only, or running - scripts using modules.builds. Some problems you might encounter with more complex - setups: + + Dependencies/Notes: This feature is not + available on Windows builds. The internal chroot functionality provided + by ModSecurity works great for simple setups. One example of a simple + setup is Apache serving static files only, or running scripts using + modules.builds. Some problems you might encounter with more complex + setups: + - DNS lookups do not work (this is because this feature requires a shared library that - is loaded on demand, after chroot takes place). + DNS lookups do not work (this is because this feature requires + a shared library that is loaded on demand, after chroot takes + place). + - You cannot send email from PHP because it uses sendmail and sendmail is outside the - jail. + You cannot send email from PHP because it uses sendmail and + sendmail is outside the jail. + In some cases Apache graceful (reload) no longer works. - You should be aware that the internal chroot feature might not be 100% reliable. Due to - the large number of default and third-party modules available for the Apache web server, it - is not possible to verify the internal chroot works reliably with all of them. A module, - working from within Apache, can do things that make it easy to break out of the jail. In - particular, if you are using any of the modules that fork in the module initialisation phase - (e.g. mod_fastcgi, mod_fcgid, mod_cgid), you are advised to examine each Apache process and observe its - current working directory, process root, and the list of open files. Consider what your - options are and make your own decision. + + You should be aware that the internal chroot feature might not be + 100% reliable. Due to the large number of default and third-party + modules available for the Apache web server, it is not possible to + verify the internal chroot works reliably with all of them. A module, + working from within Apache, can do things that make it easy to break out + of the jail. In particular, if you are using any of the modules that + fork in the module initialisation phase (e.g. + mod_fastcgi, mod_fcgid, + mod_cgid), you are advised to examine each Apache + process and observe its current working directory, process root, and the + list of open files. Consider what your options are and make your own + decision.
+
<literal>SecComponentSignature</literal> - Description: Appends component signature to the ModSecurity - signature. - Syntax: SecComponentSignature "COMPONENT_NAME/X.Y.Z - (COMMENT)" - Example usage: SecComponentSignature "Core - Rules/1.2.3" + + Description: Appends component signature to + the ModSecurity signature. + + Syntax: SecComponentSignature + "COMPONENT_NAME/X.Y.Z (COMMENT)" + + Example usage: SecComponentSignature + "Core Rules/1.2.3" + Processing Phase: N/A + Scope: Main + Version: 2.5.0 - Dependencies/Notes: This directive should be used to make the - presence of significant ModSecurity components known. The entire signature will be recorded - in transaction audit log. It should be used by ModSecurity module and rule set writers to - make debugging easier. + + Dependencies/Notes: This directive should be + used to make the presence of significant ModSecurity components known. + The entire signature will be recorded in transaction audit log. It + should be used by ModSecurity module and rule set writers to make + debugging easier.
+
<literal>SecContentInjection</literal> - Description: Enables content injection using actions append and prepend. - Syntax: - SecContentInjection (On|Off) - Example Usage: - SecContentInjection On + + Description: Enables content injection using + actions append and prepend. + + Syntax: SecContentInjection + (On|Off) + + Example Usage: SecContentInjection + On + Processing Phase: N/A + Scope: Any + Version: 2.5.0 + Dependencies/Notes: N/A
+
<literal>SecCookieFormat</literal> - Description: Selects the cookie format that will be used in the - current configuration context. - Syntax: - SecCookieFormat 0|1 - Example Usage: - SecCookieFormat 0 + + Description: Selects the cookie format that + will be used in the current configuration context. + + Syntax: SecCookieFormat 0|1 + + Example Usage: SecCookieFormat 0 + Processing Phase: N/A + Scope: Any + Version: 2.0.0 + Dependencies/Notes: None + Possible values are: + - 0 - use version 0 (Netscape) cookies. This is - what most applications use. It is the default value. + 0 - use version 0 + (Netscape) cookies. This is what most applications use. It is the + default value. + - 1 - use version 1 cookies. + 1 - use version 1 + cookies.
+
<literal>SecDataDir</literal> - Description: Path where persistent data (e.g. IP address data, - session data, etc) is to be stored. - Syntax: - SecDataDir /path/to/dir - Example Usage: - SecDataDir /usr/local/apache/logs/data + + Description: Path where persistent data (e.g. + IP address data, session data, etc) is to be stored. + + Syntax: SecDataDir + /path/to/dir + + Example Usage: SecDataDir /usr/local/apache/logs/data + Processing Phase: N/A + Scope: Main - Dependencies/Notes: This directive is needed when initcol, setsid - an setuid are used. Must be writable by the web server user. + + Dependencies/Notes: This directive is needed + when initcol, setsid an setuid are used. Must be writable by the web + server user.
+
<literal>SecDebugLog</literal> - Description: Path to the ModSecurity debug log file. - Syntax: - SecDebugLog /path/to/modsec-debug.log - Example Usage: - SecDebugLog - /usr/local/apache/logs/modsec-debug.log + + Description: Path to the ModSecurity debug + log file. + + Syntax: SecDebugLog + /path/to/modsec-debug.log + + Example Usage: SecDebugLog + /usr/local/apache/logs/modsec-debug.log + Processing Phase: N/A + Scope: Any + Version: 2.0.0 + Dependencies/Notes: None
+
<literal>SecDebugLogLevel</literal> - Description: Configures the verboseness of the debug log - data. - Syntax: - SecDebugLogLevel 0|1|2|3|4|5|6|7|8|9 - Example Usage: - SecDebugLogLevel 4 + + Description: Configures the verboseness of + the debug log data. + + Syntax: SecDebugLogLevel 0|1|2|3|4|5|6|7|8|9 + + Example Usage: SecDebugLogLevel 4 + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: Levels 1 - 3 - are always sent to the Apache error log. Therefore you can always use level 0 as the default logging level in production. Level 5 is useful when debugging. It is not advisable to use higher - logging levels in production as excessive logging can slow down server significantly. + + Dependencies/Notes: Levels 1 - 3 are always sent to the Apache error log. + Therefore you can always use level 0 + as the default logging level in production. Level 5 is useful when debugging. It is not + advisable to use higher logging levels in production as excessive + logging can slow down server significantly. + Possible values are: + 0 - no logging. + - 1 - errors (intercepted requests) only. + 1 - errors (intercepted + requests) only. + 2 - warnings. + 3 - notices. + - 4 - details of how transactions are - handled. + 4 - details of how + transactions are handled. + - 5 - as above, but including information about - each piece of information handled. + 5 - as above, but including + information about each piece of information handled. + - 9 - log everything, including very detailed - debugging information. + 9 - log everything, + including very detailed debugging information.
+
<literal>SecDefaultAction</literal> - Description: Defines the default action to take on a rule - match. - Syntax: - SecDefaultAction action1,action2,action3 - Example Usage: - SecDefaultAction - log,auditlog,deny,status:403,phase:2 + + Description: Defines the default action to + take on a rule match. + + Syntax: SecDefaultAction + action1,action2,action3 + + Example Usage: SecDefaultAction + log,auditlog,deny,status:403,phase:2 + Processing Phase: Any + Scope: Any + Version: 2.0.0 - Dependencies/Notes: Rules following a SecDefaultAction directive will inherit this setting unless a specific action - is specified for an individual rule or until another SecDefaultAction is - specified. Take special note that in the logging disruptive actions are not allowed, but - this can inadvertently be inherited using a disruptive action in SecDefaultAction. - The default value is minimal (differing from previous versions): + + Dependencies/Notes: Rules following a + SecDefaultAction directive will inherit this setting + unless a specific action is specified for an individual rule or until + another SecDefaultAction is specified. Take special + note that in the logging disruptive actions are not allowed, but this + can inadvertently be inherited using a disruptive action in + SecDefaultAction. + + The default value is minimal (differing from previous + versions): + SecDefaultAction phase:2,log,auditlog,pass + - SecDefaultAction must specify a disruptive action and a processing - phase and cannot contain metadata actions. + SecDefaultAction must specify a disruptive + action and a processing phase and cannot contain metadata + actions. + - SecDefaultAction is not inherited across - configuration contexts. (For an example of why this may be a problem for you, read the - following ModSecurity Blog entry http://blog.modsecurity.org/2008/07/modsecurity-tri.html). + SecDefaultAction is not + inherited across configuration contexts. (For an example of why this + may be a problem for you, read the following ModSecurity Blog entry + http://blog.modsecurity.org/2008/07/modsecurity-tri.html).
+
<literal>SecGeoLookupDb</literal> - Description: Defines the path to the geographical database - file. - Syntax: - SecGeoLookupDb /path/to/db - Example Usage: - SecGeoLookupDb /usr/local/geo/data/GeoLiteCity.dat + + Description: Defines the path to the + geographical database file. + + Syntax: SecGeoLookupDb /path/to/db + + Example Usage: SecGeoLookupDb + /usr/local/geo/data/GeoLiteCity.dat + Processing Phase: N/A + Scope: Any + Version: 2.5.0 - Dependencies/Notes: Check out maxmind.com for - free database files. + + Dependencies/Notes: Check out + maxmind.com for free database files.
+
<literal>SecGuardianLog</literal> - Description: Configuration directive to use the httpd-guardian - script to monitor for Denial of Service (DoS) attacks. - Syntax: - SecGuardianLog |/path/to/httpd-guardian - Example Usage: - SecGuardianLog - |/usr/local/apache/bin/httpd-guardian + + Description: Configuration directive to use + the httpd-guardian script to monitor for Denial of Service (DoS) + attacks. + + Syntax: SecGuardianLog |/path/to/httpd-guardian + + Example Usage: SecGuardianLog + |/usr/local/apache/bin/httpd-guardian + Processing Phase: N/A + Scope: Main + Version: 2.0.0 - Dependencies/Notes: By default httpd-guardian will defend against - clients that send more than 120 requests in a minute, or more than 360 requests in five - minutes. - Since 1.9, ModSecurity supports a new directive, SecGuardianLog, that is designed to - send all access data to another program using the piped logging feature. Since Apache is - typically deployed in a multi-process fashion, making information sharing difficult, the - idea is to deploy a single external process to observe all requests in a stateful manner, - providing additional protection. - Development of a state of the art external protection tool will be a focus of subsequent - ModSecurity releases. However, a fully functional tool is already available as part of the - Apache httpd tools - project. The tool is called httpd-guardian and can be used to defend against - Denial of Service attacks. It uses the blacklist tool (from the same project) to interact - with an iptables-based (Linux) or pf-based (*BSD) firewall, dynamically blacklisting the - offending IP addresses. It can also interact with SnortSam (http://www.snortsam.net). - Assuming httpd-guardian is already configured (look into the source code for the detailed - instructions) you only need to add one line to your Apache configuration to deploy - it: + + Dependencies/Notes: By default httpd-guardian + will defend against clients that send more than 120 requests in a + minute, or more than 360 requests in five minutes. + + Since 1.9, ModSecurity supports a new directive, SecGuardianLog, + that is designed to send all access data to another program using the + piped logging feature. Since Apache is typically deployed in a + multi-process fashion, making information sharing difficult, the idea is + to deploy a single external process to observe all requests in a + stateful manner, providing additional protection. + + Development of a state of the art external protection tool will be + a focus of subsequent ModSecurity releases. However, a fully functional + tool is already available as part of the Apache httpd tools + project. The tool is called httpd-guardian and can be used to + defend against Denial of Service attacks. It uses the blacklist tool + (from the same project) to interact with an iptables-based (Linux) or + pf-based (*BSD) firewall, dynamically blacklisting the offending IP + addresses. It can also interact with SnortSam (http://www.snortsam.net). + Assuming httpd-guardian is already configured (look into the source code + for the detailed instructions) you only need to add one line to your + Apache configuration to deploy it: + SecGuardianLog |/path/to/httpd-guardian
+
<literal>SecMarker</literal> - Description: Adds a fixed rule marker in the ruleset to be used as - a target in a skipAfter action. A SecMarker directive - essentially creates a rule that does nothing and whose only purpose it to carry the given - ID. - Syntax: - SecMarker ID - Example Usage: - SecMarker 9999 + + Description: Adds a fixed rule marker in the + ruleset to be used as a target in a skipAfter action. + A SecMarker directive essentially creates a rule that + does nothing and whose only purpose it to carry the given ID. + + Syntax: SecMarker + ID + + Example Usage: SecMarker 9999 + Processing Phase: Any + Scope: Any + Version: 2.5.0 + Dependencies/Notes: None - - SecRule REQUEST_URI "^/$" \ + + SecRule REQUEST_URI "^/$" \ "chain,t:none,t:urlDecode,t:lowercase,t:normalisePath,skipAfter:99" SecRule REMOTE_ADDR "^127\.0\.0\.1$" "chain" SecRule REQUEST_HEADERS:User-Agent \ @@ -850,432 +1343,662 @@ SecRule &REQUEST_HEADERS:Host "@eq 0" \ SecRule &REQUEST_HEADERS:Accept "@eq 0" \ "log,deny,log,status:400,id:15,msg:'Request Missing an Accept Header'" -SecMarker 99 - +SecMarker 99
+
<literal>SecPdfProtect</literal> - Description: Enables the PDF XSS protection functionality. Once - enabled access to PDF files is tracked. Direct access attempts are redirected to links that - contain one-time tokens. Requests with valid tokens are allowed through unmodified. Requests - with invalid tokens are also allowed through but with forced download of the PDF files. This - implementation uses response headers to detect PDF files and thus can be used with - dynamically generated PDF files that do not have the .pdf extension in - the request URI. - Syntax: - SecPdfProtect On|Off - Example Usage: - SecPdfProtect On + + Description: Enables the PDF XSS protection + functionality. Once enabled access to PDF files is tracked. Direct + access attempts are redirected to links that contain one-time tokens. + Requests with valid tokens are allowed through unmodified. Requests with + invalid tokens are also allowed through but with forced download of the + PDF files. This implementation uses response headers to detect PDF files + and thus can be used with dynamically generated PDF files that do not + have the .pdf extension in the request URI. + + Syntax: SecPdfProtect On|Off + + Example Usage: SecPdfProtect On + Processing Phase: N/A + Scope: Any + Version: 2.5.0 + Dependencies/Notes: None
+
<literal>SecPdfProtectMethod</literal> - Description: Configure desired protection method to be used when - requests for PDF files are detected. Possible values are TokenRedirection - and ForcedDownload. The token redirection approach will attempt to - redirect with tokens where possible. This allows PDF files to continue to be opened inline - but only works for GET requests. Forced download always causes PDF files to be delivered as - opaque binaries and attachments. The latter will always be used for non-GET requests. Forced - download is considered to be more secure but may cause usability problems for users ("This - PDF won't open anymore!"). - Syntax: - SecPdfProtectMethod method - Example Usage: - SecPdfProtectMethod TokenRedirection + + Description: Configure desired protection + method to be used when requests for PDF files are detected. Possible + values are TokenRedirection and + ForcedDownload. The token redirection approach will + attempt to redirect with tokens where possible. This allows PDF files to + continue to be opened inline but only works for GET requests. Forced + download always causes PDF files to be delivered as opaque binaries and + attachments. The latter will always be used for non-GET requests. Forced + download is considered to be more secure but may cause usability + problems for users ("This PDF won't open anymore!"). + + Syntax: SecPdfProtectMethod method + + Example Usage: SecPdfProtectMethod TokenRedirection + Processing Phase: N/A + Scope: Any + Version: 2.5.0 + Dependencies/Notes: None + Default: - TokenRedirection + TokenRedirection
+
<literal>SecPdfProtectSecret</literal> - Description: Defines the secret that will be used to construct - one-time tokens. You should use a reasonably long value for the secret (e.g. 16 characters - is good). Once selected the secret should not be changed as it will break the tokens that - were sent prior to change. But it's not a big deal even if you change it. It will just force - download of PDF files with tokens that were issued in the last few seconds. - Syntax: - SecPdfProtectSecret secret - Example Usage: - SecPdfProtectSecret MyRandomSecretString + + Description: Defines the secret that will be + used to construct one-time tokens. You should use a reasonably long + value for the secret (e.g. 16 characters is good). Once selected the + secret should not be changed as it will break the tokens that were sent + prior to change. But it's not a big deal even if you change it. It will + just force download of PDF files with tokens that were issued in the + last few seconds. + + Syntax: SecPdfProtectSecret secret + + Example Usage: SecPdfProtectSecret + MyRandomSecretString + Processing Phase: N/A + Scope: Any + Version: 2.5.0 + Dependencies/Notes: None
+
<literal>SecPdfProtectTimeout</literal> - Description: Defines the token timeout. After token expires it can - no longer be used to allow access to PDF file. Request will be allowed through but the PDF - will be delivered as attachment. - Syntax: - SecPdfProtectTimeout timeout - Example Usage: - SecPdfProtectTimeout 10 + + Description: Defines the token timeout. After + token expires it can no longer be used to allow access to PDF file. + Request will be allowed through but the PDF will be delivered as + attachment. + + Syntax: SecPdfProtectTimeout timeout + + Example Usage: SecPdfProtectTimeout 10 + Processing Phase: N/A + Scope: Any + Version: 2.5.0 + Dependencies/Notes: None - Default: - 10 + + Default: 10
+
<literal>SecPdfProtectTokenName</literal> - Description: Defines the name of the token. The only reason you - would want to change the name of the token is if you wanted to hide the fact you are running - ModSecurity. It's a good reason but it won't really help as the adversary can look into the - algorithm used for PDF protection and figure it out anyway. It does raise the bar slightly - so go ahead if you want to. - Syntax: - SecPdfProtectTokenName name - Example Usage: - SecPdfProtectTokenName PDFTOKEN + + Description: Defines the name of the token. + The only reason you would want to change the name of the token is if you + wanted to hide the fact you are running ModSecurity. It's a good reason + but it won't really help as the adversary can look into the algorithm + used for PDF protection and figure it out anyway. It does raise the bar + slightly so go ahead if you want to. + + Syntax: SecPdfProtectTokenName name + + Example Usage: SecPdfProtectTokenName PDFTOKEN + Processing Phase: N/A + Scope: Any + Version: 2.5.0 + Dependencies/Notes: None - Default: - PDFTOKEN + + Default: PDFTOKEN
+
<literal>SecRequestBodyAccess</literal> - Description: Configures whether request bodies will be buffered and - processed by ModSecurity by default. - Syntax: - SecRequestBodyAccess On|Off - Example Usage: - SecRequestBodyAccess On + + Description: Configures whether request + bodies will be buffered and processed by ModSecurity by default. + + Syntax: SecRequestBodyAccess On|Off + + Example Usage: SecRequestBodyAccess On + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: This directive is required if you plan to - inspect POST_PAYLOAD. This directive must be used along with the - "phase:2" processing phase action and REQUEST_BODY variable/location. If - any of these 3 parts are not configured, you will not be able to inspect the request - bodies. + + Dependencies/Notes: This directive is + required if you plan to inspect POST_PAYLOAD. This + directive must be used along with the "phase:2" processing phase action + and REQUEST_BODY variable/location. If any of these 3 + parts are not configured, you will not be able to inspect the request + bodies. + Possible values are: + - On - access request bodies. + On - access request + bodies. + - Off - do not attempt to access request - bodies. + Off - do not attempt to + access request bodies.
+
<literal>SecRequestBodyLimit</literal> - Description: Configures the maximum request body size ModSecurity - will accept for buffering. - Syntax: - SecRequestBodyLimit NUMBER_IN_BYTES - Example Usage: - SecRequestBodyLimit 134217728 + + Description: Configures the maximum request + body size ModSecurity will accept for buffering. + + Syntax: SecRequestBodyLimit NUMBER_IN_BYTES + + Example Usage: SecRequestBodyLimit 134217728 + Scope: Any + Version: 2.0.0 - Dependencies/Notes: 131072 KB (134217728 bytes) is the default - setting. Anything over this limit will be rejected with status code 413 Request Entity Too - Large. There is a hard limit of 1 GB. + + Dependencies/Notes: 131072 KB (134217728 + bytes) is the default setting. Anything over this limit will be rejected + with status code 413 Request Entity Too Large. There is a hard limit of + 1 GB.
+
<literal>SecRequestBodyNoFilesLimit</literal> - Description: Configures the maximum request body size ModSecurity - will accept for buffering, excluding the size of files being transported in the request. - This directive comes handy to further reduce susceptibility to DoS attacks when someone is - sending request bodies of very large sizes. Web applications that require file uploads must - configure SecRequestBodyLimit to a high value. Since large files are - streamed to disk file uploads will not increase memory consumption. However, it's still - possible for someone to take advantage of a large request body limit and send non-upload - requests with large body sizes. This directive eliminates that loophole. - Syntax: - SecRequestBodyNoFilesLimit NUMBER_IN_BYTES - Example Usage: - SecRequestBodyLimit 131072 + + Description: Configures the maximum request + body size ModSecurity will accept for buffering, excluding the size of + files being transported in the request. This directive comes handy to + further reduce susceptibility to DoS attacks when someone is sending + request bodies of very large sizes. Web applications that require file + uploads must configure SecRequestBodyLimit to a high + value. Since large files are streamed to disk file uploads will not + increase memory consumption. However, it's still possible for someone to + take advantage of a large request body limit and send non-upload + requests with large body sizes. This directive eliminates that + loophole. + + Syntax: SecRequestBodyNoFilesLimit + NUMBER_IN_BYTES + + Example Usage: SecRequestBodyLimit 131072 + Scope: Any + Version: 2.5.0 - Dependencies/Notes: 1 MB (1048576 bytes) is the default setting. - This value is very conservative. For most applications you should be able to reduce it down - to 128 KB or lower. Anything over the limit will be rejected with status code 413 - Request Entity Too Large. There is a hard limit of 1 GB. + + Dependencies/Notes: 1 MB (1048576 bytes) is + the default setting. This value is very conservative. For most + applications you should be able to reduce it down to 128 KB or lower. + Anything over the limit will be rejected with status code 413 + Request Entity Too Large. There is a hard limit of 1 + GB.
+
<literal>SecRequestBodyInMemoryLimit</literal> - Description: Configures the maximum request body size ModSecurity - will store in memory. - Syntax: - SecRequestBodyInMemoryLimit NUMBER_IN_BYTES - Example Usage: - SecRequestBodyInMemoryLimit 131072 + + Description: Configures the maximum request + body size ModSecurity will store in memory. + + Syntax: SecRequestBodyInMemoryLimit + NUMBER_IN_BYTES + + Example Usage: SecRequestBodyInMemoryLimit 131072 + Processing Phase: N/A + Scope: Any + Version: 2.0.0 + Dependencies/Notes: None + By default the limit is 128 KB: + # Store up to 128 KB in memory SecRequestBodyInMemoryLimit 131072
+
<literal>SecResponseBodyLimit</literal> - Description: Configures the maximum response body size that will be - accepted for buffering. - Syntax: - SecResponseBodyLimit NUMBER_IN_BYTES - Example Usage: - SecResponseBodyLimit 524228 + + Description: Configures the maximum response + body size that will be accepted for buffering. + + Syntax: SecResponseBodyLimit NUMBER_IN_BYTES + + Example Usage: SecResponseBodyLimit 524228 + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: Anything over this limit will be rejected with - status code 500 Internal Server Error. This setting will not affect the responses with MIME - types that are not marked for buffering. There is a hard limit of 1 GB. + + Dependencies/Notes: Anything over this limit + will be rejected with status code 500 Internal Server Error. This + setting will not affect the responses with MIME types that are not + marked for buffering. There is a hard limit of 1 GB. + By default this limit is configured to 512 KB: + # Buffer response bodies of up to 512 KB in length SecResponseBodyLimit 524288
+
<literal>SecResponseBodyLimitAction</literal> - Description: Controls what happens once a response body limit, - configured with SecResponseBodyLimit, is encountered. By default - ModSecurity will reject a response body that is longer than specified. Some web sites, - however, will produce very long responses making it difficult to come up with a reasonable - limit. Such sites would have to raise the limit significantly to function properly defying - the purpose of having the limit in the first place (to control memory consumption). With the - ability to choose what happens once a limit is reached site administrators can choose to - inspect only the first part of the response, the part that can fit into the desired limit, - and let the rest through. Some could argue that allowing parts of responses to go - uninspected is a weakness. This is true in theory but only applies to cases where the - attacker controls the output (e.g. can make it arbitrary long). In such cases, however, it - is not possible to prevent leakage anyway. The attacker could compress, obfuscate, or even - encrypt data before it is sent back, and therefore bypass any monitoring device. + + Description: Controls what happens once a + response body limit, configured with + SecResponseBodyLimit, is encountered. By default + ModSecurity will reject a response body that is longer than specified. + Some web sites, however, will produce very long responses making it + difficult to come up with a reasonable limit. Such sites would have to + raise the limit significantly to function properly defying the purpose + of having the limit in the first place (to control memory consumption). + With the ability to choose what happens once a limit is reached site + administrators can choose to inspect only the first part of the + response, the part that can fit into the desired limit, and let the rest + through. Some could argue that allowing parts of responses to go + uninspected is a weakness. This is true in theory but only applies to + cases where the attacker controls the output (e.g. can make it arbitrary + long). In such cases, however, it is not possible to prevent leakage + anyway. The attacker could compress, obfuscate, or even encrypt data + before it is sent back, and therefore bypass any monitoring + device. + Syntax: SecResponseBodyLimitAction - Reject|ProcessPartial - Example Usage: SecResponseBodyLimitAction - ProcessPartial + Reject|ProcessPartial + + Example Usage: + SecResponseBodyLimitAction ProcessPartial + Processing Phase: N/A + Scope: Any + Version: 2.5.0 + Dependencies/Notes: None
+
<literal>SecResponseBodyMimeType</literal> - Description: Configures which - MIME types are to be considered for response body buffering. - Syntax: - SecResponseBodyMimeType mime/type - Example Usage: - SecResponseBodyMimeType text/plain text/html + + Description: Configures which MIME types are to be considered for response + body buffering. + + Syntax: SecResponseBodyMimeType mime/type + + Example Usage: SecResponseBodyMimeType text/plain + text/html + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: Multiple - SecResponseBodyMimeType directives can be used to add - MIME types. - The default value is text/plaintext/html: + + Dependencies/Notes: Multiple SecResponseBodyMimeType directives can be + used to add MIME types. + + The default value is text/plaintext/html: + SecResponseBodyMimeType text/plain text/html
+
<literal>SecResponseBodyMimeTypesClear</literal> - Description: Clears the list of MIME types considered for response body buffering, allowing you to start - populating the list from scratch. - Syntax: - SecResponseBodyMimeTypesClear - Example Usage: - SecResponseBodyMimeTypesClear + + Description: Clears the list of MIME types considered for response body + buffering, allowing you to start populating the list from + scratch. + + Syntax: SecResponseBodyMimeTypesClear + + Example Usage: SecResponseBodyMimeTypesClear + Processing Phase: N/A + Scope: Any + Version: 2.0.0 + Dependencies/Notes: None
+
<literal>SecResponseBodyAccess</literal> - Description: Configures whether response bodies are to be buffer - and analysed or not. - Syntax: - SecResponseBodyAccess On|Off - Example Usage: - SecResponseBodyAccess On + + Description: Configures whether response + bodies are to be buffer and analysed or not. + + Syntax: SecResponseBodyAccess On|Off + + Example Usage: SecResponseBodyAccess On + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: This directive is required if you plan to - inspect HTML responses. This directive must be used along with the "phase:4" processing - phase action and RESPONSE_BODY variable/location. If any of these 3 parts are not - configured, you will not be able to inspect the response bodies. + + Dependencies/Notes: This directive is + required if you plan to inspect HTML responses. This directive must be + used along with the "phase:4" processing phase action and RESPONSE_BODY + variable/location. If any of these 3 parts are not configured, you will + not be able to inspect the response bodies. + Possible values are: + - On - access response bodies (but only if the MIME - type matches, see above). + On - access response bodies + (but only if the MIME type matches, see above). + - Off - do not attempt to access response - bodies. + Off - do not attempt to + access response bodies.
+
<literal>SecRule</literal> - Description: - SecRule is the main ModSecurity directive. It is used to - analyse data and perform actions based on the results. - Syntax: - SecRule VARIABLES OPERATOR [ACTIONS] - Example Usage: - SecRule REQUEST_URI "attack" \ - "phase:1,t:none,t:urlDecode,t:lowercase,t:normalisePath" + + Description: SecRule is the main ModSecurity directive. It + is used to analyse data and perform actions based on the results. + + Syntax: SecRule + VARIABLES OPERATOR [ACTIONS] + + Example Usage: SecRule REQUEST_URI "attack" \ + + + "phase:1,t:none,t:urlDecode,t:lowercase,t:normalisePath" + Processing Phase: Any + Scope: Any + Version: 2.0.0 + Dependencies/Notes: None + In general, the format of this rule is as follows: + SecRule VARIABLES OPERATOR [ACTIONS] - The second part, OPERATOR, specifies how they are - going to be checked. The third (optional) part, ACTIONS, - specifies what to do whenever the operator used performs a successful match against a - variable. + + The second part, OPERATOR, + specifies how they are going to be checked. The third (optional) part, + ACTIONS, specifies what to do + whenever the operator used performs a successful match against a + variable. +
Variables in rules - The first part, VARIABLES, specifies which - variables are to be checked. For example, the following rule will reject a transaction - that has the word dirty in the URI: + + The first part, VARIABLES, + specifies which variables are to be checked. For example, the + following rule will reject a transaction that has the word + dirty in the URI: + SecRule ARGS dirty + Each rule can specify one or more variables: + SecRule ARGS|REQUEST_HEADERS:User-Agent dirty - There is a third format supported by the selection operator - XPath expression. XPath - expressions can only used against the special variable XML, which is available only of the - request body was processed as XML. + + There is a third format supported by the selection operator - + XPath expression. XPath expressions can only used against the special + variable XML, which is available only of the request body was + processed as XML. + SecRule XML:/xPath/Expression dirty + - Not all collections support all selection operator format types. You should refer to - the documentation of each collection to determine what is and isn't supported. + Not all collections support all selection operator format + types. You should refer to the documentation of each collection to + determine what is and isn't supported.
+
Collections - A variable can contain one or many pieces of data, depending on the nature of the - variable and the way it is used. We've seen examples of both approaches in the previous - section. When a variable can contain more than one value we refer to it as a - collection. - Collections are always expanded before a rule is run. For example, the following - rule: + + A variable can contain one or many pieces of data, depending on + the nature of the variable and the way it is used. We've seen examples + of both approaches in the previous section. When a variable can + contain more than one value we refer to it as a + collection. + + Collections are always expanded before a rule is run. For + example, the following rule: + SecRule ARGS dirty + will be expanded to: + SecRule ARGS:p dirty SecRule ARGS:q dirty - in a requests that has only two parameters, named p and q. + + in a requests that has only two parameters, named + p and q. + Collections come in several flavours: + Read-only + - Created at runtime using transaction data. For example: ARGS - (contains a list of all request parameter values) and REQUEST_HEADERS (contains a list of all request header values). + Created at runtime using transaction data. For example: + ARGS (contains a list of all request + parameter values) and REQUEST_HEADERS + (contains a list of all request header values). + Transient Read/Write + - The TX collection is created (empty) for every transaction. - Rules can read from it and write to it (using the setvar action, - for example), but the information stored in this collection will not survive the end - of transaction. + The TX collection is created (empty) + for every transaction. Rules can read from it and write to it + (using the setvar action, for example), but + the information stored in this collection will not survive the + end of transaction. + Persistent Read/Write + - There are several collections that can be written to, but which are persisted to - the storage backend. These collections are used to track clients across - transactions. Examples of collections that fall into this type are IP, SESSION and USER. + There are several collections that can be written to, but + which are persisted to the storage backend. These collections + are used to track clients across transactions. Examples of + collections that fall into this type are IP, + SESSION and USER.
+
Operators in rules - In the simplest possible case you will use a regular expression pattern as the second - rule parameter. This is what we've done in the examples above. If you do this ModSecurity - assumes you want to use the rx (regular expression) - operator. You can also explicitly specify the operator you want to use by using @, followed by the name of an operator, at the beginning of - the second SecRule parameter: + + In the simplest possible case you will use a regular expression + pattern as the second rule parameter. This is what we've done in the + examples above. If you do this ModSecurity assumes you want to use the + rx (regular expression) operator. + You can also explicitly specify the operator you want to use by using + @, followed by the name of an + operator, at the beginning of the second SecRule + parameter: + SecRule ARGS "@rx dirty" - Note how we had to use double quotes to delimit the second rule parameter. This is - because the second parameter now has whitespace in it. Any number of whitespace characters - can follow the name of the operator. If there are any non-whitespace characters there, - they will all be treated as a special parameter to the operator. In the case of the - regular expression operator the special parameter is the pattern that will be used for - comparison. - The @ can be the second character if you are using negation to negate the result - returned by the operator: + + Note how we had to use double quotes to delimit the second rule + parameter. This is because the second parameter now has whitespace in + it. Any number of whitespace characters can follow the name of the + operator. If there are any non-whitespace characters there, they will + all be treated as a special parameter to the operator. In the case of + the regular expression operator the special parameter is the pattern + that will be used for comparison. + + The @ can be the second character if you are using negation to + negate the result returned by the operator: + SecRule &ARGS "!@rx ^0$"
+
Operator negation - Operator results can be negated by using an exclamation mark at the beginning of the - second parameter. The following rule matches if the word dirty does - not appear in the User-Agent request - header: + + Operator results can be negated by using an exclamation mark at + the beginning of the second parameter. The following rule matches if + the word dirty does not appear + in the User-Agent request header: + SecRule REQUEST_HEADERS:User-Agent !dirty - You can use the exclamation mark in combination with any parameter. If you do, the - exclamation mark needs to go first, followed by the explicit operator reference. The - following rule has the same effect as the previous example: + + You can use the exclamation mark in combination with any + parameter. If you do, the exclamation mark needs to go first, followed + by the explicit operator reference. The following rule has the same + effect as the previous example: + SecRule REQUEST_HEADERS:User-Agent "!@rx dirty" - If you need to use negation in a rule that is going to be applied to several variables - then it may not be immediately clear what will happen. Consider the following - example: + + If you need to use negation in a rule that is going to be + applied to several variables then it may not be immediately clear what + will happen. Consider the following example: + SecRule ARGS:p|ARGS:q !dirty + The above rule is identical to: + SecRule ARGS:p !dirty SecRule ARGS:q !dirty + - Negation is applied to operations against individual operations, not agains the - entire variable list. + Negation is applied to operations against individual + operations, not agains the entire variable list.
+
Actions in rules - The third parameter, ACTIONS, can be omitted only - because there is a helper feature that specifies the default action list. If the parameter - isn't omitted the actions specified in the parameter will be merged with the default - action list to create the actual list of actions that will be processed on a rule - match. + + The third parameter, ACTIONS, + can be omitted only because there is a helper feature that specifies + the default action list. If the parameter isn't omitted the actions + specified in the parameter will be merged with the default action list + to create the actual list of actions that will be processed on a rule + match.
+
<literal>SecRuleInheritance</literal> - Description: Configures whether the current context will inherit - rules from the parent context (configuration options are inherited in most cases - you - should look up the documentation for every directive to determine if it is inherited or - not). - Syntax: - SecRuleInheritance On|Off - Example Usage: - SecRuleInheritance Off + + Description: Configures whether the current + context will inherit rules from the parent context (configuration + options are inherited in most cases - you should look up the + documentation for every directive to determine if it is inherited or + not). + + Syntax: SecRuleInheritance On|Off + + Example Usage: SecRuleInheritance Off + Processing Phase: Any + Scope: Any + Version: 2.0.0 - Dependencies/Notes: Resource-specific contexts (e.g. Location, Directory, etc) - cannot override phase1 rules configured in the main server or in the - virtual server. This is because phase 1 is run early in the request processing process, - before Apache maps request to resource. Virtual host context can override phase 1 rules - configured in the main server. - Example: The following example shows where ModSecurity may be enabled in the main Apache - configuration scope, however you might want to configure your VirtualHosts differently. In - the first example, the first VirtualHost is not inheriting the ModSecurity main config - directives and in the second one it is. - SecRuleEnine On + + Dependencies/Notes: Resource-specific + contexts (e.g. Location, Directory, etc) cannot override + phase1 rules configured in the main server or in + the virtual server. This is because phase 1 is run early in the request + processing process, before Apache maps request to resource. Virtual host + context can override phase 1 rules configured in the main server. + + Example: The following example shows where ModSecurity may be + enabled in the main Apache configuration scope, however you might want + to configure your VirtualHosts differently. In the first example, the + first VirtualHost is not inheriting the ModSecurity main config + directives and in the second one it is. + + SecRuleEngine On SecDefaultAction log,pass,phase:2 ... @@ -1293,104 +2016,161 @@ ServerAlias www.app2.com SecRuleInheritance On SecRule ARGS "attack" ... </VirtualHost> + Possible values are: + - On - inherit rules from the parent - context. + On - inherit rules from the + parent context. + - Off - do not inherit rules from the parent - context. + Off - do not inherit rules + from the parent context. + - Configuration contexts are an Apache concept. Directives <Directory>, <Files>, <Location> and <VirtualHost> are all used - to create configuration contexts. For more information please go to the Apache - documentation section Configuration Sections. + Configuration contexts are an Apache concept. Directives + <Directory>, + <Files>, + <Location> and + <VirtualHost> are all used to create + configuration contexts. For more information please go to the + Apache documentation section Configuration + Sections.
+
<literal>SecRuleEngine</literal> - Description: Configures the rules engine. - Syntax: - SecRuleEngine On|Off|DetectionOnly - Example Usage: - SecRuleEngine On + + Description: Configures the rules + engine. + + Syntax: SecRuleEngine On|Off|DetectionOnly + + Example Usage: SecRuleEngine On + Processing Phase: Any + Scope: Any + Version: 2.0.0 - Dependencies/Notes: This directive can also be controlled by the - ctl action (ctl:ruleEngine=off) for per rule processing. + + Dependencies/Notes: This directive can also + be controlled by the ctl action (ctl:ruleEngine=off) for per rule + processing. + Possible values are: + On - process rules. + - Off - do not process rules. + Off - do not process + rules. + - DetectionOnly - process rules but never intercept - transactions, even when rules are configured to do so. + DetectionOnly - process + rules but never intercept transactions, even when rules are + configured to do so.
+
<literal>SecRuleRemoveById</literal> - Description: Removes matching rules from the parent - contexts. - Syntax: - SecRuleUpdateActionById RULEID ACTIONLIST - Example Usage: - SecRuleRemoveByID 1 2 "9000-9010" + + Description: Removes matching rules from the + parent contexts. + + Syntax: SecRuleUpdateActionById RULEID + ACTIONLIST + + Example Usage: SecRuleRemoveByID 1 2 "9000-9010" + Processing Phase: Any + Scope: Any + Version: 2.0.0 - Dependencies/Notes: This directive supports multiple parameters, - where each parameter can either be a rule ID, or a range. Parameters that contain spaces - must be delimited using double quotes. + + Dependencies/Notes: This directive supports + multiple parameters, where each parameter can either be a rule ID, or a + range. Parameters that contain spaces must be delimited using double + quotes. + SecRuleRemoveById 1 2 5 10-20 "400-556" 673
+
<literal>SecRuleRemoveByMsg</literal> - Description: Removes matching rules from the parent - contexts. - Syntax: - SecRuleRemoveByMsg REGEX - Example Usage: - SecRuleRemoveByMsg "FAIL" + + Description: Removes matching rules from the + parent contexts. + + Syntax: SecRuleRemoveByMsg REGEX + + Example Usage: SecRuleRemoveByMsg "FAIL" + Processing Phase: Any + Scope: Any + Version: 2.0.0 - Dependencies/Notes: This directive supports multiple parameters. - Each parameter is a regular expression that will be applied to the message (specified using - the msg action). + + Dependencies/Notes: This directive supports + multiple parameters. Each parameter is a regular expression that will be + applied to the message (specified using the msg action).
+
<literal>SecRuleScript</literal> (Experimental) - Description: This directive creates a special rule that executes a - Lua script to decide whether to match or not. The main difference from SecRule is that there are no targets nor operators. The script can fetch any - variable from the ModSecurity context and use any (Lua) operator to test them. The second - optional parameter is the list of actions whose meaning is identical to that of SecRule. - Syntax: - SecRuleScript /path/to/script.lua [ACTIONS] - Example Usage: - SecRuleScript "/path/to/file.lua" "block" + + Description: This directive creates a special + rule that executes a Lua script to decide whether to match or not. The + main difference from SecRule is that there are no + targets nor operators. The script can fetch any variable from the + ModSecurity context and use any (Lua) operator to test them. The second + optional parameter is the list of actions whose meaning is identical to + that of SecRule. + + Syntax: SecRuleScript + /path/to/script.lua [ACTIONS] + + Example Usage: SecRuleScript "/path/to/file.lua" + "block" + Processing Phase: Any + Scope: Any + Version: 2.5.0 + Dependencies/Notes: None + - All Lua scripts are compiled at configuration time and cached in memory. To reload - scripts you must reload the entire ModSecurity configuration by restarting Apache. + All Lua scripts are compiled at configuration time and cached in + memory. To reload scripts you must reload the entire ModSecurity + configuration by restarting Apache. + Example script: + -- Your script must define the main entry -- point, as below. function main() @@ -1420,11 +2200,15 @@ function main() -- Otherwise, simply return nil. return nil; end - In this first example we were only retrieving one variable at the time. In this case the - name of the variable is known to you. In many cases, however, you will want to examine - variables whose names you won't know in advance, for example script parameters. - Example showing use of m.getvars() to retrieve many variables at - once: + + In this first example we were only retrieving one variable at the + time. In this case the name of the variable is known to you. In many + cases, however, you will want to examine variables whose names you won't + know in advance, for example script parameters. + + Example showing use of m.getvars() to retrieve + many variables at once: + function main() -- Retrieve script parameters. local d = m.getvars("ARGS", { "lowercase", "htmlEntityDecode" } ); @@ -1442,162 +2226,233 @@ end -- Nothing wrong found. return nil; end + - Go to http://www.lua.org/ to find more about - the Lua programming language. The reference manual too is available online, at http://www.lua.org/manual/5.1/. + Go to http://www.lua.org/ to find more + about the Lua programming language. The reference manual too is + available online, at http://www.lua.org/manual/5.1/. + - Lua support is marked as experimental as the way the progamming - interface may continue to evolve while we are working for the best implementation style. - Any user input into the programming interface is appreciated. + Lua support is marked as experimental as + the way the progamming interface may continue to evolve while we are + working for the best implementation style. Any user input into the + programming interface is appreciated.
+
<literal>SecRuleUpdateActionById</literal> - Description: Updates the action list of the specified rule. - Syntax: - SecRuleUpdateActionById RULEID ACTIONLIST - Example Usage: - SecRuleUpdateActionById 12345 deny,status:403 + + Description: Updates the action list of the + specified rule. + + Syntax: SecRuleRemoveById RULEID ACTIONLIST + + Example Usage: SecRuleUpdateActionById 12345 + deny,status:403 + Processing Phase: Any + Scope: Any + Version: 2.5.0 - Dependencies/Notes: This directive merges the specified action list - with the rule's action list. There are two limitations. The rule ID cannot be changed, nor - can the phase. Further note that actions that may be specified multiple times are appended - to the original. + + Dependencies/Notes: This directive merges the + specified action list with the rule's action list. There are two + limitations. The rule ID cannot be changed, nor can the phase. Further + note that actions that may be specified multiple times are appended to + the original. + SecAction \ "t:lowercase,phase:2,id:12345,pass,msg:'The Message',log,auditlog" SecRuleUpdateActionById 12345 "t:compressWhitespace,deny,status:403,msg:'A new message' - The example above will cause the rule to be executed as if it was specified as - follows: + + The example above will cause the rule to be executed as if it was + specified as follows: + SecAction \ "t:lowercase,phase:2,id:12345,log,auditlog,t:compressWhitespace,deny,status:403,msg:'A new message'"
+
<literal>SecServerSignature</literal> - Description: Instructs ModSecurity to change the data presented in - the Server response header token. - Syntax: - SecServerSignature "WEB SERVER SOFTWARE" - Example Usage: - SecServerSignature "Netscape-Enterprise/6.0" + + Description: Instructs ModSecurity to change + the data presented in the "Server:" response header token. + + Syntax: SecServerSignature "WEB SERVER + SOFTWARE" + + Example Usage: SecServerSignature + "Netscape-Enterprise/6.0" + Processing Phase: N/A + Scope: Main + Version: 2.0.0 - Dependencies/Notes: In order for this directive to work, you must - set the Apache ServerTokens directive to Full. ModSecurity will overwrite the server - signature data held in this memory space with the data set in this directive. If - ServerTokens is not set to Full, then the memory space is most likely not large enough to - hold the new data we are looking to insert. -
-
- <literal>SecStreamInspection</literal> - Description: Controls inspection of streams. Enabled by default. - Example: SecStreamInspection Off - Processing Phase: N/A - Version: 3.0.0 -
-
- <literal>SecStreamInspect</literal> - Description: - Example: SecStreamInspect REQUEST_BODY "@pm this that" - log,warn,t:none - Processing Phase: N/A; streams are processed as they become available. - Version: 3.0.0 + + Dependencies/Notes: In order for this + directive to work, you must set the Apache ServerTokens directive to + Full. ModSecurity will overwrite the server signature data held in this + memory space with the data set in this directive. If ServerTokens is not + set to Full, then the memory space is most likely not large enough to + hold the new data we are looking to insert.
+
<literal>SecTmpDir</literal> - Description: Configures the directory where temporary files will be - created. - Syntax: - SecTmpDir /path/to/dir - Example Usage: - SecTmpDir /tmp + + Description: Configures the directory where + temporary files will be created. + + Syntax: SecTmpDir + /path/to/dir + + Example Usage: SecTmpDir /tmp + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: Needs to be writable by the Apache user - process. This is the directory location where Apache will swap data to disk if it runs out - of memory (more data than what was specified in the SecRequestBodyInMemoryLimit directive) - during inspection. + + Dependencies/Notes: Needs to be writable by + the Apache user process. This is the directory location where Apache + will swap data to disk if it runs out of memory (more data than what was + specified in the SecRequestBodyInMemoryLimit directive) during + inspection.
+
<literal>SecUploadDir</literal> - Description: Configures the directory where intercepted files will - be stored. - Syntax: - SecUploadDir /path/to/dir - Example Usage: - SecUploadDir /tmp + + Description: Configures the directory where + intercepted files will be stored. + + Syntax: SecUploadDir + /path/to/dir + + Example Usage: SecUploadDir /tmp + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: This directory must be on the same filesystem - as the temporary directory defined with SecTmpDir. This - directive is used with SecUploadKeepFiles. + + Dependencies/Notes: This directory must be on + the same filesystem as the temporary directory defined with SecTmpDir. This directive is used with + SecUploadKeepFiles.
+
<literal>SecUploadFileMode</literal> - Description: Configures the mode (permissions) of any uploaded - files using an octal number (as used in chmod). - Syntax: - SecUploadFileMode octal_mode|"default" - Example Usage: - SecUploadFileMode 0640 + + Description: Configures the mode + (permissions) of any uploaded files using an octal number (as used in + chmod). + + Syntax: SecUploadFileMode octal_mode|"default" + + Example Usage: SecUploadFileMode 0640 + Processing Phase: N/A + Scope: Any + Version: 2.1.6 - Dependencies/Notes: This feature is not available on operating - systems not supporting octal file modes. The default mode (0600) only grants read/write - access to the account writing the file. If access from another account is needed (using - clamd is a good example), then this directive may be required. However, use this directive - with caution to avoid exposing potentially sensitive data to unauthorized users. Using the - value "default" will revert back to the default setting. + + Dependencies/Notes: This feature is not + available on operating systems not supporting octal file modes. The + default mode (0600) only grants read/write access to the account writing + the file. If access from another account is needed (using clamd is a + good example), then this directive may be required. However, use this + directive with caution to avoid exposing potentially sensitive data to + unauthorized users. Using the value "default" will revert back to the + default setting.
+
<literal>SecUploadKeepFiles</literal> - Description: Configures whether or not the intercepted files will - be kept after transaction is processed. - Syntax: - SecUploadKeepFiles On|Off|RelevantOnly - Example Usage: - SecUploadKeepFiles On + + Description: Configures whether or not the + intercepted files will be kept after transaction is processed. + + Syntax: SecUploadKeepFiles On|Off|RelevantOnly + + Example Usage: SecUploadKeepFiles On + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: This directive requires the storage directory - to be defined (using SecUploadDir). + + Dependencies/Notes: This directive requires + the storage directory to be defined (using SecUploadDir). + Possible values are: + - On - Keep uploaded files. + On - Keep uploaded + files. + - Off - Do not keep uploaded files. + Off - Do not keep uploaded + files. + - RelevantOnly - This will keep only those files - that belong to requests that are deemed relevant. + RelevantOnly - This will + keep only those files that belong to requests that are deemed + relevant.
+
<literal>SecWebAppId</literal> - Description: Creates a partition on the server that belongs to one - web application. - Syntax: - SecWebAppId "NAME" - Example Usage: - SecWebAppId "WebApp1" + + Description: Creates a partition on the + server that belongs to one web application. + + Syntax: SecWebAppId + "NAME" + + Example Usage: SecWebAppId "WebApp1" + Processing Phase: N/A + Scope: Any + Version: 2.0.0 - Dependencies/Notes: Partitions are used to avoid collisions between - session IDs and user IDs. This directive must be used if there are multiple applications - deployed on the same server. If it isn't used, a collision between session IDs might occur. - The default value is default. Example: + + Dependencies/Notes: Partitions are used to + avoid collisions between session IDs and user IDs. This directive must + be used if there are multiple applications deployed on the same server. + If it isn't used, a collision between session IDs might occur. The + default value is default. + Example: + <VirtualHost *:80> ServerName app1.com ServerAlias www.app1.com @@ -1615,378 +2470,533 @@ SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass SecAction setsid:%{REQUEST_COOKIES.PHPSESSID} ... </VirtualHost> - In the two examples configurations shown, SecWebAppId is being used in conjunction with - the Apache VirtualHost directives. What this achieves is to create more unique collection - names when being hosted on one server. Normally, when setsid is used, ModSecurity will - create a collection with the name "SESSION" and it will hold the value specified. With using - SecWebAppId as shown in the examples, however, the name of the collection would become - "App1_SESSION" and "App2_SESSION". + + In the two examples configurations shown, SecWebAppId is being + used in conjunction with the Apache VirtualHost directives. What this + achieves is to create more unique collection names when being hosted on + one server. Normally, when setsid is used, ModSecurity will create a + collection with the name "SESSION" and it will hold the value specified. + With using SecWebAppId as shown in the examples, however, the name of + the collection would become "App1_SESSION" and "App2_SESSION". + SecWebAppId is relevant in two cases: + - You are logging transactions/alerts to the ModSecurity Console and you want to use - the web application ID to search only the transactions belonging to that - application. + You are logging transactions/alerts to the ModSecurity Console + and you want to use the web application ID to search only the + transactions belonging to that application. + - You are using the data persistence facility (collections SESSION and USER) and you - need to avoid collisions between sessions and users belonging to different - applications. + You are using the data persistence facility (collections + SESSION and USER) and you need to avoid collisions between sessions + and users belonging to different applications.
+
Processing Phases - ModSecurity 2.x allows rules to be placed in one of the following five phases: + + ModSecurity 2.x allows rules to be placed in one of the following + five phases: + Request headers (REQUEST_HEADERS) + Request body (REQUEST_BODY) + Response headers (RESPONSE_HEADERS) + Response body (RESPONSE_BODY) + Logging (LOGGING) - Below is a diagram of the standard Apache Request Cycle. In the diagram, the 5 ModSecurity - processing phases are shown. - - - - In order to select the phase a rule executes during, use the phase action either directly - in the rule or in using the SecDefaultAction directive: + + Below is a diagram of the standard Apache Request Cycle. In the + diagram, the 5 ModSecurity processing phases are shown. + + + + In order to select the phase a rule executes during, use the phase + action either directly in the rule or in using the + SecDefaultAction directive: + SecDefaultAction "log,pass,phase:2" SecRule REQUEST_HEADERS:Host "!^$" "deny,phase:1" + - Keep in mind that rules are executed according to phases, so even if two rules are - adjacent in a configuration file, but are set to execute in different phases, they would not - happen one after the other. The order of rules in the configuration file is important only - within the rules of each phase. This is especially important when using the skip and skipAfter actions. + Keep in mind that rules are executed according to phases, so even + if two rules are adjacent in a configuration file, but are set to + execute in different phases, they would not happen one after the other. + The order of rules in the configuration file is important only within + the rules of each phase. This is especially important when using the + skip and skipAfter actions. + - The LOGGING phase is special. It is executed at the end of each - transaction no matter what happened in the previous phases. This means it will be processed - even if the request was intercepted or the allow action was used to pass - the transaction through. + The LOGGING phase is special. It is executed at + the end of each transaction no matter what happened in the previous + phases. This means it will be processed even if the request was + intercepted or the allow action was used to pass the + transaction through. +
Phase Request Headers - Rules in this phase are processed immediately after Apache completes reading the request - headers (post-read-request phase). At this point the request body has not been read yet, - meaning not all request arguments are available. Rules should be placed in this phase if you - need to have them run early (before Apache does something with the request), to do something - before the request body has been read, determine whether or not the request body should be - buffered, or decide how you want the request body to be processed (e.g. whether to parse it - as XML or not). + + Rules in this phase are processed immediately after Apache + completes reading the request headers (post-read-request phase). At this + point the request body has not been read yet, meaning not all request + arguments are available. Rules should be placed in this phase if you + need to have them run early (before Apache does something with the + request), to do something before the request body has been read, + determine whether or not the request body should be buffered, or decide + how you want the request body to be processed (e.g. whether to parse it + as XML or not). + Note - Rules in this phase can not leverage Apache scope directives (Directory, Location, - LocationMatch, etc...) as the post-read-request hook does not have this information yet. The - exception here is the VirtualHost directive. If you want to use ModSecurity rules inside - Apache locations, then they should run in Phase 2. Refer to the Apache Request - Cycle/ModSecurity Processing Phases diagram. + + Rules in this phase can not leverage Apache scope directives + (Directory, Location, LocationMatch, etc...) as the post-read-request + hook does not have this information yet. The exception here is the + VirtualHost directive. If you want to use ModSecurity rules inside + Apache locations, then they should run in Phase 2. Refer to the Apache + Request Cycle/ModSecurity Processing Phases diagram.
+
Phase Request Body - This is the general-purpose input analysis phase. Most of the application-oriented rules - should go here. In this phase you are guaranteed to have received the request arguments - (provided the request body has been read). ModSecurity supports three encoding types for the - request body phase: + + This is the general-purpose input analysis phase. Most of the + application-oriented rules should go here. In this phase you are + guaranteed to have received the request arguments (provided the request + body has been read). ModSecurity supports three encoding types for the + request body phase: + - application/x-www-form-urlencoded - used to transfer form - data + application/x-www-form-urlencoded - used to + transfer form data + - multipart/form-data - used for file transfers + multipart/form-data - used for file + transfers + text/xml - used for passing XML data + Other encodings are not used by most web applications.
+
Phase Response Headers - This phase takes place just before response headers are sent back to the client. Run - here if you want to observe the response before that happens, and if you want to use the - response headers to determine if you want to buffer the response body. Note that some - response status codes (such as 404) are handled earlier in the request cycle by Apache and - my not be able to be triggered as expected. Additionally, there are some response headers - that are added by Apache at a later hook (such as Date, Server and Connection) that we would - not be able to trigger on or sanitize. This should work appropriately in a proxy setup or - within phase:5 (logging). + + This phase takes place just before response headers are sent back + to the client. Run here if you want to observe the response before that + happens, and if you want to use the response headers to determine if you + want to buffer the response body. Note that some response status codes + (such as 404) are handled earlier in the request cycle by Apache and my + not be able to be triggered as expected. Additionally, there are some + response headers that are added by Apache at a later hook (such as Date, + Server and Connection) that we would not be able to trigger on or + sanitize. This should work appropriately in a proxy setup or within + phase:5 (logging).
+
Phase Response Body - This is the general-purpose output analysis phase. At this point you can run rules - against the response body (provided it was buffered, of course). This is the phase where you - would want to inspect the outbound HTML for information disclosure, error messages or failed - authentication text. + + This is the general-purpose output analysis phase. At this point + you can run rules against the response body (provided it was buffered, + of course). This is the phase where you would want to inspect the + outbound HTML for information disclosure, error messages or failed + authentication text.
+
Phase Logging - This phase is run just before logging takes place. The rules placed into this phase can - only affect how the logging is performed. This phase can be used to inspect the error - messages logged by Apache. You cannot deny/block connections in this phase as it is too - late. This phase also allows for inspection of other response headers that weren't available - during phase:3 or phase:4. Note that you must be careful not to inherit a disruptive action - into a rule in this phase as this is a configuration error in ModSecurity 2.5.0 and later - versions. + + This phase is run just before logging takes place. The rules + placed into this phase can only affect how the logging is performed. + This phase can be used to inspect the error messages logged by Apache. + You cannot deny/block connections in this phase as it is too late. This + phase also allows for inspection of other response headers that weren't + available during phase:3 or phase:4. Note that you must be careful not + to inherit a disruptive action into a rule in this phase as this is a + configuration error in ModSecurity 2.5.0 and later versions.
+
Variables + The following variables are supported in ModSecurity 2.x: +
<literal moreinfo="none">ARGS</literal> - ARGS is a collection and can be used on its own (means all arguments - including the POST Payload), with a static parameter (matches arguments with that name), or - with a regular expression (matches all arguments with name that matches the regular - expression). To look at only the query string or body arguments, see the ARGS_GET and ARGS_POST collections. - Some variables are actually collections, which are expanded into more variables at - runtime. The following example will examine all request - arguments:SecRule ARGS dirty - Sometimes, however, you will want to look only at parts of a collection. This can be - achieved with the help of the selection operator(colon). The following - example will only look at the arguments named p (do note - that, in general, requests can contain multiple arguments with the same name): - SecRule ARGS:p dirty It is also - possible to specify exclusions. The following will examine all request arguments for the - word dirty, except the ones named z (again, there can be zero or more arguments named - z): - SecRule ARGS|!ARGS:z dirty There is a - special operator that allows you to count how many variables there are in a collection. The - following rule will trigger if there is more than zero arguments in the request (ignore the - second parameter for the time being): - SecRule &ARGS !^0$ And sometimes - you need to look at an array of parameters, each with a slightly different name. In this - case you can specify a regular expression in the selection operator itself. The following - rule will look into all arguments whose names begin with id_: - SecRule ARGS:/^id_/ dirty + + ARGS is a collection and can be used on its own + (means all arguments including the POST Payload), with a static + parameter (matches arguments with that name), or with a regular + expression (matches all arguments with name that matches the regular + expression). To look at only the query string or body arguments, see the + ARGS_GET and ARGS_POST + collections. + + Some variables are actually collections, which are expanded into + more variables at runtime. The following example will examine all + request arguments:SecRule ARGS dirty + Sometimes, however, you will want to look only at parts of a collection. + This can be achieved with the help of the selection + operator(colon). The following example will only look at the + arguments named p (do note that, in + general, requests can contain multiple arguments with the same name): + SecRule ARGS:p dirty + It is also possible to specify exclusions. The following will examine + all request arguments for the word dirty, except + the ones named z (again, there can be + zero or more arguments named z): + SecRule ARGS|!ARGS:z dirty + There is a special operator that allows you to count how many variables + there are in a collection. The following rule will trigger if there is + more than zero arguments in the request (ignore the second parameter for + the time being): SecRule &ARGS !^0$ + And sometimes you need to look at an array of parameters, each with a + slightly different name. In this case you can specify a regular + expression in the selection operator itself. The following rule will + look into all arguments whose names begin with id_: SecRule ARGS:/^id_/ dirty + - Using ARGS:p will not result in any invocations against the - operator if argument p does not exist. - In ModSecurity 1.X, the ARGS variable stood for QUERY_STRING + POST_PAYLOAD, whereas now it expands to - individual variables. + Using ARGS:p will not result in any + invocations against the operator if argument p does not exist. + + In ModSecurity 1.X, the ARGS variable stood + for QUERY_STRING + POST_PAYLOAD, + whereas now it expands to individual variables.
+
<literal moreinfo="none">ARGS_COMBINED_SIZE</literal> - This variable allows you to set more targeted evaluations on the total size of the - Arguments as compared with normal Apache LimitRequest directives. For example, you could - create a rule to ensure that the total size of the argument data is below a certain - threshold (to help prevent buffer overflow issues). Example: Block request if the size of - the arguments is above 25 characters. + + This variable allows you to set more targeted evaluations on the + total size of the Arguments as compared with normal Apache LimitRequest + directives. For example, you could create a rule to ensure that the + total size of the argument data is below a certain threshold (to help + prevent buffer overflow issues). Example: Block request if the size of + the arguments is above 25 characters. + SecRule REQUEST_FILENAME "^/cgi-bin/login\.php" \ "chain,log,deny,phase:2,t:none,t:lowercase,t:normalisePath" SecRule ARGS_COMBINED_SIZE "@gt 25"
+
<literal moreinfo="none">ARGS_NAMES</literal> - Is a collection of the argument names. You can search for specific argument names that - you want to block. In a positive policy scenario, you can also whitelist (using an inverted - rule with the ! character) only authorized argument names. Example: This example rule will - only allow 2 argument names - p and a. If any other argument names are injected, it will be - blocked. + + Is a collection of the argument names. You can search for specific + argument names that you want to block. In a positive policy scenario, + you can also whitelist (using an inverted rule with the ! character) + only authorized argument names. Example: This example rule will only + allow 2 argument names - p and a. If any other argument names are + injected, it will be blocked. + SecRule REQUEST_FILENAME "/index.php" \ "chain,log,deny,status:403,phase:2,t:none,t:lowercase,t:normalisePath" SecRule ARGS_NAMES "!^(p|a)$" "t:none,t:lowercase"
+
<literal moreinfo="none">ARGS_GET</literal> - ARGS_GET is similar to ARGS, but only contains - arguments from the query string. + + ARGS_GET is similar to ARGS, + but only contains arguments from the query string.
+
<literal moreinfo="none">ARGS_GET_NAMES</literal> - ARGS_GET_NAMES is similar to ARGS_NAMES, but only - contains argument names from the query string. + + ARGS_GET_NAMES is similar to + ARGS_NAMES, but only contains argument names from the + query string.
+
<literal moreinfo="none">ARGS_POST</literal> - ARGS_POST is similar to ARGS, but only contains - arguments from the POST body. + + ARGS_POST is similar to + ARGS, but only contains arguments from the POST + body.
+
<literal moreinfo="none">ARGS_POST_NAMES</literal> - ARGS_POST_NAMES is similar to ARGS_NAMES, but only - contains argument names from the POST body. + + ARGS_POST_NAMES is similar to + ARGS_NAMES, but only contains argument names from the + POST body.
+
<literal moreinfo="none">AUTH_TYPE</literal> - This variable holds the authentication method used to validate a user. Example: + + This variable holds the authentication method used to validate a + user. Example: + SecRule AUTH_TYPE "basic" log,deny,status:403,phase:1,t:lowercase + Note - This data will not be available in a proxy-mode deployment as the authentication is not - local. In a proxy-mode deployment, you would need to inspect the REQUEST_HEADERS:Authorization header. + + This data will not be available in a proxy-mode deployment as the + authentication is not local. In a proxy-mode deployment, you would need + to inspect the REQUEST_HEADERS:Authorization + header.
+
<literal moreinfo="none">ENV</literal> - Collection, requires a single parameter (after colon). The ENV - variable is set with setenv and does not give access to the CGI environment variables. - Example: + + Collection, requires a single parameter (after colon). The + ENV variable is set with setenv and does not give + access to the CGI environment variables. Example: + SecRule REQUEST_FILENAME "printenv" pass,setenv:tag=suspicious SecRule ENV:tag "suspicious"
+
<literal moreinfo="none">FILES</literal> - Collection. Contains a collection of original file names (as they were called on the - remote user's file system). Note: only available if files were extracted from the request - body. Example: + + Collection. Contains a collection of original file names (as they + were called on the remote user's file system). Note: only available if + files were extracted from the request body. Example: + SecRule FILES "\.conf$" log,deny,status:403,phase:2
+
<literal moreinfo="none">FILES_COMBINED_SIZE</literal> - Single value. Total size of the uploaded files. Note: only available if files were - extracted from the request body. Example: + + Single value. Total size of the uploaded files. Note: only + available if files were extracted from the request body. Example: + SecRule FILES_COMBINED_SIZE "@gt 1000" log,deny,status:403,phase:2
+
<literal moreinfo="none">FILES_NAMES</literal> - Collection w/o parameter. Contains a list of form fields that were used for file upload. - Note: only available if files were extracted from the request body. Example: + + Collection w/o parameter. Contains a list of form fields that were + used for file upload. Note: only available if files were extracted from + the request body. Example: + SecRule FILES_NAMES "^upfile$" log,deny,status:403,phase:2
+
<literal moreinfo="none">FILES_SIZES</literal> - Collection. Contains a list of file sizes. Useful for implementing a size limitation on - individual uploaded files. Note: only available if files were extracted from the request - body. Example: + + Collection. Contains a list of file sizes. Useful for implementing + a size limitation on individual uploaded files. Note: only available if + files were extracted from the request body. Example: + SecRule FILES_SIZES "@gt 100" log,deny,status:403,phase:2
+
<literal moreinfo="none">FILES_TMPNAMES</literal> - Collection. Contains a collection of temporary files' names on the disk. Useful when - used together with @inspectFile. Note: only available if - files were extracted from the request body. Example: + + Collection. Contains a collection of temporary files' names on the + disk. Useful when used together with @inspectFile. Note: only available if files + were extracted from the request body. Example: + SecRule FILES_TMPNAMES "@inspectFile /path/to/inspect_script.pl"
+
<literal moreinfo="none">GEO</literal> - GEO is a collection populated by the @geoLookups operator. It can be used to match geographical fields looked up by - an IP address or hostname. + + GEO is a collection populated by the @geoLookups operator. It can be used to match + geographical fields looked up by an IP address or hostname. + Available since 2.2.0. + Fields: + - COUNTRY_CODE: Two character country code. EX: US, UK, - etc. + COUNTRY_CODE: Two character country code. + EX: US, UK, etc. + - COUNTRY_CODE3: Up to three character country code. + COUNTRY_CODE3: Up to three character + country code. + - COUNTRY_NAME: The full country name. + COUNTRY_NAME: The full country + name. + - COUNTRY_CONTINENT: The two character continent that the country - is located. EX: EU + COUNTRY_CONTINENT: The two character + continent that the country is located. EX: EU + - REGION: The two character region. For US, this is state. For - Canada, providence, etc. + REGION: The two character region. For US, + this is state. For Canada, providence, etc. + CITY: The city name. + POSTAL_CODE: The postal code. + LATITUDE: The latitude. + LONGITUDE: The longitude. + - DMA_CODE: The metropolitan area code. (US only) + DMA_CODE: The metropolitan area code. (US + only) + - AREA_CODE: The phone system area code. (US only) + AREA_CODE: The phone system area code. + (US only) + Example: + SecRule REMOTE_ADDR "@geoLookup" "chain,drop,msg:'Non-UK IP address'" SecRule GEO:COUNTRY_CODE "!@streq UK"
+
<literal moreinfo="none">HIGHEST_SEVERITY</literal> - This variable holds the highest severity of any rules that have matched so far. - Severities are numeric values and thus can be used with comparison operators such as - @lt, etc. + + This variable holds the highest severity of any rules that have + matched so far. Severities are numeric values and thus can be used with + comparison operators such as @lt, + etc. + Higher severities have a lower numeric value. + A value of 255 indicates no severity has been set. + SecRule HIGHEST_SEVERITY "@le 2" "phase:2,deny,status:500,msg:'severity %{HIGHEST_SEVERITY}'"
+
<literal moreinfo="none">MATCHED_VAR</literal> - This variable holds the value of the variable that was matched against. It is similar to - the TX:0, except it can be used for all operators and does not require that the capture action be specified. + + This variable holds the value of the variable that was matched + against. It is similar to the TX:0, except it can be used for all + operators and does not require that the capture action be specified. + SecRule ARGS pattern chain,deny ... SecRule MATCHED_VAR "further scrutiny"
+
<literal moreinfo="none">MATCHED_VAR_NAME</literal> - This variable holds the full name of the variable that was matched against. + + This variable holds the full name of the variable that was matched + against. + SecRule ARGS pattern setvar:tx.mymatch=%{MATCHED_VAR_NAME} ... SecRule TX:MYMATCH "@eq ARGS:param" deny
+
<literal moreinfo="none">MODSEC_BUILD</literal> - This variable holds the ModSecurity build number. This variable is intended to be used - to check the build number prior to using a feature that is available only in a certain - build. Example: + + This variable holds the ModSecurity build number. This variable is + intended to be used to check the build number prior to using a feature + that is available only in a certain build. Example: + SecRule MODSEC_BUILD "!@ge 02050102" skipAfter:12345 SecRule ARGS "@pm some key words" id:12345,deny,status:500
+
<literal>MULTIPART_CRLF_LF_LINES</literal> - This flag variable will be set to 1 whenever a multi-part request - uses mixed line terminators. The multipart/form-data RFC requires - CRLF sequence to be used to terminate lines. Since some client - implementations use only LF to terminate lines you might want to allow - them to proceed under certain circumstances (if you want to do this you will need to stop - using MULTIPART_STRICT_ERROR and check each multi-part flag variable - individually, avoiding MULTIPART_LF_LINE). However, mixing CRLF and LF line terminators is dangerous as it can allow - for evasion. Therefore, in such cases, you will have to add a check for MULTIPART_CRLF_LF_LINES. + + This flag variable will be set to 1 whenever a + multi-part request uses mixed line terminators. The + multipart/form-data RFC requires + CRLF sequence to be used to terminate lines. Since + some client implementations use only LF to terminate + lines you might want to allow them to proceed under certain + circumstances (if you want to do this you will need to stop using + MULTIPART_STRICT_ERROR and check each multi-part flag + variable individually, avoiding MULTIPART_LF_LINE). + However, mixing CRLF and LF line + terminators is dangerous as it can allow for evasion. Therefore, in such + cases, you will have to add a check for + MULTIPART_CRLF_LF_LINES.
+
<literal>MULTIPART_STRICT_ERROR</literal> - MULTIPART_STRICT_ERROR will be set to 1 when any - of the following variables is also set to 1: REQBODY_PROCESSOR_ERROR, MULTIPART_BOUNDARY_QUOTED, MULTIPART_BOUNDARY_WHITESPACE, MULTIPART_DATA_BEFORE, - MULTIPART_DATA_AFTER, MULTIPART_HEADER_FOLDING, - MULTIPART_LF_LINE, MULTIPART_SEMICOLON_MISSING. Each - of these variables covers one unusual (although sometimes legal) aspect of the request body - in multipart/form-data format. Your policies should - always contain a rule to check either this variable (easier) or one - or more individual variables (if you know exactly what you want to accomplish). Depending on - the rate of false positives and your default policy you should decide whether to block or - just warn when the rule is triggered. - The best way to use this variable is as in the example below: + + MULTIPART_STRICT_ERROR will be set to + 1 when any of the following variables is also set to + 1: REQBODY_PROCESSOR_ERROR, + MULTIPART_BOUNDARY_QUOTED, + MULTIPART_BOUNDARY_WHITESPACE, + MULTIPART_DATA_BEFORE, + MULTIPART_DATA_AFTER, + MULTIPART_HEADER_FOLDING, + MULTIPART_LF_LINE, + MULTIPART_SEMICOLON_MISSING. Each of these variables + covers one unusual (although sometimes legal) aspect of the request body + in multipart/form-data format. Your policies should + always contain a rule to check either this variable + (easier) or one or more individual variables (if you know exactly what + you want to accomplish). Depending on the rate of false positives and + your default policy you should decide whether to block or just warn when + the rule is triggered. + + The best way to use this variable is as in the example + below: + SecRule MULTIPART_STRICT_ERROR "!@eq 0" \ "phase:2,t:none,log,deny,msg:'Multipart request body \ failed strict validation: \ @@ -1998,354 +3008,566 @@ DA %{MULTIPART_DATA_AFTER}, \ HF %{MULTIPART_HEADER_FOLDING}, \ LF %{MULTIPART_LF_LINE}, \ SM %{MULTIPART_SEMICOLON_MISSING}'" - The multipart/form-data parser was upgraded in ModSecurity v2.1.3 to - actively look for signs of evasion. Many variables (as listed above) were added to expose - various facts discovered during the parsing process. The MULTIPART_STRICT_ERROR variable is handy to check on all abnormalities at once. - The individual variables allow detection to be fine-tuned according to your circumstances in - order to reduce the number of false positives. Detailed analysis of various evasion - techniques covered will be released as a separated document at a later date. + + The multipart/form-data parser was upgraded in + ModSecurity v2.1.3 to actively look for signs of evasion. Many variables + (as listed above) were added to expose various facts discovered during + the parsing process. The MULTIPART_STRICT_ERROR + variable is handy to check on all abnormalities at once. The individual + variables allow detection to be fine-tuned according to your + circumstances in order to reduce the number of false positives. Detailed + analysis of various evasion techniques covered will be released as a + separated document at a later date.
+
<literal>MULTIPART_UNMATCHED_BOUNDARY</literal> - Set to 1 when, during the parsing phase of a multipart/request-body, ModSecurity encounters what feels like a boundary but - it is not. Such an event may occur when evasion of ModSecurity is attempted. - The best way to use this variable is as in the example below: + + Set to 1 when, during the parsing phase of a + multipart/request-body, ModSecurity encounters what + feels like a boundary but it is not. Such an event may occur when + evasion of ModSecurity is attempted. + + The best way to use this variable is as in the example + below: + SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \ "phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'" - Change the rule from blocking to logging-only if many false positives are - encountered. + + Change the rule from blocking to logging-only if many false + positives are encountered.
+
<literal moreinfo="none">PATH_INFO</literal> - Besides passing query information to a script/handler, you can also pass additional - data, known as extra path information, as part of the URL. Example: + + Besides passing query information to a script/handler, you can + also pass additional data, known as extra path information, as part of + the URL. Example: + SecRule PATH_INFO "^/(bin|etc|sbin|opt|usr)"
+
<literal moreinfo="none">QUERY_STRING</literal> - This variable holds form data passed to the script/handler by appending data after a - question mark. Warning: Not URL-decoded. Example: + + This variable holds form data passed to the script/handler by + appending data after a question mark. Warning: Not URL-decoded. + Example: + SecRule QUERY_STRING "attack"
+
<literal moreinfo="none">REMOTE_ADDR</literal> - This variable holds the IP address of the remote client. Example: + + This variable holds the IP address of the remote client. + Example: + SecRule REMOTE_ADDR "^192\.168\.1\.101$"
+
<literal moreinfo="none">REMOTE_HOST</literal> - If HostnameLookUps are set to On, then this variable will hold the DNS resolved remote - host name. If it is set to Off, then it will hold the remote IP address. Possible uses for - this variable would be to deny known bad client hosts or network blocks, or conversely, to - allow in authorized hosts. Example: + + If HostnameLookUps are set to On, then this variable will hold the + DNS resolved remote host name. If it is set to Off, then it will hold + the remote IP address. Possible uses for this variable would be to deny + known bad client hosts or network blocks, or conversely, to allow in + authorized hosts. Example: + SecRule REMOTE_HOST "\.evil\.network\org$"
+
<literal moreinfo="none">REMOTE_PORT</literal> - This variable holds information on the source port that the client used when initiating - the connection to our web server. Example: in this example, we are evaluating to see if the - REMOTE_PORT is less than 1024, which would indicate that the user is a - privileged user (root). + + This variable holds information on the source port that the client + used when initiating the connection to our web server. Example: in this + example, we are evaluating to see if the REMOTE_PORT + is less than 1024, which would indicate that the user is a privileged + user (root). + SecRule REMOTE_PORT "@lt 1024" phase:1,log,pass,setenv:remote_port=privileged
+
<literal moreinfo="none">REMOTE_USER</literal> - This variable holds the username of the authenticated user. If there are no password - (basic|digest) access controls in place, then this variable will be empty. Example: + + This variable holds the username of the authenticated user. If + there are no password (basic|digest) access controls in place, then this + variable will be empty. Example: + SecRule REMOTE_USER "admin" + Note - This data will not be available in a proxy-mode deployment as the authentication is not - local. + + This data will not be available in a proxy-mode deployment as the + authentication is not local.
+
<literal moreinfo="none">REQBODY_PROCESSOR</literal> - Built-in processors are URLENCODED, MULTIPART, and XML. - Example: + + Built-in processors are URLENCODED, + MULTIPART, and XML. + Example: + SecRule REQBODY_PROCESSOR "^XML$ chain SecRule XML "@validateDTD /opt/apache-frontend/conf/xml.dtd"
+
- <literal moreinfo="none">REQBODY_PROCESSOR_ERROR</literal> - Possible values are 0 (no error) or 1 (error). This variable will be set by request body - processors (typically the multipart/request-data parser or the XML - parser) when they fail to properly parse a request payload. + <literal + moreinfo="none">REQBODY_PROCESSOR_ERROR</literal> + + Possible values are 0 (no error) or 1 (error). This variable will + be set by request body processors (typically the + multipart/request-data parser or the XML parser) + when they fail to properly parse a request payload. + Example: + SecRule REQBODY_PROCESSOR_ERROR "@eq 1" deny,phase:2 + - Your policies must have a rule to check REQBODY_PROCESSOR_ERROR - at the beginning of phase 2. Failure to do so will leave the door open for impedance - mismatch attacks. It is possible, for example, that a payload that cannot be parsed by - ModSecurity can be successfully parsed by more tolerant parser operating in the - application. If your policy dictates blocking then you should reject the request if error - is detected. When operating in detection-only mode your rule should alert with high - severity when request body processing fails. + Your policies must have a rule to check + REQBODY_PROCESSOR_ERROR at the beginning of phase 2. Failure to do so + will leave the door open for impedance mismatch attacks. It is + possible, for example, that a payload that cannot be parsed by + ModSecurity can be successfully parsed by more tolerant parser + operating in the application. If your policy dictates blocking then + you should reject the request if error is detected. When operating in + detection-only mode your rule should alert with high severity when + request body processing fails.
+
- <literal moreinfo="none">REQBODY_PROCESSOR_ERROR_MSG</literal> - Empty, or contains the error message from the processor. Example: + <literal + moreinfo="none">REQBODY_PROCESSOR_ERROR_MSG</literal> + + Empty, or contains the error message from the processor. + Example: + SecRule REQBODY_PROCESSOR_ERROR_MSG "failed to parse" t:lowercase
+
<literal moreinfo="none">REQUEST_BASENAME</literal> - This variable holds just the filename part of REQUEST_FILENAME (e.g. - index.php). + + This variable holds just the filename part of + REQUEST_FILENAME (e.g. index.php). + Example: + SecRule REQUEST_BASENAME "^login\.php$" phase:2,t:none,t:lowercase + - Please note that anti-evasion transformations are not applied to this variable by - default. REQUEST_BASENAME will recognise both / and - \ as path separators. + Please note that anti-evasion transformations are not applied to + this variable by default. REQUEST_BASENAME will + recognise both / and \ as path + separators.
+
<literal moreinfo="none">REQUEST_BODY</literal> - This variable holds the data in the request body (including POST_PAYLOAD data). REQUEST_BODY should be used if the - original order of the arguments is important (ARGS should be used in all - other cases). Example: + + This variable holds the data in the request body (including + POST_PAYLOAD data). REQUEST_BODY + should be used if the original order of the arguments is important + (ARGS should be used in all other cases). + Example: + SecRule REQUEST_BODY "^username=\w{25,}\&password=\w{25,}\&Submit\=login$" + - This variable is only available if the URLENCODED request body - processor parsed a request body. This will occur by default when an application/x-www-form-urlencoded is detected, or the URLENCODED request body parser is forced. As of 2.5.7 it is possible to force - the presence of the REQUEST_BODY variable, but only when there is no - request body processor defined, using the ctl:forceRequestBodyVariable - option in the REQUEST_HEADERS phase. + This variable is only available if the + URLENCODED request body processor parsed a request + body. This will occur by default when an + application/x-www-form-urlencoded is detected, or + the URLENCODED request body parser is forced. As of + 2.5.7 it is possible to force the presence of the + REQUEST_BODY variable, but only when there is no + request body processor defined, using the + ctl:forceRequestBodyVariable option in the + REQUEST_HEADERS phase.
+
<literal moreinfo="none">REQUEST_COOKIES</literal> - This variable is a collection of all of the cookie data. Example: the following example - is using the Ampersand special operator to count how many variables are in the collection. - In this rule, it would trigger if the request does not include any Cookie headers. + + This variable is a collection of all of the cookie data. Example: + the following example is using the Ampersand special operator to count + how many variables are in the collection. In this rule, it would trigger + if the request does not include any Cookie headers. + SecRule &REQUEST_COOKIES "@eq 0"
+
<literal moreinfo="none">REQUEST_COOKIES_NAMES</literal> - This variable is a collection of the cookie names in the request headers. Example: the - following rule will trigger if the JSESSIONID cookie is not present. + + This variable is a collection of the cookie names in the request + headers. Example: the following rule will trigger if the JSESSIONID + cookie is not present. + SecRule &REQUEST_COOKIES_NAMES:JSESSIONID "@eq 0"
+
<literal moreinfo="none">REQUEST_FILENAME</literal> - This variable holds the relative REQUEST_URI minus the QUERY_STRING part (e.g. /index.php). Example: + + This variable holds the relative REQUEST_URI + minus the QUERY_STRING part (e.g. /index.php). + Example: + SecRule REQUEST_FILENAME "^/cgi-bin/login\.php$" phase:2,t:none,t:normalisePath + - Please note that anti-evasion transformations are not used on REQUEST_FILENAME by default. + Please note that anti-evasion transformations are not used on + REQUEST_FILENAME by default.
+
<literal moreinfo="none">REQUEST_HEADERS</literal> - This variable can be used as either a collection of all of the request headers or can be - used to specify individual headers (by using - REQUEST_HEADERS:Header-Name). Example: the first example uses - REQUEST_HEADERS as a collection and is applying the validateUrlEncoding operator against all headers. + + This variable can be used as either a collection of all of the + request headers or can be used to specify individual headers (by using + REQUEST_HEADERS:Header-Name). Example: the first + example uses REQUEST_HEADERS as a collection and is + applying the validateUrlEncoding operator against all + headers. + SecRule REQUEST_HEADERS "@validateUrlEncoding" - Example: the second example is targeting only the Host header. + + Example: the second example is targeting only the + Host header. + SecRule REQUEST_HEADERS:Host "^[\d\.]+$" \ "deny,log,status:400,msg:'Host header is a numeric IP address'"
+
<literal moreinfo="none">REQUEST_HEADERS_NAMES</literal> - This variable is a collection of the names of all of the request headers. - Example: + + This variable is a collection of the names of all of the request + headers. Example: + SecRule REQUEST_HEADERS_NAMES "^x-forwarded-for" \ "log,deny,status:403,t:lowercase,msg:'Proxy Server Used'"
+
<literal moreinfo="none">REQUEST_LINE</literal> - This variable holds the complete request line sent to the server (including the - REQUEST_METHOD and HTTP version data). Example: this example rule will trigger if the - request method is something other than GET, HEAD, POST or if the HTTP is something other - than HTTP/0.9, 1.0 or 1.1. + + This variable holds the complete request line sent to the server + (including the REQUEST_METHOD and HTTP version data). Example: this + example rule will trigger if the request method is something other than + GET, HEAD, POST or if the HTTP is something other than HTTP/0.9, 1.0 or + 1.1. + SecRule REQUEST_LINE "!(^((?:(?:pos|ge)t|head))|http/(0\.9|1\.0|1\.1)$)" t:none,t:lowercase
+
<literal moreinfo="none">REQUEST_METHOD</literal> + This variable holds the request method used by the client. - The following example will trigger if the request method is either CONNECT or TRACE. + + The following example will trigger if the request method is either + CONNECT or TRACE. + SecRule REQUEST_METHOD "^((?:connect|trace))$" t:none,t:lowercase
+
<literal moreinfo="none">REQUEST_PROTOCOL</literal> - This variable holds the request protocol version information. Example: + + This variable holds the request protocol version information. + Example: + SecRule REQUEST_PROTOCOL "!^http/(0\.9|1\.0|1\.1)$" t:none,t:lowercase
+
<literal moreinfo="none">REQUEST_URI</literal> - This variable holds the full URL including the QUERY_STRING data - (e.g. /index.php?p=X), however it will never contain a domain name, even if it was provided - on the request line. It also does not include either the REQUEST_METHOD - or the HTTP version info. + + This variable holds the full URL including the + QUERY_STRING data (e.g. /index.php?p=X), however it + will never contain a domain name, even if it was provided on the request + line. It also does not include either the + REQUEST_METHOD or the HTTP version info. + Example: + SecRule REQUEST_URI "attack" phase:1,t:none,t:urlDecode,t:lowercase,t:normalisePath + - Please note that anti-evasion transformations are not used on REQUEST_URI by default. + Please note that anti-evasion transformations are not used on + REQUEST_URI by default.
+
<literal moreinfo="none">REQUEST_URI_RAW</literal> - Same as REQUEST_URI but will contain the domain name if it was - provided on the request line (e.g. http://www.example.com/index.php?p=X). + + Same as REQUEST_URI but will contain the domain + name if it was provided on the request line (e.g. + http://www.example.com/index.php?p=X). + Example: + SecRule REQUEST_URI_RAW "http:/" phase:1,t:none,t:urlDecode,t:lowercase,t:normalisePath + - Please note that anti-evasion transformations are not used on REQUEST_URI_RAW by default. + Please note that anti-evasion transformations are not used on + REQUEST_URI_RAW by default.
+
<literal moreinfo="none">RESPONSE_BODY</literal> + This variable holds the data for the response payload. + Example: + SecRule RESPONSE_BODY "ODBC Error Code"
+
<literal>RESPONSE_CONTENT_LENGTH</literal> - Response body length in bytes. Can be available starting with phase 3 but it does not - have to be (as the length of response body is not always known in advance.) If the size is - not known this variable will contain a zero. If RESPONSE_CONTENT_LENGTH - contains a zero in phase 5 that means the actual size of the response body was 0. - The value of this variable can change between phases if the body is modified. For - example, in embedded mode mod_deflate can compress the response body - between phases 4 and 5. + + Response body length in bytes. Can be available starting with + phase 3 but it does not have to be (as the length of response body is + not always known in advance.) If the size is not known this variable + will contain a zero. If RESPONSE_CONTENT_LENGTH + contains a zero in phase 5 that means the actual size of the response + body was 0. + + The value of this variable can change between phases if the body + is modified. For example, in embedded mode + mod_deflate can compress the response body between + phases 4 and 5.
+
<literal>RESPONSE_CONTENT_TYPE</literal> - Response content type. Only available starting with phase 3. + + Response content type. Only available starting with phase + 3.
+
<literal moreinfo="none">RESPONSE_HEADERS</literal> - This variable is similar to the REQUEST_HEADERS variable and can be used in the same - manner. Example: + + This variable is similar to the REQUEST_HEADERS variable and can + be used in the same manner. Example: + SecRule RESPONSE_HEADERS:X-Cache "MISS" + Note - This variable may not have access to some headers when running in embedded-mode. Headers - such as Server, Date, Connection and Content-Type are added during a later Apache hook just - prior to sending the data to the client. This data should be available, however, either - during ModSecurity phase:5 (logging) or when running in proxy-mode. + + This variable may not have access to some headers when running in + embedded-mode. Headers such as Server, Date, Connection and Content-Type + are added during a later Apache hook just prior to sending the data to + the client. This data should be available, however, either during + ModSecurity phase:5 (logging) or when running in proxy-mode.
+
<literal moreinfo="none">RESPONSE_HEADERS_NAMES</literal> - This variable is a collection of the response header names. Example: + + This variable is a collection of the response header names. + Example: + SecRule RESPONSE_HEADERS_NAMES "Set-Cookie" + Note - Same limitations as RESPONSE_HEADERS with regards to access to some headers in - embedded-mode. + + Same limitations as RESPONSE_HEADERS with regards to access to + some headers in embedded-mode.
+
<literal moreinfo="none">RESPONSE_PROTOCOL</literal> - This variable holds the HTTP response protocol information. Example: + + This variable holds the HTTP response protocol information. + Example: + SecRule RESPONSE_PROTOCOL "^HTTP\/0\.9"
+
<literal moreinfo="none">RESPONSE_STATUS</literal> - This variable holds the HTTP response status code as generated by Apache. - Example: + + This variable holds the HTTP response status code as generated by + Apache. Example: + SecRule RESPONSE_STATUS "^[45]" + Note - This directive may not work as expected in embedded-mode as Apache handles many of the - stock response codes (404, 401, etc...) earlier in Phase 2. This variable should work as - expected in a proxy-mode deployment. + + This directive may not work as expected in embedded-mode as Apache + handles many of the stock response codes (404, 401, etc...) earlier in + Phase 2. This variable should work as expected in a proxy-mode + deployment.
+
<literal moreinfo="none">RULE</literal> - This variable provides access to the id, rev, severity, logdata, and msg fields of - the rule that triggered the action. Only available for expansion in action strings - (e.g.setvar:tx.varname=%{rule.id}). Example: + + This variable provides access to the id, rev, + severity, logdata, and msg fields of the rule that triggered the + action. Only available for expansion in action strings (e.g.setvar:tx.varname=%{rule.id}). Example: + SecRule &REQUEST_HEADERS:Host "@eq 0" "log,deny,setvar:tx.varname=%{rule.id}"
+
<literal moreinfo="none">SCRIPT_BASENAME</literal> - This variable holds just the local filename part of SCRIPT_FILENAME. Example: + + This variable holds just the local filename part of + SCRIPT_FILENAME. Example: + SecRule SCRIPT_BASENAME "^login\.php$" + Note + This variable is not available in proxy mode.
+
<literal moreinfo="none">SCRIPT_FILENAME</literal> - This variable holds the full path on the server to the requested script. (e.g. - SCRIPT_NAME plus the server path). Example: + + This variable holds the full path on the server to the requested + script. (e.g. SCRIPT_NAME plus the server path). Example: + SecRule SCRIPT_FILENAME "^/usr/local/apache/cgi-bin/login\.php$" + Note + This variable is not available in proxy mode.
+
<literal moreinfo="none">SCRIPT_GID</literal> - This variable holds the group id (numerical value) of the group owner of the script. - Example: + + This variable holds the group id (numerical value) of the group + owner of the script. Example: + SecRule SCRIPT_GID "!^46$" + Note + This variable is not available in proxy mode.
+
<literal moreinfo="none">SCRIPT_GROUPNAME</literal> - This variable holds the group name of the group owner of the script. Example: + + This variable holds the group name of the group owner of the + script. Example: + SecRule SCRIPT_GROUPNAME "!^apache$" + Note + This variable is not available in proxy mode.
+
<literal moreinfo="none">SCRIPT_MODE</literal> - This variable holds the script's permissions mode data (numerical - 1=execute, 2=write, - 4=read and 7=read/write/execute). Example: will trigger if the script has the WRITE - permissions set. + + This variable holds the script's permissions mode data (numerical + - 1=execute, 2=write, 4=read and 7=read/write/execute). Example: will + trigger if the script has the WRITE permissions set. + SecRule SCRIPT_MODE "^(2|3|6|7)$" + Note + This variable is not available in proxy mode.
+
<literal moreinfo="none">SCRIPT_UID</literal> - This variable holds the user id (numerical value) of the owner of the script. Example: - the example rule below will trigger if the UID is not 46 (the Apache user). + + This variable holds the user id (numerical value) of the owner of + the script. Example: the example rule below will trigger if the UID is + not 46 (the Apache user). + SecRule SCRIPT_UID "!^46$" + Note + This variable is not available in proxy mode.
+
<literal moreinfo="none">SCRIPT_USERNAME</literal> - This variable holds the username of the owner of the script. Example: + + This variable holds the username of the owner of the script. + Example: + SecRule SCRIPT_USERNAME "!^apache$" + Note + This variable is not available in proxy mode.
+
<literal moreinfo="none">SERVER_ADDR</literal> - This variable contains the IP address of the server. Example: + + This variable contains the IP address of the server. + Example: + SecRule SERVER_ADDR "^192\.168\.1\.100$"
+
<literal moreinfo="none">SERVER_NAME</literal> - This variable contains the server's hostname or IP address. Example: + + This variable contains the server's hostname or IP address. + Example: + SecRule SERVER_NAME "hostname\.com$" + Note - This data is taken from the Host header submitted in the client request. + + This data is taken from the Host header submitted in the client + request.
+
<literal moreinfo="none">SERVER_PORT</literal> - This variable contains the local port that the web server is listening on. - Example: + + This variable contains the local port that the web server is + listening on. Example: + SecRule SERVER_PORT "^80$"
+
<literal moreinfo="none">SESSION</literal> - This variable is a collection, available only after setsid is executed. Example: the following example shows how to initialize a - SESSION collection with setsid, how to use setvar to increase the session.score values, how - to set the session.blocked variable and finally how to deny the connection based on the - session:blocked value. + + This variable is a collection, available only after setsid is executed. Example: the following + example shows how to initialize a SESSION collection with setsid, how to + use setvar to increase the session.score values, how to set the + session.blocked variable and finally how to deny the connection based on + the session:blocked value. + SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass SecAction setsid:%{REQUEST_COOKIES.PHPSESSID} SecRule REQUEST_URI "^/cgi-bin/finger$" \ @@ -2353,115 +3575,174 @@ SecRule REQUEST_URI "^/cgi-bin/finger$" \ SecRule SESSION:SCORE "@gt 50" "pass,log,setvar:session.blocked=1" SecRule SESSION:BLOCKED "@eq 1" "log,deny,status:403"
+
<literal moreinfo="none">SESSIONID</literal> - This variable is the value set with setsid. - Example: + + This variable is the value set with setsid. Example: + SecRule SESSIONID !^$ chain,nolog,pass SecRule REQUEST_COOKIES:PHPSESSID !^$ SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}
+
<literal moreinfo="none">TIME</literal> - This variable holds a formatted string representing the time (hour:minute:second). - Example: + + This variable holds a formatted string representing the time + (hour:minute:second). Example: + SecRule TIME "^(([1](8|9))|([2](0|1|2|3))):\d{2}:\d{2}$"
+
<literal moreinfo="none">TIME_DAY</literal> - This variable holds the current date (1-31). Example: this rule would trigger anytime - between the 10th and 20th days of the month. + + This variable holds the current date (1-31). Example: this rule + would trigger anytime between the 10th and 20th days of the + month. + SecRule TIME_DAY "^(([1](0|1|2|3|4|5|6|7|8|9))|20)$"
+
<literal moreinfo="none">TIME_EPOCH</literal> - This variable holds the time in seconds since 1970. Example: + + This variable holds the time in seconds since 1970. + Example: + SecRule TIME_EPOCH "@gt 1000"
+
<literal moreinfo="none">TIME_HOUR</literal> - This variable holds the current hour (0-23). Example: this rule would trigger during - "off hours". + + This variable holds the current hour (0-23). Example: this rule + would trigger during "off hours". + SecRule TIME_HOUR "^(0|1|2|3|4|5|6|[1](8|9)|[2](0|1|2|3))$"
+
<literal moreinfo="none">TIME_MIN</literal> - This variable holds the current minute (0-59). Example: this rule would trigger during - the last half hour of every hour. + + This variable holds the current minute (0-59). Example: this rule + would trigger during the last half hour of every hour. + SecRule TIME_MIN "^(3|4|5)"
+
<literal moreinfo="none">TIME_MON</literal> - This variable holds the current month (0-11). Example: this rule would match if the - month was either November (10) or December (11). + + This variable holds the current month (0-11). Example: this rule + would match if the month was either November (10) or December + (11). + SecRule TIME_MON "^1"
+
<literal moreinfo="none">TIME_SEC</literal> - This variable holds the current second count (0-59). Example: + + This variable holds the current second count (0-59). + Example: + SecRule TIME_SEC "@gt 30"
+
<literal moreinfo="none">TIME_WDAY</literal> - This variable holds the current weekday (0-6). Example: this rule would trigger only on - week-ends (Saturday and Sunday). + + This variable holds the current weekday (0-6). Example: this rule + would trigger only on week-ends (Saturday and Sunday). + SecRule TIME_WDAY "^(0|6)$"
+
<literal moreinfo="none">TIME_YEAR</literal> - This variable holds the current four-digit year data. Example: + + This variable holds the current four-digit year data. + Example: + SecRule TIME_YEAR "^2006$"
+
<literal moreinfo="none">TX</literal> - Transaction Collection. This is used to store pieces of data, create a transaction - anomaly score, and so on. Transaction variables are set for 1 request/response cycle. The - scoring and evaluation will not last past the current request/response process. Example: In - this example, we are using setvar to increase the tx.score value by 5 points. We then have a - follow-up run that will evaluate the transactional score this request and then it will - decided whether or not to allow/deny the request through. - The following is a list of reserved names in the TX collection: + + Transaction Collection. This is used to store pieces of data, + create a transaction anomaly score, and so on. Transaction variables are + set for 1 request/response cycle. The scoring and evaluation will not + last past the current request/response process. Example: In this + example, we are using setvar to increase the tx.score value by 5 points. + We then have a follow-up run that will evaluate the transactional score + this request and then it will decided whether or not to allow/deny the + request through. + + The following is a list of reserved names in the TX + collection: + - TX:0 - The matching value when using the @rx or @pm operator with - the capture action. + TX:0 - The matching value + when using the @rx or @pm operator with the capture action. + - TX:1-TX:9 - The captured subexpression value when - using the @rx operator with capturing parens and the - capture action. + TX:1-TX:9 - The captured + subexpression value when using the @rx operator with capturing parens and the + capture action. + SecRule WEBSERVER_ERROR_LOG "does not exist" "phase:5,pass,setvar:tx.score=+5" SecRule TX:SCORE "@gt 20" deny,log
+
<literal moreinfo="none">USERID</literal> - This variable is the value set with setuid. - Example: + + This variable is the value set with setuid. Example: + SecAction setuid:%{REMOTE_USER},nolog SecRule USERID "Admin"
+
<literal moreinfo="none">WEBAPPID</literal> - This variable is the value set with SecWebAppId. - Example: + + This variable is the value set with SecWebAppId. Example: + SecWebAppId "WebApp1" SecRule WEBAPPID "WebApp1" "chain,log,deny,status:403" SecRule REQUEST_HEADERS:Transfer-Encoding "!^$"
+
<literal moreinfo="none">WEBSERVER_ERROR_LOG</literal> - Contains zero or more error messages produced by the web server. Access to this variable - is in phase:5 (logging). Example: + + Contains zero or more error messages produced by the web server. + Access to this variable is in phase:5 (logging). Example: + SecRule WEBSERVER_ERROR_LOG "File does not exist" "phase:5,setvar:tx.score=+5"
+
<literal moreinfo="none">XML</literal> - Can be used standalone (as a target for validateDTD and validateSchema) or with an XPath expression parameter (which makes it a valid - target for any function that accepts plain text). Example using XPath: + + Can be used standalone (as a target for + validateDTD and validateSchema) or + with an XPath expression parameter (which makes it a valid target for + any function that accepts plain text). Example using XPath: + SecDefaultAction log,deny,status:403,phase:2 SecRule REQUEST_HEADERS:Content-Type ^text/xml$ \ phase:1,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML @@ -2469,8 +3750,10 @@ SecRule REQBODY_PROCESSOR "!^XML$" skipAfter:12345 SecRule XML:/employees/employee/name/text() Fred SecRule XML:/xq:employees/employee/name/text() Fred \ id:12345,xmlns:xq=http://www.example.com/employees - The first XPath expression does not use namespaces. It would match against payload such - as this one: + + The first XPath expression does not use namespaces. It would match + against payload such as this one: + <employees> <employee> <name>Fred Jones</name> @@ -2491,8 +3774,10 @@ SecRule XML:/xq:employees/employee/name/text() Fred \ <phone location="mobile">(206)555-4321</phone> </employee> </employees> - The second XPath expression does use namespaces. It would match the following - payload: + + The second XPath expression does use namespaces. It would match + the following payload: + <xq:employees xmlns:xq="http://www.example.com/employees"> <employee> <name>Fred Jones</name> @@ -2513,361 +3798,525 @@ SecRule XML:/xq:employees/employee/name/text() Fred \ <phone location="mobile">(206)555-4321</phone> </employee> </xq:employees> + Note the different namespace used in the second example. - To learn more about XPath we suggest the following resources: + + To learn more about XPath we suggest the following + resources: + - XPath Standard + XPath + Standard + - XPath - Tutorial + XPath + Tutorial
+
Transformation functions - When ModSecurity receives request or response information, it makes a copy of this data - and places it into memory. It is on this data in memory that transformation functions are - applied. The raw request/response data is never altered. Transformation functions are used to - transform a variable before testing it in a rule. + + When ModSecurity receives request or response information, it makes + a copy of this data and places it into memory. It is on this data in + memory that transformation functions are applied. The raw request/response + data is never altered. Transformation functions are used to transform a + variable before testing it in a rule. + Note - There are no default transformation functions as there were in previous versions of - ModSecurity. - The following rule will ensure that an attacker does not use mixed case in order to evade - the ModSecurity rule: + + There are no default transformation functions as there were in + previous versions of ModSecurity. + + The following rule will ensure that an attacker does not use mixed + case in order to evade the ModSecurity rule: + SecRule ARG:p "xp_cmdshell" "t:lowercase" - multiple transformation actions can be used in the same rule, for example the following rule - also ensures that an attacker does not use URL encoding (%xx encoding) for evasion. Note the - order of the transformation functions, which ensures that a URL encoded letter is first - decoded and than translated to lower case. - - SecRule ARG:p "xp_cmdshell" "t:urlDecode,t:lowercase" - - One can use the SecDefaultAction command to ensure the translation occurs for every rule - until the next. Note that transformation actions are additive, so if a rule explicitly list - actions, the translation actions set by SecDefaultAction are still performed. - - SecDefaultAction t:urlDecode,t:lowercase - + multiple transformation actions can be used in the same rule, for example + the following rule also ensures that an attacker does not use URL encoding + (%xx encoding) for evasion. Note the order of the transformation + functions, which ensures that a URL encoded letter is first decoded and + than translated to lower case. + + SecRule ARG:p "xp_cmdshell" "t:urlDecode,t:lowercase" + + One can use the SecDefaultAction command to ensure the translation + occurs for every rule until the next. Note that transformation actions are + additive, so if a rule explicitly list actions, the translation actions + set by SecDefaultAction are still performed. + + SecDefaultAction t:urlDecode,t:lowercase + The following transformation functions are supported: +
<literal>base64Decode</literal> + This function decodes a base64-encoded string.
+
<literal>base64Encode</literal> + This function encodes input string using base64 encoding.
+
<literal>compressWhitespace</literal> - It converts whitespace characters (32, \f, \t, \n, \r, \v, 160) to spaces (ASCII 32) and - then compresses multiple consecutive space characters into one. + + It converts whitespace characters (32, \f, \t, \n, \r, \v, 160) to + spaces (ASCII 32) and then compresses multiple consecutive space + characters into one.
+
cssDecode + Decodes CSS-encoded characters, as specified at http://www.w3.org/TR/REC-CSS2/syndata.html. This function uses only up to two - bytes in the decoding process, meaning it is useful to uncover ASCII characters (that - wouldn't normally be encoded) encoded using CSS encoding, or to counter evasion which is a - combination of a backslash and non-hexadecimal characters (e.g. ja\vascript is equivalent to javascript). + url="http://www.w3.org/TR/REC-CSS2/syndata.html">http://www.w3.org/TR/REC-CSS2/syndata.html. + This function uses only up to two bytes in the decoding process, meaning + it is useful to uncover ASCII characters (that wouldn't normally be + encoded) encoded using CSS encoding, or to counter evasion which is a + combination of a backslash and non-hexadecimal characters (e.g. + ja\vascript is equivalent to + javascript).
+
<literal>escapeSeqDecode</literal> - This function decode ANSI C escape sequences: - \a, \b, \f, \n, \r, - \t, \v, \\, \?, \', \", \xHH (hexadecimal), \0OOO - (octal). Invalid encodings are left in the output. + + This function decode ANSI C escape sequences: \a, \b, + \f, \n, \r, + \t, \v, \\, + \?, \', \", + \xHH (hexadecimal), \0OOO (octal). Invalid encodings are left in + the output.
+
<literal>hexDecode</literal> + This function decodes a hex-encoded string.
+
<literal>hexEncode</literal> + This function encodes input as hex-encoded string.
+
<literal>htmlEntityDecode</literal> - This function decodes HTML entities present in input. The following variants are - supported: + + This function decodes HTML entities present in input. The + following variants are supported: + - &#xHH and &#xHH; (where H is any hexadecimal number) + &#xHH and &#xHH; (where H is any hexadecimal + number) + - &#DDD and &#DDD; (where D is any decimal number) + &#DDD and &#DDD; (where D is any decimal + number) + - &quot and &quot; + &quot and &quot; + - &nbsp and &nbsp; + &nbsp and &nbsp; + - &lt and &lt; + &lt and &lt; + - &gt and &gt; + &gt and &gt; - This function will convert any entity into a single byte only, possibly resulting in a - loss of information. It is thus useful to uncover bytes that would otherwise not need to be - encoded, but it cannot do anything with the characters from the range above 255. + + This function will convert any entity into a single byte only, + possibly resulting in a loss of information. It is thus useful to + uncover bytes that would otherwise not need to be encoded, but it cannot + do anything with the characters from the range above 255.
+
<literal>jsDecode</literal> - Decodes JavaScript escape sequences. If a \uHHHH code is in the range - of FF01-FF5E (the full width ASCII codes), then the - higher byte is used to detect and adjust the lower byte. Otherwise, only the lower byte will - be used and the higher byte zeroed. + + Decodes JavaScript escape sequences. If a + \uHHHH code is in the range of + FF01-FF5E (the full width ASCII + codes), then the higher byte is used to detect and adjust the lower + byte. Otherwise, only the lower byte will be used and the higher byte + zeroed.
+
<literal>length</literal> - This function converts the input to its numeric length (count of bytes). + + This function converts the input to its numeric length (count of + bytes).
+
<literal>lowercase</literal> - This function converts all characters to lowercase using the current C locale. + + This function converts all characters to lowercase using the + current C locale.
+
<literal>md5</literal> - This function calculates an MD5 hash from input. Note that the computed hash is in a raw - binary form and may need encoded into text to be usable (for example: t:md5,t:hexEncode). + + This function calculates an MD5 hash from input. Note that the + computed hash is in a raw binary form and may need encoded into text to + be usable (for example: t:md5,t:hexEncode).
+
<literal><literal>none</literal></literal> - Not an actual transformation function, but an instruction to ModSecurity to remove all - transformation functions associated with the current rule. + + Not an actual transformation function, but an instruction to + ModSecurity to remove all transformation functions associated with the + current rule.
+
<literal>normalisePath</literal> - This function will remove multiple slashes, self-references and directory - back-references (except when they are at the beginning of the input). + + This function will remove multiple slashes, self-references and + directory back-references (except when they are at the beginning of the + input).
+
<literal>normalisePathWin</literal> - Same as normalisePath, but will first convert backslash characters to - forward slashes. + + Same as normalisePath, but will first convert + backslash characters to forward slashes.
+
<literal>parityEven7bit</literal> - This function calculates even parity of 7-bit data replacing the 8th bit of each target - byte with the calculated parity bit. + + This function calculates even parity of 7-bit data replacing the + 8th bit of each target byte with the calculated parity bit.
+
<literal>parityOdd7bit</literal> - This function calculates odd parity of 7-bit data replacing the 8th bit of each target - byte with the calculated parity bit. + + This function calculates odd parity of 7-bit data replacing the + 8th bit of each target byte with the calculated parity bit.
+
<literal>parityZero7bit</literal> - This function calculates zero parity of 7-bit data replacing the 8th bit of each target - byte with a zero parity bit which allows inspection of even/odd parity 7bit data as ASCII7 - data. + + This function calculates zero parity of 7-bit data replacing the + 8th bit of each target byte with a zero parity bit which allows + inspection of even/odd parity 7bit data as ASCII7 data.
+
<literal>removeNulls</literal> + This function removes NULL bytes from input.
+
<literal>removeWhitespace</literal> + This function removes all whitespace characters from input.
+
<literal>replaceComments</literal> - This function replaces each occurrence of a C-style comments (/* ... */) with a single space (multiple consecutive occurrences of a space - will not be compressed). Unterminated comments will too be replaced with a space (ASCII 32). - However, a standalone termination of a comment (*/) will - not be acted upon. + + This function replaces each occurrence of a C-style comments + (/* ... */) with a single space + (multiple consecutive occurrences of a space will not be compressed). + Unterminated comments will too be replaced with a space (ASCII 32). + However, a standalone termination of a comment (*/) will not be acted upon.
+
<literal>replaceNulls</literal> - This function is enabled by default. It replaces NULL bytes in input with spaces (ASCII - 32). + + This function is enabled by default. It replaces NULL bytes in + input with spaces (ASCII 32).
+
<literal>urlDecode</literal> - This function decodes an URL-encoded input string. Invalid encodings (i.e. the ones that - use non-hexadecimal characters, or the ones that are at the end of string and have one or - two characters missing) will not be converted. If you want to detect invalid encodings use - the @validateUrlEncoding operator. The transformation - function should not be used against variables that have already been URL-decoded unless it - is your intention to perform URL decoding twice! + + This function decodes an URL-encoded input string. Invalid + encodings (i.e. the ones that use non-hexadecimal characters, or the + ones that are at the end of string and have one or two characters + missing) will not be converted. If you want to detect invalid encodings + use the @validateUrlEncoding + operator. The transformation function should not be used against + variables that have already been URL-decoded unless it is your intention + to perform URL decoding twice!
+
<literal>urlDecodeUni</literal> - In addition to decoding %xx like urlDecode, - urlDecodeUni also decodes %uXXXX encoding. If - the code is in the range of FF01-FF5E (the full width - ASCII codes), then the higher byte is used to detect and adjust the lower byte. Otherwise, - only the lower byte will be used and the higher byte zeroed. + + In addition to decoding %xx like urlDecode, urlDecodeUni also decodes %uXXXX encoding. If the code is in the range + of FF01-FF5E (the full width ASCII + codes), then the higher byte is used to detect and adjust the lower + byte. Otherwise, only the lower byte will be used and the higher byte + zeroed.
+
<literal>urlEncode</literal> + This function encodes input using URL encoding.
+
<literal>sha1</literal> - This function calculates a SHA1 hash from input. Note that the computed hash is in a raw - binary form and may need encoded to be usable (for example: t:sha1,t:hexEncode). + + This function calculates a SHA1 hash from input. Note that the + computed hash is in a raw binary form and may need encoded to be usable + (for example: t:sha1,t:hexEncode).
+
<literal>trimLeft</literal> - This function removes whitespace from the left side of input. + + This function removes whitespace from the left side of + input.
+
<literal>trimRight</literal> - This function removes whitespace from the right side of input. + + This function removes whitespace from the right side of + input.
+
<literal>trim</literal> - This function removes whitespace from both the left and right sides of input. + + This function removes whitespace from both the left and right + sides of input.
+
Actions + Each action belongs to one of five groups: + Disruptive actions + - Cause ModSecurity to do something. In many cases something means block transaction, - but not in all. For example, the allow action is classified as a disruptive action, but - it does the opposite of blocking. There can only be one disruptive action per rule (if - there are multiple disruptive actions present, or inherited, only the last one will take - effect), or rule chain (in a chain, a disruptive action can only appear in the first - rule). + Cause ModSecurity to do something. In many cases something + means block transaction, but not in all. For example, the allow + action is classified as a disruptive action, but it does the + opposite of blocking. There can only be one disruptive action per + rule (if there are multiple disruptive actions present, or + inherited, only the last one will take effect), or rule chain (in a + chain, a disruptive action can only appear in the first + rule). + Non-disruptive actions + - Do something, but that something does not and cannot affect the rule processing - flow. Setting a variable, or changing its value is an example of a non-disruptive - action. Non-disruptive action can appear in any rule, including each rule belonging to a - chain. + Do something, but that something does not and cannot affect + the rule processing flow. Setting a variable, or changing its value + is an example of a non-disruptive action. Non-disruptive action can + appear in any rule, including each rule belonging to a chain. + Flow actions + - These actions affect the rule flow (for example skip or skipAfter). + These actions affect the rule flow (for example + skip or skipAfter). + Meta-data actions + - Meta-data actions are used to provide more information about rules. Examples include - id, rev, severity and - msg. + Meta-data actions are used to provide more information about + rules. Examples include id, + rev, severity and + msg. + Data actions + - Not really actions, these are mere containers that hold data used by other actions. - For example, the status action holds the status that will be used for - blocking (if it takes place). + Not really actions, these are mere containers that hold data + used by other actions. For example, the status + action holds the status that will be used for blocking (if it takes + place). +
<literal>allow</literal> - Description: Stops rule processing on a successful match and allows - the transaction to proceed. + + Description: Stops rule processing on a + successful match and allows the transaction to proceed. + Action Group: Disruptive + Example: + SecRule REMOTE_ADDR "^192\.168\.1\.100$" nolog,phase:1,allow - Prior to ModSecurity 2.5 the allow action would only affect the - current phase. An allow in phase 1 would skip processing the remaining - rules in phase 1 but the rules from phase 2 would execute. Starting with v2.5.0 allow was enhanced to allow for fine-grained control of what is done. The - following rules now apply: + + Prior to ModSecurity 2.5 the allow action would + only affect the current phase. An allow in phase 1 + would skip processing the remaining rules in phase 1 but the rules from + phase 2 would execute. Starting with v2.5.0 allow was + enhanced to allow for fine-grained control of what is done. The + following rules now apply: + - If used one its own, like in the example above, allow will affect - the entire transaction, stopping processing of the current phase but also skipping over - all other phases apart from the logging phase. (The logging phase is special; it is - designed to always execute.) + If used one its own, like in the example above, + allow will affect the entire transaction, + stopping processing of the current phase but also skipping over all + other phases apart from the logging phase. (The logging phase is + special; it is designed to always execute.) + - If used with parameter "phase", allow will cause the engine to - stop processing the current phase. Other phases will continue as normal. + If used with parameter "phase", allow will + cause the engine to stop processing the current phase. Other phases + will continue as normal. + - If used with parameter "request", allow will cause the engine to - stop processing the current phase. The next phase to be processed will be phase RESPONSE_HEADERS. + If used with parameter "request", allow + will cause the engine to stop processing the current phase. The next + phase to be processed will be phase + RESPONSE_HEADERS. + Examples: + # Do not process request but process response. SecAction phase:1,allow:request # Do not process transaction (request and response). SecAction phase:1,allow - If you want to allow a response through, put a rule in phase RESPONSE_HEADERS and simply use allow on its own: + + If you want to allow a response through, put a rule in phase + RESPONSE_HEADERS and simply use + allow on its own: + # Allow response through. SecAction phase:3,allow
+
append - Description: Appends text given as parameter to the end of response - body. For this action to work content injection must be enabled by setting SecContentInjection to On. Also make sure you check the - content type of the response before you make changes to it (e.g. you don't want to inject - stuff into images). + + Description: Appends text given as parameter + to the end of response body. For this action to work content injection + must be enabled by setting SecContentInjection to + On. Also make sure you check the content type of the + response before you make changes to it (e.g. you don't want to inject + stuff into images). + Action Group: Non-disruptive + Processing Phases: 3 and 4. + Example: + SecRule RESPONSE_CONTENT_TYPE "^text/html" "nolog,pass,append:'<hr>Footer'"
+
<literal>auditlog</literal> - Description: Marks the transaction for logging in the audit - log. + + Description: Marks the transaction for + logging in the audit log. + Action Group: Non-disruptive + Example: + SecRule REMOTE_ADDR "^192\.168\.1\.100$" auditlog,phase:1,allow + Note - The auditlog action is now explicit if log is already specified. + + The auditlog action is now explicit if log is already + specified.
+
<literal>block</literal> - Description: Performs the default disruptive action. + + Description: Performs the default disruptive + action. + Action Group: Disruptive - It is intended to be used by ruleset writers to signify that the rule was intended to - block and leaves the "how" up to the administrator. This action is currently a placeholder - which will just be replaced by the action from the last SecDefaultAction - in the same context. Using the block action with the SecRuleUpdateActionById directive allows a rule to be reverted back to the - previous SecDefaultAction disruptive action. - In future versions of ModSecurity, more control and functionality will be added to - define "how" to block. + + It is intended to be used by ruleset writers to signify that the + rule was intended to block and leaves the "how" up to the administrator. + This action is currently a placeholder which will just be replaced by + the action from the last SecDefaultAction in the same + context. Using the block action with the + SecRuleUpdateActionById directive allows a rule to be + reverted back to the previous SecDefaultAction + disruptive action. + + In future versions of ModSecurity, more control and functionality + will be added to define "how" to block. + Examples: - In the following example, the second rule will "deny" because of the SecDefaultAction - disruptive action. The intent being that the administrator could easily change this to - another disruptive action without editing the actual rules. + + In the following example, the second rule will "deny" because of + the SecDefaultAction disruptive action. The intent being that the + administrator could easily change this to another disruptive action + without editing the actual rules. + ### Administrator defines "how" to block (deny,status:403)... SecDefaultAction phase:2,deny,status:403,log,auditlog @@ -2876,11 +4325,14 @@ SecDefaultAction phase:2,deny,status:403,log,auditlog SecRule REQUEST_HEADERS:User-Agent "perl" "phase:2,pass,msg:'Perl based user agent identified'" # Intent is to block for this User Agent, "how" described in SecDefaultAction SecRule REQUEST_HEADERS:User-Agent "nikto" "phase:2,block,msg:'Nikto Scanners Identified'" - In the following example, The rule is reverted back to the pass - action defined in the SecDefaultAction directive by using the SecRuleUpdateActionById directive in conjuction with the block action. This allows an administrator to override an action in a 3rd party - rule without modifying the rule itself. + + In the following example, The rule is reverted back to the + pass action defined in the SecDefaultAction directive + by using the SecRuleUpdateActionById directive in + conjuction with the block action. This allows an + administrator to override an action in a 3rd party rule without + modifying the rule itself. + ### Administrator defines "how" to block (deny,status:403)... SecDefaultAction phase:2,pass,log,auditlog @@ -2890,158 +4342,238 @@ SecRule REQUEST_HEADERS:User-Agent "nikto" "id:1,phase:2,denyblock"
+
<literal>capture</literal> - Description: When used together with the regular expression - operator, capture action will create copies of regular expression captures and place them - into the transaction variable collection. Up to ten captures will be copied on a successful - pattern match, each with a name consisting of a digit from 0 to 9. + + Description: When used together with the + regular expression operator, capture action will create copies of + regular expression captures and place them into the transaction variable + collection. Up to ten captures will be copied on a successful pattern + match, each with a name consisting of a digit from 0 to 9. + Action Group: Non-disruptive + Example: + SecRule REQUEST_BODY "^username=(\w{25,})" phase:2,capture,t:none,chain SecRule TX:1 "(?:(?:a(dmin|nonymous)))" + Note - The 0 data captures the entire REGEX match and 1 captures the data in the first parens, - etc... + + The 0 data captures the entire REGEX match and 1 captures the data + in the first parens, etc...
+
<literal>chain</literal> - Description: Chains the rule where the action is placed with the - rule that immediately follows it. The result is called a rule chain. - Chained rules allow for more complex rule matches where you want to use a number of - different VARIABLES to create a better rule and to help prevent false positives. + + Description: Chains the rule where the action + is placed with the rule that immediately follows it. The result is + called a rule chain. Chained rules allow for more + complex rule matches where you want to use a number of different + VARIABLES to create a better rule and to help prevent false + positives. + Action Group: Flow + Example: + # Refuse to accept POST requests that do # not specify request body length. Do note that # this rule should be preceeded by a rule that verifies # only valid request methods (e.g. GET, HEAD and POST) are used. SecRule REQUEST_METHOD ^POST$ chain,t:none SecRule REQUEST_HEADER:Content-Length ^$ t:none + - In programming language concepts, think of chained rules somewhat similar to AND - conditional statements. The actions specified in the first portion of the chained rule - will only be triggered if all of the variable checks return positive hits. If one aspect - of the chained rule is negative, then the entire rule chain is negative. Also note that - disruptive actions, execution phases, metadata actions (id, rev, msg), skip and skipAfter - actions can only be specified on by the chain starter rule. + In programming language concepts, think of chained rules + somewhat similar to AND conditional statements. The actions specified + in the first portion of the chained rule will only be triggered if all + of the variable checks return positive hits. If one aspect of the + chained rule is negative, then the entire rule chain is negative. Also + note that disruptive actions, execution phases, metadata actions (id, + rev, msg), skip and skipAfter actions can only be specified on by the + chain starter rule.
+
<literal>ctl</literal> - Description: The ctl action allows configuration options to be - updated for the transaction. + + Description: The ctl action allows + configuration options to be updated for the transaction. + Action Group: Non-disruptive + Example: + # Parse requests with Content-Type "text/xml" as XML SecRule REQUEST_CONTENT_TYPE ^text/xml nolog,pass,ctl:requestBodyProcessor=XML + Note + The following configuration options are supported: + auditEngine + auditLogParts + debugLogLevel + - ruleRemoveById (single rule ID, or a single rule - ID range accepted as parameter) + ruleRemoveById (single rule + ID, or a single rule ID range accepted as parameter) + requestBodyAccess + - forceRequestBodyVariable + forceRequestBodyVariable + requestBodyLimit + requestBodyProcessor + responseBodyAccess + responseBodyLimit + ruleEngine - With the exception of requestBodyProcessor and - forceRequestBodyVariable, each configuration option - corresponds to one configuration directive and the usage is identical. - The requestBodyProcessor option allows you to configure the request - body processor. By default ModSecurity will use the URLENCODED and MULTIPART processors to - process an application/x-www-form-urlencoded and a - multipart/form-data bodies, respectively. A third - processor, XML, is also supported, but it is never used implicitly. - Instead you must tell ModSecurity to use it by placing a few rules in the REQUEST_HEADERS processing phase. After the request body was - processed as XML you will be able to use the XML-related features to inspect it. - Request body processors will not interrupt a transaction if an error occurs during - parsing. Instead they will set variables - REQBODY_PROCESSOR_ERROR and - REQBODY_PROCESSOR_ERROR_MSG. These variables should be inspected in the REQUEST_BODY phase and an appropriate action taken. - The forceRequestBodyVariable option allows you to configure the - REQUEST_BODY variable to be set when there is no request body processor - configured. This allows for inspection of request bodies of unknown types. + + With the exception of + requestBodyProcessor and + forceRequestBodyVariable, each configuration option + corresponds to one configuration directive and the usage is + identical. + + The requestBodyProcessor option allows you to + configure the request body processor. By default ModSecurity will use + the URLENCODED and MULTIPART processors to process an application/x-www-form-urlencoded and a + multipart/form-data bodies, + respectively. A third processor, XML, is also + supported, but it is never used implicitly. Instead you must tell + ModSecurity to use it by placing a few rules in the REQUEST_HEADERS processing phase. After the + request body was processed as XML you will be able to use the + XML-related features to inspect it. + + Request body processors will not interrupt a transaction if an + error occurs during parsing. Instead they will set variables REQBODY_PROCESSOR_ERROR and REQBODY_PROCESSOR_ERROR_MSG. These variables + should be inspected in the REQUEST_BODY phase and an appropriate action + taken. + + The forceRequestBodyVariable option allows you + to configure the REQUEST_BODY variable to be set when + there is no request body processor configured. This allows for + inspection of request bodies of unknown types.
+
<literal>deny</literal> - Description: Stops rule processing and intercepts - transaction. + + Description: Stops rule processing and + intercepts transaction. + Action Group: Disruptive + Example: + SecRule REQUEST_HEADERS:User-Agent "nikto" "log,deny,msg:'Nikto Scanners Identified'"
+
<literal>deprecatevar</literal> - Description: Decrement counter based on its age. + + Description: Decrement counter based on its + age. + Action Group: Non-Disruptive - Example: The following example will decrement the counter by 60 every 300 - seconds. + + Example: The following example will decrement the counter by 60 + every 300 seconds. + SecAction deprecatevar:session.score=60/300 + Note - Counter values are always positive, meaning the value will never go below zero. + + Counter values are always positive, meaning the value will never + go below zero.
+
<literal>drop</literal> - Description: Immediately initiate a "connection close" action to - tear down the TCP connection by sending a FIN packet. + + Description: Immediately initiate a + "connection close" action to tear down the TCP connection by sending a + FIN packet. + Action Group: Disruptive - Example: The following example initiates an IP collection for tracking Basic - Authentication attempts. If the client goes over the threshold of more than 25 attempts in 2 - minutes, it will DROP subsequent connections. + + Example: The following example initiates an IP collection for + tracking Basic Authentication attempts. If the client goes over the + threshold of more than 25 attempts in 2 minutes, it will DROP subsequent + connections. + SecAction initcol:ip=%{REMOTE_ADDR},nolog SecRule ARGS:login "!^$" \ nolog,phase:1,setvar:ip.auth_attempt=+1,deprecatevar:ip.auth_attempt=20/120 SecRule IP:AUTH_ATTEMPT "@gt 25" \ log,drop,phase:1,msg:'Possible Brute Force Attack" + Note - This action is currently not available on Windows based builds. This action is extremely - useful when responding to both Brute Force and Denial of Service attacks in that, in both - cases, you want to minimize both the network bandwidth and the data returned to the client. - This action causes error message to appear in the log "(9)Bad file descriptor: - core_output_filter: writing data to the network" + + This action is currently not available on Windows based builds. + This action is extremely useful when responding to both Brute Force and + Denial of Service attacks in that, in both cases, you want to minimize + both the network bandwidth and the data returned to the client. This + action causes error message to appear in the log "(9)Bad file + descriptor: core_output_filter: writing data to the network"
+
<literal>exec</literal> - Description: Executes an external script/binary supplied as - parameter. As of v2.5.0, if the parameter supplied to exec is a Lua - script (detected by the .lua extension) the script will be processed - internally. This means you will get direct access to the internal - request context from the script. Please read the SecRuleScript - documentation for more details on how to write Lua scripts. + + Description: Executes an external + script/binary supplied as parameter. As of v2.5.0, if the parameter + supplied to exec is a Lua script (detected by the + .lua extension) the script will be processed + internally. This means you will get direct access + to the internal request context from the script. Please read the + SecRuleScript documentation for more details on how + to write Lua scripts. + Action Group: Non-disruptive + Example: + # The following is going to execute /usr/local/apache/bin/test.sh # as a shell script on rule match. SecRule REQUEST_URI "^/cgi-bin/script\.pl" \ @@ -3050,574 +4582,908 @@ SecRule REQUEST_URI "^/cgi-bin/script\.pl" \ # The following is going to process /usr/local/apache/conf/exec.lua # internally as a Lua script on rule match. SecRule ARGS:p attack log,exec:/usr/local/apache/conf/exec.lua + - The exec action is executed independently from any disruptive actions. External - scripts will always be called with no parameters. Some transaction information will be - placed in environment variables. All the usual CGI environment variables will be there. - You should be aware that forking a threaded process results in all threads being - replicated in the new process. Forking can therefore incur larger overhead in - multi-threaded operation. The script you execute must write something (anything) to - stdout. If it doesn't ModSecurity will assume execution didn't work. + The exec action is executed independently from any disruptive + actions. External scripts will always be called with no parameters. + Some transaction information will be placed in environment variables. + All the usual CGI environment variables will be there. You should be + aware that forking a threaded process results in all threads being + replicated in the new process. Forking can therefore incur larger + overhead in multi-threaded operation. The script you execute must + write something (anything) to stdout. If it doesn't ModSecurity will + assume execution didn't work.
+
<literal>expirevar</literal> - Description: Configures a collection variable to expire after the - given time in seconds. + + Description: Configures a collection variable + to expire after the given time in seconds. + Action Group: Non-disruptive + Example: + SecRule REQUEST_COOKIES:JSESSIONID "!^$" nolog,phase:1,pass,chain SecAction setsid:%{REQUEST_COOKIES:JSESSIONID} SecRule REQUEST_URI "^/cgi-bin/script\.pl" \ "phase:2,t:none,t:lowercase,t:normalisePath,log,allow,\ setvar:session.suspicious=1,expirevar:session.suspicious=3600,phase:1" + Note - You should use expirevar actions at the same time that you use setvar actions in order - to keep the indented expiration time. If they are used on their own (perhaps in a SecAction - directive) the expire time could get re-set. When variables are removed from collections, - and there are no other changes, collections are not written to disk at the end of request. - This is because the variables can always be expired again when the collection is read again - on a subsequent request. + + You should use expirevar actions at the same time that you use + setvar actions in order to keep the indented expiration time. If they + are used on their own (perhaps in a SecAction directive) the expire time + could get re-set. When variables are removed from collections, and there + are no other changes, collections are not written to disk at the end of + request. This is because the variables can always be expired again when + the collection is read again on a subsequent request.
+
<literal>id</literal> - Description: Assigns a unique ID to the rule or chain. + + Description: Assigns a unique ID to the rule + or chain. + Action Group: Meta-data + Example: + SecRule &REQUEST_HEADERS:Host "@eq 0" \ "log,id:60008,severity:2,msg:'Request Missing a Host Header'" + Note + These are the reserved ranges: + - 1-99,999; reserved for local (internal) use. Use as you see fit but do not use this - range for rules that are distributed to others. + 1-99,999; reserved for local (internal) use. Use as you see + fit but do not use this range for rules that are distributed to + others. + - 100,000-199,999; reserved for internal use of the engine, to assign to rules that do - not have explicit IDs. + 100,000-199,999; reserved for internal use of the engine, to + assign to rules that do not have explicit IDs. + - 200,000-299,999; reserved for rules published at modsecurity.org. + 200,000-299,999; reserved for rules published at + modsecurity.org. + - 300,000-399,999; reserved for rules published at gotroot.com. + 300,000-399,999; reserved for rules published at + gotroot.com. + 400,000-419,999; unused (available for reservation). + 420,000-429,999; reserved for ScallyWhack. + url="http://projects.otaku42.de/wiki/ScallyWhack">ScallyWhack. + 430,000-899,999; unused (available for reservation). + 900,000-999,999; reserved for the Core Rules project. + url="http://www.modsecurity.org/projects/rules/">Core Rules + project. + - 1,000,000 and above; unused (available for reservation). + 1,000,000 and above; unused (available for + reservation).
+
<literal>initcol</literal> - Description: Initialises a named persistent collection, either by - loading data from storage or by creating a new collection in memory. + + Description: Initialises a named persistent + collection, either by loading data from storage or by creating a new + collection in memory. + Action Group: Non-disruptive - Example: The following example initiates IP address tracking. + + Example: The following example initiates IP address + tracking. + SecAction initcol:ip=%{REMOTE_ADDR},nolog + Note - Collections are loaded into memory when the initcol action is encountered. The - collection in storage will be persisted (and the appropriate counters increased) - only if it was changed during transaction processing. + + Collections are loaded into memory when the initcol action is + encountered. The collection in storage will be persisted (and the + appropriate counters increased) only if it was + changed during transaction processing. + See the "Persistant Storage" section for further details.
+
<literal>log</literal> - Description: Indicates that a successful match of the rule needs to - be logged. + + Description: Indicates that a successful + match of the rule needs to be logged. + Action Group: Non-disruptive + Example: + SecAction initcol:ip=%{REMOTE_ADDR},log + Note - This action will log matches to the Apache error log file and the ModSecurity audit - log. + + This action will log matches to the Apache error log file and the + ModSecurity audit log.
+
<literal>logdata</literal> - Description: Allows a data fragment to be logged as part of the - alert message. + + Description: Allows a data fragment to be + logged as part of the alert message. + Action Group: Non-disruptive + Example: + SecRule &ARGS:p "@eq 0" "log,logdata:'%{TX.0}'" + Note - The logdata information appears in the error and/or audit log files and is not sent back - to the client in response headers. Macro expansion is preformed so you may use variable - names such as %{TX.0}, etc. The information is properly escaped for use with logging binary - data. + + The logdata information appears in the error and/or audit log + files and is not sent back to the client in response headers. Macro + expansion is preformed so you may use variable names such as %{TX.0}, + etc. The information is properly escaped for use with logging binary + data.
+
<literal>msg</literal> - Description: Assigns a custom message to the rule or chain. + + Description: Assigns a custom message to the + rule or chain. + Action Group: Meta-data + Example: + SecRule &REQUEST_HEADERS:Host "@eq 0" \ "log,id:60008,severity:2,msg:'Request Missing a Host Header'" + Note - The msg information appears in the error and/or audit log files and is not sent back to - the client in response headers. + + The msg information appears in the error and/or audit log files + and is not sent back to the client in response headers.
+
<literal>multiMatch</literal> - Description: If enabled ModSecurity will perform multiple operator - invocations for every target, before and after every anti-evasion transformation is - performed. + + Description: If enabled ModSecurity will + perform multiple operator invocations for every target, before and after + every anti-evasion transformation is performed. + Action Group: Non-disruptive + Example: + SecDefaultAction log,deny,phase:1,t:removeNulls,t:lowercase SecRule ARGS "attack" multiMatch + Note - Normally, variables are evaluated once, only after all transformation functions have - completed. With multiMatch, variables are checked against the operator before and after - every transformation function that changes the input. + + Normally, variables are evaluated once, only after all + transformation functions have completed. With multiMatch, variables are + checked against the operator before and after every transformation + function that changes the input.
+
<literal>noauditlog</literal> - Description: Indicates that a successful match of the rule should - not be used as criteria whether the transaction should be logged to the audit log. + + Description: Indicates that a successful + match of the rule should not be used as criteria whether the transaction + should be logged to the audit log. + Action Group: Non-disruptive + Example: + SecRule REQUEST_HEADERS:User-Agent "Test" allow,noauditlog + Note - If the SecAuditEngine is set to On, all of the transactions will be logged. If it is set - to RelevantOnly, then you can control it with the noauditlog action. Even if the noauditlog - action is applied to a specific rule and a rule either before or after triggered an audit - event, then the transaction will be logged to the audit log. The correct way to disable - audit logging for the entire transaction is to use "ctl:auditEngine=Off" + + If the SecAuditEngine is set to On, all of the transactions will + be logged. If it is set to RelevantOnly, then you can control it with + the noauditlog action. Even if the noauditlog action is applied to a + specific rule and a rule either before or after triggered an audit + event, then the transaction will be logged to the audit log. The correct + way to disable audit logging for the entire transaction is to use + "ctl:auditEngine=Off"
+
<literal>nolog</literal> - Description: Prevents rule matches from appearing in both the error - and audit logs. + + Description: Prevents rule matches from + appearing in both the error and audit logs. + Action Group: Non-disruptive + Example: + SecRule REQUEST_HEADERS:User-Agent "Test" allow,nolog + Note + The nolog action also implies noauditlog.
+
<literal>pass</literal> - Description: Continues processing with the next rule in spite of a - successful match. + + Description: Continues processing with the + next rule in spite of a successful match. + Action Group: Disruptive + Example1: + SecRule REQUEST_HEADERS:User-Agent "Test" log,pass - When using pass with SecRule with multiple targets, - all targets will be processed and all - non-disruptive actions will trigger for every match found. In the - second example the TX:test target would be incremented by 1 for each matching - argument. + + When using pass with SecRule with multiple + targets, all targets will be processed and + all non-disruptive actions will trigger for + every match found. In the second example the + TX:test target would be incremented by 1 for each matching + argument. + Example2: + SecRule ARGS "test" log,pass,setvar:TX.test=+1 + Note - The transaction will not be interrupted but a log will be generated for each matching - target (unless logging has been suppressed). + + The transaction will not be interrupted but a log will be + generated for each matching target (unless logging has been + suppressed).
+
<literal>pause</literal> - Description: Pauses transaction processing for the specified number - of milliseconds. + + Description: Pauses transaction processing + for the specified number of milliseconds. + Action Group: Non-disruptive + Example: + SecRule REQUEST_HEADERS:User-Agent "Test" log,deny,status:403,pause:5000 + Note - This feature can be of limited benefit for slowing down Brute Force Scanners, however - use with care. If you are under a Denial of Service type of attack, the pause feature may - make matters worse as this feature will cause child processes to sit idle until the pause is - completed. + + This feature can be of limited benefit for slowing down Brute + Force Scanners, however use with care. If you are under a Denial of + Service type of attack, the pause feature may make matters worse as this + feature will cause child processes to sit idle until the pause is + completed.
+
<literal>phase</literal> - Description: Places the rule (or the rule chain) into one of five - available processing phases. + + Description: Places the rule (or the rule + chain) into one of five available processing phases. + Action Group: Meta-data + Example: + SecDefaultAction log,deny,phase:1,t:removeNulls,t:lowercase SecRule REQUEST_HEADERS:User-Agent "Test" log,deny,status:403 + Note - Keep in mind that is you specify the incorrect phase, the target variable that you - specify may be empty. This could lead to a false negative situation where your variable and - operator (RegEx) may be correct, but it misses malicious data because you specified the - wrong phase. + + Keep in mind that is you specify the incorrect phase, the target + variable that you specify may be empty. This could lead to a false + negative situation where your variable and operator (RegEx) may be + correct, but it misses malicious data because you specified the wrong + phase.
+
prepend - Description: Prepends text given as parameter to the response body. - For this action to work content injection must be enabled by setting SecContentInjection to On. Also make sure you check the - content type of the response before you make changes to it (e.g. you don't want to inject - stuff into images). + + Description: Prepends text given as parameter + to the response body. For this action to work content injection must be + enabled by setting SecContentInjection to + On. Also make sure you check the content type of the + response before you make changes to it (e.g. you don't want to inject + stuff into images). + Action Group: Non-disruptive + Processing Phases: 3 and 4. + Example: + SecRule RESPONSE_CONTENT_TYPE ^text/html "phase:3,nolog,pass,prepend:'Header<br>'"
+
<literal>proxy</literal> - Description: Intercepts transaction by forwarding request to - another web server using the proxy backend. + + Description: Intercepts transaction by + forwarding request to another web server using the proxy backend. + Action Group: Disruptive + Example: + SecRule REQUEST_HEADERS:User-Agent "Test" log,proxy:http://www.honeypothost.com/ + Note - For this action to work, mod_proxy must also be installed. This action is useful if you - would like to proxy matching requests onto a honeypot webserver. + + For this action to work, mod_proxy must also be installed. This + action is useful if you would like to proxy matching requests onto a + honeypot webserver.
+
<literal>redirect</literal> - Description: Intercepts transaction by issuing a redirect to the - given location. + + Description: Intercepts transaction by + issuing a redirect to the given location. + Action Group: Disruptive + Example: + SecRule REQUEST_HEADERS:User-Agent "Test" \ log,redirect:http://www.hostname.com/failed.html + Note - If the status action is present and its value is - acceptable (301, 302, 303, or 307) it will be used for the redirection. Otherwise status - code 302 will be used. + + If the status action is present + and its value is acceptable (301, 302, 303, or 307) it will be used for + the redirection. Otherwise status code 302 will be used.
+
<literal>rev</literal> + Description: Specifies rule revision. + Action Group: Meta-data + Example: + SecRule REQUEST_METHOD "^PUT$" "id:340002,rev:1,severity:2,msg:'Restricted HTTP function'" + Note - This action is used in combination with the id action - to allow the same rule ID to be used after changes take place but to still provide some - indication the rule changed. + + This action is used in combination with the id action to allow the same rule ID to be used + after changes take place but to still provide some indication the rule + changed.
+
<literal>sanitiseArg</literal> - Description: Sanitises (replaces each byte with an asterisk) a - named request argument prior to audit logging. + + Description: Sanitises (replaces each byte + with an asterisk) a named request argument prior to audit + logging. + Action Group: Non-disruptive + Example: + SecAction nolog,phase:2,sanitiseArg:password + Note - The sanitize actions do not sanitize any data within the actual raw requests but only on - the copy of data within memory that is set to log to the audit log. It will not sanitize the - data in the modsec_debug.log file (if the log level is set high enough to capture this - data). + + The sanitize actions do not sanitize any data within the actual + raw requests but only on the copy of data within memory that is set to + log to the audit log. It will not sanitize the data in the + modsec_debug.log file (if the log level is set high enough to capture + this data).
+
<literal>sanitiseMatched</literal> - Description: Sanitises the variable (request argument, request - header, or response header) that caused a rule match. + + Description: Sanitises the variable (request + argument, request header, or response header) that caused a rule + match. + Action Group: Non-disruptive - Example: This action can be used to sanitise arbitrary transaction elements when they - match a condition. For example, the example below will sanitise any argument that contains - the word password in the name. + + Example: This action can be used to sanitise arbitrary transaction + elements when they match a condition. For example, the example below + will sanitise any argument that contains the word + password in the name. + SecRule ARGS_NAMES password nolog,pass,sanitiseMatched + Note + Same note as sanitiseArg.
+
<literal>sanitiseRequestHeader</literal> - Description: Sanitises a named request header. + + Description: Sanitises a named request + header. + Action Group: Non-disruptive - Example: This will sanitise the data in the Authorization header. + + Example: This will sanitise the data in the Authorization + header. + SecAction log,phase:1,sanitiseRequestHeader:Authorization + Note + Same note as sanitiseArg.
+
<literal>sanitiseResponseHeader</literal> - Description: Sanitises a named response header. + + Description: Sanitises a named response + header. + Action Group: Non-disruptive - Example: This will sanitise the Set-Cookie data sent to the client. + + Example: This will sanitise the Set-Cookie data sent to the + client. + SecAction log,phase:3,sanitiseResponseHeader:Set-Cookie + Note + Same note as sanitiseArg.
+
<literal>severity</literal> - Description: Assigns severity to the rule it is placed with. + + Description: Assigns severity to the rule it + is placed with. + Action Group: Meta-data + Example: + SecRule REQUEST_METHOD "^PUT$" "id:340002,rev:1,severity:CRITICAL,msg:'Restricted HTTP function'" + Note - Severity values in ModSecurity follow those of syslog, as below: + + Severity values in ModSecurity follow those of syslog, as + below: + 0 - EMERGENCY + 1 - ALERT + 2 - CRITICAL + 3 - ERROR + 4 - WARNING + 5 - NOTICE + 6 - INFO + 7 - DEBUG - It is possible to specify severity levels using either the numerical values or the text - values. You should always specify severity levels using the text values. The use of the - numerical values is deprecated (as of v2.5.0) and may be removed in one of the susequent - major updates. + + It is possible to specify severity levels using either the + numerical values or the text values. You should always specify severity + levels using the text values. The use of the numerical values is + deprecated (as of v2.5.0) and may be removed in one of the susequent + major updates.
+
<literal>setuid</literal> - Description: Special-purpose action that initialises the USER collection. + + Description: Special-purpose action that + initialises the USER + collection. + Action Group: Non-disruptive + Example: + SecAction setuid:%{REMOTE_USER},nolog + Note - After initialisation takes place the variable USERID - will be available for use in the subsequent rules. + + After initialisation takes place the variable USERID will be available for use in the + subsequent rules.
+
<literal>setsid</literal> - Description: Special-purpose action that initialises the SESSION collection. + + Description: Special-purpose action that + initialises the SESSION + collection. + Action Group: Non-disruptive + Example: + # Initialise session variables using the session cookie value SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass SecAction setsid:%{REQUEST_COOKIES.PHPSESSID} + Note - On first invocation of this action the collection will be empty (not taking the - predefined variables into account - see initcol for more - information). On subsequent invocations the contents of the collection (session, in this - case) will be retrieved from storage. After initialisation takes place the variable SESSIONID will be available for use in the subsequent - rules.This action understands each application maintains its own set of sessions. It will - utilise the current web application ID to create a session namespace. + + On first invocation of this action the collection will be empty + (not taking the predefined variables into account - see initcol for more information). On subsequent + invocations the contents of the collection (session, in this case) will + be retrieved from storage. After initialisation takes place the + variable SESSIONID will be available + for use in the subsequent rules.This action understands each application + maintains its own set of sessions. It will utilise the current web + application ID to create a session namespace.
+
<literal>setenv</literal> - Description: Creates, removes, or updates an environment - variable. + + Description: Creates, removes, or updates an + environment variable. + Action Group: Non-disruptive + Examples: - To create a new variable (if you omit the value 1 - will be used): + + To create a new variable (if you omit the value 1 will be used): + setenv:name=value + To remove a variable: + setenv:!name + Note - This action can be used to establish communication with other Apache modules. + + This action can be used to establish communication with other + Apache modules.
+
<literal>setvar</literal> - Description: Creates, removes, or updates a variable in the - specified collection. + + Description: Creates, removes, or updates a + variable in the specified collection. + Action Group: Non-disruptive + Examples: + To create a new variable: + setvar:tx.score=10 + To remove a variable prefix the name with exclamation mark: + setvar:!tx.score - To increase or decrease variable value use + and - - characters in front of a numerical value: + + To increase or decrease variable value use + and - + characters in front of a numerical value: + setvar:tx.score=+5
+
<literal>skip</literal> - Description: Skips one or more rules (or chains) on successful - match. + + Description: Skips one or more rules (or + chains) on successful match. + Action Group: Flow + Example: - - SecRule REQUEST_URI "^/$" \ + + SecRule REQUEST_URI "^/$" \ "phase:2,chain,t:none,skip:2" SecRule REMOTE_ADDR "^127\.0\.0\.1$" "chain" SecRule REQUEST_HEADERS:User-Agent "^Apache \(internal dummy connection\)$" "t:none" SecRule &REQUEST_HEADERS:Host "@eq 0" \ "deny,log,status:400,id:960008,severity:4,msg:'Request Missing a Host Header'" SecRule &REQUEST_HEADERS:Accept "@eq 0" \ - "log,deny,log,status:400,id:960015,msg:'Request Missing an Accept Header'" - + "log,deny,log,status:400,id:960015,msg:'Request Missing an Accept Header'" + Note - Skip only applies to the current processing phase and not necessarily the order in which - the rules appear in the configuration file. If you group rules by processing phases, then - skip should work as expected. This action can not be used to skip rules within one chain. - Accepts a single parameter denoting the number of rules (or chains) to skip. + + Skip only applies to the current processing phase and not + necessarily the order in which the rules appear in the configuration + file. If you group rules by processing phases, then skip should work as + expected. This action can not be used to skip rules within one chain. + Accepts a single parameter denoting the number of rules (or chains) to + skip.
+
<literal>skipAfter</literal> - Description: Skips rules (or chains) on successful match resuming - rule execution after the specified rule ID or marker (see SecMarker) is - found. + + Description: Skips rules (or chains) on + successful match resuming rule execution after the specified rule ID or + marker (see SecMarker) is found. + Action Group: Flow + Example: - - SecRule REQUEST_URI "^/$" "chain,t:none,skipAfter:960015" + + SecRule REQUEST_URI "^/$" "chain,t:none,skipAfter:960015" SecRule REMOTE_ADDR "^127\.0\.0\.1$" "chain" SecRule REQUEST_HEADERS:User-Agent "^Apache \(internal dummy connection\)$" "t:none" SecRule &REQUEST_HEADERS:Host "@eq 0" \ "deny,log,status:400,id:960008,severity:4,msg:'Request Missing a Host Header'" SecRule &REQUEST_HEADERS:Accept "@eq 0" \ - "log,deny,log,status:400,id:960015,msg:'Request Missing an Accept Header'" - + "log,deny,log,status:400,id:960015,msg:'Request Missing an Accept Header'" + Note - SkipAfter only applies to the current processing phase and not - necessarily the order in which the rules appear in the configuration file. If you group - rules by processing phases, then skip should work as expected. This action can not be used - to skip rules within one chain. Accepts a single parameter denoting the last rule ID to - skip. + + SkipAfter only applies to the current + processing phase and not necessarily the order in which the rules appear + in the configuration file. If you group rules by processing phases, then + skip should work as expected. This action can not be used to skip rules + within one chain. Accepts a single parameter denoting the last rule ID + to skip.
+
<literal>status</literal> - Description: Specifies the response status code to use with - actions deny and - redirect. + + Description: Specifies the response status + code to use with actions deny + and redirect. + Action Group: Data + Example: + SecDefaultAction log,deny,status:403,phase:1 + Note - Status actions defined in Apache scope locations (such as Directory, Location, etc...) - may be superseded by phase:1 action settings. The Apache ErrorDocument directive will be - triggered if present in the configuration. Therefore if you have previously defined a custom - error page for a given status then it will be executed and its output presented to the - user. + + Status actions defined in Apache scope locations (such as + Directory, Location, etc...) may be superseded by phase:1 action + settings. The Apache ErrorDocument directive will be triggered if + present in the configuration. Therefore if you have previously defined a + custom error page for a given status then it will be executed and its + output presented to the user.
+
<literal>t</literal> - Description: This action can be used which transformation function - should be used against the specified variables before they (or the results, rather) are run - against the operator specified in the rule. + + Description: This action can be used which + transformation function should be used against the specified variables + before they (or the results, rather) are run against the operator + specified in the rule. + Action Group: Non-disruptive + Example: + SecDefaultAction log,deny,phase:1,t:removeNulls,t:lowercase SecRule REQUEST_COOKIES:SESSIONID "47414e81cbbef3cf8366e84eeacba091" \ log,deny,status:403,t:md5,t:hexEncode + Note - Any transformation functions that you specify in a SecRule will be in addition to - previous ones specified in SecDefaultAction. Use of "t:none" will remove all transformation - functions for the specified rule. + + Any transformation functions that you specify in a SecRule will be + in addition to previous ones specified in SecDefaultAction. Use of + "t:none" will remove all transformation functions for the specified + rule.
+
<literal>tag</literal> - Description: Assigns custom text to a rule or chain. + + Description: Assigns custom text to a rule or + chain. + Action Group: Meta-data + Example: + SecRule REQUEST_FILENAME "\b(?:n(?:map|et|c)|w(?:guest|sh)|cmd(?:32)?|telnet|rcmd|ftp)\.exe\b" \ "t:none,t:lowercase,deny,msg:'System Command Access',id:'950002',\ tag:'WEB_ATTACK/FILE_INJECTION',tag:'OWASP/A2',severity:'2'" + Note - The tag information appears in the error and/or audit log files. Its intent is to be - used to automate classification of rules and the alerts generated by rules. Multiple tags - can be used per rule/chain. + + The tag information appears in the error and/or audit log files. + Its intent is to be used to automate classification of rules and the + alerts generated by rules. Multiple tags can be used per + rule/chain.
+
<literal>xmlns</literal> - Description: This action should be used together with an XPath - expression to register a namespace. + + Description: This action should be used + together with an XPath expression to register a namespace. + Action Group: Data + Example: + SecRule REQUEST_HEADERS:Content-Type "text/xml" \ "phase:1,pass,ctl:requestBodyProcessor=XML,ctl:requestBodyAccess=On, \ xmlns:xsd="http://www.w3.org/2001/XMLSchema" SecRule XML:/soap:Envelope/soap:Body/q1:getInput/id() "123" phase:2,deny
+
Operators - A number of operators can be used in rules, as documented below. The operator syntax uses - the @ symbol followed by the specific operator name. + + A number of operators can be used in rules, as documented below. The + operator syntax uses the @ symbol followed by the + specific operator name. +
<literal>beginsWith</literal> - Description: This operator is a string comparison and returns true - if the parameter value is found at the beginning of the input. Macro expansion is performed - so you may use variable names such as %{TX.1}, etc. + + Description: This operator is a string + comparison and returns true if the parameter value is found at the + beginning of the input. Macro expansion is performed so you may use + variable names such as %{TX.1}, etc. + Example: + SecRule REQUEST_LINE "!@beginsWith GET" t:none,deny,status:403 SecRule REQUEST_ADDR "^(.*)\.\d+$" deny,status:403,capture,chain SecRule ARGS:gw "!@beginsWith %{TX.1}"
+
<literal>contains</literal> - Description: This operator is a string comparison and returns true - if the parameter value is found anywhere in the input. Macro expansion is performed so you - may use variable names such as %{TX.1}, etc. + + Description: This operator is a string + comparison and returns true if the parameter value is found anywhere in + the input. Macro expansion is performed so you may use variable names + such as %{TX.1}, etc. + Example: + SecRule REQUEST_LINE "!@contains .php" t:none,deny,status:403 SecRule REQUEST_ADDR "^(.*)$" deny,status:403,capture,chain SecRule ARGS:ip "!@contains %{TX.1}"
+
<literal>endsWith</literal> - Description: This operator is a string comparison and returns true - if the parameter value is found at the end of the input. Macro expansion is performed so you - may use variable names such as %{TX.1}, etc. + + Description: This operator is a string + comparison and returns true if the parameter value is found at the end + of the input. Macro expansion is performed so you may use variable names + such as %{TX.1}, etc. + Example: + SecRule REQUEST_LINE "!@endsWith HTTP/1.1" t:none,deny,status:403 SecRule ARGS:route "!@endsWith %{REQUEST_ADDR}" t:none,deny,status:403
+
<literal>eq</literal> - Description: This operator is a numerical comparison and stands for - "equal to." + + Description: This operator is a numerical + comparison and stands for "equal to." + Example: + SecRule &REQUEST_HEADERS_NAMES "@eq 15"
+
<literal>ge</literal> - Description: This operator is a numerical comparison and stands for - "greater than or equal to." + + Description: This operator is a numerical + comparison and stands for "greater than or equal to." + Example: + SecRule &REQUEST_HEADERS_NAMES "@ge 15"
+
<literal>geoLookup</literal> - Description: This operator looks up various data fields from an IP - address or hostname. The results will be captured in the GEO collection. - You must provide a database via SecGeoLookupDb before - this operator can be used. - See the GEO variable for an example and more - information on various fields available. + + Description: This operator looks up various + data fields from an IP address or hostname. The results will be captured + in the GEO collection. + + You must provide a database via SecGeoLookupDb before this operator can be + used. + + See the GEO variable for an + example and more information on various fields available.
+
<literal>gt</literal> - Description: This operator is a numerical comparison and stands for - "greater than." + + Description: This operator is a numerical + comparison and stands for "greater than." + Example: + SecRule &REQUEST_HEADERS_NAMES "@gt 15"
+
<literal>inspectFile</literal> - Description: Executes the external script/binary given as parameter - to the operator against every file extracted from the request. As of v2.5.0, if the supplied - filename is not absolute it is treated as relative to the directory in which the - configuration file resides. Also as of v2.5.0, if the filename is determined to be a Lua - script (based on its extension) the script will be processed by the internal engine. As such - it will have full access to the ModSecurity context. + + Description: Executes the external + script/binary given as parameter to the operator against every file + extracted from the request. As of v2.5.0, if the supplied filename is + not absolute it is treated as relative to the directory in which the + configuration file resides. Also as of v2.5.0, if the filename is + determined to be a Lua script (based on its extension) the script will + be processed by the internal engine. As such it will have full access to + the ModSecurity context. + Example of using an external binary/script: + # Execute external script to validate uploaded files. SecRule FILES_TMPNAMES "@inspectFile /opt/apache/bin/inspect_script.pl" + Example of using Lua script: + SecRule FILES_TMPNANMES "@inspectFile inspect.lua" + Script inspect.lua: + function main(filename) -- Do something to the file to verify it. In this example, we -- read up to 10 characters from the beginning of the file. @@ -3631,369 +5497,542 @@ SecRule FILES_TMPNAMES "@inspectFile /opt/apache/bin/inspec return null; end
+
<literal>le</literal> - Description: This operator is a numerical comparison and stands for - "less than or equal to." + + Description: This operator is a numerical + comparison and stands for "less than or equal to." + Example: + SecRule &REQUEST_HEADERS_NAMES "@le 15"
+
<literal>lt</literal> - Description: This operator is a numerical comparison and stands for - "less than." + + Description: This operator is a numerical + comparison and stands for "less than." + Example: + SecRule &REQUEST_HEADERS_NAMES "@lt 15"
+
<literal>pm</literal> - Description: Phrase Match operator. This operator uses a set based - matching engine (Aho-Corasick) for faster matches of keyword lists. It will match any one of - its arguments anywhere in the target value. + + Description: Phrase Match operator. This + operator uses a set based matching engine (Aho-Corasick) for faster + matches of keyword lists. It will match any one of its arguments + anywhere in the target value. + Example: + SecRule REQUEST_HEADERS:User-Agent "@pm WebZIP WebCopier Webster WebStripper SiteSnagger ProWebWalker CheeseBot" "deny,status:403 - The above would deny access with 403 if any of the words matched within the User-Agent - HTTP header value. + + The above would deny access with 403 if any of the words matched + within the User-Agent HTTP header value.
+
<literal>pmFromFile</literal> - Description: Phrase Match operator. This operator uses a set based - matching engine (Aho-Corasick) for faster matches of keyword lists. This operator is the - same as @pm except that it takes a list of files as arguments. It will - match any one of the phrases listed in the file(s) anywhere in the target value. + + Description: Phrase Match operator. This + operator uses a set based matching engine (Aho-Corasick) for faster + matches of keyword lists. This operator is the same as + @pm except that it takes a list of files as + arguments. It will match any one of the phrases listed in the file(s) + anywhere in the target value. + Notes: + - The contents of the files should be one phrase per line. End of line markers will be - stripped from the phrases, however, whitespace will not be trimmed from phrases in the - file. Empty lines and comment lines (beginning with a '#') are ignored. + The contents of the files should be one phrase per line. End + of line markers will be stripped from the phrases, however, + whitespace will not be trimmed from phrases in the file. Empty lines + and comment lines (beginning with a '#') are ignored. + - To allow easier inclusion of phrase files with rulesets, relative paths may be used - to the phrase files. In this case, the path of the file containing the rule is prepended - to the phrase file path. + To allow easier inclusion of phrase files with rulesets, + relative paths may be used to the phrase files. In this case, the + path of the file containing the rule is prepended to the phrase file + path. + Example: + SecRule REQUEST_HEADERS:User-Agent "@pm /path/to/blacklist1 blacklist2" "deny,status:403 - The above would deny access with 403 if any of the patterns in the two files matched - within the User-Agent HTTP header value. The blacklist2 file would need - to be placed in the same path as the file containing the rule. + + The above would deny access with 403 if any of the patterns in the + two files matched within the User-Agent HTTP header value. The + blacklist2 file would need to be placed in the same + path as the file containing the rule.
+
<literal>rbl</literal> - Description: Look up the parameter in the RBL given as parameter. - Parameter can be an IPv4 address, or a hostname. + + Description: Look up the parameter in the RBL + given as parameter. Parameter can be an IPv4 address, or a + hostname. + Example: + SecRule REMOTE_ADDR "@rbl sc.surbl.org"
+
<literal>rx</literal> - Description: Regular expression operator. This is the default - operator, so if the "@" operator is not defined, it is assumed to be rx. + + Description: Regular expression operator. + This is the default operator, so if the "@" operator is not defined, it + is assumed to be rx. + Example: + SecRule REQUEST_HEADERS:User-Agent "@rx nikto" + Note - Regular expressions are handled by the PCRE library (http://www.pcre.org). ModSecurity compiles its regular expressions with the - following settings: + + Regular expressions are handled by the PCRE library (http://www.pcre.org). ModSecurity + compiles its regular expressions with the following settings: + - The entire input is treated as a single line, even when there are newline characters - present. + The entire input is treated as a single line, even when there + are newline characters present. + - All matches are case-sensitive. If you do not care about case sensitivity you either - need to implement the lowercase transformation - function, or use the per-pattern(?i)modifier, as - allowed by PCRE. + All matches are case-sensitive. If you do not care about case + sensitivity you either need to implement the lowercase transformation function, or use + the per-pattern(?i)modifier, as + allowed by PCRE. + - The PCRE_DOTALL and PCRE_DOLLAR_ENDONLY flags are set during compilation, meaning a single dot - will match any character, including the newlines and a $ end anchor will not match a trailing newline character. + The PCRE_DOTALL and + PCRE_DOLLAR_ENDONLY flags are set + during compilation, meaning a single dot will match any character, + including the newlines and a $ + end anchor will not match a trailing newline character.
+
<literal>streq</literal> - Description: This operator is a string comparison and returns true - if the parameter value matches the input exactly. Macro expansion is performed so you may - use variable names such as %{TX.1}, etc. + + Description: This operator is a string + comparison and returns true if the parameter value matches the input + exactly. Macro expansion is performed so you may use variable names such + as %{TX.1}, etc. + Example: + SecRule ARGS:foo "!@streq bar" t:none,deny,status:403 SecRule REQUEST_ADDR "^(.*)$" deny,status:403,capture,chain SecRule REQUEST_HEADERS:Ip-Address "!@streq %{TX.1}"
+
<literal>validateByteRange</literal> - Description: Validates the byte range used in the variable falls - into the specified range. + + Description: Validates the byte range used in + the variable falls into the specified range. + Example: + SecRule ARG:text "@validateByteRange 10, 13, 32-126" + Note - You can force requests to consist only of bytes from a certain byte range. This can be - useful to avoid stack overflow attacks (since they usually contain "random" binary content). - Default range values are 0 and 255, i.e. all byte values are allowed. This directive does - not check byte range in a POST payload when multipart/form-data encoding - (file upload) is used. Doing so would prevent binary files from being uploaded. However, - after the parameters are extracted from such request they are checked for a valid - range. - validateByteRange is similar to the ModSecurity 1.X SecFilterForceByteRange Directive - however since it works in a rule context, it has the following differences: + + You can force requests to consist only of bytes from a certain + byte range. This can be useful to avoid stack overflow attacks (since + they usually contain "random" binary content). Default range values are + 0 and 255, i.e. all byte values are allowed. This directive does not + check byte range in a POST payload when + multipart/form-data encoding (file upload) is used. + Doing so would prevent binary files from being uploaded. However, after + the parameters are extracted from such request they are checked for a + valid range. + + validateByteRange is similar to the ModSecurity 1.X + SecFilterForceByteRange Directive however since it works in a rule + context, it has the following differences: + - You can specify a different range for different variables. + You can specify a different range for different + variables. + It has an "event" context (id, msg....) + - It is executed in the flow of rules rather than being a built in pre-check. + It is executed in the flow of rules rather than being a built + in pre-check.
+
<literal>validateDTD</literal> - Description: Validates the DOM tree generated by the XML request - body processor against the supplied DTD. + + Description: Validates the DOM tree generated + by the XML request body processor against the supplied DTD. + Example: + SecDefaultAction log,deny,status:403,phase:2 SecRule REQUEST_HEADERS:Content-Type ^text/xml$ \ phase:1,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML SecRule REQBODY_PROCESSOR "!^XML$" nolog,pass,skipAfter:12345 SecRule XML "@validateDTD /path/to/apache2/conf/xml.dtd" "deny,id:12345" + - This operator requires request body to be processed as XML. + This operator requires request body to be processed as + XML.
+
<literal>validateSchema</literal> - Description: Validates the DOM tree generated by the XML request - body processor against the supplied XML Schema. + + Description: Validates the DOM tree generated + by the XML request body processor against the supplied XML + Schema. + Example: + SecDefaultAction log,deny,status:403,phase:2 SecRule REQUEST_HEADERS:Content-Type ^text/xml$ \ phase:1,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML SecRule REQBODY_PROCESSOR "!^XML$" nolog,pass,skipAfter:12345 SecRule XML "@validateSchema /path/to/apache2/conf/xml.xsd" "deny,id:12345" + - This operator requires request body to be processed as XML. + This operator requires request body to be processed as + XML.
+
<literal>validateUrlEncoding</literal> - Description: Verifies the encodings used in the variable (if any) - are valid. + + Description: Verifies the encodings used in + the variable (if any) are valid. + Example: + SecRule ARGS "@validateUrlEncoding" + Note - URL encoding is an HTTP standard for encoding byte values within a URL. The byte is - escaped with a % followed by two hexadecimal values (0-F). This directive does not check - encoding in a POST payload when the multipart/form-data encoding (file - upload) is used. It is not necessary to do so because URL encoding is not used for this - encoding. + + URL encoding is an HTTP standard for encoding byte values within a + URL. The byte is escaped with a % followed by two hexadecimal values + (0-F). This directive does not check encoding in a POST payload when the + multipart/form-data encoding (file upload) is used. + It is not necessary to do so because URL encoding is not used for this + encoding.
+
<literal>validateUtf8Encoding</literal> - Description: Verifies the variable is a valid UTF-8 encoded - string. + + Description: Verifies the variable is a valid + UTF-8 encoded string. + Example: + SecRule ARGS "@validateUtf8Encoding" + Note - UTF-8 encoding is valid on most web servers. Integer values between 0-65535 are encoded - in a UTF-8 byte sequence that is escaped by percents. The short form is two bytes in - length. + + UTF-8 encoding is valid on most web servers. Integer values + between 0-65535 are encoded in a UTF-8 byte sequence that is escaped by + percents. The short form is two bytes in length. + check for three types of errors: + - Not enough bytes. UTF-8 supports two, three, four, five, and six byte encodings. - ModSecurity will locate cases when a byte or more is missing. + Not enough bytes. UTF-8 supports two, three, four, five, and + six byte encodings. ModSecurity will locate cases when a byte or + more is missing. + - Invalid encoding. The two most significant bits in most characters are supposed to - be fixed to 0x80. Attackers can use this to subvert Unicode decoders. + Invalid encoding. The two most significant bits in most + characters are supposed to be fixed to 0x80. Attackers can use this + to subvert Unicode decoders. + - Overlong characters. ASCII characters are mapped directly into the Unicode space and - are thus represented with a single byte. However, most ASCII characters can also be - encoded with two, three, four, five, and six characters thus tricking the decoder into - thinking that the character is something else (and, presumably, avoiding the security - check). + Overlong characters. ASCII characters are mapped directly into + the Unicode space and are thus represented with a single byte. + However, most ASCII characters can also be encoded with two, three, + four, five, and six characters thus tricking the decoder into + thinking that the character is something else (and, presumably, + avoiding the security check).
+
<literal>verifyCC</literal> - Description: This operator verifies a given regular expression as a - potential credit card number. It first matches with a single generic regular expression then - runs the resulting match through a Luhn checksum algorithm to further verify it as a - potential credit card number. + + Description: This operator verifies a given + regular expression as a potential credit card number. It first matches + with a single generic regular expression then runs the resulting match + through a Luhn checksum algorithm to further verify it as a potential + credit card number. + Example: + SecRule ARGS "@verifyCC \d{13,16}" \ "phase:2,sanitiseMatched,log,auditlog,pass,msg:'Potential credit card number'"
+
<literal>within</literal> - Description: This operator is a string comparison and returns true - if the input value is found anywhere within the parameter value. Note that this is similar - to @contains, except that the target and match values are reversed. Macro - expansion is performed so you may use variable names such as %{TX.1}, etc. + + Description: This operator is a string + comparison and returns true if the input value is found anywhere within + the parameter value. Note that this is similar to + @contains, except that the target and match values + are reversed. Macro expansion is performed so you may use variable names + such as %{TX.1}, etc. + Example: + SecRule REQUEST_METHOD "!@within get,post,head" t:lowercase,deny,status:403 SecAction "pass,setvar:'tx.allowed_methods=get,post,head'" SecRule REQUEST_METHOD "!@within %{tx.allowed_methods}" t:lowercase,deny,status:403
+
Macro Expansion - Macros allow for using place holders in rules that will be expanded out to their values at - runtime. Currently only variable expansion is supported, however more options may be added in - future versions of ModSecurity. + + Macros allow for using place holders in rules that will be expanded + out to their values at runtime. Currently only variable expansion is + supported, however more options may be added in future versions of + ModSecurity. + Format: + %{VARIABLE} %{COLLECTION.VARIABLE} - Macro expansion can be used in actions such as initcol, setsid, setuid, setvar, setenv, - logdata. Operators that are evaluated at runtime support expansion and are noted above. Such - operators include @beginsWith, @endsWith, @contains, @within and @streq. You cannot use macro - expansion for operators that are "compiled" such as @pm, @rx, etc. as these operators have - their values fixed at configure time for efficiency. - Some values you may want to expand include: TX, REMOTE_ADDR, USERID, HIGHEST_SEVERITY, - MATCHED_VAR, MATCHED_VAR_NAME, MULTIPART_STRICT_ERROR, RULE, SESSION, USERID, among - others. + + Macro expansion can be used in actions such as initcol, setsid, + setuid, setvar, setenv, logdata. Operators that are evaluated at runtime + support expansion and are noted above. Such operators include @beginsWith, + @endsWith, @contains, @within and @streq. You cannot use macro expansion + for operators that are "compiled" such as @pm, @rx, etc. as these + operators have their values fixed at configure time for efficiency. + + Some values you may want to expand include: TX, REMOTE_ADDR, USERID, + HIGHEST_SEVERITY, MATCHED_VAR, MATCHED_VAR_NAME, MULTIPART_STRICT_ERROR, + RULE, SESSION, USERID, among others.
+
Persistant Storage - At this time it is only possible to have three collections in which data is stored - persistantly (i.e. data available to multiple requests). These are: IP, SESSION and USER. - Every collection contains several built-in variables that are available and are read-only - unless otherwise specified: + + At this time it is only possible to have three collections in which + data is stored persistantly (i.e. data available to multiple requests). + These are: IP, SESSION and USER. + + Every collection contains several built-in variables that are + available and are read-only unless otherwise specified: + - CREATE_TIME - date/time of the creation of the - collection. + CREATE_TIME - date/time of + the creation of the collection. + - IS_NEW - set to 1 if the collection is new (not yet - persisted) otherwise set to 0. + IS_NEW - set to 1 if the + collection is new (not yet persisted) otherwise set to 0. + - KEY - the value of the initcol variable (the - client's IP address in the example). + KEY - the value of the + initcol variable (the client's IP address in the example). + - LAST_UPDATE_TIME - date/time of the last update to - the collection. + LAST_UPDATE_TIME - date/time + of the last update to the collection. + - TIMEOUT - date/time in seconds when the collection - will be updated on disk from memory (if no other updates occur). This variable may be set - if you wish to specifiy an explicit expiration time (default is 3600 seconds). + TIMEOUT - date/time in + seconds when the collection will be updated on disk from memory (if no + other updates occur). This variable may be set if you wish to specifiy + an explicit expiration time (default is 3600 seconds). + - UPDATE_COUNTER - how many times the collection has - been updated since creation. + UPDATE_COUNTER - how many + times the collection has been updated since creation. + - UPDATE_RATE - is the average rate updates per - minute since creation. + UPDATE_RATE - is the average + rate updates per minute since creation. - To create a collection to hold session variables (SESSION) use action setsid. To create a - collection to hold user variables (USER) use action - setuid. To create a collection to hold client address - variables (IP) use action initcol. + + To create a collection to hold session variables (SESSION) use action setsid. To create a collection to hold user + variables (USER) use action setuid. To create a collection to hold client + address variables (IP) use action + initcol. + - ModSecurity implements atomic updates of persistent variables only for integer variables - (counters) at this time. Variables are read from storage whenever initcol - is encountered in the rules and persisted at the end of request processing. Counters are - adjusted by applying a delta generated by re-reading the persisted data just before being - persisted. This keeps counter data consistent even if the counter was modified and persisted - by another thread/process during the transaction. + ModSecurity implements atomic updates of persistent variables only + for integer variables (counters) at this time. Variables are read from + storage whenever initcol is encountered in the rules + and persisted at the end of request processing. Counters are adjusted by + applying a delta generated by re-reading the persisted data just before + being persisted. This keeps counter data consistent even if the counter + was modified and persisted by another thread/process during the + transaction. + + Please note that ModSecurity does not implement atomic updates of + persistent variables at this time. Variables are read from storage + whenever initcol is encountered in the rules and + persisted at the end of request processing. On busy servers requests + often run in parallel, leading to situations where one request + overwrites the changes made by another request. We anticipate + implementing atomic updates of counter values in a future + version. + - ModSecurity uses a Berkley Database (SDBM) for persistant storage. This type of database - is generally limited to storing a maximum of 1008 bytes per key. This may be a limitation if - you are attempting to store a considerable amount of data in variables for a single key. - Some of this limitation is planned to be reduced in a future version of ModSecurity. + ModSecurity uses a Berkley Database (SDBM) for persistant storage. + This type of database is generally limited to storing a maximum of 1008 + bytes per key. This may be a limitation if you are attempting to store a + considerable amount of data in variables for a single key. Some of this + limitation is planned to be reduced in a future version of + ModSecurity.
+
Miscellaneous Topics - + + +
Impedance Mismatch - Web application firewalls have a difficult job trying to make sense of data that passes - by, without any knowledge of the application and its business logic. The protection they - provide comes from having an independent layer of security on the outside. Because data - validation is done twice, security can be increased without having to touch the application. - In some cases, however, the fact that everything is done twice brings problems. Problems can - arise in the areas where the communication protocols are not well specified, or where either - the device or the application do things that are not in the specification. In such cases it - may be possible to design payload that will be interpreted in one way by one device and in - another by the other device. This problem is better known as Impedance Mismatch. It can be - exploited to evade the security devices. - While we will continue to enhance ModSecurity to deal with various evasion techniques - the problem can only be minimized, but never solved. With so many different application - backend chances are some will always do something completely unexpected. The only solution - is to be aware of the technologies in the backend when writing rules, adapting the rules to - remove the mismatch. See the next section for some examples. + + Web application firewalls have a difficult job trying to make + sense of data that passes by, without any knowledge of the application + and its business logic. The protection they provide comes from having an + independent layer of security on the outside. Because data validation is + done twice, security can be increased without having to touch the + application. In some cases, however, the fact that everything is done + twice brings problems. Problems can arise in the areas where the + communication protocols are not well specified, or where either the + device or the application do things that are not in the specification. + In such cases it may be possible to design payload that will be + interpreted in one way by one device and in another by the other device. + This problem is better known as Impedance Mismatch. It can be exploited + to evade the security devices. + + While we will continue to enhance ModSecurity to deal with various + evasion techniques the problem can only be minimized, but never solved. + With so many different application backend chances are some will always + do something completely unexpected. The only solution is to be aware of + the technologies in the backend when writing rules, adapting the rules + to remove the mismatch. See the next section for some examples. +
PHP Peculiarities for ModSecurity Users - When writing rules to protect PHP applications you need to pay attention to the - following facts: + + When writing rules to protect PHP applications you need to pay + attention to the following facts: + - When "register_globals" is set to "On" request parameters are automatically - converted to script variables. In some PHP versions it is even possible to override - the $GLOBALS array. + When "register_globals" is set to "On" request parameters + are automatically converted to script variables. In some PHP + versions it is even possible to override the $GLOBALS + array. + - Whitespace at the beginning of parameter names is ignored. (This is very dangerous - if you are writing rules to target specific named variables.) + Whitespace at the beginning of parameter names is ignored. + (This is very dangerous if you are writing rules to target + specific named variables.) + - The remaining whitespace (in parameter names) is converted to underscores. The - same applies to dots and to a "[" if the variable name does not contain a matching - closing bracket. (Meaning that if you want to exploit a script through a variable that - contains an underscore in the name you can send a parameter with a whitespace or a dot - instead.) + The remaining whitespace (in parameter names) is converted + to underscores. The same applies to dots and to a "[" if the + variable name does not contain a matching closing bracket. + (Meaning that if you want to exploit a script through a variable + that contains an underscore in the name you can send a parameter + with a whitespace or a dot instead.) + Cookies can be treated as request parameters. + - The discussion about variable names applies equally to the cookie names. + The discussion about variable names applies equally to the + cookie names. + - The order in which parameters are taken from the request and the environment is - EGPCS (environment, GET, POST, Cookies, built-in variables). This means that a POST - parameter will overwrite the parameters transported on the request line (in - QUERY_STRING). + The order in which parameters are taken from the request and + the environment is EGPCS (environment, GET, POST, Cookies, + built-in variables). This means that a POST parameter will + overwrite the parameters transported on the request line (in + QUERY_STRING). + - When "magic_quotes_gpc" is set to "On" PHP will use backslash to escape the - following characters: single quote, double quote, backslash, and the nul byte. + When "magic_quotes_gpc" is set to "On" PHP will use + backslash to escape the following characters: single quote, double + quote, backslash, and the nul byte. + - If "magic_quotes_sybase" is set to "On" only the single quote will be escaped - using another single quote. In this case the "magic_quotes_gpc" setting becomes - irrelevant. The "magic_quotes_sybase" setting completely overrides the - "magic_quotes_gpc" behaviour but "magic_quotes_gpc" still must be set to "On" for the - Sybase-specific quoting to be work. + If "magic_quotes_sybase" is set to "On" only the single + quote will be escaped using another single quote. In this case the + "magic_quotes_gpc" setting becomes irrelevant. The + "magic_quotes_sybase" setting completely overrides the + "magic_quotes_gpc" behaviour but "magic_quotes_gpc" still must be + set to "On" for the Sybase-specific quoting to be work. + - PHP will also automatically create nested arrays for you. For example "p[x][y]=1" - results in a total of three variables. + PHP will also automatically create nested arrays for you. + For example "p[x][y]=1" results in a total of three + variables.
-
+ \ No newline at end of file diff --git a/doc/modsecurity2-data-formats.xml b/doc/modsecurity2-data-formats.xml index 12ffe318..d473023b 100644 --- a/doc/modsecurity2-data-formats.xml +++ b/doc/modsecurity2-data-formats.xml @@ -4,7 +4,7 @@
ModSecurity 2 Data Formats - Version 2.6.0-trunk (December 3, 2008) + Version 2.6.0-trunk (March 5, 2009) 2004-2008 Breach Security, Inc. ( - - - - 2008-01-04 :: 10:55:40:361 GMT-08:00 - 2008-01-11 :: 16:47:15:701 GMT-08:00 - - brian - brian - apache2/re_variables.c - item.type.label.suggestion - item.severity.label.normal - Is ENV really cacheable? It could change via setenv. - /* ENV */ - msre_engine_variable_register(engine, - "ENV", - VAR_LIST, - 0, 1, - var_env_validate, - var_env_generate, - VAR_CACHE, - PHASE_REQUEST_HEADERS - ); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 10:57:54:279 GMT-08:00 - 2008-01-11 :: 16:43:38:825 GMT-08:00 - - brian - brian - apache2/re_variables.c - item.type.label.suggestion - item.severity.label.trivial - GEO is probably not cacheable as it changes with every @geoLookup operator. - /* GEO */ - msre_engine_variable_register(engine, - "GEO", - VAR_LIST, - 1, 1, - var_generic_list_validate, - var_geo_generate, - VAR_CACHE, - PHASE_REQUEST_HEADERS - ); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 11:02:30:450 GMT-08:00 - 2008-01-11 :: 16:43:20:652 GMT-08:00 - - brian - brian - apache2/re_variables.c - item.type.label.suggestion - item.severity.label.trivial - GLOBAL is not documented. Is it cacheable? - /* GLOBAL */ - msre_engine_variable_register(engine, - "GLOBAL", - VAR_LIST, - 1, 1, - var_generic_list_validate, - var_global_generate, - VAR_CACHE, - PHASE_REQUEST_HEADERS - ); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 11:06:50:690 GMT-08:00 - 2008-01-11 :: 16:43:02:916 GMT-08:00 - - brian - brian - apache2/re_variables.c - item.type.label.suggestion - item.severity.label.trivial - IP undocumented. Probably not cacheable as it can change via setvar, etc. - /* IP */ - msre_engine_variable_register(engine, - "IP", - VAR_LIST, - 1, 1, - var_generic_list_validate, - var_ip_generate, - VAR_CACHE, - PHASE_REQUEST_HEADERS - ); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 11:08:36:733 GMT-08:00 - 2008-01-11 :: 16:42:44:589 GMT-08:00 - - brian - brian - apache2/re_variables.c - item.type.label.suggestion - item.severity.label.trivial - RESOURCE is undocumented. Probably not cacheable as it is easily changed. - /* RESOURCE */ - msre_engine_variable_register(engine, - "RESOURCE", - VAR_LIST, - 1, 1, - var_generic_list_validate, - var_resource_generate, - VAR_CACHE, - PHASE_REQUEST_HEADERS - ); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 11:14:32:043 GMT-08:00 - 2008-01-11 :: 16:41:31:558 GMT-08:00 - - brian - brian - apache2/re_variables.c - item.type.label.suggestion - item.severity.label.trivial - SESSION is probably not cacheable since it is modifyable via setvar. - /* SESSION */ - msre_engine_variable_register(engine, - "SESSION", - VAR_LIST, - 1, 1, - var_generic_list_validate, - var_session_generate, - VAR_CACHE, - PHASE_REQUEST_HEADERS - ); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 11:25:25:879 GMT-08:00 - 2008-01-11 :: 17:00:23:571 GMT-08:00 - - brian - brian - apache2/apache2_util.c - item.type.label.suggestion - item.severity.label.trivial - Portable way to format sizeof()? - msr_log(msr, 1, "Exec: Unable to allocate %lu bytes.", (unsigned long)sizeof(*procnew)); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 11:48:52:563 GMT-08:00 - 2008-01-04 :: 11:50:30:473 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.irrelevant - item.severity.label.trivial - This #if 0'd out code should be removed. - /* Removed %0-9 macros as it messes up urlEncoding in the match - * where having '%0a' will be treated as %{TX.0}a, which is incorrect. - * */ -#if 0 - else if ((*(p + 1) >= '0')&&(*(p + 1) <= '9')) { - /* Special case for regex captures. */ - var_name = "TX"; - var_value = apr_pstrmemdup(mptmp, p + 1, 1); - next_text_start = p + 2; - } -#endif - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 11:53:45:291 GMT-08:00 - 2008-01-04 :: 14:51:42:573 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.optimization - item.severity.label.trivial - Use apr_array_pstrcat(msr->mp, arr, NULL) instead? - /* If there's more than one member of the array that - * means there was at least one macro present. Combine - * text parts into a single string now. - */ - if (arr->nelts > 1) { - /* Figure out the required size for the string. */ - var->value_len = 0; - for(i = 0; i < arr->nelts; i++) { - part = ((msc_string **)arr->elts)[i]; - var->value_len += part->value_len; - } - - /* Allocate the string. */ - var->value = apr_palloc(msr->mp, var->value_len + 1); - if (var->value == NULL) return -1; - - /* Combine the parts. */ - offset = 0; - for(i = 0; i < arr->nelts; i++) { - part = ((msc_string **)arr->elts)[i]; - memcpy((char *)(var->value + offset), part->value, part->value_len); - offset += part->value_len; - } - var->value[offset] = '\0'; - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 12:00:50:877 GMT-08:00 - 2008-01-04 :: 12:03:50:156 GMT-08:00 - - brian - brian - apache2/re_operators.c - Suggestion - item.severity.label.trivial - Use resolve_relative_path() instead? Maybe a config_relative_path() to just get the path? - /* Get the path of the rule filename to use as a base */ - rulefile_path = apr_pstrndup(rule->ruleset->mp, rule->filename, strlen(rule->filename) - strlen(apr_filepath_name_get(rule->filename))); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 13:23:49:834 GMT-08:00 - 2008-01-11 :: 16:26:24:257 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.clarity - item.severity.label.trivial - Add parens for clarity. - *next++ = '\0'; - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 14:54:09:456 GMT-08:00 - 2008-01-04 :: 14:55:05:945 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.missing - item.severity.label.trivial - Need to check return code and log an error on failure. - acmp_add_pattern(p, buf, NULL, NULL, strlen(buf)); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 14:55:53:308 GMT-08:00 - 2008-01-04 :: 14:56:17:267 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.missing - item.severity.label.trivial - Need to check return code and log an error on failure. - acmp_prepare(p); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 14:58:08:006 GMT-08:00 - 2008-01-04 :: 15:00:17:190 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.optimization - item.severity.label.minor - See if apr_strmatch is faster. - msre_op_within_execute - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 14:59:32:341 GMT-08:00 - 2008-01-04 :: 14:59:59:858 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.optimization - item.severity.label.minor - See if apr_strmatch is faster. - msre_op_contains_execute - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 15:01:39:208 GMT-08:00 - 2008-01-04 :: 15:02:04:258 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.optimization - item.severity.label.minor - See if apr_strmatch is faster. - msre_op_containsWord_execute - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 15:03:12:792 GMT-08:00 - 2008-01-04 :: 15:04:40:965 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.optimization - item.severity.label.minor - This implementation comment needs to be coded as many string operators now attempt to resolve macros. - /* IMP1 Duplicate the string and create the array on - * demand, thus not having to do it if there are - * no macros in the input data. - */ - - data = apr_pstrdup(mptmp, var->value); /* IMP1 Are we modifying data anywhere? */ - arr = apr_array_make(mptmp, 16, sizeof(msc_string *)); - if ((data == NULL)||(arr == NULL)) return -1; - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 15:12:55:300 GMT-08:00 - 2008-01-04 :: 15:13:19:677 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.missing - item.severity.label.minor - Need more unit tests for operators. Start with new operators. - - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 15:36:54:292 GMT-08:00 - 2008-01-04 :: 15:37:50:111 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.missing - item.severity.label.trivial - @m operator is not documented. This does the same as @contains, so it was suggested earlier to use the @m algorithm for contains (if faster) and drop @m. - /* m */ - msre_engine_op_register(engine, - "m", - msre_op_m_param_init, - msre_op_m_execute - ); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 15:43:40:931 GMT-08:00 - 2008-01-11 :: 16:38:59:940 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.missing - item.severity.label.trivial - @geoLookup should set error_msg on success to something like "Successful geograpical lookup of \"%s\" at %s." - msre_op_geoLookup_execute - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 15:47:09:574 GMT-08:00 - 2008-01-11 :: 16:40:07:483 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.missing - item.severity.label.trivial - @rbl fails to set the var name in error_msg. Should append "at %s". - rc = apr_sockaddr_info_get(&sa, name_to_check, - APR_UNSPEC/*msr->r->connection->remote_addr->family*/, 0, 0, msr->mp); - if (rc == APR_SUCCESS) { - *error_msg = apr_psprintf(msr->r->pool, "RBL lookup of %s succeeded.", - log_escape_nq(msr->mp, name_to_check)); - return 1; /* Match. */ - } - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 15:49:05:878 GMT-08:00 - 2008-01-11 :: 14:56:55:081 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.suggestion - item.severity.label.major - Change from TODO to ENH. - - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 15:54:24:055 GMT-08:00 - 2008-01-11 :: 14:57:08:520 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.suggestion - item.severity.label.trivial - Need to remove the LUA #ifdef's - #ifdef WITH_LUA - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 15:56:23:415 GMT-08:00 - 2008-01-11 :: 14:57:21:641 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.suggestion - item.severity.label.trivial - The LUA #ifdef's should be removed, but if it is decided not to, then this lua call needs to be #ifdef'd. - } else { - /* Execute internally, as Lua script. */ - char *target = apr_pstrmemdup(msr->mp, var->value, var->value_len); - msc_script *script = (msc_script *)rule->op_param_data; - int rc; - - rc = lua_execute(script, target, msr, rule, error_msg); - if (rc < 0) { - /* Error. */ - return -1; - } - - return rc; - } - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 15:58:01:918 GMT-08:00 - 2008-01-04 :: 15:58:58:621 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.missing - item.severity.label.major - Need an error_msg set for lua execution error. - rc = lua_execute(script, target, msr, rule, error_msg); - if (rc < 0) { - /* Error. */ - return -1; - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 16:00:09:204 GMT-08:00 - 2008-01-11 :: 16:38:08:350 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.missing - item.severity.label.trivial - @validateByteRange does not output the VAR name on match. Need to append " at %s." - msre_op_validateByteRange_execute - - - item.resolution.label.invalidWontfix - item.status.label.closed - - - - 2008-01-04 :: 16:02:02:403 GMT-08:00 - 2008-01-04 :: 16:06:22:410 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.missing - item.severity.label.trivial - @validateurlEncoding does not output VAR name nor offset in error_msg on match. - msre_op_validateUrlEncoding_execute - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 16:03:51:127 GMT-08:00 - 2008-01-11 :: 16:30:07:550 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.missing - item.severity.label.trivial - Numeric operators (@eq, etc) do not output VAR name on match. - msre_op_eq_execute -msre_op_gt_execute -msre_op_lt_execute -msre_op_ge_execute -msre_op_le_execute - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 16:12:30:943 GMT-08:00 - 2008-01-11 :: 14:57:45:711 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - No. - /* ENH Do we want to support %{DIGIT} as well? */ - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 16:14:51:515 GMT-08:00 - 2008-01-07 :: 14:22:10:119 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.missing - item.severity.label.trivial - Implement. Need to check if Apache will return an invalid status code - /* status */ -static char *msre_action_status_validate(msre_engine *engine, msre_action *action) { - /* ENH action->param must be a valid HTTP status code. */ - return NULL; -} - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 16:15:55:149 GMT-08:00 - 2008-01-04 :: 16:16:52:467 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.missing - item.severity.label.trivial - Implement. - /* pause */ -static char *msre_action_pause_validate(msre_engine *engine, msre_action *action) { - /* ENH Validate a positive number. */ - return NULL; -} - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 16:17:34:464 GMT-08:00 - 2008-01-04 :: 16:22:35:501 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.missing - item.severity.label.trivial - Implement as a valid URI check with apr_uri_parse()? - /* redirect */ - -static char *msre_action_redirect_validate(msre_engine *engine, msre_action *action) { - /* ENH Add validation. */ - return NULL; -} - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 16:22:43:274 GMT-08:00 - 2008-01-04 :: 16:22:54:679 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.missing - item.severity.label.trivial - Implement as a valid URI check with apr_uri_parse()? - /* proxy */ - -static char *msre_action_proxy_validate(msre_engine *engine, msre_action *action) { - /* ENH Add validation. */ - return NULL; -} - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 16:24:58:322 GMT-08:00 - 2008-01-11 :: 16:13:48:178 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.irrelevant - item.severity.label.trivial - I believe this is already done and comment needs removed. - // TODO: Need to keep track of skipAfter IDs so we can insert placeholders after - // we get to the real rule with that ID. - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 16:26:46:732 GMT-08:00 - 2008-01-04 :: 16:27:54:881 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.irrelevant - item.severity.label.trivial - I do not see a need to validate beyound what is already done in the init function. - msre_action_skip_validate -msre_action_skipAfter_validate - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 16:28:48:332 GMT-08:00 - 2008-01-04 :: 16:29:03:587 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.missing - item.severity.label.trivial - Implement. - /* phase */ - -static char *msre_action_phase_validate(msre_engine *engine, msre_action *action) { - /* ENH Add validation. */ - return NULL; -} - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 16:51:52:029 GMT-08:00 - 2008-01-04 :: 17:03:32:872 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - Probably should also calc length and validate a length > 0 instead of just checking NULL. Other checks would benefit from checking a length as well, so no harm in calculating that. - if (value == NULL) { - return apr_psprintf(engine->mp, "Missing ctl value for name: %s", name); - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 16:56:10:995 GMT-08:00 - 2008-01-04 :: 16:59:47:800 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.irrelevant - item.severity.label.trivial - Why register init() if we do not use it? - static apr_status_t msre_action_ctl_init(msre_engine *engine, msre_actionset *actionset, - msre_action *action) -{ - /* Do nothing. */ - return 1; -} - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 17:00:49:340 GMT-08:00 - 2008-01-04 :: 17:02:15:141 GMT-08:00 - - brian - brian - apache2/msc_logging.c - item.type.label.programLogic - item.severity.label.trivial - This allows an empty string as a valid part. This misvalidates "ctl:auditLogParts=+", etc. - is_valid_parts_specification - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 17:04:51:155 GMT-08:00 - 2008-01-11 :: 16:12:33:664 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.optimization - item.severity.label.trivial - Inner if's should be else if's. - if (strcasecmp(name, "ruleEngine") == 0) { - if (strcasecmp(value, "on") == 0) { - msr->txcfg->is_enabled = MODSEC_ENABLED; - msr->usercfg->is_enabled = MODSEC_ENABLED; - } - - if (strcasecmp(value, "off") == 0) { - msr->txcfg->is_enabled = MODSEC_DISABLED; - msr->usercfg->is_enabled = MODSEC_DISABLED; - } - - if (strcasecmp(value, "detectiononly") == 0) { - msr->txcfg->is_enabled = MODSEC_DETECTION_ONLY; - msr->usercfg->is_enabled = MODSEC_DETECTION_ONLY; - } - - return 1; - } else - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 17:05:44:757 GMT-08:00 - 2008-01-11 :: 16:12:12:876 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.optimization - item.severity.label.trivial - TODO needs looked into. - if (strcasecmp(name, "auditEngine") == 0) { - if (strcasecmp(value, "on") == 0) { - msr->txcfg->auditlog_flag = AUDITLOG_ON; - msr->usercfg->auditlog_flag = AUDITLOG_ON; - } - - if (strcasecmp(value, "off") == 0) { - msr->txcfg->auditlog_flag = AUDITLOG_OFF; - msr->usercfg->auditlog_flag = AUDITLOG_OFF; - } - - if (strcasecmp(value, "relevantonly") == 0) { - msr->txcfg->auditlog_flag = AUDITLOG_RELEVANT; - msr->usercfg->auditlog_flag = AUDITLOG_RELEVANT; - } - - msr_log(msr, 4, "Ctl: Set auditEngine to %d.", msr->txcfg->auditlog_flag); // TODO - - return 1; - } else - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-04 :: 17:08:00:396 GMT-08:00 - 2008-01-11 :: 14:59:05:782 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - That warning quieter should be s++. An evil typo that was fixed in 2.1.x, but not trunk! - while(*s != '\0') { - if (*s != c) { - *d++ = *s++; - } else { - (*s)++; /* parens quiet compiler warning */ - } - } - *d = '\0'; - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-04 :: 17:13:11:886 GMT-08:00 - 2008-01-04 :: 17:13:40:681 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.missing - item.severity.label.trivial - Should log an internal error here. - else { - /* ENH Should never happen, but log if it does. */ - return -1; - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 11:14:40:912 GMT-08:00 - 2008-01-07 :: 11:15:54:834 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - Should log a level 9 msg here. - } else { - /* We could not identify a valid macro so add it as text. */ - part = (msc_string *)apr_pcalloc(mptmp, sizeof(msc_string)); - if (part == NULL) return -1; - part->value_len = p - text_start + 1; /* len(text)+len("%") */ - part->value = apr_pstrmemdup(mptmp, text_start, part->value_len); - *(msc_string **)apr_array_push(arr) = part; - - next_text_start = p + 1; - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 11:37:09:009 GMT-08:00 - 2008-01-07 :: 11:41:55:614 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - Probably should use apr_strtoi64 where we can tell if there was an error in conversion since we are potentially taking a value from a macro expansion. Also may want to look for overflow. - value += atoi(var_value); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 11:43:13:789 GMT-08:00 - 2008-01-11 :: 16:10:24:140 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.missing - item.severity.label.trivial - Missing error log needs implemented. - } else { - /* ENH Log warning detected variable name but no collection. */ - return 0; - } - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 11:52:38:857 GMT-08:00 - 2008-01-07 :: 11:53:56:791 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - Not sure why we would not want to deprecate a TX var. Further rules could use this even if TX is not persisted. - /* IMP1 Add message TX variables cannot deprecate in value. */ - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 11:54:14:673 GMT-08:00 - 2008-01-11 :: 15:04:13:383 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - Missing error log needs implemented. - } else { - /* ENH Log warning detected variable name but no collection. */ - return 0; - } - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 12:03:17:626 GMT-08:00 - 2008-01-07 :: 23:10:15:221 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - The timeout is hardcoded to 3600. The docs state TIMEOUT is read-only, but this is not true. So, you can modify TIMEOUT. - /* IMP1 Is the timeout hard-coded to 3600? */ - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 14:12:19:250 GMT-08:00 - 2008-01-07 :: 14:14:28:669 GMT-08:00 - - brian - brian - apache2/msc_logging.c - item.type.label.suggestion - item.severity.label.trivial - apr_dir_make_recursive will attempt to create the dir straight away and if that fails keep backing off a dir until it can start creating, so I see no need to cache. Besides, what happens if you cache, then someone deletes the path from outside apache? - /* IMP1 Surely it would be more efficient to check the folders for - * the audit log repository base path in the configuration phase, to reduce - * the work we do on every request. Also, since our path depends on time, - * we could cache the time we last checked and don't check if we know - * the folder is there. - */ - rc = apr_dir_make_recursive(entry_basename, CREATEMODE_DIR, msr->mp); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 14:24:02:378 GMT-08:00 - 2008-01-07 :: 14:50:55:762 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - We already have support for relative filenames, but cannot get to this data from here. This needs solved by passing more data to the validate function (cmd_parms rec). Maybe need a warning here stating we do not support them yet, or it might be confusing to users that we do not here but do elsewhere. - /* TODO Support relative filenames. */ - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 14:33:59:432 GMT-08:00 - 2008-01-07 :: 15:59:35:056 GMT-08:00 - - brian - brian - apache2/re.h - item.type.label.suggestion - item.severity.label.trivial - Why not stored in op_param_data like @rx, etc. The param_data is used w/exec action for lua. - /* Compiled Lua script. */ - msc_script *script; - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 15:55:08:220 GMT-08:00 - 2008-01-07 :: 16:02:36:938 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - This assumes lua is the only type (which it is now), but should be re-writen with a script_rec stored in param_data. - if (action->param_data != NULL) { /* Lua */ - msc_script *script = (msc_script *)action->param_data; - char *my_error_msg = NULL; - - if (lua_execute(script, NULL, msr, rule, &my_error_msg) < 0) { - msr_log(msr, 1, "%s", my_error_msg); - return 0; - } - } else { /* Execute as shell script. */ - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 16:00:51:901 GMT-08:00 - 2008-01-07 :: 16:04:13:185 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - Not sure using an extension is a good idea here. Better I think would be to specify a type: "exec:[type=]/path/to/file" as in "exec:lua=/path/to/script" and make param_data a script_rec with a type and value. Also we use the abstract param_data here vs using a specific field as in SecRuleScript. - /* Process Lua scripts internally. */ - if (strlen(filename) > 4) { - char *p = filename + strlen(filename) - 4; - if ((p[0] == '.')&&(p[1] == 'l')&&(p[2] == 'u')&&(p[3] == 'a')) { - /* It's a Lua script. */ - msc_script *script = NULL; - - /* Compile script. */ - char *msg = lua_compile(&script, filename, engine->mp); - if (msg != NULL) return msg; - - action->param_data = script; - } - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 16:08:53:365 GMT-08:00 - 2008-01-11 :: 15:25:58:269 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.suggestion - item.severity.label.trivial - Should not log_escape the actions as they will get double escaped (once now and again when logged). - } else { - rule->unparsed = apr_psprintf(ruleset->mp, "SecRuleScript \"%s\" \"%s\"", - script_filename, log_escape(ruleset->mp, actions)); - } - - - item.resolution.label.invalidWontfix - item.status.label.closed - - - - 2008-01-07 :: 16:17:58:895 GMT-08:00 - 2008-01-11 :: 15:26:18:631 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.suggestion - item.severity.label.trivial - Should not log_escape the actions as they will get double escaped (once now and again when logged). - /* Add the unparsed rule */ - if ((strcmp(SECACTION_TARGETS, targets) == 0) && (strcmp(SECACTION_ARGS, args) == 0)) { - rule->unparsed = apr_psprintf(ruleset->mp, "SecAction \"%s\"", - log_escape(ruleset->mp, actions)); - } - else - if ((strcmp(SECMARKER_TARGETS, targets) == 0) - && (strcmp(SECMARKER_ARGS, args) == 0) - && (strncmp(SECMARKER_BASE_ACTIONS, actions, strlen(SECMARKER_BASE_ACTIONS)) == 0)) - { - rule->unparsed = apr_psprintf(ruleset->mp, "SecMarker \"%s\"", - log_escape(ruleset->mp, actions + strlen(SECMARKER_BASE_ACTIONS))); - } - else { - if (actions == NULL) { - rule->unparsed = apr_psprintf(ruleset->mp, "SecRule \"%s\" \"%s\"", - log_escape(ruleset->mp, targets), log_escape(ruleset->mp, args)); - } else { - rule->unparsed = apr_psprintf(ruleset->mp, "SecRule \"%s\" \"%s\" \"%s\"", - log_escape(ruleset->mp, targets), log_escape(ruleset->mp, args), - log_escape(ruleset->mp, actions)); - } - } - - - item.resolution.label.invalidWontfix - item.status.label.closed - - - - 2008-01-07 :: 16:22:43:295 GMT-08:00 - 2008-01-11 :: 15:26:48:665 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.suggestion - item.severity.label.trivial - No logging should be done here as we are passing the error_msg back to the parent and they are responsible for this. - if (*error_msg != NULL) { - /* ENH Shouldn't we log the problem? */ - return NULL; - } - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 16:30:41:403 GMT-08:00 - 2008-01-07 :: 16:31:00:930 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.missing - item.severity.label.trivial - Need to log on failure. - var = msre_create_var(ruleset, telts[i].key, telts[i].val, NULL, error_msg); - if (var == NULL) return -1; - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 16:36:31:466 GMT-08:00 - 2008-01-07 :: 16:36:54:189 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.suggestion - item.severity.label.trivial - Should replace with isvarnamechar() if possible. - while((*p != '\0')&&(*p != '|')&&(*p != ':')&&(*p != ',')&&(!isspace(*p))) p++; /* ENH replace with isvarnamechar() */ - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 16:39:21:316 GMT-08:00 - 2008-01-11 :: 15:28:02:997 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.suggestion - item.severity.label.trivial - Fix or remove TODO. - // TODO better 64-bit support here - *error_msg = apr_psprintf(mp, "Missing closing quote at position %d: %s", - (int)(p - text), text); - free(value); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 16:39:47:318 GMT-08:00 - 2008-01-11 :: 15:28:24:355 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.suggestion - item.severity.label.trivial - Fix or remove TODO. - // TODO better 64-bit support here - *error_msg = apr_psprintf(mp, "Invalid quoted pair at position %d: %s", - (int)(p - text), text); - free(value); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 16:40:15:634 GMT-08:00 - 2008-01-11 :: 16:07:58:168 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.clarity - item.severity.label.trivial - Add parens for clarity. - *d++ = *p++; - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 16:40:43:464 GMT-08:00 - 2008-01-11 :: 16:07:34:306 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.clarity - item.severity.label.trivial - Add parens for clarity. - *d++ = *p++; - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 20:46:50:832 GMT-08:00 - 2008-01-11 :: 16:06:54:324 GMT-08:00 - - brian - brian - apache2/acmp.c - item.type.label.clarity - item.severity.label.trivial - Add parens for clarity. - *ucs_chars++ = *c++; - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 20:47:54:093 GMT-08:00 - 2008-01-11 :: 16:06:02:231 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.clarity - item.severity.label.trivial - Add parens for clarity. - *t++ = *p++; - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 20:48:42:400 GMT-08:00 - 2008-01-11 :: 16:05:23:686 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.clarity - item.severity.label.trivial - Add parens for clarity. - *d++ = *s++; - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 21:42:51:192 GMT-08:00 - 2008-01-07 :: 21:44:12:097 GMT-08:00 - - brian - brian - apache2/apache2_io.c - item.type.label.programLogic - item.severity.label.major - Returning here may fail to free chunks data due to modsecurity_request_body_end() not being called. - int rcbs = modsecurity_request_body_store(msr, buf, buflen, error_msg); - if (rcbs < 0) { - if (rcbs == -5) { - *error_msg = apr_psprintf(msr->mp, "Requests body no files data length is larger than the " - "configured limit (%lu).", msr->txcfg->reqbody_no_files_limit); - return -5; - } - - return -1; - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 21:50:32:890 GMT-08:00 - 2008-01-07 :: 21:52:29:239 GMT-08:00 - - brian - brian - apache2/modsecurity.c - item.type.label.suggestion - item.severity.label.major - Good. This looks to solve the other issues noted as possible memory leaks in body chunk data due to modsecurity_request_body_end() not being called. Need to verify, though. - /* Register TX cleanup */ - apr_pool_cleanup_register(msr->mp, msr, modsecurity_tx_cleanup, apr_pool_cleanup_null); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 21:59:33:579 GMT-08:00 - 2008-01-11 :: 15:29:21:240 GMT-08:00 - - brian - brian - apache2/msc_util.c - item.type.label.suggestion - item.severity.label.trivial - Actually, the parens are *required* for correctness, so remove the comments. - (*invalid_count)++; /* parens quiet compiler warning */ - } - } else { - /* Not enough bytes available, copy the raw bytes. */ - *d++ = input[i++]; - count ++; - (*invalid_count)++; /* parens quiet compiler warning */ - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 22:03:31:138 GMT-08:00 - 2008-01-07 :: 22:04:07:108 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.irrelevant - item.severity.label.trivial - Does not appear to be used anywhere. - /** - * Destroys an engine instance, releasing the consumed memory. - */ -void msre_engine_destroy(msre_engine *engine) { - /* Destroyed automatically by the parent pool. - * apr_pool_destroy(engine->mp); - */ -} - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 22:04:22:398 GMT-08:00 - 2008-01-07 :: 22:04:35:724 GMT-08:00 - - brian - brian - apache2/re.h - item.type.label.irrelevant - item.severity.label.trivial - Does not appear to be used anywhere. - void DSOLOCAL msre_engine_destroy(msre_engine *engine); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 22:23:48:909 GMT-08:00 - 2008-01-11 :: 16:04:30:061 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.clarity - item.severity.label.trivial - This version should be moved up next to the normal version. - #if defined(PERFORMANCE_MEASUREMENT) -apr_status_t msre_ruleset_process_phase(msre_ruleset *ruleset, modsec_rec *msr) { - ... -} - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 22:30:42:215 GMT-08:00 - 2008-01-11 :: 16:02:09:916 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.missing - item.severity.label.major - Hmm, I thought this had already been fixed in trunk. Missing logging phase. Need to fix in 2.1.5 as well. - /** - * Removes from the ruleset all rules that match the given exception. - */ -int msre_ruleset_rule_remove_with_exception(msre_ruleset *ruleset, rule_exception *re) { - int count = 0; - - if (ruleset == NULL) return 0; - - count += msre_ruleset_phase_rule_remove_with_exception(ruleset, re, ruleset->phase_request_headers); - count += msre_ruleset_phase_rule_remove_with_exception(ruleset, re, ruleset->phase_request_body); - count += msre_ruleset_phase_rule_remove_with_exception(ruleset, re, ruleset->phase_response_headers); - count += msre_ruleset_phase_rule_remove_with_exception(ruleset, re, ruleset->phase_response_body); - - return count; -} - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 22:46:51:423 GMT-08:00 - 2008-01-11 :: 16:01:31:111 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.optimization - item.severity.label.trivial - Should move this to a static global for performance. - static const char *const severities[] = { - "EMERGENCY", - "ALERT", - "CRITICAL", - "ERROR", - "WARNING", - "NOTICE", - "INFO", - "DEBUG", - NULL, - }; - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-07 :: 22:49:04:822 GMT-08:00 - 2008-01-07 :: 22:49:16:740 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.suggestion - item.severity.label.trivial - Implement TODO. - //TODO: restrict to 512 bytes - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-07 :: 22:51:40:727 GMT-08:00 - 2008-01-07 :: 22:53:13:118 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.optimization - item.severity.label.trivial - tags set to NULL would be a bit better as it would stop apr_pstrcat() earlier, but tags *must* remain last or wierd results. - char *tags = ""; - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-08 :: 11:44:13:484 GMT-08:00 - 2008-01-08 :: 11:45:29:864 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.optimization - item.severity.label.trivial - This causes two loops through the action list. Perhaps there is a more performant way to do these at the same time? Maybe split into two lists? - /* Perform non-disruptive actions. */ - msre_perform_nondisruptive_actions(msr, rule, rule->actionset, mptmp); - - /* Perform disruptive actions, but only if - * this rule is not part of a chain. - */ - if (rule->actionset->is_chained == 0) { - msre_perform_disruptive_actions(msr, rule, acting_actionset, mptmp, my_error_msg); - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-08 :: 12:16:20:280 GMT-08:00 - 2008-01-11 :: 15:59:48:300 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.irrelevant - item.severity.label.trivial - These do not appear to be needed. - tfnspath = NULL; - tfnskey = NULL; - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-08 :: 12:20:29:491 GMT-08:00 - 2008-01-11 :: 15:59:23:210 GMT-08:00 - - brian - brian - apache2/re.c - item.type.label.programLogic - item.severity.label.major - This does not appear to work as the tfnskey is not being built here. Need to build the tfnskey in this loop for this to work. - /* check cache, saving the 'most complete' */ - crec = (msre_cache_rec *)apr_table_get(cachetab, tfnskey); - if (crec != NULL) { - last_crec = crec; - last_cached_tfn = tfnscount; - } - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-08 :: 21:29:14:889 GMT-08:00 - 2008-01-08 :: 21:30:41:759 GMT-08:00 - - brian - brian - apache2/re_tfns.c - item.type.label.optimization - item.severity.label.trivial - No need to set this on all. Only set it once when we find the first non-space char. - (*rval)[i] = '\0'; - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-08 :: 22:09:10:463 GMT-08:00 - 2008-01-11 :: 14:20:53:411 GMT-08:00 - - brian - brian - apache2/re_variables.c - item.type.label.suggestion - item.severity.label.trivial - Indention off. - return var_simple_generate_ex(var, vartab, mptmp, - apr_pmemdup(mptmp, - msr->matched_var->value, - msr->matched_var->value_len), - msr->matched_var->value_len); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-08 :: 22:09:35:664 GMT-08:00 - 2008-01-11 :: 14:21:28:242 GMT-08:00 - - brian - brian - apache2/re_variables.c - item.type.label.suggestion - item.severity.label.trivial - Indention off. - return var_simple_generate_ex(var, vartab, mptmp, - apr_pmemdup(mptmp, - msr->matched_var->name, - msr->matched_var->name_len), - msr->matched_var->name_len); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 10:55:38:639 GMT-08:00 - 2008-01-11 :: 14:25:15:860 GMT-08:00 - - brian - brian - apache2/acmp.c - item.type.label.suggestion - item.severity.label.trivial - Remove comment. - //return acmp_child_for_code(node, letter) - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 11:01:01:815 GMT-08:00 - 2008-01-11 :: 15:55:50:363 GMT-08:00 - - brian - brian - apache2/acmp.c - item.type.label.suggestion - item.severity.label.trivial - Change to #idef DEBUG_ACMP or similar. - /* printf("%c ->left %c \n", node->node->letter, node->left->node->letter); */ - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 11:01:41:424 GMT-08:00 - 2008-01-11 :: 15:56:10:175 GMT-08:00 - - brian - brian - apache2/acmp.c - item.type.label.suggestion - item.severity.label.trivial - Change to #idef DEBUG_ACMP or similar. - /* printf("%c ->right %c \n", node->node->letter, node->right->node->letter); */ - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 11:02:22:279 GMT-08:00 - 2008-01-11 :: 15:56:41:045 GMT-08:00 - - brian - brian - apache2/acmp.c - item.type.label.suggestion - item.severity.label.trivial - Change to #idef DEBUG_ACMP or similar. - /* printf("fail direction: *%s* => *%s*\n", child->text, child->fail->text); */ - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 11:02:42:897 GMT-08:00 - 2008-01-11 :: 15:54:16:807 GMT-08:00 - - brian - brian - apache2/acmp.c - item.type.label.suggestion - item.severity.label.trivial - Change to #idef DEBUG_ACMP or similar. - /* printf("fail direction: *%s* => *%s*\n", node->text, node->fail->text); */ - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 11:10:25:157 GMT-08:00 - 2008-01-11 :: 14:24:57:212 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - The 'tag' and 'severity' metadata actions should be included. Some actions are missing from the log msg. - /* Must NOT use metadata actions. */ - if ((rule->actionset->id != NOT_SET_P) - ||(rule->actionset->rev != NOT_SET_P) - ||(rule->actionset->msg != NOT_SET_P) - ||(rule->actionset->logdata != NOT_SET_P)) - { - return apr_psprintf(cmd->pool, "ModSecurity: Metadata actions (id, rev, msg) " - " can only be specified by chain starter rules."); - } - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 11:18:38:672 GMT-08:00 - 2008-01-11 :: 14:29:49:134 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Probably should check we were able to allocate. - msre_rule *phrule = apr_palloc(rule->ruleset->mp, sizeof(msre_rule)); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:05:40:949 GMT-08:00 - 2008-01-11 :: 14:30:01:771 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Comment or remove. - TODO - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:06:48:653 GMT-08:00 - 2008-01-11 :: 14:30:40:514 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - ENH instead of TODO - TODO - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:09:17:114 GMT-08:00 - 2008-01-11 :: 14:31:50:812 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - The 'tag' and 'severity' metadata actions should be included. Some actions are missing from the log msg. - /* Must not use metadata actions. */ - if ((dcfg->tmp_default_actionset->id != NOT_SET_P) - ||(dcfg->tmp_default_actionset->rev != NOT_SET_P) - ||(dcfg->tmp_default_actionset->msg != NOT_SET_P) - ||(dcfg->tmp_default_actionset->logdata != NOT_SET_P)) - { - return apr_psprintf(cmd->pool, "ModSecurity: SecDefaultAction must not " - "contain any metadata actions (id, rev, msg)."); - } - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:17:06:712 GMT-08:00 - 2008-01-11 :: 14:33:23:560 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or make ENH - // TODO Validate encoding - // return apr_psprintf(cmd->pool, "ModSecurity: Invalid value for SecRequestBodyAccess: %s", p1); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:17:55:545 GMT-08:00 - 2008-01-09 :: 12:25:33:617 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.irrelevant - item.severity.label.trivial - Remove code? - /* -static const char *cmd_rule_import_by_id(cmd_parms *cmd, void *_dcfg, const char *p1) { - directory_config *dcfg = (directory_config *)_dcfg; - rule_exception *re = apr_pcalloc(cmd->pool, sizeof(rule_exception)); - if (dcfg == NULL) return NULL; - - re->type = RULE_EXCEPTION_IMPORT_ID; - // TODO verify p1 - re->param = p1; - *(rule_exception **)apr_array_push(dcfg->rule_exceptions) = re; - - return NULL; -} - -static const char *cmd_rule_import_by_msg(cmd_parms *cmd, void *_dcfg, const char *p1) { - directory_config *dcfg = (directory_config *)_dcfg; - rule_exception *re = apr_pcalloc(cmd->pool, sizeof(rule_exception)); - if (dcfg == NULL) return NULL; - - re->type = RULE_EXCEPTION_IMPORT_MSG; - // TODO verify p1 - re->param = p1; - *(rule_exception **)apr_array_push(dcfg->rule_exceptions) = re; - - return NULL; -} -*/ - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 12:18:34:399 GMT-08:00 - 2008-01-11 :: 14:34:07:673 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Fix or TODO->ENH - // TODO enforce format (letters, digits, ., _, -) - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:20:16:234 GMT-08:00 - 2008-01-11 :: 14:40:53:633 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Need to allow for relative filename based of rule file. - /* -- Geo Lookup configuration -- */ - -static const char *cmd_geo_lookup_db(cmd_parms *cmd, void *_dcfg, - const char *p1) -{ - char *error_msg; - directory_config *dcfg = (directory_config *)_dcfg; - if (dcfg == NULL) return NULL; - - if (geo_init(dcfg, p1, &error_msg) <= 0) { - return error_msg; - } - - return NULL; -} - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:22:58:798 GMT-08:00 - 2008-01-09 :: 12:23:11:462 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Portable? - /* The NOT_SET indicator is -1, a signed long, and therfore - * we cannot be >= the unsigned value of NOT_SET. - */ - if ((unsigned long)intval >= (unsigned long)NOT_SET) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations minlen must be less than: %lu", (unsigned long)NOT_SET); - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 12:23:33:676 GMT-08:00 - 2008-01-09 :: 12:23:39:437 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Portable? - /* The NOT_SET indicator is -1, a signed long, and therfore - * we cannot be >= the unsigned value of NOT_SET. - */ - if ((unsigned long)intval >= (unsigned long)NOT_SET) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations maxlen must be less than: %lu", (unsigned long)NOT_SET); - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 12:24:06:001 GMT-08:00 - 2008-01-09 :: 12:24:23:994 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Could use strtol as Ivan has as well. - intval = apr_atoi64(charval); - if (errno == ERANGE) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations minlen out of range: %s", charval); - } - if (intval < 0) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations minlen must be positive: %s", charval); - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 12:24:37:453 GMT-08:00 - 2008-01-09 :: 12:24:42:462 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Could use strtol as Ivan has as well. - intval = apr_atoi64(charval); - if (errno == ERANGE) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations maxlen out of range: %s", charval); - } - if (intval < 0) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations maxlen must be positive: %s", charval); - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 12:25:36:799 GMT-08:00 - 2008-01-09 :: 12:31:35:264 GMT-08:00 - - brian - brian - apache2/apache2_io.c - item.type.label.programLogic - item.severity.label.major - Remove code? It is actually used below, so need to verify. - #if 0 -static void dummy_free_func(void *data) {} -#endif - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 12:27:10:252 GMT-08:00 - 2008-01-09 :: 12:29:31:617 GMT-08:00 - - brian - brian - apache2/apache2_io.c - item.type.label.programLogic - item.severity.label.major - dummy_free_func() is defined where? It is ifdef'd out at the top of source, so need to verify it is valid. - /* Do not make a copy of the data we received in the chunk. */ - bucket = apr_bucket_heap_create(chunk->data, chunk->length, dummy_free_func, - f->r->connection->bucket_alloc); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 12:35:21:613 GMT-08:00 - 2008-01-09 :: 13:02:40:668 GMT-08:00 - - brian - brian - apache2/apache2_io.c - item.type.label.suggestion - item.severity.label.trivial - Yes, why do we ignore the rc - why have one at all? - // TODO: Why ignore the return code here? - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 12:55:19:633 GMT-08:00 - 2008-01-11 :: 17:00:04:416 GMT-08:00 - - brian - brian - apache2/msc_reqbody.c - item.type.label.suggestion - item.severity.label.trivial - Portable way to format sizeof()? - *error_msg = apr_psprintf(msr->mp, "Input filter: Failed to allocate %lu bytes for request body chunk.", (unsigned long)sizeof(msc_data_chunk)); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:55:39:585 GMT-08:00 - 2008-01-11 :: 16:58:16:438 GMT-08:00 - - brian - brian - apache2/msc_reqbody.c - item.type.label.suggestion - item.severity.label.trivial - Portable way to format sizeof()? - *error_msg = apr_psprintf(msr->mp, "Failed to allocate %lu bytes for request body disk chunk.", (unsigned long)sizeof(msc_data_chunk)); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:56:05:302 GMT-08:00 - 2008-01-11 :: 16:57:58:049 GMT-08:00 - - brian - brian - apache2/msc_reqbody.c - item.type.label.suggestion - item.severity.label.trivial - Portable way to format sizeof()? - *error_msg = apr_psprintf(msr->mp, "Failed to allocate %lu bytes for request body disk chunk.", (unsigned long)sizeof(msc_data_chunk)); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:56:51:734 GMT-08:00 - 2008-01-11 :: 14:41:50:773 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or change to ENH. - // TODO check whether the parameter is a valid MIME type of "null" - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:58:11:331 GMT-08:00 - 2008-01-11 :: 14:42:59:645 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or change to ENH. - AP_INIT_TAKE1 ( - "SecAction", - cmd_action, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:58:29:461 GMT-08:00 - 2008-01-11 :: 14:46:15:813 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or change to ENH. - AP_INIT_TAKE1 ( - "SecDataDir", - cmd_data_dir, - NULL, - CMD_SCOPE_MAIN, - "" // TODO - ), - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:58:45:647 GMT-08:00 - 2008-01-11 :: 14:46:51:173 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or change to ENH. - AP_INIT_TAKE1 ( - "SecDefaultAction", - cmd_default_action, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:59:03:959 GMT-08:00 - 2008-01-11 :: 14:47:05:294 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or change to ENH. - AP_INIT_TAKE1 ( - "SecResponseBodyLimit", - cmd_response_body_limit, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 12:59:17:580 GMT-08:00 - 2008-01-11 :: 14:49:00:349 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or change to ENH. - AP_INIT_TAKE1 ( - "SecResponseBodyLimitAction", - cmd_response_body_limit_action, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 13:00:04:205 GMT-08:00 - 2008-01-11 :: 14:50:22:367 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or change to ENH. - AP_INIT_TAKE23 ( - "SecRule", - cmd_rule, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 13:00:30:606 GMT-08:00 - 2008-01-11 :: 14:51:16:772 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or change to ENH. - AP_INIT_TAKE12 ( - "SecRuleScript", - cmd_rule_script, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - AP_INIT_ITERATE ( - "SecRuleRemoveById", - cmd_rule_remove_by_id, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - AP_INIT_ITERATE ( - "SecRuleRemoveByMsg", - cmd_rule_remove_by_msg, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 13:00:56:319 GMT-08:00 - 2008-01-11 :: 14:52:48:192 GMT-08:00 - - brian - brian - apache2/apache2_config.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or change to ENH. - AP_INIT_TAKE1 ( - "SecTmpDir", - cmd_tmp_dir, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - AP_INIT_TAKE1 ( - "SecUploadDir", - cmd_upload_dir, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - AP_INIT_TAKE1 ( - "SecUploadKeepFiles", - cmd_upload_keep_files, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - AP_INIT_TAKE1 ( - "SecWebAppId", - cmd_web_app_id, - NULL, - CMD_SCOPE_ANY, - "" // TODO - ), - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 13:01:32:996 GMT-08:00 - 2008-01-11 :: 14:54:32:209 GMT-08:00 - - brian - brian - apache2/mod_security2.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or change to ENH. - /* Update the request headers. They might have changed after - * the body was read (trailers). - */ - // TODO We still need to keep a copy of the original headers - // to log in the audit log. - msr->request_headers = apr_table_copy(msr->mp, r->headers_in); - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 13:02:05:035 GMT-08:00 - 2008-01-09 :: 13:02:47:482 GMT-08:00 - - brian - brian - apache2/modsecurity.c - item.type.label.suggestion - item.severity.label.trivial - Yes, why do we ignore the rc - why have one at all? - // TODO: Why do we ignore return code here? - modsecurity_request_body_clear(msr, &my_error_msg); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:03:24:928 GMT-08:00 - 2008-01-09 :: 13:04:49:633 GMT-08:00 - - brian - brian - apache2/msc_geo.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO. - offset = -3; - apr_file_seek(geo->db, APR_END, &offset); - /* TODO check offset */ - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:04:20:937 GMT-08:00 - 2008-01-09 :: 13:04:39:295 GMT-08:00 - - brian - brian - apache2/msc_geo.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO. - rc = apr_file_read_full(geo->db, &buf, 1, &nbytes); - /* TODO: check rc */ - geo->dbtype = (int)buf[0]; - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:05:16:204 GMT-08:00 - 2008-01-09 :: 13:05:27:720 GMT-08:00 - - brian - brian - apache2/msc_geo.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO. - apr_file_seek(geo->db, APR_SET, &seekto); - /* TODO: check rc */ - rc = apr_file_read_full(geo->db, &buf, (2 * reclen), &nbytes); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:05:58:953 GMT-08:00 - 2008-01-09 :: 13:06:03:494 GMT-08:00 - - brian - brian - apache2/msc_geo.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO. - apr_file_seek(geo->db, APR_SET, &seekto); - /* TODO: check rc */ - rc = apr_file_read_full(geo->db, &cbuf, sizeof(cbuf), &nbytes); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:06:45:422 GMT-08:00 - 2008-01-11 :: 14:55:10:355 GMT-08:00 - - brian - brian - apache2/msc_logging.c - item.type.label.suggestion - item.severity.label.trivial - Fix TODO or change to ENH. - /* The audit log storage directory should be explicitly - * defined. But if it isn't try to write to the same - * directory where the index file is placed. Of course, - * it is *very* bad practice to allow the Apache user - * to write to the same directory where a root user is - * writing to but it's not us that's causing the problem - * and there isn't anything we can do about that. - * - * TODO Actually there is something we can do! We will make - * SecAuditStorageDir mandatory, ask the user to explicitly - * define the storage location *and* refuse to work if the - * index and the storage location are in the same folder. - */ - if (msr->txcfg->auditlog_storage_dir == NULL) { - entry_filename = file_dirname(msr->mp, msr->txcfg->auditlog_name); - } - else { - entry_filename = msr->txcfg->auditlog_storage_dir; - } - if (entry_filename == NULL) return; - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 13:07:22:398 GMT-08:00 - 2008-01-11 :: 14:55:42:896 GMT-08:00 - - brian - brian - apache2/msc_logging.c - item.type.label.suggestion - item.severity.label.trivial - Change TODO to ENH. - /* AUDITLOG_PART_UPLOADS */ - // TODO: Implement - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 13:08:02:613 GMT-08:00 - 2008-01-11 :: 15:51:28:546 GMT-08:00 - - brian - brian - apache2/msc_lua.c - item.type.label.missing - item.severity.label.trivial - Log an error. - } else { - // TODO Error - return NULL; - } - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 13:08:51:978 GMT-08:00 - 2008-01-09 :: 13:09:44:680 GMT-08:00 - - brian - brian - apache2/msc_util.c - item.type.label.suggestion - item.severity.label.normal - Fix TODO. - char *resolve_relative_path(apr_pool_t *pool, const char *parent_filename, const char *filename) { - if (filename == NULL) return NULL; - // TODO Support paths on operating systems other than Unix. - if (filename[0] == '/') return (char *)filename; - - return apr_pstrcat(pool, apr_pstrndup(pool, parent_filename, - strlen(parent_filename) - strlen(apr_filepath_name_get(parent_filename))), - filename, NULL); -} - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:10:22:786 GMT-08:00 - 2008-01-09 :: 13:10:31:982 GMT-08:00 - - brian - brian - apache2/pdf_protect.c - item.type.label.suggestion - item.severity.label.trivial - Change from TODO to ENH. - // TODO We need ID and REV values for the PDF XSS alert. - -// TODO It would be nice if the user could choose the ID/REV/SEVERITY/MESSAGE, etc. - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:10:53:181 GMT-08:00 - 2008-01-09 :: 13:11:06:931 GMT-08:00 - - brian - brian - apache2/pdf_protect.c - item.type.label.suggestion - item.severity.label.trivial - Change from TODO to ENH. - // TODO Should we look at err_headers_out too? - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:11:23:251 GMT-08:00 - 2008-01-09 :: 13:11:28:132 GMT-08:00 - - brian - brian - apache2/pdf_protect.c - item.type.label.suggestion - item.severity.label.trivial - Change from TODO to ENH. - // TODO application/x-pdf, application/vnd.fdf, application/vnd.adobe.xfdf, - // application/vnd.adobe.xdp+xml, application/vnd.adobe.xfd+xml, application/vnd.pdf - // application/acrobat, text/pdf, text/x-pdf ??? - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:11:54:942 GMT-08:00 - 2008-01-09 :: 13:12:24:617 GMT-08:00 - - brian - brian - apache2/pdf_protect.c - item.type.label.missing - item.severity.label.trivial - Add the missing alert. - // TODO Log alert - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:13:04:159 GMT-08:00 - 2008-01-09 :: 13:13:38:064 GMT-08:00 - - brian - brian - apache2/re_actions.c - item.type.label.suggestion - item.severity.label.trivial - Not positive why the TODO here. Perhaps for a decision as to log and/or at what level? - msr_log(msr, 4, "Ctl: Set auditEngine to %d.", msr->txcfg->auditlog_flag); // TODO - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:14:02:379 GMT-08:00 - 2008-01-11 :: 15:42:21:749 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.suggestion - item.severity.label.trivial - Change from TODO to ENH. - // TODO Write & use string_ends(s, e). - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 13:14:29:571 GMT-08:00 - 2008-01-11 :: 15:43:53:997 GMT-08:00 - - brian - brian - apache2/re_operators.c - item.type.label.suggestion - item.severity.label.trivial - Remove the ifdef as lua is required? - #ifdef WITH_LUA - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 13:17:47:759 GMT-08:00 - 2008-01-11 :: 15:41:12:538 GMT-08:00 - - brian - brian - CHANGES - item.type.label.suggestion - item.severity.label.trivial - Remove TODO. - TODO: more to come - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 13:35:00:891 GMT-08:00 - 2008-01-09 :: 13:35:40:975 GMT-08:00 - - brian - brian - apache2/modsecurity.h - item.type.label.optimization - item.severity.label.trivial - Need to re-test implementing this as just a table. - /* data cache */ - apr_hash_t *tcache; - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 13:37:04:264 GMT-08:00 - 2008-01-09 :: 13:37:25:196 GMT-08:00 - - brian - brian - apache2/modsecurity.h - item.type.label.suggestion - item.severity.label.trivial - Should probably use STRINGIFY and define the numeric value. - #define MODSEC_VERSION_MAJOR "2" -#define MODSEC_VERSION_MINOR "5" -#define MODSEC_VERSION_MAINT "0" -#define MODSEC_VERSION_TYPE "rc" -#define MODSEC_VERSION_RELEASE "1" - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 14:08:14:025 GMT-08:00 - 2008-01-11 :: 15:40:12:054 GMT-08:00 - - brian - brian - apache2/msc_logging.c - item.type.label.suggestion - item.severity.label.trivial - Spelling. - throught - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-09 :: 14:21:32:782 GMT-08:00 - 2008-01-09 :: 14:22:32:803 GMT-08:00 - - brian - brian - apache2/msc_geo.h - item.type.label.suggestion - item.severity.label.trivial - This value may not be portable based on endianness. The algorithm compares it to the IP address as int in host order. - #define GEO_COUNTRY_OFFSET 0xffff00 - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 14:31:25:720 GMT-08:00 - 2008-01-09 :: 14:45:20:612 GMT-08:00 - - brian - brian - apache2/msc_geo.c - item.type.label.suggestion - item.severity.label.trivial - Check portability due to endianness. It seems that the DB values are assumed to be in host order. Perhaps the compiled DB is little-endian and we need to compensate? - - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 15:28:14:563 GMT-08:00 - 2008-01-09 :: 15:28:24:203 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.irrelevant - item.severity.label.trivial - Remove code? - #if 0 -static char *multipart_construct_filename(modsec_rec *msr) { - char c, *p, *q = msr->mpd->mpp->filename; - char *filename; - - /* find the last backward slash and consider the - * filename to be only what's right from it - */ - p = strrchr(q, '\\'); - if (p != NULL) q = p + 1; - - /* do the same for the forward slash */ - p = strrchr(q, '/'); - if (p != NULL) q = p + 1; - - /* allow letters, digits and dots, replace - * everything else with underscores - */ - p = filename = apr_pstrdup(msr->mp, q); - while((c = *p) != 0) { - if (!( isalnum(c)||(c == '.') )) *p = '_'; - p++; - } - - return filename; -} -#endif - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 15:35:50:978 GMT-08:00 - 2008-01-09 :: 15:49:54:128 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.programLogic - item.severity.label.trivial - The multipart C-D header is case insensitive (rfc 2183), so we should probably use strncasecmp() here. - /* accept only what we understand */ - if (strncmp(c_d_value, "form-data", 9) != 0) { - return -1; - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 16:05:05:601 GMT-08:00 - 2008-01-09 :: 16:07:17:436 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.suggestion - item.severity.label.trivial - This allows for a name of "", so maybe check for name[0] == '\0' and return an error. Although we catch this later on as an unrecognized name and return -10. - start = p; - while((*p != '\0')&&(*p != '=')&&(*p != '\t')&&(*p != ' ')) p++; - if (*p == '\0') return -4; - - name = apr_pstrmemdup(msr->mp, start, (p - start)); - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 16:14:36:307 GMT-08:00 - 2008-01-09 :: 17:02:47:324 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.suggestion - item.severity.label.trivial - For a quoted value we just include everything until the end quote. The field values should be US-ASCII 'qtext' or 'quoted-pair' (RFC 822) or escaped using RFC 2047. - if (*p == '"') { - *t = '\0'; - break; - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 16:59:12:520 GMT-08:00 - 2008-01-09 :: 17:00:55:566 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.suggestion - item.severity.label.trivial - I think this is wrong. RFC 822 defines a quoted-string as <"> *(qtext/quoted-pair) <"> and quoted-par being able to quote any CHAR. - /* only " and \ can be escaped */ - if ((*(p + 1) == '"')||(*(p + 1) == '\\')) { - p++; - } - else { - /* improper escaping */ - - /* We allow for now because IE sends - * improperly escaped content and there's - * nothing we can do about it. - * - * return -9; - */ - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-09 :: 17:04:30:357 GMT-08:00 - 2008-01-09 :: 17:05:19:369 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.suggestion - item.severity.label.trivial - RFC 2045 defines an 'attribute' as "ALWAYS case-insensitive", so these should be strncasecmp() - if (strcmp(name, "name") == 0) { - if (msr->mpd->mpp->name != NULL) return -14; - msr->mpd->mpp->name = value; - - if (msr->txcfg->debuglog_level >= 9) { - msr_log(msr, 9, "Multipart: Content-Disposition name: %s", - log_escape_nq(msr->mp, value)); - } - } - else - if (strcmp(name, "filename") == 0) { - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-10 :: 12:24:59:317 GMT-08:00 - 2008-01-11 :: 16:58:44:275 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.suggestion - item.severity.label.trivial - len is always assumed to be at least 1. What is preventing a len of 0? - if (len > 1) { - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-10 :: 12:27:34:472 GMT-08:00 - 2008-01-11 :: 15:39:17:001 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.suggestion - item.severity.label.trivial - Use MULTIPART_BUF_SIZE for the constant. - if (strlen(new_value) > 4096) { - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-10 :: 13:04:27:048 GMT-08:00 - 2008-01-10 :: 13:04:57:229 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.suggestion - item.severity.label.trivial - Cannot find anything that supports that this is or is not allowed. - /* Flag for whitespace after parameter name. */ - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-10 :: 13:05:06:226 GMT-08:00 - 2008-01-10 :: 13:05:11:552 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.suggestion - item.severity.label.trivial - Cannot find anything that supports that this is or is not allowed. - /* Flag for whitespace before parameter value. */ - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-10 :: 13:12:20:299 GMT-08:00 - 2008-01-11 :: 15:38:39:261 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.suggestion - item.severity.label.trivial - Use '\r' vs 0x0d as is done elsewhere. - if ((c == 0x0d)&&(msr->mpd->bufleft == 1)) { - /* we don't want to take 0x0d as the last byte in the buffer */ - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-10 :: 13:12:54:295 GMT-08:00 - 2008-01-11 :: 15:36:43:726 GMT-08:00 - - brian - brian - apache2/msc_multipart.c - item.type.label.suggestion - item.severity.label.trivial - Use '\n' vs 0x0a as is done elsewhere. - if ((c == 0x0a)||(msr->mpd->bufleft == 0)||(process_buffer)) { - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-10 :: 13:19:16:539 GMT-08:00 - 2008-01-11 :: 15:35:53:104 GMT-08:00 - - brian - brian - apache2/msc_parsers.c - item.type.label.suggestion - item.severity.label.trivial - Headers are not used. I think they were added for iconv support, but Ivan removed it. - #include "iconv.h" -#include <errno.h> - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-10 :: 13:26:56:609 GMT-08:00 - 2008-01-10 :: 13:27:21:817 GMT-08:00 - - brian - brian - apache2/msc_util.c - item.type.label.suggestion - item.severity.label.trivial - Be more consistent in naming. - #define VALID_HEX(X) (((X >= '0')&&(X <= '9')) || ((X >= 'a')&&(X <= 'f')) || ((X >= 'A')&&(X <= 'F'))) -#define ISODIGIT(X) ((X >= '0')&&(X <= '7')) - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-10 :: 13:32:29:278 GMT-08:00 - 2008-01-11 :: 16:51:13:950 GMT-08:00 - - brian - brian - apache2/msc_util.c - item.type.label.optimization - item.severity.label.trivial - No need to do a strlen twice *and* loop through the string. Just loop and exit on non-space. - if (strlen(string) == 0) return 1; - - for(i = 0; i < strlen(string); i++) { - if (!isspace(string[i])) { - return 0; - } - } - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - - 2008-01-10 :: 13:35:40:307 GMT-08:00 - 2008-01-10 :: 13:36:03:933 GMT-08:00 - - brian - brian - apache2/modsecurity.c - item.type.label.irrelevant - item.severity.label.trivial - Remove commented code? - /* Serial audit log mutext */ - rc = apr_global_mutex_create(&msce->auditlog_lock, NULL, APR_LOCK_DEFAULT, mp); - if (rc != APR_SUCCESS) { - //ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "mod_security: Could not create modsec_auditlog_lock"); - //return HTTP_INTERNAL_SERVER_ERROR; - return -1; - } - - #ifdef __SET_MUTEX_PERMS - rc = unixd_set_global_mutex_perms(msce->auditlog_lock); - if (rc != APR_SUCCESS) { - // ap_log_error(APLOG_MARK, APLOG_ERR, rc, s, "mod_security: Could not set permissions on modsec_auditlog_lock; check User and Group directives"); - // return HTTP_INTERNAL_SERVER_ERROR; - return -1; - } - #endif - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-10 :: 13:36:28:229 GMT-08:00 - 2008-01-10 :: 13:36:52:702 GMT-08:00 - - brian - brian - apache2/modsecurity.c - item.type.label.suggestion - item.severity.label.trivial - What *should* we do on error here? - if (rc != APR_SUCCESS) { - // ap_log_error(APLOG_MARK, APLOG_ERR, rs, s, "Failed to child-init auditlog mutex"); - } - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-10 :: 13:37:17:326 GMT-08:00 - 2008-01-10 :: 13:37:25:682 GMT-08:00 - - brian - brian - apache2/modsecurity.c - item.type.label.suggestion - item.severity.label.trivial - This does nothing. - /** - * Releases resources held by engine instance. - */ -void modsecurity_shutdown(msc_engine *msce) { - if (msce == NULL) return; -} - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-10 :: 13:39:01:265 GMT-08:00 - 2008-01-10 :: 13:39:22:070 GMT-08:00 - - brian - brian - apache2/modsecurity.c - item.type.label.suggestion - item.severity.label.trivial - Figure out the optimal initial size for the arrays/tables. - /* Collections. */ - msr->tx_vars = apr_table_make(msr->mp, 32); - if (msr->tx_vars == NULL) return -1; - - msr->geo_vars = apr_table_make(msr->mp, 8); - if (msr->geo_vars == NULL) return -1; - - msr->collections = apr_table_make(msr->mp, 8); - if (msr->collections == NULL) return -1; - msr->collections_dirty = apr_table_make(msr->mp, 8); - if (msr->collections_dirty == NULL) return -1; - - /* Other */ - msr->tcache = apr_hash_make(msr->mp); - if (msr->tcache == NULL) return -1; - - msr->matched_rules = apr_array_make(msr->mp, 16, sizeof(void *)); - if (msr->matched_rules == NULL) return -1; - - msr->matched_var = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string)); - if (msr->matched_var == NULL) return -1; - - msr->highest_severity = 255; /* high, invalid value */ - - msr->removed_rules = apr_array_make(msr->mp, 16, sizeof(char *)); - if (msr->removed_rules == NULL) return -1; - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-10 :: 13:42:33:518 GMT-08:00 - 2008-01-10 :: 13:42:50:351 GMT-08:00 - - brian - brian - apache2/msc_xml.c - item.type.label.suggestion - item.severity.label.trivial - Remove #if 0'd code? - #if 0 -static void xml_receive_sax_error(void *data, const char *msg, ...) { - modsec_rec *msr = (modsec_rec *)data; - char message[256]; - - if (msr == NULL) return; - - apr_snprintf(message, sizeof(message), "%s (line %d offset %d)", - log_escape_nq(msr->mp, msr->xml->parsing_ctx->lastError.message), - msr->xml->parsing_ctx->lastError.line, - msr->xml->parsing_ctx->lastError.int2); - - msr_log(msr, 5, "XML: Parsing error: %s", message); -} -#endif - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-10 :: 13:54:16:193 GMT-08:00 - 2008-01-10 :: 13:54:45:610 GMT-08:00 - - brian - brian - apache2/mod_security2.c - item.type.label.suggestion - item.severity.label.trivial - What is the history of this? - /* Our own hook to handle RPC transactions (not used at the moment). - * // ap_hook_handler(hook_handler, NULL, NULL, APR_HOOK_MIDDLE); - */ - - - item.resolution.label.validNeedsfixing - item.status.label.open - - - - 2008-01-10 :: 13:56:58:413 GMT-08:00 - 2008-01-11 :: 15:34:14:676 GMT-08:00 - - brian - brian - apache2/msc_lua.c - item.type.label.suggestion - item.severity.label.trivial - Change C++ to C style comment. - // Get the response from the script. - - - item.resolution.label.validNeedsfixing - item.status.label.resolved - - - diff --git a/review/pre-2.5-brian.txt b/review/pre-2.5-brian.txt deleted file mode 100644 index 3f2f49f9..00000000 --- a/review/pre-2.5-brian.txt +++ /dev/null @@ -1,982 +0,0 @@ -File: apache2/apache2_config.c -=================================================================== -[brian] Irrelevant @ 1251 - -Remove code? - -/* -static const char *cmd_rule_import_by_id(cmd_parms *cmd, void *_dcfg, const char *p1) { - directory_config *dcfg = (directory_config *)_dcfg; - rule_exception *re = apr_pcalloc(cmd->pool, sizeof(rule_exception)); - if (dcfg == NULL) return NULL; - - re->type = RULE_EXCEPTION_IMPORT_ID; - // TODO verify p1 - re->param = p1; - *(rule_exception **)apr_array_push(dcfg->rule_exceptions) = re; - - return NULL; -} - -static const char *cmd_rule_import_by_msg(cmd_parms *cmd, void *_dcfg, const char *p1) { - directory_config *dcfg = (directory_config *)_dcfg; - rule_exception *re = apr_pcalloc(cmd->pool, sizeof(rule_exception)); - if (dcfg == NULL) return NULL; - - re->type = RULE_EXCEPTION_IMPORT_MSG; - // TODO verify p1 - re->param = p1; - *(rule_exception **)apr_array_push(dcfg->rule_exceptions) = re; - - return NULL; -} -*/ - - -[brian] Suggestion @ 1514 - -Could use strtol as Ivan has as well. - -intval = apr_atoi64(charval); - if (errno == ERANGE) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations minlen out of range: %s", charval); - } - if (intval < 0) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations minlen must be positive: %s", charval); - } - - -[brian] Suggestion @ 1522 - -Portable? - -/* The NOT_SET indicator is -1, a signed long, and therfore - * we cannot be >= the unsigned value of NOT_SET. - */ - if ((unsigned long)intval >= (unsigned long)NOT_SET) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations minlen must be less than: %lu", (unsigned long)NOT_SET); - } - - -[brian] Suggestion @ 1534 - -Could use strtol as Ivan has as well. - -intval = apr_atoi64(charval); - if (errno == ERANGE) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations maxlen out of range: %s", charval); - } - if (intval < 0) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations maxlen must be positive: %s", charval); - } - - -[brian] Suggestion @ 1542 - -Portable? - -/* The NOT_SET indicator is -1, a signed long, and therfore - * we cannot be >= the unsigned value of NOT_SET. - */ - if ((unsigned long)intval >= (unsigned long)NOT_SET) { - return apr_psprintf(cmd->pool, "ModSecurity: SecCacheTransformations maxlen must be less than: %lu", (unsigned long)NOT_SET); - } - - - -File: apache2/apache2_io.c -=================================================================== -[brian] ProgramLogic @ 17 - -Remove code? It is actually used below, so need to verify. - -#if 0 -static void dummy_free_func(void *data) {} -#endif - - -[brian] ProgramLogic @ 92 - -dummy_free_func() is defined where? It is ifdef'd out at the top of source, so need to verify it is valid. - -/* Do not make a copy of the data we received in the chunk. */ - bucket = apr_bucket_heap_create(chunk->data, chunk->length, dummy_free_func, - f->r->connection->bucket_alloc); - - -[brian] ProgramLogic @ 224 - -Returning here may fail to free chunks data due to modsecurity_request_body_end() not being called. - -int rcbs = modsecurity_request_body_store(msr, buf, buflen, error_msg); - if (rcbs < 0) { - if (rcbs == -5) { - *error_msg = apr_psprintf(msr->mp, "Requests body no files data length is larger than the " - "configured limit (%lu).", msr->txcfg->reqbody_no_files_limit); - return -5; - } - - return -1; - } - - -[brian] Suggestion @ 246 - -Yes, why do we ignore the rc - why have one at all? - -// TODO: Why ignore the return code here? - - - -File: apache2/mod_security2.c -=================================================================== -[brian] Suggestion @ 1074 - -What is the history of this? - -/* Our own hook to handle RPC transactions (not used at the moment). - * // ap_hook_handler(hook_handler, NULL, NULL, APR_HOOK_MIDDLE); - */ - - - -File: apache2/modsecurity.c -=================================================================== -[brian] Irrelevant @ 100 - -Remove commented code? - -/* Serial audit log mutext */ - rc = apr_global_mutex_create(&msce->auditlog_lock, NULL, APR_LOCK_DEFAULT, mp); - if (rc != APR_SUCCESS) { - //ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "mod_security: Could not create modsec_auditlog_lock"); - //return HTTP_INTERNAL_SERVER_ERROR; - return -1; - } - - #ifdef __SET_MUTEX_PERMS - rc = unixd_set_global_mutex_perms(msce->auditlog_lock); - if (rc != APR_SUCCESS) { - // ap_log_error(APLOG_MARK, APLOG_ERR, rc, s, "mod_security: Could not set permissions on modsec_auditlog_lock; check User and Group directives"); - // return HTTP_INTERNAL_SERVER_ERROR; - return -1; - } - #endif - - -[brian] Suggestion @ 126 - -What *should* we do on error here? - -if (rc != APR_SUCCESS) { - // ap_log_error(APLOG_MARK, APLOG_ERR, rs, s, "Failed to child-init auditlog mutex"); - } - - -[brian] Suggestion @ 132 - -This does nothing. - -/** - * Releases resources held by engine instance. - */ -void modsecurity_shutdown(msc_engine *msce) { - if (msce == NULL) return; -} - - -[brian] Suggestion @ 178 - -Yes, why do we ignore the rc - why have one at all? - -// TODO: Why do we ignore return code here? - modsecurity_request_body_clear(msr, &my_error_msg); - - -[brian] Suggestion @ 196 - -Good. This looks to solve the other issues noted as possible memory leaks in body chunk data due to modsecurity_request_body_end() not being called. Need to verify, though. - -/* Register TX cleanup */ - apr_pool_cleanup_register(msr->mp, msr, modsecurity_tx_cleanup, apr_pool_cleanup_null); - - -[brian] Suggestion @ 298 - -Figure out the optimal initial size for the arrays/tables. - -/* Collections. */ - msr->tx_vars = apr_table_make(msr->mp, 32); - if (msr->tx_vars == NULL) return -1; - - msr->geo_vars = apr_table_make(msr->mp, 8); - if (msr->geo_vars == NULL) return -1; - - msr->collections = apr_table_make(msr->mp, 8); - if (msr->collections == NULL) return -1; - msr->collections_dirty = apr_table_make(msr->mp, 8); - if (msr->collections_dirty == NULL) return -1; - - /* Other */ - msr->tcache = apr_hash_make(msr->mp); - if (msr->tcache == NULL) return -1; - - msr->matched_rules = apr_array_make(msr->mp, 16, sizeof(void *)); - if (msr->matched_rules == NULL) return -1; - - msr->matched_var = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string)); - if (msr->matched_var == NULL) return -1; - - msr->highest_severity = 255; /* high, invalid value */ - - msr->removed_rules = apr_array_make(msr->mp, 16, sizeof(char *)); - if (msr->removed_rules == NULL) return -1; - - - -File: apache2/modsecurity.h -=================================================================== -[brian] Suggestion @ 63 - -Should probably use STRINGIFY and define the numeric value. - -#define MODSEC_VERSION_MAJOR "2" -#define MODSEC_VERSION_MINOR "5" -#define MODSEC_VERSION_MAINT "0" -#define MODSEC_VERSION_TYPE "rc" -#define MODSEC_VERSION_RELEASE "1" - - -[brian] Optimization @ 363 - -Need to re-test implementing this as just a table. - -/* data cache */ - apr_hash_t *tcache; - - - -File: apache2/msc_geo.c -=================================================================== -[brian] Suggestion - -Check portability due to endianness. It seems that the DB values are assumed to be in host order. Perhaps the compiled DB is little-endian and we need to compensate? - - -[brian] Suggestion @ 153 - -Fix TODO. - -offset = -3; - apr_file_seek(geo->db, APR_END, &offset); - /* TODO check offset */ - - -[brian] Suggestion @ 176 - -Fix TODO. - -rc = apr_file_read_full(geo->db, &buf, 1, &nbytes); - /* TODO: check rc */ - geo->dbtype = (int)buf[0]; - - -[brian] Suggestion @ 325 - -Fix TODO. - -apr_file_seek(geo->db, APR_SET, &seekto); - /* TODO: check rc */ - rc = apr_file_read_full(geo->db, &buf, (2 * reclen), &nbytes); - - -[brian] Suggestion @ 374 - -Fix TODO. - -apr_file_seek(geo->db, APR_SET, &seekto); - /* TODO: check rc */ - rc = apr_file_read_full(geo->db, &cbuf, sizeof(cbuf), &nbytes); - - - -File: apache2/msc_geo.h -=================================================================== -[brian] Suggestion @ 16 - -This value may not be portable based on endianness. The algorithm compares it to the IP address as int in host order. - -#define GEO_COUNTRY_OFFSET 0xffff00 - - - -File: apache2/msc_logging.c -=================================================================== -[brian] ProgramLogic @ 235 - -This allows an empty string as a valid part. This misvalidates "ctl:auditLogParts=+", etc. - -is_valid_parts_specification - - -[brian] Suggestion @ 432 - -apr_dir_make_recursive will attempt to create the dir straight away and if that fails keep backing off a dir until it can start creating, so I see no need to cache. Besides, what happens if you cache, then someone deletes the path from outside apache? - -/* IMP1 Surely it would be more efficient to check the folders for - * the audit log repository base path in the configuration phase, to reduce - * the work we do on every request. Also, since our path depends on time, - * we could cache the time we last checked and don't check if we know - * the folder is there. - */ - rc = apr_dir_make_recursive(entry_basename, CREATEMODE_DIR, msr->mp); - - - -File: apache2/msc_multipart.c -=================================================================== -[brian] Irrelevant @ 18 - -Remove code? - -#if 0 -static char *multipart_construct_filename(modsec_rec *msr) { - char c, *p, *q = msr->mpd->mpp->filename; - char *filename; - - /* find the last backward slash and consider the - * filename to be only what's right from it - */ - p = strrchr(q, '\\'); - if (p != NULL) q = p + 1; - - /* do the same for the forward slash */ - p = strrchr(q, '/'); - if (p != NULL) q = p + 1; - - /* allow letters, digits and dots, replace - * everything else with underscores - */ - p = filename = apr_pstrdup(msr->mp, q); - while((c = *p) != 0) { - if (!( isalnum(c)||(c == '.') )) *p = '_'; - p++; - } - - return filename; -} -#endif - - -[brian] ProgramLogic @ 52 - -The multipart C-D header is case insensitive (rfc 2183), so we should probably use strncasecmp() here. - -/* accept only what we understand */ - if (strncmp(c_d_value, "form-data", 9) != 0) { - return -1; - } - - -[brian] Suggestion @ 75 - -This allows for a name of "", so maybe check for name[0] == '\0' and return an error. Although we catch this later on as an unrecognized name and return -10. - -start = p; - while((*p != '\0')&&(*p != '=')&&(*p != '\t')&&(*p != ' ')) p++; - if (*p == '\0') return -4; - - name = apr_pstrmemdup(msr->mp, start, (p - start)); - - -[brian] Suggestion @ 106 - -I think this is wrong. RFC 822 defines a quoted-string as <"> *(qtext/quoted-pair) <"> and quoted-par being able to quote any CHAR. - -/* only " and \ can be escaped */ - if ((*(p + 1) == '"')||(*(p + 1) == '\\')) { - p++; - } - else { - /* improper escaping */ - - /* We allow for now because IE sends - * improperly escaped content and there's - * nothing we can do about it. - * - * return -9; - */ - } - - -[brian] Suggestion @ 122 - -For a quoted value we just include everything until the end quote. The field values should be US-ASCII 'qtext' or 'quoted-pair' (RFC 822) or escaped using RFC 2047. - -if (*p == '"') { - *t = '\0'; - break; - } - - -[brian] Suggestion @ 143 - -RFC 2045 defines an 'attribute' as "ALWAYS case-insensitive", so these should be strncasecmp() - -if (strcmp(name, "name") == 0) { - if (msr->mpd->mpp->name != NULL) return -14; - msr->mpd->mpp->name = value; - - if (msr->txcfg->debuglog_level >= 9) { - msr_log(msr, 9, "Multipart: Content-Disposition name: %s", - log_escape_nq(msr->mp, value)); - } - } - else - if (strcmp(name, "filename") == 0) { - - -[brian] Suggestion @ 722 - -Cannot find anything that supports that this is or is not allowed. - -/* Flag for whitespace after parameter name. */ - - -[brian] Suggestion @ 735 - -Cannot find anything that supports that this is or is not allowed. - -/* Flag for whitespace before parameter value. */ - - - -File: apache2/msc_util.c -=================================================================== -[brian] Suggestion @ 24 - -Be more consistent in naming. - -#define VALID_HEX(X) (((X >= '0')&&(X <= '9')) || ((X >= 'a')&&(X <= 'f')) || ((X >= 'A')&&(X <= 'F'))) -#define ISODIGIT(X) ((X >= '0')&&(X <= '7')) - - -[brian] Suggestion @ 1186 - -Fix TODO. - -char *resolve_relative_path(apr_pool_t *pool, const char *parent_filename, const char *filename) { - if (filename == NULL) return NULL; - // TODO Support paths on operating systems other than Unix. - if (filename[0] == '/') return (char *)filename; - - return apr_pstrcat(pool, apr_pstrndup(pool, parent_filename, - strlen(parent_filename) - strlen(apr_filepath_name_get(parent_filename))), - filename, NULL); -} - - - -File: apache2/msc_xml.c -=================================================================== -[brian] Suggestion @ 27 - -Remove #if 0'd code? - -#if 0 -static void xml_receive_sax_error(void *data, const char *msg, ...) { - modsec_rec *msr = (modsec_rec *)data; - char message[256]; - - if (msr == NULL) return; - - apr_snprintf(message, sizeof(message), "%s (line %d offset %d)", - log_escape_nq(msr->mp, msr->xml->parsing_ctx->lastError.message), - msr->xml->parsing_ctx->lastError.line, - msr->xml->parsing_ctx->lastError.int2); - - msr_log(msr, 5, "XML: Parsing error: %s", message); -} -#endif - - - -File: apache2/pdf_protect.c -=================================================================== -[brian] Suggestion @ 26 - -Change from TODO to ENH. - -// TODO We need ID and REV values for the PDF XSS alert. - -// TODO It would be nice if the user could choose the ID/REV/SEVERITY/MESSAGE, etc. - - -[brian] Suggestion @ 217 - -Change from TODO to ENH. - -// TODO Should we look at err_headers_out too? - - -[brian] Suggestion @ 244 - -Change from TODO to ENH. - -// TODO application/x-pdf, application/vnd.fdf, application/vnd.adobe.xfdf, - // application/vnd.adobe.xdp+xml, application/vnd.adobe.xfd+xml, application/vnd.pdf - // application/acrobat, text/pdf, text/x-pdf ??? - - -[brian] Missing @ 472 - -Add the missing alert. - -// TODO Log alert - - - -File: apache2/re.c -=================================================================== -[brian] Missing @ 47 - -Need to log on failure. - -var = msre_create_var(ruleset, telts[i].key, telts[i].val, NULL, error_msg); - if (var == NULL) return -1; - - -[brian] Suggestion @ 297 - -Should replace with isvarnamechar() if possible. - -while((*p != '\0')&&(*p != '|')&&(*p != ':')&&(*p != ',')&&(!isspace(*p))) p++; /* ENH replace with isvarnamechar() */ - - -[brian] Irrelevant @ 608 - -Does not appear to be used anywhere. - -/** - * Destroys an engine instance, releasing the consumed memory. - */ -void msre_engine_destroy(msre_engine *engine) { - /* Destroyed automatically by the parent pool. - * apr_pool_destroy(engine->mp); - */ -} - - -[brian] Optimization @ 1150 - -tags set to NULL would be a bit better as it would stop apr_pstrcat() earlier, but tags *must* remain last or wierd results. - -char *tags = ""; - - -[brian] Suggestion @ 1179 - -Implement TODO. - -//TODO: restrict to 512 bytes - - -[brian] Optimization @ 1528 - -This causes two loops through the action list. Perhaps there is a more performant way to do these at the same time? Maybe split into two lists? - -/* Perform non-disruptive actions. */ - msre_perform_nondisruptive_actions(msr, rule, rule->actionset, mptmp); - - /* Perform disruptive actions, but only if - * this rule is not part of a chain. - */ - if (rule->actionset->is_chained == 0) { - msre_perform_disruptive_actions(msr, rule, acting_actionset, mptmp, my_error_msg); - } - - - -File: apache2/re.h -=================================================================== -[brian] Irrelevant @ 86 - -Does not appear to be used anywhere. - -void DSOLOCAL msre_engine_destroy(msre_engine *engine); - - -[brian] Suggestion @ 148 - -Why not stored in op_param_data like @rx, etc. The param_data is used w/exec action for lua. - -/* Compiled Lua script. */ - msc_script *script; - - - -File: apache2/re_actions.c -=================================================================== -[brian] Optimization @ 170 - -This implementation comment needs to be coded as many string operators now attempt to resolve macros. - -/* IMP1 Duplicate the string and create the array on - * demand, thus not having to do it if there are - * no macros in the input data. - */ - - data = apr_pstrdup(mptmp, var->value); /* IMP1 Are we modifying data anywhere? */ - arr = apr_array_make(mptmp, 16, sizeof(msc_string *)); - if ((data == NULL)||(arr == NULL)) return -1; - - -[brian] Irrelevant @ 209 - -This #if 0'd out code should be removed. - -/* Removed %0-9 macros as it messes up urlEncoding in the match - * where having '%0a' will be treated as %{TX.0}a, which is incorrect. - * */ -#if 0 - else if ((*(p + 1) >= '0')&&(*(p + 1) <= '9')) { - /* Special case for regex captures. */ - var_name = "TX"; - var_value = apr_pstrmemdup(mptmp, p + 1, 1); - next_text_start = p + 2; - } -#endif - - -[brian] Suggestion @ 257 - -Should log a level 9 msg here. - -} else { - /* We could not identify a valid macro so add it as text. */ - part = (msc_string *)apr_pcalloc(mptmp, sizeof(msc_string)); - if (part == NULL) return -1; - part->value_len = p - text_start + 1; /* len(text)+len("%") */ - part->value = apr_pstrmemdup(mptmp, text_start, part->value_len); - *(msc_string **)apr_array_push(arr) = part; - - next_text_start = p + 1; - } - - -[brian] Optimization @ 276 - -Use apr_array_pstrcat(msr->mp, arr, NULL) instead? - -/* If there's more than one member of the array that - * means there was at least one macro present. Combine - * text parts into a single string now. - */ - if (arr->nelts > 1) { - /* Figure out the required size for the string. */ - var->value_len = 0; - for(i = 0; i < arr->nelts; i++) { - part = ((msc_string **)arr->elts)[i]; - var->value_len += part->value_len; - } - - /* Allocate the string. */ - var->value = apr_palloc(msr->mp, var->value_len + 1); - if (var->value == NULL) return -1; - - /* Combine the parts. */ - offset = 0; - for(i = 0; i < arr->nelts; i++) { - part = ((msc_string **)arr->elts)[i]; - memcpy((char *)(var->value + offset), part->value, part->value_len); - offset += part->value_len; - } - var->value[offset] = '\0'; - } - - -[brian] Missing @ 402 - -Implement. Need to check if Apache will return an invalid status code - -/* status */ -static char *msre_action_status_validate(msre_engine *engine, msre_action *action) { - /* ENH action->param must be a valid HTTP status code. */ - return NULL; -} - - -[brian] Missing @ 422 - -Implement. - -/* pause */ -static char *msre_action_pause_validate(msre_engine *engine, msre_action *action) { - /* ENH Validate a positive number. */ - return NULL; -} - - -[brian] Missing @ 434 - -Implement as a valid URI check with apr_uri_parse()? - -/* redirect */ - -static char *msre_action_redirect_validate(msre_engine *engine, msre_action *action) { - /* ENH Add validation. */ - return NULL; -} - - -[brian] Missing @ 465 - -Implement as a valid URI check with apr_uri_parse()? - -/* proxy */ - -static char *msre_action_proxy_validate(msre_engine *engine, msre_action *action) { - /* ENH Add validation. */ - return NULL; -} - - -[brian] Irrelevant @ 507 - -I do not see a need to validate beyound what is already done in the init function. - -msre_action_skip_validate -msre_action_skipAfter_validate - - -[brian] Missing @ 570 - -Implement. - -/* phase */ - -static char *msre_action_phase_validate(msre_engine *engine, msre_action *action) { - /* ENH Add validation. */ - return NULL; -} - - -[brian] Suggestion @ 612 - -Probably should also calc length and validate a length > 0 instead of just checking NULL. Other checks would benefit from checking a length as well, so no harm in calculating that. - -if (value == NULL) { - return apr_psprintf(engine->mp, "Missing ctl value for name: %s", name); - } - - -[brian] Irrelevant @ 708 - -Why register init() if we do not use it? - -static apr_status_t msre_action_ctl_init(msre_engine *engine, msre_actionset *actionset, - msre_action *action) -{ - /* Do nothing. */ - return 1; -} - - -[brian] Optimization @ 774 - -TODO needs looked into. - -if (strcasecmp(name, "auditEngine") == 0) { - if (strcasecmp(value, "on") == 0) { - msr->txcfg->auditlog_flag = AUDITLOG_ON; - msr->usercfg->auditlog_flag = AUDITLOG_ON; - } - - if (strcasecmp(value, "off") == 0) { - msr->txcfg->auditlog_flag = AUDITLOG_OFF; - msr->usercfg->auditlog_flag = AUDITLOG_OFF; - } - - if (strcasecmp(value, "relevantonly") == 0) { - msr->txcfg->auditlog_flag = AUDITLOG_RELEVANT; - msr->usercfg->auditlog_flag = AUDITLOG_RELEVANT; - } - - msr_log(msr, 4, "Ctl: Set auditEngine to %d.", msr->txcfg->auditlog_flag); // TODO - - return 1; - } else - - -[brian] Suggestion @ 790 - -Not positive why the TODO here. Perhaps for a decision as to log and/or at what level? - -msr_log(msr, 4, "Ctl: Set auditEngine to %d.", msr->txcfg->auditlog_flag); // TODO - - -[brian] Missing @ 855 - -Should log an internal error here. - -else { - /* ENH Should never happen, but log if it does. */ - return -1; - } - - -[brian] Suggestion @ 1152 - -Probably should use apr_strtoi64 where we can tell if there was an error in conversion since we are potentially taking a value from a macro expansion. Also may want to look for overflow. - -value += atoi(var_value); - - -[brian] Suggestion @ 1288 - -Not sure why we would not want to deprecate a TX var. Further rules could use this even if TX is not persisted. - -/* IMP1 Add message TX variables cannot deprecate in value. */ - - -[brian] Suggestion @ 1383 - -The timeout is hardcoded to 3600. The docs state TIMEOUT is read-only, but this is not true. So, you can modify TIMEOUT. - -/* IMP1 Is the timeout hard-coded to 3600? */ - - -[brian] Suggestion @ 1555 - -We already have support for relative filenames, but cannot get to this data from here. This needs solved by passing more data to the validate function (cmd_parms rec). Maybe need a warning here stating we do not support them yet, or it might be confusing to users that we do not here but do elsewhere. - -/* TODO Support relative filenames. */ - - -[brian] Suggestion @ 1557 - -Not sure using an extension is a good idea here. Better I think would be to specify a type: "exec:[type=]/path/to/file" as in "exec:lua=/path/to/script" and make param_data a script_rec with a type and value. Also we use the abstract param_data here vs using a specific field as in SecRuleScript. - -/* Process Lua scripts internally. */ - if (strlen(filename) > 4) { - char *p = filename + strlen(filename) - 4; - if ((p[0] == '.')&&(p[1] == 'l')&&(p[2] == 'u')&&(p[3] == 'a')) { - /* It's a Lua script. */ - msc_script *script = NULL; - - /* Compile script. */ - char *msg = lua_compile(&script, filename, engine->mp); - if (msg != NULL) return msg; - - action->param_data = script; - } - } - - -[brian] Suggestion @ 1578 - -This assumes lua is the only type (which it is now), but should be re-writen with a script_rec stored in param_data. - -if (action->param_data != NULL) { /* Lua */ - msc_script *script = (msc_script *)action->param_data; - char *my_error_msg = NULL; - - if (lua_execute(script, NULL, msr, rule, &my_error_msg) < 0) { - msr_log(msr, 1, "%s", my_error_msg); - return 0; - } - } else { /* Execute as shell script. */ - - - -File: apache2/re_operators.c -=================================================================== -[brian] Missing - -Need more unit tests for operators. Start with new operators. - - -[brian] Suggestion @ 246 - -Use resolve_relative_path() instead? Maybe a config_relative_path() to just get the path? - -/* Get the path of the rule filename to use as a base */ - rulefile_path = apr_pstrndup(rule->ruleset->mp, rule->filename, strlen(rule->filename) - strlen(apr_filepath_name_get(rule->filename))); - - -[brian] Missing @ 310 - -Need to check return code and log an error on failure. - -acmp_add_pattern(p, buf, NULL, NULL, strlen(buf)); - - -[brian] Missing @ 315 - -Need to check return code and log an error on failure. - -acmp_prepare(p); - - -[brian] Optimization @ 379 - -See if apr_strmatch is faster. - -msre_op_within_execute - - -[brian] Optimization @ 442 - -See if apr_strmatch is faster. - -msre_op_contains_execute - - -[brian] Optimization @ 506 - -See if apr_strmatch is faster. - -msre_op_containsWord_execute - - -[brian] Missing @ 1330 - -Need an error_msg set for lua execution error. - -rc = lua_execute(script, target, msr, rule, error_msg); - if (rc < 0) { - /* Error. */ - return -1; - } - - -[brian] Missing @ 1477 - -@validateurlEncoding does not output VAR name nor offset in error_msg on match. - -msre_op_validateUrlEncoding_execute - - -[brian] Missing @ 1885 - -@m operator is not documented. This does the same as @contains, so it was suggested earlier to use the @m algorithm for contains (if faster) and drop @m. - -/* m */ - msre_engine_op_register(engine, - "m", - msre_op_m_param_init, - msre_op_m_execute - ); - - - -File: apache2/re_tfns.c -=================================================================== -[brian] Optimization @ 77 - -No need to set this on all. Only set it once when we find the first non-space char. - -(*rval)[i] = '\0'; - - - diff --git a/review/review-summary.pl b/review/review-summary.pl deleted file mode 100755 index 799f1672..00000000 --- a/review/review-summary.pl +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/perl -use strict; -use XML::Simple; -#use Data::Dumper; - -my $REVIEW = shift @ARGV; -my %ISSUES = (); - -unless (defined $REVIEW) { - print STDERR "Usage: $0 [ ... ]\n"; - exit 1; -} - -# XML => hashref -my $review = XMLin( - $REVIEW, - KeepRoot => 0, - KeyAttr => { ReviewIssue => "+id" }, - ContentKey => "value", - SuppressEmpty => undef, -); -#print Dumper($review); - -# Reorg hashref to be only open issues by filename -for my $rec (values %{$review->{ReviewIssue} || {}}) { - my $key = defined($rec->{File}->{value}) ? $rec->{File}->{value} : ""; - push @{$ISSUES{$key}}, $rec if ($rec->{Status} =~ m/\.open$/); -} - - -# Write report -for my $fn (@ARGV ? (@ARGV) : (sort keys %ISSUES)) { - print "File: $fn\n"; - print "===================================================================\n"; - for my $r (sort { $a->{File}->{line} <=> $b->{File}->{line} || $a->{ReviewerId} cmp $b->{ReviewerId} } @{$ISSUES{$fn} || []}) { - (my $type = $r->{Type}) =~ s/^.*\.([^\.]+)$/$1/; - $type = ucfirst($type); - (my $res = $r->{Resolution}) =~ s/^.*\.([^\.]+)$/$1/; - my $line = ($r->{File}->{line} and $r->{File}->{line} > 1) ? " @ $r->{File}->{line}" : ""; - my $summary = $r->{Summary} ? "\n$r->{Summary}\n\n" : ""; - my $desc = $r->{Description} ? "$r->{Description}\n\n" : ""; - - print << "EOT"; -[$r->{ReviewerId}] $type$line -$summary$desc -EOT - } - print "\n"; -} -