diff --git a/apache2/libinjection/COPYING.txt b/apache2/libinjection/COPYING.txt index 772b0562..ef2f78d7 100644 --- a/apache2/libinjection/COPYING.txt +++ b/apache2/libinjection/COPYING.txt @@ -1,4 +1,5 @@ -/* Copyright 2012, 2013 +/* + * Copyright 2012, 2013 * Nick Galbreath -- nickg [at] client9 [dot] com * http://www.client9.com/projects/libinjection/ * diff --git a/apache2/libinjection/sqli_fingerprints.h b/apache2/libinjection/sqli_fingerprints.h index 8b883d03..42e0b3c6 100644 --- a/apache2/libinjection/sqli_fingerprints.h +++ b/apache2/libinjection/sqli_fingerprints.h @@ -10,7 +10,9 @@ static const char* patmap[] = { "&f(1o", "&f(s)", "&f(v)", + "&f(vo", "&so1U", + "&sosU", "&sovU", "&vo1U", "&vosU", @@ -89,9 +91,11 @@ static const char* patmap[] = { "1&soo", "1&sos", "1&sov", + "1&v", "1&vBf", "1&vU(", "1&vUk", + "1&vc", "1&vf(", "1&vo(", "1&vo1", @@ -134,14 +138,17 @@ static const char* patmap[] = { "1)));", "1)))B", "1)))U", + "1)))c", "1)))k", "1)))o", + "1));c", "1));k", "1))B1", "1))Bs", "1))Bv", "1))Uk", "1))Un", + "1))c", "1))k1", "1))kk", "1))ks", @@ -156,6 +163,7 @@ static const char* patmap[] = { "1),(1", "1),(s", "1),(v", + "1);c", "1);k&", "1);k(", "1);kf", @@ -184,6 +192,7 @@ static const char* patmap[] = { "1)Uks", "1)Ukv", "1)Unk", + "1)c", "1)k1", "1)k1c", "1)k1o", @@ -213,7 +222,6 @@ static const char* patmap[] = { "1)oks", "1)okv", "1)on&", - "1)ono", "1)os)", "1)osB", "1)osU", @@ -244,6 +252,7 @@ static const char* patmap[] = { "1,s),", "1,s)o", "1,sB1", + "1,sBs", "1,sBv", "1,sUk", "1,v),", @@ -252,6 +261,7 @@ static const char* patmap[] = { "1,vBs", "1,vBv", "1,vUk", + "1;c", "1;k&k", "1;k((", "1;k(1", @@ -293,6 +303,7 @@ static const char* patmap[] = { "1Bs", "1Bs,1", "1Bs,n", + "1Bs,s", "1Bs,v", "1BsUk", "1Bsc", @@ -385,6 +396,7 @@ static const char* patmap[] = { "1Uons", "1Uonv", "1Us,1", + "1Us,s", "1Us,v", "1Uv,1", "1Uv,s", @@ -395,6 +407,7 @@ static const char* patmap[] = { "1k1Uk", "1k1c", "1k1o1", + "1k1ov", "1kU1,", "1kUs,", "1kUv,", @@ -408,6 +421,7 @@ static const char* patmap[] = { "1kkvc", "1knkn", "1kno1", + "1knov", "1kokn", "1ksU(", "1ksUk", @@ -415,6 +429,8 @@ static const char* patmap[] = { "1kvU(", "1kvUk", "1kvc", + "1kvo1", + "1kvov", "1n&f(", "1n)Uk", "1nUk1", @@ -442,6 +458,7 @@ static const char* patmap[] = { "1o(n)", "1o(o1", "1o(os", + "1o(ov", "1o(s)", "1o(so", "1o(v)", @@ -484,6 +501,7 @@ static const char* patmap[] = { "1okv,", "1okvc", "1okvk", + "1onos", "1onov", "1os)&", "1os)U", @@ -521,6 +539,7 @@ static const char* patmap[] = { "Uks,1", "Uks,f", "Uks,n", + "Uks,s", "Uks,v", "Ukv,1", "Ukv,f", @@ -549,6 +568,7 @@ static const char* patmap[] = { "f(f(v", "f(k()", "f(k,(", + "f(k,f", "f(k,n", "f(n()", "f(s)&", @@ -556,8 +576,10 @@ static const char* patmap[] = { "f(s)o", "f(s,1", "f(s,f", + "f(s,s", "f(s,v", "f(so1", + "f(sos", "f(sov", "f(v)&", "f(v)U", @@ -572,6 +594,7 @@ static const char* patmap[] = { "k()ok", "k(1)U", "k(f(1", + "k(f(v", "k(ok(", "k(s)U", "k(sv)", @@ -594,6 +617,7 @@ static const char* patmap[] = { "k1o(s", "k1o(v", "k;non", + "kc", "kf((f", "kf(1)", "kf(1,", @@ -611,8 +635,10 @@ static const char* patmap[] = { "kk1fn", "kk1kk", "kk1nk", + "kk1sf", "kk1sk", "kk1sn", + "kk1vf", "kk1vk", "kk1vn", "kksf(", @@ -625,8 +651,10 @@ static const char* patmap[] = { "kkvfn", "kkvkk", "kkvnk", + "kkvsf", "kkvsk", "kkvsn", + "kkvvf", "kkvvk", "kkvvn", "kn1kk", @@ -647,6 +675,7 @@ static const char* patmap[] = { "ko(kf", "ko(n,", "ko(s,", + "ko(v,", "kok(k", "ks&(k", "ks&(o", @@ -655,21 +684,29 @@ static const char* patmap[] = { "ks,1c", "ks,1k", "ks,f(", + "ks,s,", + "ks,sc", + "ks,sk", "ks,v,", "ks,vc", "ks,vk", "ksf(1", + "ksf(s", "ksf(v", "ksk(1", "ksk(k", + "ksk(s", "ksk(v", "kso(s", "kso(v", + "kv&(k", + "kv&(o", "kv)", "kv,1,", "kv,1c", "kv,1k", "kv,f(", + "kv,n,", "kv,s,", "kv,sc", "kv,sk", @@ -683,6 +720,7 @@ static const char* patmap[] = { "kvk(k", "kvk(s", "kvk(v", + "kvkf(", "kvo(s", "kvo(v", "n&(1)", @@ -720,7 +758,9 @@ static const char* patmap[] = { "n&so1", "n&sof", "n&soo", + "n&sos", "n&sov", + "n&vBf", "n&vf(", "n&vo(", "n&vo1", @@ -745,11 +785,15 @@ static const char* patmap[] = { "n)));", "n)))B", "n)))U", + "n)))c", "n)))k", "n)))o", + "n));c", "n));k", "n))B1", + "n))Bv", "n))Uk", + "n))c", "n))kk", "n))o(", "n))o1", @@ -757,6 +801,7 @@ static const char* patmap[] = { "n))ok", "n))os", "n))ov", + "n);c", "n);k&", "n);k(", "n);kf", @@ -764,7 +809,10 @@ static const char* patmap[] = { "n);kn", "n);ko", "n)B1c", + "n)Bvc", "n)Uk1", + "n)Ukv", + "n)c", "n)k1o", "n)kks", "n)kkv", @@ -794,6 +842,7 @@ static const char* patmap[] = { "n:o1U", "n:osU", "n:ovU", + "n;c", "n;k&k", "n;k((", "n;k(1", @@ -806,6 +855,7 @@ static const char* patmap[] = { "n;ko(", "n;kok", "nB1c", + "nBvc", "nUk(k", "nUk1,", "nUk1c", @@ -813,9 +863,12 @@ static const char* patmap[] = { "nUkn,", "nUks,", "nUkv,", + "nUkvc", "nUnk(", + "nc", "nk1Uk", "nk1o1", + "nk1ov", "nkf(1", "nkf(s", "nkf(v", @@ -823,6 +876,8 @@ static const char* patmap[] = { "nkkvc", "nksUk", "nkvUk", + "nkvo1", + "nkvov", "nnn)U", "nno1U", "nnosU", @@ -852,7 +907,9 @@ static const char* patmap[] = { "nok(s", "nok(v", "nono1", + "nonov", "nos&1", + "nos&s", "nos&v", "nosUk", "nosf(", @@ -860,6 +917,7 @@ static const char* patmap[] = { "noso1", "nosof", "nosoo", + "nosos", "nosov", "nov&1", "nov&s", @@ -876,6 +934,7 @@ static const char* patmap[] = { "oUk1,", "oUks,", "oUkv,", + "oc", "of()o", "of(1)", "of(s)", @@ -885,6 +944,7 @@ static const char* patmap[] = { "ok1ov", "okkkn", "okso1", + "oksos", "oksov", "okvo1", "okvos", @@ -903,6 +963,7 @@ static const char* patmap[] = { "s&(k(", "s&(k)", "s&(k1", + "s&(kc", "s&(kf", "s&(kk", "s&(kn", @@ -948,6 +1009,7 @@ static const char* patmap[] = { "s&kUk", "s&kc", "s&kk1", + "s&kks", "s&kkv", "s&knk", "s&ko(", @@ -955,6 +1017,7 @@ static const char* patmap[] = { "s&kok", "s&kos", "s&kov", + "s&ksk", "s&kso", "s&kvk", "s&kvo", @@ -985,12 +1048,13 @@ static const char* patmap[] = { "s&so(", "s&so1", "s&sof", + "s&sok", "s&son", "s&soo", "s&sos", "s&sov", - "s&sso", "s&svo", + "s&v", "s&v:o", "s&vBf", "s&vU(", @@ -1007,6 +1071,7 @@ static const char* patmap[] = { "s&vov", "s&vso", "s&vvo", + "s(c", "s)&(1", "s)&(f", "s)&(k", @@ -1020,6 +1085,7 @@ static const char* patmap[] = { "s)&f(", "s)&o(", "s)&sB", + "s)&sU", "s)&sf", "s)&so", "s)&vB", @@ -1040,14 +1106,17 @@ static const char* patmap[] = { "s)));", "s)))B", "s)))U", + "s)))c", "s)))k", "s)))o", + "s));c", "s));k", "s))B1", "s))Bs", "s))Bv", "s))Uk", "s))Un", + "s))c", "s))k1", "s))kk", "s))ks", @@ -1062,6 +1131,7 @@ static const char* patmap[] = { "s),(1", "s),(s", "s),(v", + "s);c", "s);k&", "s);k(", "s);kf", @@ -1090,6 +1160,7 @@ static const char* patmap[] = { "s)Uks", "s)Ukv", "s)Unk", + "s)c", "s)k1", "s)k1c", "s)k1o", @@ -1107,6 +1178,7 @@ static const char* patmap[] = { "s)o(s", "s)o(v", "s)o1B", + "s)o1U", "s)o1f", "s)o1k", "s)o1o", @@ -1124,6 +1196,7 @@ static const char* patmap[] = { "s)oso", "s)ov)", "s)ovB", + "s)ovU", "s)ovf", "s)ovk", "s)ovo", @@ -1131,22 +1204,33 @@ static const char* patmap[] = { "s,(k(", "s,(k1", "s,(kf", + "s,(ks", "s,(kv", "s,1),", "s,1)o", "s,1B1", + "s,1Bs", "s,1Bv", "s,1Uk", "s,f(1", + "s,f(s", "s,f(v", "s,s),", + "s,s)o", + "s,sB1", + "s,sBs", + "s,sBv", + "s,sUk", "s,v),", "s,v)o", "s,vB1", + "s,vBs", "s,vBv", "s,vUk", "s:o1)", + "s:os)", "s:ov)", + "s;c", "s;k&k", "s;k((", "s;k(1", @@ -1183,6 +1267,7 @@ static const char* patmap[] = { "sB1&v", "sB1,1", "sB1,n", + "sB1,s", "sB1,v", "sB1Uk", "sB1c", @@ -1193,17 +1278,27 @@ static const char* patmap[] = { "sB1ov", "sBf(1", "sBf(f", + "sBf(s", "sBf(v", "sBk(1", + "sBk(s", "sBk(v", "sBn,n", "sBnk1", + "sBnks", "sBnkv", "sBs", "sBs&s", "sBs&v", + "sBs,1", + "sBs,n", + "sBs,s", + "sBs,v", "sBsUk", "sBsc", + "sBsk1", + "sBsks", + "sBskv", "sBsos", "sBsov", "sBv", @@ -1211,6 +1306,7 @@ static const char* patmap[] = { "sBv&v", "sBv,1", "sBv,n", + "sBv,s", "sBv,v", "sBvUk", "sBvc", @@ -1228,12 +1324,14 @@ static const char* patmap[] = { "sU(ks", "sU(kv", "sU1,1", + "sU1,s", "sU1,v", "sUc", "sUk", "sUk(1", "sUk(k", "sUk(n", + "sUk(s", "sUk(v", "sUk1", "sUk1&", @@ -1264,12 +1362,15 @@ static const char* patmap[] = { "sUknv", "sUko1", "sUkok", + "sUkos", "sUkov", "sUks", "sUks&", "sUks,", "sUksc", + "sUksf", "sUksk", + "sUksn", "sUkso", "sUkv", "sUkv&", @@ -1281,6 +1382,7 @@ static const char* patmap[] = { "sUkvo", "sUn(k", "sUn,1", + "sUn,s", "sUn,v", "sUn1,", "sUnk(", @@ -1291,10 +1393,16 @@ static const char* patmap[] = { "sUno1", "sUnos", "sUnov", + "sUns,", "sUnv,", "sUon1", + "sUons", "sUonv", + "sUs,1", + "sUs,s", + "sUs,v", "sUv,1", + "sUv,s", "sUv,v", "sc", "sf()k", @@ -1336,8 +1444,10 @@ static const char* patmap[] = { "skUs,", "skUv,", "skf(1", + "skf(s", "skf(v", "skk(1", + "skk(s", "skk(v", "skks", "skksc", @@ -1345,7 +1455,9 @@ static const char* patmap[] = { "skkvc", "sknkn", "sks&1", + "sks&s", "sks&v", + "sksU(", "sksUk", "sksc", "skso1", @@ -1364,11 +1476,14 @@ static const char* patmap[] = { "sn,f(", "snUk1", "snUkn", + "snUks", "snUkv", "snk1c", "snkf(", + "snksc", "snkvc", "sno(s", + "sno(v", "sno1U", "snosU", "snovU", @@ -1384,6 +1499,7 @@ static const char* patmap[] = { "so(k(", "so(k)", "so(k1", + "so(kc", "so(kf", "so(kk", "so(kn", @@ -1448,6 +1564,7 @@ static const char* patmap[] = { "soks", "soks,", "soksc", + "soksk", "sokso", "sokv", "sokv,", @@ -1465,6 +1582,8 @@ static const char* patmap[] = { "sos&o", "sos&s", "sos&v", + "sos)&", + "sos)o", "sos:o", "sosBf", "sosUk", @@ -1478,7 +1597,6 @@ static const char* patmap[] = { "sosoo", "sosos", "sosov", - "sosso", "sosvo", "sov", "sov&(", @@ -1512,6 +1630,7 @@ static const char* patmap[] = { "v&(k(", "v&(k)", "v&(k1", + "v&(kc", "v&(kf", "v&(kk", "v&(kn", @@ -1524,6 +1643,7 @@ static const char* patmap[] = { "v&(v)", "v&(v,", "v&(vo", + "v&1", "v&1Bf", "v&1Uk", "v&1c", @@ -1585,6 +1705,7 @@ static const char* patmap[] = { "v&oso", "v&ov", "v&ovo", + "v&s", "v&s:o", "v&sBf", "v&sU(", @@ -1599,8 +1720,8 @@ static const char* patmap[] = { "v&soo", "v&sos", "v&sov", - "v&sso", "v&svo", + "v&v", "v&v:o", "v&vBf", "v&vU(", @@ -1617,6 +1738,7 @@ static const char* patmap[] = { "v&vov", "v&vso", "v&vvo", + "v(c", "v)&(1", "v)&(f", "v)&(k", @@ -1651,14 +1773,17 @@ static const char* patmap[] = { "v)));", "v)))B", "v)))U", + "v)))c", "v)))k", "v)))o", + "v));c", "v));k", "v))B1", "v))Bs", "v))Bv", "v))Uk", "v))Un", + "v))c", "v))k1", "v))kk", "v))ks", @@ -1673,6 +1798,7 @@ static const char* patmap[] = { "v),(1", "v),(s", "v),(v", + "v);c", "v);k&", "v);k(", "v);kf", @@ -1701,11 +1827,13 @@ static const char* patmap[] = { "v)Uks", "v)Ukv", "v)Unk", + "v)c", "v)k1", "v)k1c", "v)k1o", "v)kks", "v)kkv", + "v)knk", "v)ks", "v)ksc", "v)kso", @@ -1717,6 +1845,7 @@ static const char* patmap[] = { "v)o(n", "v)o(s", "v)o(v", + "v)o1)", "v)o1B", "v)o1U", "v)o1f", @@ -1728,13 +1857,13 @@ static const char* patmap[] = { "v)oks", "v)okv", "v)on&", - "v)ono", "v)os)", "v)osB", "v)osU", "v)osf", "v)osk", "v)oso", + "v)ov)", "v)ovB", "v)ovU", "v)ovf", @@ -1758,6 +1887,7 @@ static const char* patmap[] = { "v,s),", "v,s)o", "v,sB1", + "v,sBs", "v,sBv", "v,sUk", "v,v),", @@ -1769,6 +1899,7 @@ static const char* patmap[] = { "v:o1)", "v:os)", "v:ov)", + "v;c", "v;k&k", "v;k((", "v;k(1", @@ -1830,6 +1961,7 @@ static const char* patmap[] = { "vBs&v", "vBs,1", "vBs,n", + "vBs,s", "vBs,v", "vBsUk", "vBsc", @@ -1852,6 +1984,7 @@ static const char* patmap[] = { "vBvkv", "vBvos", "vBvov", + "vU", "vU((k", "vU(k(", "vU(k1", @@ -1936,6 +2069,7 @@ static const char* patmap[] = { "vUons", "vUonv", "vUs,1", + "vUs,s", "vUs,v", "vUv,1", "vUv,s", @@ -1990,7 +2124,11 @@ static const char* patmap[] = { "vkkv", "vkkvc", "vknkn", + "vkno1", + "vknov", + "vkokn", "vks&1", + "vks&s", "vks&v", "vksU(", "vksUk", @@ -2008,6 +2146,7 @@ static const char* patmap[] = { "vkvos", "vkvov", "vn&f(", + "vn)Uk", "vn,f(", "vnUk1", "vnUkn", @@ -2017,6 +2156,8 @@ static const char* patmap[] = { "vnkf(", "vnksc", "vnkvc", + "vno(s", + "vno(v", "vno1U", "vnosU", "vnovU", @@ -2032,6 +2173,7 @@ static const char* patmap[] = { "vo(k(", "vo(k)", "vo(k1", + "vo(kc", "vo(kf", "vo(kk", "vo(kn", @@ -2078,6 +2220,8 @@ static const char* patmap[] = { "vok(o", "vok(s", "vok(v", + "vok)U", + "vok)o", "vok1", "vok1,", "vok1c", @@ -2116,6 +2260,7 @@ static const char* patmap[] = { "vos&s", "vos&v", "vos)&", + "vos)U", "vos)o", "vos:o", "vosBf", @@ -2130,7 +2275,6 @@ static const char* patmap[] = { "vosoo", "vosos", "vosov", - "vosso", "vosvo", "vov", "vov&(", @@ -2139,6 +2283,7 @@ static const char* patmap[] = { "vov&s", "vov&v", "vov)&", + "vov)U", "vov)o", "vov:o", "vovBf", @@ -2156,7 +2301,7 @@ static const char* patmap[] = { "vovso", "vovvo", }; -static const size_t patmap_sz = 2153; +static const size_t patmap_sz = 2298; /* Simple binary search */ diff --git a/apache2/libinjection/sqlparse.c b/apache2/libinjection/sqlparse.c index 9a23f3a1..a8582f66 100644 --- a/apache2/libinjection/sqlparse.c +++ b/apache2/libinjection/sqlparse.c @@ -32,63 +32,38 @@ #include "sqlparse_private.h" #include "sqlparse_data.h" -/* memmem is a linux function - * may not exist in Windows, and doesn't exist - * in Mac OS X < 10.8 and FreeBSD < 6.0 - * Define our own. Modified to use 'const char*' - * instead of (void *) - */ - -/*- - * Copyright (c) 2005 Pascal Gloor +/* memchr2 finds a string of 2 characters inside another string + * This a specialized version of "memmem" or "memchr". + * 'memmem' doesn't exist on all platforms * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. + * Porting notes: this is just a special version of + * astring.find("AB") * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. */ const char * -my_memmem(const char *cl, size_t l_len, const char *cs, size_t s_len) +memchr2(const char *haystack, size_t haystack_len, char c0, char c1) { - register const char *cur, *last; + const char *cur = haystack; + const char *last = haystack + haystack_len - 1; - /* we need something to compare */ - if (l_len == 0 || s_len == 0) + if (haystack_len < 2) { return NULL; - - /* "s" must be smaller or equal to "l" */ - if (l_len < s_len) + } + if (c0 == c1) { return NULL; + } - /* special case where s_len == 1 */ - if (s_len == 1) - return (const char*) memchr(cl, (int)*cs, l_len); - - /* the last position where its possible to find "s" in "l" */ - last = cl + l_len - s_len; - - for (cur = cl; cur <= last; cur++) - if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) - return cur; + while (cur < last) { + if (cur[0] == c0) { + if (cur[1] == c1) { + return cur; + } else { + cur += 2; + } + } else { + cur += 1; + } + } return NULL; } @@ -391,8 +366,7 @@ size_t parse_slash(sfilter * sf) /* * skip over initial '/x' */ - const char *ptr = - (const char *) my_memmem(cur + 2, slen - (pos + 2), "*/", 2); + const char *ptr = memchr2(cur + 2, slen - (pos + 2), '*', '/'); if (ptr == NULL) { /* * unterminated comment @@ -408,8 +382,7 @@ size_t parse_slash(sfilter * sf) */ char ctype = 'c'; const size_t clen = (ptr + 2) - (cur); - if (my_memmem(cur + 2, ptr - (cur + 2), "/*", 2) != - NULL) { + if (memchr2(cur + 2, ptr - (cur + 1), '/', '*') != NULL) { ctype = 'X'; } st_assign(current, ctype, cs + pos, clen); @@ -1102,20 +1075,45 @@ int is_string_sqli(sfilter * sql_state, const char *s, size_t slen, /* * if 'comment' is '#' ignore.. too many FP */ - if (sql_state->tokenvec[1].val[0] == '#') { + if (sql_state->tokenvec[1].val[0] == '#') { + sql_state->reason = __LINE__; + return FALSE; + } + + /* + * for fingerprint like 'nc', only comments of /x are treated + * as SQL... ending comments of "--" and "#" are not sqli + */ + if (sql_state->tokenvec[0].type == 'n' && + sql_state->tokenvec[1].type == 'c' && + sql_state->tokenvec[1].val[0] != '/') { sql_state->reason = __LINE__; return FALSE; - } - /* - * detect obvious sqli scans.. many people put '--' in plain text - * so only detect if input ends with '--', e.g. 1-- but not 1-- foo - */ - if ((strlen(sql_state->tokenvec[1].val) > 2) - && sql_state->tokenvec[1].val[0] == '-') { - sql_state->reason = __LINE__; - return FALSE; - } - break; + } + /* + * detect obvious sqli scans.. many people put '--' in plain text + * so only detect if input ends with '--', e.g. 1-- but not 1-- foo + */ + + if ((strlen(sql_state->tokenvec[1].val) > 2) + && sql_state->tokenvec[1].val[0] == '-') { + sql_state->reason = __LINE__; + return FALSE; + } + + /** + * there are some odd base64-looking query string values + * 1234-ABCDEFEhfhihwuefi-- + * which evaluate to "1c"... these are not SQLi + * but 1234-- probably is. + * Make sure the "1" in "1c" is actually a true decimal number + */ + if (sql_state->tokenvec[0].type == '1'&& sql_state->tokenvec[1].type == 'c' && + strlen(sql_state->tokenvec[0].val) != strcspn(sql_state->tokenvec[0].val, "0123456789")) { + sql_state->reason = __LINE__; + return FALSE; + } + break; } case 3:{ /* diff --git a/apache2/libinjection/sqlparse.h b/apache2/libinjection/sqlparse.h index 1b6e6c8c..f626aaa7 100644 --- a/apache2/libinjection/sqlparse.h +++ b/apache2/libinjection/sqlparse.h @@ -1,5 +1,5 @@ /** - * Copyright 2012, Nick Galbreath + * Copyright 2012, 2013 Nick Galbreath * nickg@client9.com * BSD License -- see COPYING.txt for details * @@ -7,11 +7,15 @@ * HOW TO USE: * * // Normalize query or postvar value - * // ATTENTION: this modifies user_string... make copy if that is not ok - * size_t new_len = qs_normalize(user_string, user_string_len); + * // If it comes in urlencoded, then it's up to you + * // to urldecode it. If it's in correct form already + * // then nothing to do! * * sfilter s; - * bool sqli = is_sqli(&s, user_string, new_len); + * int sqli = is_sqli(&s, user_string, new_len); + * + * // 0 = not sqli + * // 1 = is sqli * * // That's it! sfilter s has some data on how it matched or not * // details to come! @@ -25,9 +29,20 @@ extern "C" { #endif +/* + * Version info. + * See python's normalized version + * http://www.python.org/dev/peps/pep-0386/#normalizedversion + */ +#define LIBINJECTION_VERSION "1.1.0" + #define ST_MAX_SIZE 32 #define MAX_TOKENS 5 +#define CHAR_NULL '\0' +#define CHAR_SINGLE '\'' +#define CHAR_DOUBLE '"' + typedef struct { char type; char str_open; @@ -57,7 +72,7 @@ typedef struct { /* final sqli data */ stoken_t tokenvec[MAX_TOKENS]; - /* +1 for possible ending null */ + /* +1 for ending null */ char pat[MAX_TOKENS + 1]; char delim; int reason; @@ -69,12 +84,27 @@ typedef struct { typedef int (*ptr_fingerprints_fn)(const char*); /** + * Main API: tests for SQLi in three possible contexts, no quotes, + * single quote and double quote * - * - * \return TRUE if SQLi, FALSE is benign + * \return 1 (true) if SQLi, 0 (false) if benign */ int is_sqli(sfilter * sql_state, const char *s, size_t slen, - ptr_fingerprints_fn fn); + ptr_fingerprints_fn fn); + +/** + * This detects SQLi in a single context, mostly useful for custom + * logic and debugging. + * + * \param delim must be "NULL" (no context), single quote or double quote. + * Other values will likely be ignored. + * + * \return 1 (true) if SQLi, 0 (false) if not SQLi **in this context** + * + */ +int is_string_sqli(sfilter * sql_state, const char *s, size_t slen, + const char delim, + ptr_fingerprints_fn fn); #ifdef __cplusplus } diff --git a/apache2/libinjection/sqlparse_data.h b/apache2/libinjection/sqlparse_data.h index 9d14bd4e..811f883d 100644 --- a/apache2/libinjection/sqlparse_data.h +++ b/apache2/libinjection/sqlparse_data.h @@ -41,15 +41,32 @@ static const keyword_t sql_keywords[] = { {"AES_DECRYPT", 'f'}, {"AES_ENCRYPT", 'f'}, {"AGAINST", 'k'}, + {"AGE", 'f'}, {"ALL_USERS", 'k'}, {"ALTER", 'k'}, {"ANALYZE", 'k'}, {"AND", '&'}, + {"APPLOCK_MODE", 'f'}, + {"APPLOCK_TEST", 'f'}, + {"APP_NAME", 'f'}, + {"ARRAY_AGG", 'f'}, + {"ARRAY_CAT", 'f'}, + {"ARRAY_DIM", 'f'}, + {"ARRAY_FILL", 'f'}, + {"ARRAY_LENGTH", 'f'}, + {"ARRAY_LOWER", 'f'}, + {"ARRAY_NDIMS", 'f'}, + {"ARRAY_PREPEND", 'f'}, + {"ARRAY_TO_JSON", 'f'}, + {"ARRAY_TO_STRING", 'f'}, + {"ARRAY_UPPER", 'f'}, {"AS", 'k'}, {"ASC", 'k'}, {"ASCII", 'f'}, {"ASENSITIVE", 'k'}, {"ASIN", 'f'}, + {"ASSEMBLYPROPERTY", 'f'}, + {"ASYMKEY_ID", 'f'}, {"ATAN", 'f'}, {"ATAN2", 'f'}, {"AVG", 'f'}, @@ -72,27 +89,53 @@ static const keyword_t sql_keywords[] = { {"BIT_XOR", 'f'}, {"BLOB", 'k'}, {"BOOLEAN", 'k'}, + {"BOOL_AND", 'f'}, + {"BOOL_OR", 'f'}, {"BOTH", 'k'}, + {"BTRIM", 'f'}, {"BY", 'n'}, {"CALL", 'k'}, {"CASCADE", 'k'}, {"CASE", 'o'}, {"CAST", 'f'}, + {"CBOOL", 'f'}, + {"CBRT", 'f'}, + {"CBYTE", 'f'}, + {"CCUR", 'f'}, + {"CDATE", 'f'}, + {"CDBL", 'f'}, {"CEIL", 'f'}, {"CEILING", 'f'}, + {"CERTENCODED", 'f'}, + {"CERTPRIVATEKEY", 'f'}, + {"CERT_ID", 'f'}, + {"CERT_PROPERTY", 'f'}, {"CHANGE", 'k'}, {"CHAR", 'f'}, {"CHARACTER", 'k'}, {"CHARACTER_LENGTH", 'f'}, + {"CHARINDEX", 'f'}, {"CHARSET", 'f'}, {"CHAR_LENGTH", 'f'}, + {"CHDIR", 'f'}, + {"CHDRIVE", 'f'}, {"CHECK", 'k'}, + {"CHECKSUM_AGG", 'f'}, + {"CHOOSE", 'f'}, {"CHR", 'f'}, + {"CINT", 'f'}, + {"CLNG", 'f'}, + {"CLOCK_TIMESTAMP", 'f'}, {"COALESCE", 'k'}, {"COERCIBILITY", 'f'}, {"COLLATE", 'k'}, {"COLLATION", 'f'}, + {"COLLATIONPROPERTY", 'f'}, {"COLUMN", 'k'}, + {"COLUMNPROPERTY", 'f'}, + {"COLUMNS_UPDATED", 'f'}, + {"COL_LENGTH", 'f'}, + {"COL_NAME", 'f'}, {"COMPRESS", 'f'}, {"CONCAT", 'f'}, {"CONCAT_WS", 'f'}, @@ -102,28 +145,57 @@ static const keyword_t sql_keywords[] = { {"CONTINUE", 'k'}, {"CONV", 'f'}, {"CONVERT", 'f'}, + {"CONVERT_FROM", 'f'}, + {"CONVERT_TO", 'f'}, {"CONVERT_TZ", 'f'}, {"COS", 'f'}, {"COT", 'f'}, {"COUNT", 'f'}, + {"COUNT_BIG", 'k'}, {"CRC32", 'f'}, {"CREATE", 'k'}, + {"CSNG", 'f'}, {"CTXSYS.DRITHSX.SN", 'f'}, + {"CUME_DIST", 'f'}, {"CURDATE", 'f'}, + {"CURDIR", 'f'}, + {"CURRENTUSER", 'f'}, + {"CURRENT_DATABASE", 'f'}, {"CURRENT_DATE", 'k'}, - {"CURRENT_DATECURRENT_TIME", 'f'}, + {"CURRENT_QUERY", 'f'}, + {"CURRENT_SCHEMA", 'f'}, + {"CURRENT_SCHEMAS", 'f'}, + {"CURRENT_SETTING", 'p'}, {"CURRENT_TIME", 'k'}, {"CURRENT_TIMESTAMP", 'k'}, {"CURRENT_USER", 'k'}, + {"CURRVAL", 'f'}, {"CURSOR", 'k'}, + {"CURSOR_STATUS", 'f'}, {"CURTIME", 'f'}, + {"CVAR", 'f'}, {"DATABASE", 'k'}, + {"DATABASEPROPERTYEX", 'f'}, {"DATABASES", 'k'}, + {"DATABASE_PRINCIPAL_ID", 'f'}, + {"DATALENGTH", 'f'}, {"DATE", 'f'}, + {"DATEADD", 'f'}, {"DATEDIFF", 'f'}, + {"DATEFROMPARTS", 'f'}, + {"DATENAME", 'f'}, + {"DATEPART", 'f'}, + {"DATESERIAL", 'f'}, + {"DATETIME2FROMPARTS", 'f'}, + {"DATETIMEFROMPARTS", 'f'}, + {"DATETIMEOFFSETFROMPARTS", 'f'}, + {"DATEVALUE", 'f'}, {"DATE_ADD", 'f'}, {"DATE_FORMAT", 'f'}, + {"DATE_PART", 'f'}, {"DATE_SUB", 'f'}, + {"DATE_TRUNC", 'f'}, + {"DAVG", 'f'}, {"DAY", 'f'}, {"DAYNAME", 'f'}, {"DAYOFMONTH", 'f'}, @@ -134,24 +206,40 @@ static const keyword_t sql_keywords[] = { {"DAY_MINUTE", 'k'}, {"DAY_SECOND", 'k'}, {"DBMS_PIPE.RECEIVE_MESSAGE", 'f'}, + {"DB_ID", 'f'}, + {"DB_NAME", 'f'}, + {"DCOUNT", 'f'}, {"DEC", 'k'}, {"DECIMAL", 'k'}, {"DECLARE", 'k'}, {"DECODE", 'f'}, + {"DECRYPTBYASMKEY", 'f'}, + {"DECRYPTBYCERT", 'f'}, + {"DECRYPTBYKEY", 'f'}, + {"DECRYPTBYKEYAUTOCERT", 'f'}, + {"DECRYPTBYPASSPHRASE", 'f'}, {"DEFAULT", 'k'}, {"DEGREES", 'f'}, {"DELAY", 'k'}, {"DELAYED", 'k'}, {"DELETE", 'k'}, + {"DENSE_RANK", 'f'}, {"DESC", 'k'}, {"DESCRIBE", 'k'}, {"DES_DECRYPT", 'f'}, {"DES_ENCRYPT", 'f'}, {"DETERMINISTIC", 'k'}, + {"DFIRST", 'f'}, + {"DIFFERENCE", 'f'}, {"DISTINCROW", 'k'}, {"DISTINCT", 'k'}, {"DIV", 'o'}, + {"DLAST", 'f'}, + {"DLOOKUP", 'f'}, + {"DMAX", 'f'}, + {"DMIN", 'f'}, {"DROP", 'k'}, + {"DSUM", 'f'}, {"DUAL", 'k'}, {"EACH", 'k'}, {"ELSE", 'k'}, @@ -160,7 +248,16 @@ static const keyword_t sql_keywords[] = { {"ENCLOSED", 'k'}, {"ENCODE", 'f'}, {"ENCRYPT", 'f'}, + {"ENCRYPTBYASMKEY", 'f'}, + {"ENCRYPTBYCERT", 'f'}, + {"ENCRYPTBYKEY", 'f'}, + {"ENCRYPTBYPASSPHRASE", 'f'}, + {"ENUM_FIRST", 'f'}, + {"ENUM_LAST", 'f'}, + {"ENUM_RANGE", 'f'}, + {"EOMONTH", 'f'}, {"ESCAPED", 'k'}, + {"EVENTDATA", 'f'}, {"EXEC", 'k'}, {"EXECUTE", 'k'}, {"EXISTS", 'k'}, @@ -174,8 +271,19 @@ static const keyword_t sql_keywords[] = { {"FALSE", '1'}, {"FETCH", 'k'}, {"FIELD", 'f'}, + {"FILEDATETIME", 'f'}, + {"FILEGROUPPROPERTY", 'f'}, + {"FILEGROUP_ID", 'f'}, + {"FILEGROUP_NAME", 'f'}, + {"FILELEN", 'f'}, + {"FILEPROPERTY", 'f'}, + {"FILE_ID", 'f'}, + {"FILE_IDEX", 'f'}, + {"FILE_NAME", 'f'}, {"FIND_IN_SET", 'f'}, + {"FIRST_VALUE", 'f'}, {"FLOOR", 'f'}, + {"FN_VIRTUALFILESTATS", 'f'}, {"FOR", 'n'}, {"FORCE", 'k'}, {"FOREIGN", 'k'}, @@ -185,14 +293,26 @@ static const keyword_t sql_keywords[] = { {"FROM_DAYS", 'f'}, {"FROM_UNIXTIME", 'f'}, {"FULLTEXT", 'k'}, + {"FULLTEXTCATALOGPROPERTY", 'f'}, + {"FULLTEXTSERVICEPROPERTY", 'f'}, {"GENERATE_SERIES", 'f'}, + {"GENERATE_SUBSCRIPTS", 'f'}, + {"GETATTR", 'f'}, + {"GETDATE", 'f'}, + {"GETUTCDATE", 'f'}, + {"GET_BIT", 'f'}, + {"GET_BYTE", 'f'}, {"GET_FORMAT", 'f'}, {"GET_LOCK", 'f'}, {"GOTO", 'k'}, {"GRANT", 'k'}, {"GREATEST", 'f'}, {"GROUP", 'n'}, + {"GROUPING", 'f'}, + {"GROUPING_ID", 'f'}, {"GROUP_CONCAT", 'f'}, + {"HASHBYTES", 'f'}, + {"HAS_PERMS_BY_NAME", 'f'}, {"HAVING", 'k'}, {"HEX", 'f'}, {"HIGH_PRIORITY", 'k'}, @@ -201,6 +321,10 @@ static const keyword_t sql_keywords[] = { {"HOUR_MICROSECOND", 'k'}, {"HOUR_MINUTE", 'k'}, {"HOUR_SECOND", 'k'}, + {"IDENTIFY", 'f'}, + {"IDENT_CURRENT", 'f'}, + {"IDENT_INCR", 'f'}, + {"IDENT_SEED", 'f'}, {"IF", 'k'}, {"IFF", 'f'}, {"IFNULL", 'f'}, @@ -208,14 +332,19 @@ static const keyword_t sql_keywords[] = { {"IIF", 'f'}, {"IN", 'n'}, {"INDEX", 'k'}, + {"INDEXKEY_PROPERTY", 'f'}, + {"INDEXPROPERTY", 'f'}, + {"INDEX_COL", 'f'}, {"INET_ATON", 'f'}, {"INET_NTOA", 'f'}, {"INFILE", 'k'}, + {"INITCAP", 'f'}, {"INNER", 'k'}, {"INOUT", 'k'}, {"INSENSITIVE", 'k'}, {"INSERT", 'k'}, {"INSTR", 'f'}, + {"INSTRREV", 'f'}, {"INT", 'k'}, {"INT1", 'k'}, {"INT2", 'k'}, @@ -226,16 +355,32 @@ static const keyword_t sql_keywords[] = { {"INTERVAL", 'k'}, {"INTO", 'k'}, {"IS", 'o'}, + {"ISDATE", 'f'}, + {"ISEMPTY", 'f'}, + {"ISFINITE", 'f'}, {"ISNULL", 'f'}, + {"ISNUMERIC", 'f'}, {"IS_FREE_LOCK", 'f'}, - {"IS_MEMBERIS_SRVROLEMEMBER", 'f'}, + {"IS_MEMBER", 'f'}, + {"IS_OBJECTSIGNED", 'f'}, + {"IS_ROLEMEMBER", 'f'}, + {"IS_SRVROLEMEMBER", 'f'}, {"IS_USED_LOCK", 'f'}, {"ITERATE", 'k'}, {"JOIN", 'k'}, + {"JUSTIFY_DAYS", 'f'}, + {"JUSTIFY_HOURS", 'f'}, + {"JUSTIFY_INTERVAL", 'f'}, {"KEYS", 'k'}, + {"KEY_GUID", 'f'}, + {"KEY_ID", 'f'}, {"KILL", 'k'}, + {"LAG", 'f'}, + {"LASTVAL", 'f'}, {"LAST_INSERT_ID", 'f'}, + {"LAST_VALUE", 'f'}, {"LCASE", 'f'}, + {"LEAD", 'f'}, {"LEADING", 'k'}, {"LEAST", 'f'}, {"LEAVE", 'k'}, @@ -259,11 +404,14 @@ static const keyword_t sql_keywords[] = { {"LONGTEXT", 'k'}, {"LOOP", 'k'}, {"LOWER", 'f'}, + {"LOWER_INC", 'f'}, + {"LOWER_INF", 'f'}, {"LOW_PRIORITY", 'k'}, {"LPAD", 'f'}, {"LTRIM", 'f'}, {"MAKEDATE", 'f'}, {"MAKE_SET", 'f'}, + {"MASKLEN", 'f'}, {"MASTER_BIND", 'k'}, {"MASTER_POS_WAIT", 'f'}, {"MASTER_SSL_VERIFY_SERVER_CERT", 'k'}, @@ -282,18 +430,30 @@ static const keyword_t sql_keywords[] = { {"MINUTE", 'f'}, {"MINUTE_MICROSECOND", 'k'}, {"MINUTE_SECOND", 'k'}, + {"MKDIR", 'f'}, {"MOD", 'o'}, {"MODE", 'n'}, {"MODIFIES", 'k'}, {"MONTH", 'f'}, {"MONTHNAME", 'f'}, {"NAME_CONST", 'f'}, + {"NETMASK", 'f'}, + {"NEXTVAL", 'f'}, {"NOT", 'o'}, {"NOW", 'f'}, {"NO_WRITE_TO_BINLOG", 'k'}, + {"NTH_VALUE", 'f'}, + {"NTILE", 'f'}, {"NULL", '1'}, {"NULLIF", 'f'}, {"NUMERIC", 'k'}, + {"NZ", 'f'}, + {"OBJECTPROPERTY", 'f'}, + {"OBJECTPROPERTYEX", 'f'}, + {"OBJECT_DEFINITION", 'f'}, + {"OBJECT_ID", 'f'}, + {"OBJECT_NAME", 'f'}, + {"OBJECT_SCHEMA_NAME", 'f'}, {"OCT", 'f'}, {"OCTET_LENGTH", 'f'}, {"OFFSET", 'k'}, @@ -310,15 +470,49 @@ static const keyword_t sql_keywords[] = { {"OR", '&'}, {"ORD", 'f'}, {"ORDER", 'n'}, + {"ORIGINAL_DB_NAME", 'f'}, + {"ORIGINAL_LOGIN", 'f'}, {"OUT", 'k'}, {"OUTFILE", 'k'}, + {"OVERLAPS", 'f'}, + {"OVERLAY", 'f'}, {"OWN3D", 'k'}, + {"PARSENAME", 'f'}, {"PARTITION", 'k'}, {"PASSWORD", 'k'}, + {"PATHINDEX", 'f'}, + {"PATINDEX", 'f'}, + {"PERCENTILE_COUNT", 'f'}, + {"PERCENTILE_DISC", 'f'}, + {"PERCENTILE_RANK", 'f'}, + {"PERCENT_RANK", 'f'}, {"PERIOD_ADD", 'f'}, - {"PERIOID_DIFF", 'f'}, + {"PERIOD_DIFF", 'f'}, + {"PERMISSIONS", 'f'}, {"PG_ADVISORY_LOCK", 'f'}, + {"PG_BACKEND_PID", 'f'}, + {"PG_CANCEL_BACKEND", 'f'}, + {"PG_CLIENT_ENCODING", 'f'}, + {"PG_CONF_LOAD_TIME", 'f'}, + {"PG_CREATE_RESTORE_POINT", 'f'}, + {"PG_HAS_ROLE", 'f'}, + {"PG_IS_IN_RECOVERY", 'f'}, + {"PG_IS_OTHER_TEMP_SCHEMA", 'f'}, + {"PG_LISTENING_CHANNELS", 'f'}, + {"PG_LS_DIR", 'f'}, + {"PG_MY_TEMP_SCHEMA", 'f'}, + {"PG_POSTMASTER_START_TIME", 'f'}, + {"PG_READ_BINARY_FILE", 'f'}, + {"PG_READ_FILE", 'f'}, + {"PG_RELOAD_CONF", 'f'}, + {"PG_ROTATE_LOGFILE", 'f'}, {"PG_SLEEP", 'f'}, + {"PG_START_BACKUP", 'f'}, + {"PG_STAT_FILE", 'f'}, + {"PG_STOP_BACKUP", 'f'}, + {"PG_SWITCH_XLOG", 'f'}, + {"PG_TERMINATE_BACKEND", 'f'}, + {"PG_TRIGGER_DEPTH", 'f'}, {"PI", 'f'}, {"POSITION", 'f'}, {"POW", 'f'}, @@ -326,24 +520,38 @@ static const keyword_t sql_keywords[] = { {"PRECISION", 'k'}, {"PRIMARY", 'k'}, {"PROCEDURE", 'k'}, + {"PUBLISHINGSERVERNAME", 'f'}, {"PURGE", 'k'}, + {"PWDCOMPARE", 'f'}, + {"PWDENCRYPT", 'f'}, {"QUARTER", 'f'}, {"QUOTE", 'f'}, + {"QUOTENAME", 'f'}, + {"QUOTE_IDENT", 'f'}, + {"QUOTE_LITERAL", 'f'}, + {"QUOTE_NULLABLE", 'f'}, {"RADIANS", 'f'}, {"RAND", 'f'}, + {"RANDOM", 'f'}, {"RANDOMBLOB", 'f'}, {"RANGE", 'k'}, + {"RANK", 'f'}, {"READ", 'k'}, {"READS", 'k'}, {"READ_WRITE", 'k'}, {"REAL", 'n'}, {"REFERENCES", 'k'}, {"REGEXP", 'o'}, + {"REGEXP_MATCHES", 'f'}, + {"REGEXP_REPLACE", 'f'}, + {"REGEXP_SPLIT_TO_ARRAY", 'f'}, + {"REGEXP_SPLIT_TO_TABLE", 'f'}, {"RELEASE", 'k'}, {"RELEASE_LOCK", 'f'}, {"RENAME", 'k'}, {"REPEAT", 'k'}, {"REPLACE", 'k'}, + {"REPLICATE", 'f'}, {"REQUIRE", 'k'}, {"RESIGNAL", 'k'}, {"RESTRICT", 'k'}, @@ -355,10 +563,15 @@ static const keyword_t sql_keywords[] = { {"ROUND", 'f'}, {"ROW", 'f'}, {"ROW_COUNT", 'f'}, + {"ROW_NUMBER", 'f'}, + {"ROW_TO_JSON", 'f'}, {"RPAD", 'f'}, {"RTRIM", 'f'}, + {"SCHAMA_NAME", 'f'}, {"SCHEMA", 'k'}, {"SCHEMAS", 'k'}, + {"SCHEMA_ID", 'f'}, + {"SCOPE_IDENTITY", 'f'}, {"SECOND_MICROSECOND", 'k'}, {"SEC_TO_TIME", 'f'}, {"SELECT", 'k'}, @@ -366,6 +579,13 @@ static const keyword_t sql_keywords[] = { {"SEPARATOR", 'k'}, {"SESSION_USER", 'f'}, {"SET", 'k'}, + {"SETATTR", 'f'}, + {"SETSEED", 'f'}, + {"SETVAL", 'f'}, + {"SET_BIT", 'f'}, + {"SET_BYTE", 'f'}, + {"SET_CONFIG", 'f'}, + {"SET_MASKLEN", 'f'}, {"SHA", 'f'}, {"SHA1", 'f'}, {"SHA2", 'f'}, @@ -373,15 +593,19 @@ static const keyword_t sql_keywords[] = { {"SHUTDOWN", 'k'}, {"SIGN", 'f'}, {"SIGNAL", 'k'}, + {"SIGNBYASMKEY", 'f'}, + {"SIGNBYCERT", 'f'}, {"SIMILAR", 'k'}, {"SIN", 'f'}, {"SLEEP", 'f'}, + {"SMALLDATETIMEFROMPARTS", 'f'}, {"SMALLINT", 'k'}, {"SOUNDEX", 'f'}, {"SOUNDS", 'o'}, {"SPACE", 'f'}, {"SPATIAL", 'k'}, {"SPECIFIC", 'k'}, + {"SPLIT_PART", 'f'}, {"SQL", 'k'}, {"SQLEXCEPTION", 'k'}, {"SQLSTATE", 'k'}, @@ -389,49 +613,91 @@ static const keyword_t sql_keywords[] = { {"SQL_BIG_RESULT", 'k'}, {"SQL_CALC_FOUND_ROWS", 'k'}, {"SQL_SMALL_RESULT", 'k'}, + {"SQL_VARIANT_PROPERTY", 'f'}, {"SQRT", 'f'}, {"SSL", 'k'}, {"STARTING", 'k'}, - {"STDDEV", 'f'}, + {"STATEMENT_TIMESTAMP", 'f'}, + {"STATS_DATE", 'f'}, + {"STDDEV", 'p'}, {"STDDEV_POP", 'f'}, {"STDDEV_SAMP", 'f'}, {"STRAIGHT_JOIN", 'k'}, {"STRCMP", 'f'}, + {"STRCONV", 'f'}, + {"STRING_AGG", 'f'}, + {"STRING_TO_ARRAY", 'f'}, + {"STRPOS", 'f'}, {"STR_TO_DATE", 'f'}, + {"STUFF", 'f'}, {"SUBDATE", 'f'}, {"SUBSTR", 'f'}, {"SUBSTRING", 'f'}, {"SUBSTRING_INDEX", 'f'}, {"SUBTIME", 'f'}, {"SUM", 'f'}, + {"SUSER_ID", 'f'}, + {"SUSER_NAME", 'f'}, + {"SUSER_SID", 'f'}, + {"SUSER_SNAME", 'f'}, + {"SWITCHOFFET", 'f'}, + {"SYS.FN_BUILTIN_PERMISSIONS", 'f'}, + {"SYS.FN_GET_AUDIT_FILE", 'f'}, + {"SYS.FN_MY_PERMISSIONS", 'f'}, {"SYS.STRAGG", 'f'}, {"SYSCOLUMNS", 'k'}, {"SYSDATE", 'f'}, + {"SYSDATETIME", 'f'}, + {"SYSDATETIMEOFFSET", 'f'}, {"SYSOBJECTS", 'k'}, {"SYSTEM_USER", 'f'}, {"SYSUSERS", 'k'}, + {"SYSUTCDATETME", 'f'}, {"TABLE", 'k'}, {"TAN", 'f'}, {"TERMINATED", 'k'}, + {"TERTIARY_WEIGHTS", 'f'}, + {"TEXTPTR", 'f'}, + {"TEXTVALID", 'f'}, {"THEN", 'k'}, {"TIME", 'k'}, {"TIMEDIFF", 'f'}, + {"TIMEFROMPARTS", 'f'}, + {"TIMEOFDAY", 'f'}, + {"TIMESERIAL", 'f'}, {"TIMESTAMP", 'f'}, {"TIMESTAMPADD", 'f'}, + {"TIMEVALUE", 'f'}, {"TIME_FORMAT", 'f'}, {"TIME_TO_SEC", 'f'}, {"TINYBLOB", 'k'}, {"TINYINT", 'k'}, {"TINYTEXT", 'k'}, + {"TODATETIMEOFFSET", 'f'}, {"TOP", 'k'}, + {"TO_ASCII", 'f'}, {"TO_CHAR", 'f'}, + {"TO_DATE", 'f'}, {"TO_DAYS", 'f'}, + {"TO_HEX", 'f'}, + {"TO_NUMBER", 'f'}, {"TO_SECONDS", 'f'}, + {"TO_TIMESTAMP", 'f'}, {"TRAILING", 'n'}, + {"TRANSACTION_TIMESTAMP", 'f'}, + {"TRANSLATE", 'f'}, {"TRIGGER", 'k'}, + {"TRIGGER_NESTLEVEL", 'f'}, {"TRIM", 'f'}, {"TRUE", '1'}, + {"TRUNC", 'f'}, {"TRUNCATE", 'f'}, + {"TRY_CAST", 'f'}, + {"TRY_CONVERT", 'f'}, + {"TRY_PARSE", 'f'}, + {"TYPEPROPERTY", 'f'}, + {"TYPE_ID", 'f'}, + {"TYPE_NAME", 'f'}, {"UCASE", 'f'}, {"UNCOMPRESS", 'f'}, {"UNCOMPRESS_LENGTH", 'f'}, @@ -441,13 +707,19 @@ static const keyword_t sql_keywords[] = { {"UNIQUE", 'n'}, {"UNIX_TIMESTAMP", 'f'}, {"UNI_ON", 'U'}, + {"UNKNOWN", 'k'}, {"UNLOCK", 'k'}, + {"UNNEST", 'f'}, {"UNSIGNED", 'k'}, {"UPDATE", 'k'}, {"UPDATEXML", 'f'}, {"UPPER", 'f'}, + {"UPPER_INC", 'f'}, + {"UPPER_INF", 'f'}, {"USAGE", 'k'}, {"USE", 'k'}, + {"USER_ID", 'n'}, + {"USER_NAME", 'f'}, {"USING", 'f'}, {"UTC_DATE", 'k'}, {"UTC_TIME", 'k'}, @@ -456,36 +728,53 @@ static const keyword_t sql_keywords[] = { {"UUID", 'f'}, {"UUID_SHORT", 'f'}, {"VALUES", 'k'}, + {"VAR", 'f'}, {"VARBINARY", 'k'}, {"VARCHAR", 'k'}, {"VARCHARACTER", 'k'}, {"VARIANCE", 'f'}, + {"VARP", 'f'}, {"VARYING", 'k'}, {"VAR_POP", 'f'}, {"VAR_SAMP", 'f'}, + {"VERIFYSIGNEDBYASMKEY", 'f'}, + {"VERIFYSIGNEDBYCERT", 'f'}, {"VERSION", 'f'}, {"WAITFOR", 'k'}, {"WEEK", 'f'}, {"WEEKDAY", 'f'}, + {"WEEKDAYNAME", 'f'}, {"WEEKOFYEAR", 'f'}, {"WHEN", 'k'}, {"WHERE", 'k'}, {"WHILE", 'k'}, + {"WIDTH_BUCKET", 'f'}, {"WITH", 'k'}, + {"XMLAGG", 'f'}, + {"XMLCOMMENT", 'f'}, + {"XMLCONCAT", 'f'}, {"XMLELEMENT", 'f'}, + {"XMLEXISTS", 'f'}, {"XMLFOREST", 'f'}, {"XMLFORMAT", 'f'}, + {"XMLPI", 'f'}, + {"XMLROOT", 'f'}, {"XMLTYPE", 'f'}, + {"XML_IS_WELL_FORMED", 'f'}, {"XOR", 'o'}, + {"XPATH", 'f'}, + {"XPATH_EXISTS", 'f'}, {"XP_EXECRESULTSET", 'k'}, {"YEAR", 'f'}, {"YEARWEEK", 'f'}, {"YEAR_MONTH", 'k'}, {"ZEROFILL", 'k'}, }; -static const size_t sql_keywords_sz = 450; +static const size_t sql_keywords_sz = 737; static const char* multikeywords_start[] = { "ALTER", + "AT", + "AT TIME", "CROSS", "FULL", "GROUP", @@ -493,9 +782,13 @@ static const char* multikeywords_start[] = { "IN BOOLEAN", "INTERSECT", "IS", + "IS DISTINCT", + "IS NOT", "LEFT", "LOCK", "NATURAL", + "NEXT", + "NEXT VALUE", "NOT", "NOT SIMILAR", "ORDER", @@ -507,17 +800,23 @@ static const char* multikeywords_start[] = { "SOUNDS", "UNION", }; -static const size_t multikeywords_start_sz = 21; +static const size_t multikeywords_start_sz = 27; static const keyword_t multikeywords[] = { {"ALTER DOMAIN", 'k'}, {"ALTER TABLE", 'k'}, + {"AT TIME", 'n'}, + {"AT TIME ZONE", 'k'}, {"CROSS JOIN", 'k'}, {"FULL OUTER", 'k'}, {"GROUP BY", 'B'}, {"IN BOOLEAN", 'n'}, {"IN BOOLEAN MODE", 'k'}, {"INTERSECT ALL", 'o'}, + {"IS DISTINCT", 'n'}, + {"IS DISTINCT FROM", 'k'}, {"IS NOT", 'o'}, + {"IS NOT DISTINCT", 'n'}, + {"IS NOT DISTINCT FROM", 'k'}, {"LEFT JOIN", 'k'}, {"LEFT OUTER", 'k'}, {"LOCK TABLE", 'k'}, @@ -528,6 +827,8 @@ static const keyword_t multikeywords[] = { {"NATURAL LEFT", 'k'}, {"NATURAL OUTER", 'k'}, {"NATURAL RIGHT", 'k'}, + {"NEXT VALUE", 'n'}, + {"NEXT VALUE FOR", 'k'}, {"NOT BETWEEN", 'o'}, {"NOT IN", 'o'}, {"NOT LIKE", 'o'}, @@ -545,7 +846,7 @@ static const keyword_t multikeywords[] = { {"SOUNDS LIKE", 'o'}, {"UNION ALL", 'U'}, }; -static const size_t multikeywords_sz = 35; +static const size_t multikeywords_sz = 43; typedef size_t (*pt2Function)(sfilter *sf); static const pt2Function char_parse_map[] = { diff --git a/apache2/libinjection/sqlparse_private.h b/apache2/libinjection/sqlparse_private.h index 154accf6..e080a009 100644 --- a/apache2/libinjection/sqlparse_private.h +++ b/apache2/libinjection/sqlparse_private.h @@ -13,10 +13,6 @@ #include "sqlparse.h" -#define CHAR_NULL '\0' -#define CHAR_SINGLE '\'' -#define CHAR_DOUBLE '"' - /*** * The stdlib function 'strspn' assumes input to null-delimited. * This allows us to specifying and input length and allows @@ -100,10 +96,6 @@ int sqli_tokenize(sfilter * sf, stoken_t * sout); int filter_fold(sfilter * sf, stoken_t * sout); -int is_string_sqli(sfilter * sql_state, const char *s, size_t slen, - const char delim, - ptr_fingerprints_fn fn); - int char2int(char c); unsigned long long pat2int(const char *pat);