[hackers] [quark] Properly HTML-escape names in dirlistings || Laslo Hunhold

From: <git_AT_suckless.org>
Date: Wed, 25 Mar 2020 14:10:48 +0100 (CET)

commit 48e74a598247f4b81e09a0f652faf15163f9f525
Author: Laslo Hunhold <dev_AT_frign.de>
AuthorDate: Wed Mar 25 14:07:17 2020 +0100
Commit: Laslo Hunhold <dev_AT_frign.de>
CommitDate: Wed Mar 25 14:07:17 2020 +0100

    Properly HTML-escape names in dirlistings
    
    Based on a patch by guysv. We now make sure that the valid
    path-characters ", ', <, >, & can not be used for XSS on a target, for
    example with a file called
    
       "><img src="blabla" onerror="alert(1)"
    
    by properly HTML-escaping these characters.
    
    Signed-off-by: Laslo Hunhold <dev_AT_frign.de>

diff --git a/resp.c b/resp.c
index 3075c28..fbd8d5b 100644
--- a/resp.c
+++ b/resp.c
_AT_@ -38,6 +38,51 @@ suffix(int t)
         return "";
 }
 
+static void
+html_escape(char *src, char *dst, size_t dst_siz)
+{
+ const struct {
+ char c;
+ char *s;
+ } escape[] = {
+ { '&', "&amp;" },
+ { '<', "&lt;" },
+ { '>', "&gt;" },
+ { '"', "&quot;" },
+ { '\'', "&#x27;" },
+ };
+ size_t i, j, k, esclen;
+
+ for (i = 0, j = 0; src[i] != '\0'; i++) {
+ for (k = 0; k < LEN(escape); k++) {
+ if (src[i] == escape[k].c) {
+ break;
+ }
+ }
+ if (k == LEN(escape)) {
+ /* no escape char at src[i] */
+ if (j == dst_siz - 1) {
+ /* silent truncation */
+ break;
+ } else {
+ dst[j++] = src[i];
+ }
+ } else {
+ /* escape char at src[i] */
+ esclen = strlen(escape[k].s);
+
+ if (j >= dst_siz - esclen) {
+ /* silent truncation */
+ break;
+ } else {
+ memcpy(&dst[j], escape[k].s, esclen);
+ j += esclen;
+ }
+ }
+ }
+ dst[j] = '\0';
+}
+
 enum status
 resp_dir(int fd, char *name, struct request *r)
 {
_AT_@ -45,6 +90,7 @@ resp_dir(int fd, char *name, struct request *r)
         size_t i;
         int dirlen, s;
         static char t[TIMESTAMP_LEN];
+ char esc[PATH_MAX /* > NAME_MAX */ * 6]; /* strlen("&...;") <= 6 */
 
         /* read directory */
         if ((dirlen = scandir(name, &e, NULL, compareent)) < 0) {
_AT_@ -65,11 +111,12 @@ resp_dir(int fd, char *name, struct request *r)
 
         if (r->method == M_GET) {
                 /* listing header */
+ html_escape(name, esc, sizeof(esc));
                 if (dprintf(fd,
                             "<!DOCTYPE html>\n<html>\n\t<head>"
                             "<title>Index of %s</title></head>\n"
                             "\t<body>\n\t\t<a href=\"..\">..</a>",
- name) < 0) {
+ esc) < 0) {
                         s = S_REQUEST_TIMEOUT;
                         goto cleanup;
                 }
_AT_@ -82,10 +129,11 @@ resp_dir(int fd, char *name, struct request *r)
                         }
 
                         /* entry line */
+ html_escape(e[i]->d_name, esc, sizeof(esc));
                         if (dprintf(fd, "<br />\n\t\t<a href=\"%s%s\">%s%s</a>",
- e[i]->d_name,
+ esc,
                                     (e[i]->d_type == DT_DIR) ? "/" : "",
- e[i]->d_name,
+ esc,
                                     suffix(e[i]->d_type)) < 0) {
                                 s = S_REQUEST_TIMEOUT;
                                 goto cleanup;
Received on Wed Mar 25 2020 - 14:10:48 CET

This archive was generated by hypermail 2.3.0 : Wed Mar 25 2020 - 14:12:35 CET