Respond with error on unsupported query parameters (if only for specific Nessus False Positive)

1. The problem I’m having:

Hello!

Is there a way to make Caddy respond with an error message on detecting unsupported query parameters (instead of just logging it)?

Details:

I’ve beein using Caddy for some time to serve a tiny http (no s) web site, delivering static file content only. No issues at all and I like the tiny config that allows this and the neat look of the directory listing.

My company has now changed the security scanning policy and the latest tenable.sc scan reports a critical issue “A CGI application hosted on the remote web server is potentially prone to SQL injection attack.” This is Nessus plugin 43160, “CGI Generic SQL Injection (blind, time based)” with instructions to “Modify the affected CGI scripts so that they properly escape arguments.”.

Clearly this is a false positive - neither does this Caddy instance have a database connection nor does it (afaik) understand CGI in the first place…

This specific scan simply appends “/?sort=namedirfirst&order=desc’;SELECT%20pg_sleep(21);–” to the base URL. Caddy (as per log entry) seems to sanitize/strip these parameters and delivers the directory listing as usual. This in turn is wrongly interpreted by the scanning plugin as a valid response to its specific injected SQL statement.

I’ve already asked our security team to not flag this as a crittical error for the specific web server but I doubt they’ll go along with that. So:

Is there a way to make Caddy respond with an error message on detecting unsupported query parameters (instead of just logging it)?

Or, possibly just to respond with an error on this exact param string?

I’ve found nothing in the documentation but I might be using the wrong terms to search - “question mark” or “query” parameters obviously are far too generic… :frowning:

Any help or hints appreciated!
Also on any mistakes I might have made in my config…
Thanks!

Regards,
jbon

2. Error messages and/or full log output:

process log:

2023-03-23T05:02:17.760+0100    e[35mDEBUGe[0m  http.handlers.file_server       sanitized path join     {"site_root": "D:\\Caddy-ContentDir", "request_path": "/", "result": "D:\\Caddy-ContentDir"}
2023-03-23T05:02:17.760+0100    e[35mDEBUGe[0m  http.handlers.file_server       no index file in directory      {"path": "D:\\Caddy-ContentDir", "index_filenames": ["index.html", "index.txt"]}
2023-03-23T05:02:17.761+0100    e[35mDEBUGe[0m  http.handlers.file_server       browse enabled; listing directory contents      {"path": "D:\\Caddy-ContentDir", "root": "D:\\Caddy-ContentDir"}
2023-03-23T05:02:17.766+0100    e[35mDEBUGe[0m  http.stdlib     http: URL query contains semicolon, which is no longer a supported separator; parts of the query may be stripped when parsed; see golang.org/issue/25192
2023-03-23T05:02:17.955+0100    e[35mDEBUGe[0m  http.handlers.file_server       sanitized path join     {"site_root": "D:\\Caddy-ContentDir", "request_path": "/favicon.ico", "result": "D:\\Caddy-ContentDir\\favicon.ico"}
2023-03-23T05:02:17.955+0100    e[35mDEBUGe[0m  http.handlers.file_server       opening file    {"filename": "D:\\Caddy-ContentDir\\favicon.ico"}

access.log

2023-03-23T05:02:17.766+0100    e[34mINFOe[0m   http.log.access.log0    handled request {"request": {"remote_ip": "147.161.231.90", "remote_port": "16189", "proto": "HTTP/1.1", "method": "GET", "host": "mail.enmarket.de", "uri": "/?sort=namedirfirst&order=desc%27;SELECT%20pg_sleep(21);--Synopsis:", "headers": {"Accept-Language": ["en-US,en;q=0.5"], "Accept-Encoding": ["gzip, deflate"], "Dnt": ["1"], "Connection": ["keep-alive"], "Cookie": [], "Upgrade-Insecure-Requests": ["1"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,*/*;q=0.8"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0"], "X-Forwarded-For": ["149.224.53.152"]}}, "user_id": "", "duration": 0.0069085, "size": 5566, "status": 200, "resp_headers": {"Server": ["Caddy"], "Set-Cookie": [], "Content-Type": ["text/html; charset=utf-8"], "Content-Encoding": ["gzip"], "Vary": ["Accept-Encoding"]}}
2023-03-23T05:02:17.960+0100    e[34mINFOe[0m   http.log.access.log0    handled request {"request": {"remote_ip": "147.161.231.90", "remote_port": "16189", "proto": "HTTP/1.1", "method": "GET", "host": "mail.enmarket.de", "uri": "/favicon.ico", "headers": {"Accept-Language": ["en-US,en;q=0.5"], "Dnt": ["1"], "Referer": ["http://mail.enmarket.de/?sort=namedirfirst&order=desc%27;SELECT%20pg_sleep(21);--Synopsis:"], "Cookie": [], "X-Forwarded-For": ["149.224.53.152"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0"], "Accept": ["image/avif,*/*"], "Accept-Encoding": ["gzip, deflate"], "Connection": ["keep-alive"]}}, "user_id": "", "duration": 0.005148, "size": 59058, "status": 200, "resp_headers": {"Server": ["Caddy"], "Etag": ["\"rbdvm319ki\""], "Content-Type": ["image/x-icon"], "Last-Modified": ["Thu, 05 May 2022 00:20:27 GMT"], "Accept-Ranges": ["bytes"], "Content-Length": ["59058"]}}

3. Caddy version:

v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=

4. How I installed and ran Caddy:

Windows Service Wrapper executing “D:\Caddy\Caddy.exe run --config D:\Caddy\Caddyfile”

a. System environment:

Windows Server 2019

b. Command:

D:\Caddy\Caddy.exe run --config D:\Caddy\Caddyfile

c. Service/unit/compose file:

n.a.

d. My complete Caddy config:

{
	admin off
	auto_https off
	grace_period 10s
	log {
		output file "D:\Caddy-Logfiles\caddy-process.log" {
			roll_uncompressed
			roll_local_time
		}
		format console {
			time_format iso8601
		}
		level debug
	}
}

:80 {
	encode zstd gzip
	root * "D:\Caddy-ContentDir"
	file_server browse
	log {
		output file "D:\Caddy-Logfiles\caddy-access.log" {
			roll_uncompressed
			roll_local_time
		}
		format console {
			time_format iso8601
		}
		level debug
	}
	handle_errors {
		respond "{err.status_code} {err.status_text}"
	}
}

5. Links to relevant resources:

That message is coming directly from Go’s stdlib, not from Caddy. So we can’t really hook into that directly.

But you can probably use a regexp to match on the query string containing a ; I guess.

@badquery `{query}.matches(";")`
error @badquery 400

Obviously this ignores query string semantics and only looks for ; in the query at all. Depends what you’re trying to do, but that might be fine for you.

Apparently Go is removing this warning from the logs in the next version:

But it won’t become an error after this change, it will just not be handled as a delimiter (as it was a long time ago in Go).

Thanks a lot for your hints - I’ll try to extend the regexp to match not only the ; but more of/the whole query to just trigger on this specific Nessus plugin.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.