mirror of
https://github.com/openwrt/packages.git
synced 2025-12-21 23:34:31 +04:00
cgi-io: require whitelisting upload locations
Introduce further ACL checks to verify that the request-supplied
upload location may be written to. This prevents overwriting things
like /bin/busybox and allows to confine uploads to specific directories.
To setup the required ACLs, the following ubus command may be used
on the command line:
ubus call session grant '{
"ubus_rpc_session": "d41d8cd98f00b204e9800998ecf8427e",
"scope": "cgi-io",
"objects": [
[ "/etc/certificates/*", "write" ],
[ "/var/uploads/*", "write" ]
]
}'
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
committed by
John Crispin
parent
4f43e9b388
commit
22be9a1c01
@@ -8,7 +8,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=cgi-io
|
PKG_NAME:=cgi-io
|
||||||
PKG_RELEASE:=6
|
PKG_RELEASE:=7
|
||||||
|
|
||||||
PKG_LICENSE:=GPL-2.0+
|
PKG_LICENSE:=GPL-2.0+
|
||||||
|
|
||||||
|
|||||||
@@ -263,6 +263,64 @@ postdecode(char **fields, int n_fields)
|
|||||||
return (found >= n_fields);
|
return (found >= n_fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
canonicalize_path(const char *path, size_t len)
|
||||||
|
{
|
||||||
|
char *canonpath, *cp;
|
||||||
|
const char *p, *e;
|
||||||
|
|
||||||
|
if (path == NULL || *path == '\0')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
canonpath = datadup(path, len);
|
||||||
|
|
||||||
|
if (canonpath == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* normalize */
|
||||||
|
for (cp = canonpath, p = path, e = path + len; p < e; ) {
|
||||||
|
if (*p != '/')
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
/* skip repeating / */
|
||||||
|
if ((p + 1 < e) && (p[1] == '/')) {
|
||||||
|
p++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* /./ or /../ */
|
||||||
|
if ((p + 1 < e) && (p[1] == '.')) {
|
||||||
|
/* skip /./ */
|
||||||
|
if ((p + 2 >= e) || (p[2] == '/')) {
|
||||||
|
p += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* collapse /x/../ */
|
||||||
|
if ((p + 2 < e) && (p[2] == '.') && ((p + 3 >= e) || (p[3] == '/'))) {
|
||||||
|
while ((cp > canonpath) && (*--cp != '/'))
|
||||||
|
;
|
||||||
|
|
||||||
|
p += 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
*cp++ = *p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove trailing slash if not root / */
|
||||||
|
if ((cp > canonpath + 1) && (cp[-1] == '/'))
|
||||||
|
cp--;
|
||||||
|
else if (cp == canonpath)
|
||||||
|
*cp++ = '/';
|
||||||
|
|
||||||
|
*cp = '\0';
|
||||||
|
|
||||||
|
return canonpath;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
response(bool success, const char *message)
|
response(bool success, const char *message)
|
||||||
{
|
{
|
||||||
@@ -417,6 +475,9 @@ data_begin_cb(multipart_parser *p)
|
|||||||
if (!st.filename)
|
if (!st.filename)
|
||||||
return response(false, "File data without name");
|
return response(false, "File data without name");
|
||||||
|
|
||||||
|
if (!session_access(st.sessionid, st.filename, "write"))
|
||||||
|
return response(false, "Access to path denied by ACL");
|
||||||
|
|
||||||
st.tempfd = mkstemp(tmpname);
|
st.tempfd = mkstemp(tmpname);
|
||||||
|
|
||||||
if (st.tempfd < 0)
|
if (st.tempfd < 0)
|
||||||
@@ -438,7 +499,7 @@ data_cb(multipart_parser *p, const char *data, size_t len)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PART_FILENAME:
|
case PART_FILENAME:
|
||||||
st.filename = datadup(data, len);
|
st.filename = canonicalize_path(data, len);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PART_FILEMODE:
|
case PART_FILEMODE:
|
||||||
|
|||||||
Reference in New Issue
Block a user