Introduction
Introduction Statistics Contact Development Disclaimer Help
Properly HTML-escape names in dirlistings - quark - quark web server
git clone git://git.suckless.org/quark
Log
Files
Refs
LICENSE
---
commit 48e74a598247f4b81e09a0f652faf15163f9f525
parent 5ee8c07e7e3e601fce49fbc2b170227924be3804
Author: Laslo Hunhold <[email protected]>
Date: Wed, 25 Mar 2020 14:07:17 +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 <[email protected]>
Diffstat:
M resp.c | 54 +++++++++++++++++++++++++++++…
1 file changed, 51 insertions(+), 3 deletions(-)
---
diff --git a/resp.c b/resp.c
@@ -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)
{
@@ -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) {
@@ -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;
}
@@ -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;
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.