Do not render HTML attachments uploaded by users to avoid XSS

This commit is contained in:
ritt 2025-10-14 15:14:04 +02:00
parent b95c6cd4c2
commit f81e5695c4

View File

@ -8347,7 +8347,7 @@ int exist_file(char *file_name) {
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
void send_file_direct(char *file_name) { void send_file_direct(char *file_name, bool allow_html) {
int fh, i, length, delta; int fh, i, length, delta;
char str[MAX_PATH_LENGTH], dir[MAX_PATH_LENGTH], charset[80]; char str[MAX_PATH_LENGTH], dir[MAX_PATH_LENGTH], charset[80];
@ -8388,20 +8388,24 @@ void send_file_direct(char *file_name) {
strcpy(charset, DEFAULT_HTTP_CHARSET); strcpy(charset, DEFAULT_HTTP_CHARSET);
if (filetype[i].ext[0]) { if (filetype[i].ext[0]) {
if (strncmp(filetype[i].type, "text", 4) == 0) if (!allow_html && strcmp(filetype[i].type, "text/html") == 0) {
rsprintf("Content-Type: %s;charset=%s\r\n", filetype[i].type, charset); rsprintf("Content-Type: text/plain;charset=%s\r\n", charset);
else if (strcmp(filetype[i].ext, ".SVG") == 0) { } else {
rsprintf("Content-Type: %s\r\n", filetype[i].type); if (strncmp(filetype[i].type, "text", 4) == 0)
if (strrchr(file_name, '/')) rsprintf("Content-Type: %s;charset=%s\r\n", filetype[i].type, charset);
strlcpy(str, strrchr(file_name, '/')+1, sizeof(str)); else if (strcmp(filetype[i].ext, ".SVG") == 0) {
else rsprintf("Content-Type: %s\r\n", filetype[i].type);
strlcpy(str, file_name, sizeof(str)); if (strrchr(file_name, '/'))
if (str[6] == '_' && str[13] == '_') strlcpy(str, strrchr(file_name, '/') + 1, sizeof(str));
rsprintf("Content-Disposition: attachment; filename=\"%s\"\r\n", str+14); else
else strlcpy(str, file_name, sizeof(str));
rsprintf("Content-Disposition: attachment; filename=\"%s\"\r\n", str); if (str[6] == '_' && str[13] == '_')
} else rsprintf("Content-Disposition: attachment; filename=\"%s\"\r\n", str + 14);
rsprintf("Content-Type: %s\r\n", filetype[i].type); else
rsprintf("Content-Disposition: attachment; filename=\"%s\"\r\n", str);
} else
rsprintf("Content-Type: %s\r\n", filetype[i].type);
}
} else if (is_ascii(file_name)) } else if (is_ascii(file_name))
rsprintf("Content-Type: text/plain;charset=%s\r\n", charset); rsprintf("Content-Type: text/plain;charset=%s\r\n", charset);
else else
@ -9525,7 +9529,7 @@ void show_edit_form(LOGBOOK *lbs, int message_id, BOOL breply, BOOL bedit, BOOL
strlcpy(file_name, logbook_dir, sizeof(file_name)); strlcpy(file_name, logbook_dir, sizeof(file_name));
strlcat(file_name, str, sizeof(file_name)); strlcat(file_name, str, sizeof(file_name));
} }
send_file_direct(str); send_file_direct(str, true);
return; return;
} }
@ -9538,7 +9542,7 @@ void show_edit_form(LOGBOOK *lbs, int message_id, BOOL breply, BOOL bedit, BOOL
strlcpy(file_name, logbook_dir, sizeof(file_name)); strlcpy(file_name, logbook_dir, sizeof(file_name));
strlcat(file_name, str, sizeof(file_name)); strlcat(file_name, str, sizeof(file_name));
} }
send_file_direct(str); send_file_direct(str, true);
return; return;
} }
@ -23679,7 +23683,7 @@ void submit_elog(LOGBOOK *lbs) {
strlcpy(file_name, logbook_dir, sizeof(file_name)); strlcpy(file_name, logbook_dir, sizeof(file_name));
strlcat(file_name, str, sizeof(file_name)); strlcat(file_name, str, sizeof(file_name));
} }
send_file_direct(file_name); send_file_direct(file_name, true);
return; return;
} }
@ -24318,7 +24322,7 @@ void show_elog_entry(LOGBOOK *lbs, char *dec_path, char *command) {
strlcpy(file_name, logbook_dir, sizeof(file_name)); strlcpy(file_name, logbook_dir, sizeof(file_name));
strlcat(file_name, str, sizeof(file_name)); strlcat(file_name, str, sizeof(file_name));
} }
send_file_direct(str); send_file_direct(str, true);
return; return;
} }
@ -26643,7 +26647,7 @@ void show_selection_page(void) {
strlcpy(file_name, logbook_dir, sizeof(file_name)); strlcpy(file_name, logbook_dir, sizeof(file_name));
strlcat(file_name, str, sizeof(file_name)); strlcat(file_name, str, sizeof(file_name));
} }
send_file_direct(file_name); send_file_direct(file_name, true);
return; return;
} }
@ -27358,7 +27362,7 @@ void interprete(char *lbook, const char *path)
strlcpy(file_name, logbook_dir, sizeof(file_name)); strlcpy(file_name, logbook_dir, sizeof(file_name));
strlcat(file_name, str, sizeof(file_name)); strlcat(file_name, str, sizeof(file_name));
} }
send_file_direct(file_name); send_file_direct(file_name, true);
return; return;
} }
@ -27513,7 +27517,7 @@ void interprete(char *lbook, const char *path)
strlcpy(str, resource_dir, sizeof(str)); strlcpy(str, resource_dir, sizeof(str));
strlcat(str, path, sizeof(str)); strlcat(str, path, sizeof(str));
if (exist_file(str)) { if (exist_file(str)) {
send_file_direct(str); send_file_direct(str, true);
return; return;
} else { } else {
/* else search file in themes directory */ /* else search file in themes directory */
@ -27524,7 +27528,7 @@ void interprete(char *lbook, const char *path)
strlcat(str, DIR_SEPARATOR_STR, sizeof(str)); strlcat(str, DIR_SEPARATOR_STR, sizeof(str));
strlcat(str, path, sizeof(str)); strlcat(str, path, sizeof(str));
if (exist_file(str)) { if (exist_file(str)) {
send_file_direct(str); send_file_direct(str, true);
return; return;
} }
} }
@ -27778,6 +27782,8 @@ void interprete(char *lbook, const char *path)
if (strchr(pfile, '/') && pfile[13] != '/' && isdigit(pfile[0])) if (strchr(pfile, '/') && pfile[13] != '/' && isdigit(pfile[0]))
pfile = strchr(pfile, '/') + 1; pfile = strchr(pfile, '/') + 1;
bool allow_html = false;
if ((strlen(pfile) > 13 && pfile[6] == '_' && pfile[13] == '_') || (strlen(pfile) > 13 && pfile[6] == '_' if ((strlen(pfile) > 13 && pfile[6] == '_' && pfile[13] == '_') || (strlen(pfile) > 13 && pfile[6] == '_'
&& pfile[13] == '/') && pfile[13] == '/')
|| chkext(pfile, ".gif") || chkext(pfile, ".ico") || chkext(pfile, ".jpg") || chkext(pfile, ".gif") || chkext(pfile, ".ico") || chkext(pfile, ".jpg")
@ -27795,6 +27801,7 @@ void interprete(char *lbook, const char *path)
strlcat(file_name, pfile, sizeof(file_name)); strlcat(file_name, pfile, sizeof(file_name));
} else { } else {
/* file from theme directory requested */ /* file from theme directory requested */
allow_html = true;
strlcpy(file_name, resource_dir, sizeof(file_name)); strlcpy(file_name, resource_dir, sizeof(file_name));
if (file_name[0] && file_name[strlen(file_name) if (file_name[0] && file_name[strlen(file_name)
- 1] != DIR_SEPARATOR) - 1] != DIR_SEPARATOR)
@ -27811,11 +27818,11 @@ void interprete(char *lbook, const char *path)
if (isparam("thumb")) { if (isparam("thumb")) {
get_thumb_name(file_name, thumb_name, sizeof(thumb_name), 0); get_thumb_name(file_name, thumb_name, sizeof(thumb_name), 0);
if (thumb_name[0]) if (thumb_name[0])
send_file_direct(thumb_name); send_file_direct(thumb_name, allow_html);
else else
send_file_direct(file_name); send_file_direct(file_name, allow_html);
} else } else
send_file_direct(file_name); send_file_direct(file_name, allow_html);
return; return;
} }
@ -27908,7 +27915,7 @@ void interprete(char *lbook, const char *path)
show_error(str); show_error(str);
} else { } else {
fclose(f); fclose(f);
send_file_direct(file_name); send_file_direct(file_name, true);
} }
return; return;
} }
@ -27930,7 +27937,7 @@ void interprete(char *lbook, const char *path)
redirect(lbs, "https://elog.psi.ch/elog/eloghelp_english.html"); redirect(lbs, "https://elog.psi.ch/elog/eloghelp_english.html");
else { else {
fclose(f); fclose(f);
send_file_direct(file_name); send_file_direct(file_name, true);
} }
return; return;
} }
@ -27953,7 +27960,7 @@ void interprete(char *lbook, const char *path)
redirect(lbs, "https://elog.psi.ch/elog/elcode_english.html"); redirect(lbs, "https://elog.psi.ch/elog/elcode_english.html");
else { else {
fclose(f); fclose(f);
send_file_direct(file_name); send_file_direct(file_name, true);
} }
return; return;
} }
@ -28151,7 +28158,7 @@ void interprete(char *lbook, const char *path)
getcfg("global", "Allow clone", allow, sizeof(allow)); getcfg("global", "Allow clone", allow, sizeof(allow));
if (atoi(allow) == 1) { if (atoi(allow) == 1) {
if (get_password_file(lbs, file_name, sizeof(file_name))) if (get_password_file(lbs, file_name, sizeof(file_name)))
send_file_direct(file_name); send_file_direct(file_name, false);
} else { } else {
show_http_header(NULL, FALSE, NULL, 200); show_http_header(NULL, FALSE, NULL, 200);
rsputs(loc("Cloning not allowed. Set \"Allow clone = 1\" to enable cloning.")); rsputs(loc("Cloning not allowed. Set \"Allow clone = 1\" to enable cloning."));
@ -28350,7 +28357,7 @@ void interprete(char *lbook, const char *path)
strlcpy(file_name, resource_dir, sizeof(file_name)); strlcpy(file_name, resource_dir, sizeof(file_name));
strlcat(file_name, str, sizeof(file_name)); strlcat(file_name, str, sizeof(file_name));
} }
send_file_direct(file_name); send_file_direct(file_name, true);
return; return;
} }
@ -29000,7 +29007,7 @@ int process_http_request(const char *crequest, int i_conn) {
strlcat(str, DIR_SEPARATOR_STR, strsize); strlcat(str, DIR_SEPARATOR_STR, strsize);
strlcat(str, url, strsize); strlcat(str, url, strsize);
if (exist_file(str)) { if (exist_file(str)) {
send_file_direct(str); send_file_direct(str, true);
xfree(str); xfree(str);
xfree(request); xfree(request);
return 1; return 1;
@ -29104,7 +29111,7 @@ int process_http_request(const char *crequest, int i_conn) {
strlcpy(str, resource_dir, strsize); strlcpy(str, resource_dir, strsize);
strlcat(str, logbook, strsize); strlcat(str, logbook, strsize);
if (exist_file(str)) if (exist_file(str))
send_file_direct(str); send_file_direct(str, true);
else { else {
/* else search file in themes directory */ /* else search file in themes directory */
strlcpy(str, resource_dir, strsize); strlcpy(str, resource_dir, strsize);
@ -29116,7 +29123,7 @@ int process_http_request(const char *crequest, int i_conn) {
strlcat(str, "default", strsize); strlcat(str, "default", strsize);
strlcat(str, DIR_SEPARATOR_STR, strsize); strlcat(str, DIR_SEPARATOR_STR, strsize);
strlcat(str, logbook, strsize); strlcat(str, logbook, strsize);
send_file_direct(str); send_file_direct(str, true);
} }
xfree(str); xfree(str);
xfree(request); xfree(request);