Skip to content
This repository has been archived by the owner on May 14, 2020. It is now read-only.

Block proxy requests (GET http://example.org/ HTTP/1.1) #501

Open
dune73 opened this issue Aug 10, 2016 · 16 comments
Open

Block proxy requests (GET http://example.org/ HTTP/1.1) #501

dune73 opened this issue Aug 10, 2016 · 16 comments
Assignees

Comments

@dune73
Copy link
Contributor

dune73 commented Aug 10, 2016

http://www.tutorialspoint.com/http/http_requests.htm mentions:

The absoluteURI is used when an HTTP request is being made to a proxy. The proxy is requested to forward the request or service from a valid cache, and return the response. For example: 

GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

We accept this format and I do not see why an application server or a reverse proxy should. There are quite a of these attempts on my servers.

Block at PL1?

@lifeforms
Copy link
Contributor

Sounds great to me. Would solve a problem of inadvertently misconfigured open proxies.

@csanders-git csanders-git added this to the CRS v3.1.0 RC1 milestone Aug 10, 2016
@dune73
Copy link
Contributor Author

dune73 commented Nov 1, 2016

Reporting on an email conversation:

Message by @lifeforms

I investigated a request that was blocked in CRS2 and passed in CRS3.

It seems to be an open proxy probe:

HEAD http://180.163.113.82/check_proxy HTTP/1.1
Host: 180.163.113.82
Proxy-Connection: Keep-Alive

I saw the exact same request on all my servers, so it probably scanned lots of the IPv4 internet.
In CRS2, interestingly there was no anti-proxy rule, it was rejected possibly by accident, due to the Proxy-Connection header:

Message: Warning. String match within "/Proxy-Connection/ /Lock-Token/ /Content-Range/ /Translate/ /via/ /if/" at TX:header_name. [file "/etc/apache2/security2/activated_rules/modsecurity_crs_30_http_policy.conf"] [line "100"] [id "960038"] [rev "2"] [msg "HTTP header is restricted by policy"] [data
"/Proxy-Connection/"] [severity "WARNING"] [ver "OWASP_CRS/2.2.9"] [maturity "9"] [accuracy "9"] [tag "OWASP_CRS/POLICY/HEADER_RESTRICTED"] [tag "OWASP_CRS/POLICY/FILES_NOT_ALLOWED"] [tag "WASCTC/WASC-21"] [tag "OWASP_TOP_10/A7"] [tag "PCI/12.1"] [tag "WASCTC/WASC-15"] [tag "OWASP_TOP_10/A7"] [tag "PCI/12.1"]

The Proxy-Connection header is now no longer in the default restricted header list.

I think trying a proxy connection attempt is likely malicious, unless you are running a proxy, in which case you could exclude the rule.

It’s similar to the CONNECT verb which we deny by default.

So we could add a quick rule like:

REQUEST_URI “@rx ^(?:http|https)://“

Or we could do nothing for RC3, since it’s not really a regression by design, there are probably few vulnerable hosts, and there’s maybe a possibility for blocking legitimate traffic? (Probably not in my opinion but maybe you know examples?)
What do you think about the priority?

It’s not much work to add the rule but my weekend is pretty full...

Response by @csanders-git

... I have some thoughts here.

Its not altogether uncommon for users to setup modsec in such a way as internal proxies are sending data to modsec and it is forwarding it on. I have a number of customers who do this. Should the burden be on them to disable this rule, perhaps... I am leaning to yes. Additionally, although we disable CONNECT perhaps
we want to add another rule here to detect HTTPS proxy scanning (although this seems rarer). I'm unsure of if you can actually use HTTPS on a proxy the same way you use HTTP I have a feeling most servers will reject this, but i'm unsure.

In either event, a Request-URI can, according to RFC spec, be "*" | absoluteURI | abs_path | authority. The RFC states that "HTTP/1.1 clients will only generate them (AbsoluteURI's) in requests to proxies". So we'd not expect any absoluteURI's these are slightly more broad than what Walter specified (although his http
case is the most common)

       absolute-URI  = scheme ":" hier-part [ "?" query ]

Not we could look for .*?:// but... I think we might just want to leverage the following:

   relative-part = "//" authority path-abempty
           / path-absolute
           / path-noscheme
           / path-empty

Using this we can actually do the MUCH quicker REQUEST_URI "!@beginsWith /". No proxy should understand /http://www.xyz.com as this would by definition make it relative. Thoughts?

I'm also caught between REPUTATION, PROTOCOL_ATTACKS and PROTOCOL_ENFORCEMENT. leaning to the latter. If you have a preference let me know.

I'll also direct you to https://www.trustwave.com/Resources/SpiderLabs-Blog/Detecting-Malice-with-ModSecurity--Open-Proxy-Abuse/ for further ideas on possible easy additions.


So overall most important is the first question, do we add this inspite of administrators who may be using a proxy.


Here is the rule I have in mind

SecRule REQUEST_URI "!@beginsWith /" \
       "msg:'Open Proxy Scanning Detected',\
       phase:request,\
       id:TBD,\
       rev:'1',\
       ver:'OWASP_CRS/3.0.0',\
       maturity:'5',\
       accuracy:'8',\
       severity:'CRITICAL',\
       capture,\
       tag:'application-multi',\
       tag:'language-multi',\
       tag:'platform-multi',\
       tag:'attack-protocol',\
       t:none,
       block,\
       logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
       setvar:'tx.msg=%{rule.msg}',\
       setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\
       setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},\
       setvar:tx.%{rule.id}-OWASP_CRS/WEB_ATTACK/OPEN-PROXY-%{matched_var_name}=%{tx.0}"


@dune73
Copy link
Contributor Author

dune73 commented Nov 1, 2016

I do like the elegance of "!@beginsWith /".

@lifeforms
Copy link
Contributor

lifeforms commented Nov 1, 2016

Me too. I love it. Whitelisting is always better. Maybe there will be LFI attempts too by using file:// URLs.

The rule would probably need to work on REQUEST_URI_RAW variable to retrieve the full protocol scheme and host. And @beginsWith doesn't capture so capture and logdata should go. Other than that I love this rule already!

I guess we will plan this for 3.1? Maybe we should note in the 3.0 CHANGES file however, that we have changed the default restricted headers. And maybe we should note which ones we removed from the details. In fact we probably should put those type of changes at the top of the list.

@csanders-git
Copy link
Contributor

3.1 or 3.0.1, I guess 3.1 since it's a new feature.

@dune73
Copy link
Contributor Author

dune73 commented Nov 1, 2016

I agree on 3.1(.0).

On Tue, Nov 01, 2016 at 09:37:57AM -0700, Chaim Sanders wrote:

3.1 or 3.0.1, I guess 3.1 since it's a new feature.

You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub:
#501 (comment)

@fzipi
Copy link
Contributor

fzipi commented Mar 22, 2018

@dune73 Can we put this in a MR? What needs to be done here?

@csanders-git
Copy link
Contributor

Seems reasonable - @dune73 you want me to take or do you want it?

@dune73
Copy link
Contributor Author

dune73 commented Mar 23, 2018

I'm all for integrating this into 3.1. Ideally as part of 920 at PL1.

@dune73
Copy link
Contributor Author

dune73 commented Mar 23, 2018

Rather not me, though. Still not bottom in my inbox.

@dune73
Copy link
Contributor Author

dune73 commented Mar 8, 2019

Still hoping somebody is picking this up.

@theMiddleBlue
Copy link
Contributor

I'm running this on my production... let's see what happen:

SecRule REQUEST_URI "!@beginsWith /" "id:920490,\
    phase:1,\
    block,\
    t:none,\
    msg:'Open Proxy Scanning Detected',\
    ver:'OWASP_CRS/3.1.0',\
    severity:'CRITICAL',\
    tag:'application-multi',\
    tag:'language-multi',\
    tag:'platform-multi',\
    tag:'attack-protocol',\
    logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
    setvar:'tx.msg=%{rule.msg}',\
    setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\
    setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},\
    setvar:tx.%{rule.id}-OWASP_CRS/WEB_ATTACK/OPEN-PROXY-%{matched_var_name}=%{tx.0}"

@fgsch
Copy link
Contributor

fgsch commented Oct 20, 2019

@theMiddleBlue did you get any useful info from the exercise above?

@dune73
Copy link
Contributor Author

dune73 commented Feb 11, 2020

During the monthly CRS chat, @theMiddleBlue volunteered to develop the proposed rule above into a working PR.

Meeting minutes: #1671 (comment)

@dune73
Copy link
Contributor Author

dune73 commented Mar 2, 2020

@theMiddleBlue : Do you have an update here?

@theMiddleBlue
Copy link
Contributor

not yet, unfortunately it seems that this rule never triggers since my Nginx convert something like HEAD http://localhost:80 HTTP/1.1 in HEAD / HTTP/1.1.

Request:

# cat test_req.txt 
HEAD http://wordpress/test.php HTTP/1.1
Host: wordpress
Proxy-Connection: Keep-Alive

Audit log:

{
  "transaction": {
    "client_ip": "172.18.0.1",
    "time_stamp": "Wed Mar  4 15:00:02 2020",
    "server_id": "09ebdb7ebc3b9ac7a7108173cd60f9ebc8e54350",
    "client_port": 43752,
    "host_ip": "172.18.0.4",
    "host_port": 80,
    "unique_id": "15833304024.405522",
    "request": {
      "method": "HEAD",
      "http_version": 1.1,
      "uri": "/test.php",
      "body": "",
      "headers": {
        "Host": "wordpress",
        "Proxy-Connection": "Keep-Alive"
      }
    },
    "response": {
      "body": "",
      "http_code": 200,
      "headers": {}
    },
    "producer": {
      "modsecurity": "ModSecurity v3.0.4 (Linux)",
      "connector": "ModSecurity-nginx v1.0.1",
      "secrules_engine": "DetectionOnly",
      "components": [
        "OWASP_CRS/3.2.0\""
      ]
    },
    "messages": []
  }
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants