From 49320ee65976d09be082dd9c53568ae6c147dd94 Mon Sep 17 00:00:00 2001 From: Felix S Date: Mon, 12 Feb 2024 10:20:25 +0000 Subject: [PATCH 1/2] Fix shell injection bug in std.urlGet Refs: https://github.com/bellard/quickjs/pull/61 --- quickjs-libc.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/quickjs-libc.c b/quickjs-libc.c index b3e9406d8..3a12124b1 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -1291,7 +1291,7 @@ static JSValue js_std_file_putByte(JSContext *ctx, JSValue this_val, /* urlGet */ #if !defined(__wasi__) -#define URL_GET_PROGRAM "curl -s -i" +#define URL_GET_PROGRAM "curl -s -i --" #define URL_GET_BUF_SIZE 4096 static int http_get_header_line(FILE *f, char *buf, size_t buf_size, @@ -1364,16 +1364,22 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValue this_val, } js_std_dbuf_init(ctx, &cmd_buf); - dbuf_printf(&cmd_buf, "%s ''", URL_GET_PROGRAM); + dbuf_printf(&cmd_buf, "%s '", URL_GET_PROGRAM); len = strlen(url); for(i = 0; i < len; i++) { - c = url[i]; - if (c == '\'' || c == '\\') + switch (c = url[i]) { + case '\'': + dbuf_putstr(&cmd_buf, "'\\''"); + break; + case '[': case ']': case '{': case '}': case '\\': dbuf_putc(&cmd_buf, '\\'); - dbuf_putc(&cmd_buf, c); + /* FALLTHROUGH */ + default: + dbuf_putc(&cmd_buf, c); + } } JS_FreeCString(ctx, url); - dbuf_putstr(&cmd_buf, "''"); + dbuf_putstr(&cmd_buf, "'"); dbuf_putc(&cmd_buf, '\0'); if (dbuf_error(&cmd_buf)) { dbuf_free(&cmd_buf); From 4a2cdf353e87af886c2b8c0fe9ae93640453d06a Mon Sep 17 00:00:00 2001 From: Charlie Gordon Date: Mon, 12 Feb 2024 18:34:52 +0100 Subject: [PATCH 2/2] Simplify and clarify URL quoting js_std_urlGet --- quickjs-libc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/quickjs-libc.c b/quickjs-libc.c index 3a12124b1..0e618c047 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -1337,7 +1337,7 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValue this_val, DynBuf header_buf_s, *header_buf = &header_buf_s; char *buf; size_t i, len; - int c, status; + int status; JSValue response = JS_UNDEFINED, ret_obj; JSValue options_obj; FILE *f; @@ -1365,17 +1365,20 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValue this_val, js_std_dbuf_init(ctx, &cmd_buf); dbuf_printf(&cmd_buf, "%s '", URL_GET_PROGRAM); - len = strlen(url); - for(i = 0; i < len; i++) { - switch (c = url[i]) { + for(i = 0; url[i] != '\0'; i++) { + unsigned char c = url[i]; + switch (c) { case '\'': + /* shell single quoted string does not support \' */ dbuf_putstr(&cmd_buf, "'\\''"); break; case '[': case ']': case '{': case '}': case '\\': + /* prevent interpretation by curl as range or set specification */ dbuf_putc(&cmd_buf, '\\'); /* FALLTHROUGH */ default: dbuf_putc(&cmd_buf, c); + break; } } JS_FreeCString(ctx, url);