1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
From 53efaf30b50f095cad8c160488c74bba3e3b2680 Mon Sep 17 00:00:00 2001
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Fri, 3 Aug 2018 15:46:11 +0200
Subject: [PATCH] clone: fix directory traversal
This was introduced in the initial version of this code, way back when
in 2008.
$ curl http://127.0.0.1/cgit/repo/objects/?path=../../../../../../../../../etc/passwd
root:x:0:0:root:/root:/bin/sh
...
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Reported-by: Jann Horn <jannh@google.com>
---
ui-clone.c | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/ui-clone.c b/ui-clone.c
index 2c1ac3d..6ba8f36 100644
--- a/ui-clone.c
+++ b/ui-clone.c
@@ -92,17 +92,32 @@ void cgit_clone_info(void)
void cgit_clone_objects(void)
{
- if (!ctx.qry.path) {
- cgit_print_error_page(400, "Bad request", "Bad request");
- return;
- }
+ char *p;
+
+ if (!ctx.qry.path)
+ goto err;
if (!strcmp(ctx.qry.path, "info/packs")) {
print_pack_info();
return;
}
+ /* Avoid directory traversal by forbidding "..", but also work around
+ * other funny business by just specifying a fairly strict format. For
+ * example, now we don't have to stress out about the Cygwin port.
+ */
+ for (p = ctx.qry.path; *p; ++p) {
+ if (*p == '.' && *(p + 1) == '.')
+ goto err;
+ if (!isalnum(*p) && *p != '/' && *p != '.' && *p != '-')
+ goto err;
+ }
+
send_file(git_path("objects/%s", ctx.qry.path));
+ return;
+
+err:
+ cgit_print_error_page(400, "Bad request", "Bad request");
}
void cgit_clone_head(void)
--
2.18.0
|