Commit d9b66b0a authored by Martin Blix Grydeland's avatar Martin Blix Grydeland Committed by Pål Hermunn Johansen

Add VSV00003 information to the homepage

parent 0aa137fc
.. _VSV00003-mitigation:
VSV00003 DoS attack vector VCL mitigation
=========================================
Date: 2019-09-03
The issue documented in :ref:`VSV00003 <VSV00003>` can be mitigated from
VCL where deployment of binary fixes is not possible immediately.
We provide two methods of mitigation, one simple with a performance
impact, and one more complex method which can avoid the performance
impact, but may also need to the fall back to it.
Simple mitigation
-----------------
The simple mitigation method is to not use HTTP/1 keepalive connections by
setting the `Connection: close` header of the client response, which is
respected by varnish in that it closes the connection after all of the
response body has been sent.
HTTP/1 keepalive connections avoid overhead by re-using TCP
connections and, where used, TLS connections for multiple requests. By
not using keepalive connections, an increase in response times and
server load is to be expected.
To apply this mitigation method, add this snippet near the top of your
VCL after the `vcl 4.0` or `vcl 4.1` statement::
# https://varnish-cache.org/security/VSV00003-mitigation.html
sub return_deliver_mitigate_vsv00003 {
if (req.esi_level == 0 && req.proto != "HTTP/2.0") {
set resp.http.Connection = "close";
}
return (deliver);
}
and replace any `return (deliver);` statements in `sub vcl_deliver {}`
and `sub vcl_synth {}` with `call return_deliver_mitigate_vsv00003;`
For example, given you have::
sub vcl_deliver {
# ... your code
return (deliver);
}
sub vcl_synth {
# ... your code
return (deliver);
}
replace with::
sub vcl_deliver {
# ... your code
call return_deliver_mitigate_vsv00003;
}
sub vcl_synth {
# ... your code
call return_deliver_mitigate_vsv00003;
}
If there is no explicit `return (deliver)`, add the call statement at
the end of `vcl_deliver {}` and/or `vcl_synth {}`.
If there is no `vcl_deliver {}`, add one with just the call statement.
If there is no `vcl_synth {}`, copy it from the `builtin.vcl` and replace
the `return (deliver);`.
Complex mitigation avoiding the performance impact
--------------------------------------------------
The complex mitigation has the potential to avoid the performance
impact by `Connection: close`, but has the drawback of requiring
inline-C.
It can avoid the `Connection: close` for many cases, but needs to fall
back to it if newline characters are found on the workspace. For
simple VCL code, these should not exist.
Notice that this method should be applied with extra care. Though it
has been tested thoroughly, it is provided for use at your own
risk. In particular, this method may not work if the Varnish-Cache
source code has been patched.
The code has been tested with:
* varnish-6.2.0 and git master as of 2019-08-22
* varnish-6.1.1
* varnish-6.0.3
To apply this method:
* download :download:`vsv00003-mitigation.vcl`
* SHA256=03b923357c02b83110bbef065690df9f0f4a0af3e155331922b83cb7d35f6729
* and put it into a directory contained in your `vcl_path` (usually
`/usr/share/varnish/vcl` or `/etc/varnish`)
* ensure the varnish `vcc_allow_inline_c` parameter is set to `true`:
* add `-p vcc_allow_inline_c=true` to the varnishd start parameters,
unless already present
* use the following command to change the current setting::
varnishadm param.set vcc_allow_inline_c true
* at the top of your VCL, but after the `vcl 4.0` or `vcl 4.1`
statement, add::
include "vsv00003-mitigation.vcl"
* do _not_ include the `sub return_deliver_mitigate_vsv00003` from
above
* but follow the steps to *replace any `return (deliver);`
statements* as described above.
In other words, the include file is a replacement for the subroutine
from the simple mitigation method.
Monitoring the mitigation
-------------------------
The simple mitigation method should not require any monitoring.
For the complex mitigation method, an increase of the rate of the
`MAIN.sc_req_close` statistic is to be expected. If that rate increase
accounts for a relevant portion of the request rate, an attempt can be
made to avoid the additional `Connection: close` conditions by
checking if newline characters are produced by the client side VCL
code.
If `synthetic()` / `set resp.body` is used, this increase is expected.
.. _VSV00003:
VSV00003 DoS attack vector
==========================
Date: 2019-09-03
An HTTP/1 parsing failure has been uncovered in Varnish Cache that will
allow a remote attacker to trigger an assert in Varnish Cache by sending
specially crafted HTTP/1 requests. The assert will cause Varnish to
automatically restart with a clean cache, which makes it a Denial of
Service attack.
The problem was uncovered by internal testing at Varnish Software. It has
to the best of our knowledge not been exploited.
The following is required for a successful attack:
* The attacker must be able to send multiple HTTP/1 requests processed on
the same HTTP/1 keepalive connection.
Mitigation is possible from VCL or by updating to a fixed version
of Varnish Cache.
Versions affected
-----------------
* 6.1.0 and forward
* 6.0 LTS by Varnish Software up to and including 6.0.3
Versions not affected
---------------------
* Versions prior to 6.1.0 contains parsing bugs that are requisites for
successfully exploiting the issue, but these versions will not
assert. This includes the end-of-lifed 4.1 LTS series.
Fixed in
--------
* 6.2.1
* 6.0.4 LTS by Varnish Software
* GitHub Varnish Cache master branch at commit 406b583fe54634afd029e7a41e35b3cf9ccac28a
Mitigation from VCL
-------------------
See :ref:`VSV00003-mitigation` for information about mitigation
through VCL.
Thankyous and credits
---------------------
Alf-André Walla at Varnish Software for uncovering the problem.
Nils Goroll at UPLEX for patch review and VCL mitigation.
Varnish Software for handling this security incident.
......@@ -6,6 +6,7 @@ Security, bugs & vulnerabilities
.. toctree::
:maxdepth: 1
VSV00003.rst
VSV00002.rst
VSV00001.rst
......
#
# VCL inline-C workaround for 2019-08 rxbuf issue
#
# Copyright 2019 UPLEX - Nils Goroll Systemoptimierung
#
# See: https://varnish-cache.org/security/VSV00003-mitigation.html
#
# USE AT YOUR OWN RISK
#
# Author: Nils Goroll <nils.goroll@uplex.de>
#
# supported versions
# varnish-6.2.0 and newer (git master)
# varnish-6.1.1
# varnish-6.0.3
# --
#
#
# The simple workaround is
#
# sub vcl_deliver {
# if (req.esi_level == 0 && req.proto != "HTTP/2.0") {
# set resp.http.Connection = "close";
# }
# }
#
# before return(deliver)
#
#
# This file contains a more complicated workaround, which applies
# fixups and determines if "Connection: close" can be avoided. If the
# workaround determines that avoiding "Connection: close" would be
# safe, it falls back on it.
#
# Usage:
#
# * start varnishd with
#
# -p vcc_allow_inline_c=true
#
# to allow use of inline-c
#
# * put this file in your vcl_path (usually /etc/varnish)
#
# * add at the top of your VCL:
#
# include "vsv00003-mitigation.vcl"
#
# * replace all
#
# return (deliver);
#
# in vcl_deliver { } with
#
# call return_deliver_mitigate_vsv00003;
C{
#include <unistd.h> // ssize_t
#include <string.h> // memset()
struct wsf {
unsigned magic;
char id[4];
char *s;
char *f;
char *r;
char *e;
};
struct httpcf {
unsigned magic;
//define HTTP_CONN_MAGIC 0x3e19edd1
int *p;
int enums[2];
void *ws;
char *rxbuf_b;
char *rxbuf_e;
char *pipeline_b;
char *pipeline_e;
ssize_t cl;
void *priv;
double to[2];
};
}C
# the workaround changes request headers received from the client, so
# it should be the absolutely last thing to call from vcl_deliver {}
# in place of return (deliver)
#
# If it can not ensure a safe environment, it falls back to
# Connection: close
sub return_deliver_mitigate_vsv00003 {
if (req.esi_level > 0 || req.proto == "HTTP/2.0") {
return (deliver);
}
C{
struct httpcf *h;
struct wsf *wsf;
uintptr_t u;
char *p, *e;
size_t sz;
wsf = (struct wsf *)ctx->ws;
u = (uintptr_t)wsf->s;
u &= ~((uintptr_t)sizeof(uintptr_t) - 1);
h = (struct httpcf *)u;
h--;
while (h->magic == 0x3e19edd1) {
// cleanup client request
p = h->rxbuf_b;
if (h->pipeline_b != NULL)
e = h->pipeline_b;
else
e = h->rxbuf_e;
while (p < e && (p = memchr(p, '\n', e - p)) != NULL)
*p++ = '\0';
// cleanup pipeline
p = h->pipeline_b;
while (p != NULL && p < h->pipeline_e &&
(*p == '\r' || *p == '\n' ||
*p == '\t' || *p == ' ')) {
*p++ = '\0';
}
if (p == h->pipeline_e) {
h->pipeline_b = NULL;
h->pipeline_e = NULL;
} else {
h->pipeline_b = p;
}
if (h->pipeline_e != NULL)
p = h->pipeline_e;
else
p = wsf->s;
e = wsf->f;
// Connection: close for unsafe workspace
if (memchr(p, '\n', e - p) != NULL)
break;
memset(wsf->f, 0, wsf->e - wsf->f);
if (h->pipeline_b != NULL) {
// move pipeline to top of ws
sz = h->pipeline_e - h->pipeline_b;
// Connection: close for ENOSPC
if (sz + 1 > wsf->e - wsf->f)
break;
p = h->pipeline_b;
e = h->pipeline_e;
h->pipeline_b = wsf->e - sz - 1;
h->pipeline_e = wsf->e - 1;
memcpy(h->pipeline_b, p, sz);
memset(p, 0, sz);
}
VRT_handling(ctx, VCL_RET_DELIVER);
return;
}
}C
set resp.http.Connection = "close";
return (deliver);
}
## EXAMPLE
# sub vcl_deliver {
# # use instead of return (deliver);
# call return_deliver_mitigate_vsv00003;
# }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment