示例#1
0
        private void ValidateHttp11(Package package)
        {
            // Is it claiming to be HTTP/1.1?  Then it shouldn't do HTTP/1.0 things
            // Blocks some common corporate proxy servers in strict mode

            if (package.HeadersMixed.ContainsKey("Pragma")
                && package.HeadersMixed["Pragma"].Contains("no-cache")
                && !package.HeadersMixed.ContainsKey("Cache-Control")) {
                    package.RaiseStrict(Errors.Http11Invalid);
            }
        }
示例#2
0
        public RuleProcessing Validate(Package package)
        {
            if (package.Request.HttpMethod != "POST" && String.IsNullOrEmpty(package.Request.UserAgent))
                package.Raise(Errors.UserAgentMissing);

            // Broken spambots send URLs with various invalid characters
            // Some broken browsers send the #vector in the referer field :(
            // Worse yet, some Javascript client-side apps do the same in
            // blatant violation of the protocol and good sense.
            // if (strpos($package['request_uri'], "#") !== FALSE || strpos($package['headers_mixed']['Referer'], "#") !== FALSE) {

            if (package.Request.RawUrl.Contains('#'))
                package.RaiseStrict(Errors.Malicious);

            // A pretty nasty SQL injection attack on IIS servers
            if (package.Request.RawUrl.Contains(";DECLARE%20@"))
                package.Raise(Errors.Malicious);

            // Range: field exists and begins with 0
            // Real user-agents do not start ranges at 0
            // NOTE: this blocks the whois.sc bot. No big loss.
            // Exceptions: MT (not fixable); LJ (refuses to fix; may be
            // blocked again in the future); Facebook
            if (package.HeadersMixed.ContainsKey("Range")
                && package.HeadersMixed["Range"].Contains("=0-")) {
                if (!(
                    package.Request.UserAgent.StartsWith("MovableType") ||
                    package.Request.UserAgent.StartsWith("URI::Fetch") ||
                    package.Request.UserAgent.StartsWith("php-openid/") ||
                    package.Request.UserAgent.StartsWith("facebookexternalhit")
                )) {
                    package.RaiseStrict(Errors.RangeHeaderZero);
                }
            }

            // Content-Range is a response header, not a request header
            if (package.HeadersMixed.ContainsKey("Content-Range"))
                package.Raise(Errors.InvalidRangeHeader);

            // Lowercase via is used by open proxies/referrer spammers
            // Exceptions: Clearswift uses lowercase via (refuses to fix;
            // may be blocked again in the future)
            if (package.Request.Headers["via"] != null &&
                !package.Request.Headers["via"].Contains("Clearswift") &&
                !package.Request.UserAgent.Contains("CoralWebPrx"))
                package.Raise(Errors.InvalidVia);

            // pinappleproxy is used by referrer spammers
            if (package.HeadersMixed.ContainsKey("Via")) {
                string via = package.HeadersMixed["Via"].ToLowerInvariant();
                if (via.Contains("pinappleproxy") || via.Contains("pcnetserver") || via.Contains("invisiware"))
                    package.Raise(Errors.BannedProxy);
            }

            // TE: if present must have Connection: TE
            // RFC 2616 14.39
            // Blocks Microsoft ISA Server 2004 in strict mode. Contact Microsoft
            // to obtain a hotfix.
            if (package.HeadersMixed.ContainsKey("Te")) {
                if (Regex.Match(package.HeadersMixed["Connection"], @"\bTE\b").Success)
                    package.RaiseStrict(Errors.TeWithoutConnectionTe);
            }

            if (package.HeadersMixed.ContainsKey("Connection")) {
                // Connection: keep-alive and close are mutually exclusive.
                // Keep-Alive shouldn't appear twice, neither should Close.
                var connection = package.HeadersMixed.GetValues("Connection");
                var keepAlives = connection.Sum
                    (x => Regex.Matches(x, @"\bKeep-Alive\b", RegexOptions.IgnoreCase).Count);
                var closes = connection.Sum
                    (x => Regex.Matches(x, @"\bClose\b", RegexOptions.IgnoreCase).Count);
                if (keepAlives + closes > 1)
                    package.Raise(Errors.InvalidConnectionHeader);

                // Keep-Alive format in RFC 2068; some bots mangle these headers
                if (connection.Any(x => x.IndexOf
                    ("Keep-Alive: ", StringComparison.InvariantCultureIgnoreCase) >= 0))
                    package.Raise(Errors.MaliciousConnectionHeader);
            }

            // Headers which are not seen from normal user agents; only malicious bots
            if (package.HeadersMixed.ContainsKey("X-Aaaaaaaaaaaa") ||
                package.HeadersMixed.ContainsKey("X-Aaaaaaaaaa"))
                package.Raise(Errors.ProhibitedHeader);

            // Proxy-Connection does not exist and should never be seen in the wild
            // http://lists.w3.org/Archives/Public/ietf-http-wg-old/1999JanApr/0032.html
            // http://lists.w3.org/Archives/Public/ietf-http-wg-old/1999JanApr/0040.html
            if (package.HeadersMixed.ContainsKey("Proxy-Connection"))
                package.RaiseStrict(Errors.ProxyConnectionHeaderPresent);

            if (package.HeadersMixed.ContainsKey("Referer")) {
                string referer = package.HeadersMixed["Referer"];
                // Referer, if it exists, must not be blank
                if (referer == String.Empty)
                    package.Raise(Errors.BlankReferer);

                // Referer, if it exists, must contain a :
                // While a relative URL is technically valid in Referer, all known
                // legitimate user-agents send an absolute URL
                if (!referer.Contains(":"))
                    package.Raise(Errors.CorruptReferer);
            }

            return RuleProcessing.Continue;
        }