Windows only: arbitrary file read vulnerability in openssl s_server
Medium
Vulnerability Details
==(Copied from an email sent to [email protected] on August 15, 2019)==
Hi,
There's an arbitrary file read vulnerability present in openssl s_server when ran on Windows with the -WWW or -HTTP option. To reproduce:
* run `openssl s_server -tls1 -WWW -accept 443`
* run `.\curl.exe -k https://127.0.0.1/..\..\..\..\..\..\..\any-file`
* observe the contents of any-file, which could be located outside of the running directory, to be returned to the user
The root cause of this vulnerability seems to come from an incomplete check in path parsing logic: https://github.com/openssl/openssl/blob/master/apps/s_server.c#L3225. Ideally, it'd include a check for a backslash, too. It seems that this particular code has been around for some time.
Vulnerable versions seem to include 0.9.6, 0.9.7, 0.9.8, 1.0.0, 1.0.1, 1.0.2, 1.1.0, and 1.1.1.
This was tested against OpenSSL 1.1.1c on Windows 10 (64-bit).
The maintainers fixed this in [this commit](https://github.com/openssl/openssl/commit/0a4d6c67480a4d2fce514e08d3efe571f2ee99c9):
```diff
diff --git a/apps/s_server.c b/apps/s_server.c
index 038046808037..5f58ef68fefa 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -3211,6 +3211,12 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
if (e[0] == ' ')
break;
+ if (e[0] == ':') {
+ /* Windows drive. We treat this the same way as ".." */
+ dot = -1;
+ break;
+ }
+
switch (dot) {
case 1:
dot = (e[0] == '.') ? 2 : 0;
@@ -3219,11 +3225,11 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
dot = (e[0] == '.') ? 3 : 0;
break;
case 3:
- dot = (e[0] == '/') ? -1 : 0;
+ dot = (e[0] == '/' || e[0] == '\\') ? -1 : 0;
break;
}
if (dot == 0)
- dot = (e[0] == '/') ? 1 : 0;
+ dot = (e[0] == '/' || e[0] == '\\') ? 1 : 0;
}
dot = (dot == 3) || (dot == -1); /* filename contains ".."
* component */
@@ -3237,11 +3243,11 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
if (dot) {
BIO_puts(io, text);
- BIO_printf(io, "'%s' contains '..' reference\r\n", p);
+ BIO_printf(io, "'%s' contains '..' or ':'\r\n", p);
break;
}
- if (*p == '/') {
+ if (*p == '/' || *p == '\\') {
BIO_puts(io, text);
BIO_printf(io, "'%s' is an invalid path\r\n", p);
break;
```
## Impact
An attacker may be able to read arbitrary files from a user's file system.
Actions
View on HackerOneReport Stats
- Report ID: 850775
- State: Closed
- Substate: resolved
- Upvotes: 31