pentesting 0.12.13 → 0.16.2

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.
@@ -1,457 +0,0 @@
1
- // src/core/tools/web-search.ts
2
- var browser = null;
3
- var browserContext = null;
4
- async function getBrowser() {
5
- if (!browser) {
6
- const { chromium } = await import("playwright");
7
- browser = await chromium.launch({
8
- headless: true,
9
- args: [
10
- "--no-sandbox",
11
- "--disable-setuid-sandbox",
12
- "--disable-dev-shm-usage",
13
- "--disable-blink-features=AutomationControlled",
14
- "--disable-infobars",
15
- "--window-position=0,0",
16
- "--ignore-certificate-errors",
17
- "--ignore-certificate-errors-spki-list",
18
- "--disable-web-security"
19
- ]
20
- });
21
- }
22
- return browser;
23
- }
24
- var USER_AGENTS = [
25
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
26
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
27
- "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
28
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0"
29
- ];
30
- async function getFreshContext() {
31
- const b = await getBrowser();
32
- const userAgent = USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)];
33
- const context = await b.newContext({
34
- userAgent,
35
- viewport: { width: 1920, height: 1080 },
36
- locale: "en-US",
37
- timezoneId: "America/New_York",
38
- extraHTTPHeaders: {
39
- "Accept-Language": "en-US,en;q=0.9",
40
- "Upgrade-Insecure-Requests": "1"
41
- }
42
- });
43
- await context.addInitScript(() => {
44
- Object.defineProperty(navigator, "webdriver", { get: () => void 0 });
45
- Object.defineProperty(navigator, "languages", { get: () => ["en-US", "en"] });
46
- Object.defineProperty(navigator, "plugins", { get: () => [1, 2, 3, 4, 5] });
47
- window.chrome = { runtime: {} };
48
- const originalQuery = window.navigator.permissions.query;
49
- window.navigator.permissions.query = (parameters) => parameters.name === "notifications" ? Promise.resolve({ state: Notification.permission }) : originalQuery(parameters);
50
- });
51
- return context;
52
- }
53
- async function closeBrowser() {
54
- if (browserContext) {
55
- await browserContext.close();
56
- browserContext = null;
57
- }
58
- if (browser) {
59
- await browser.close();
60
- browser = null;
61
- }
62
- }
63
- var WRITEUP_SOURCES = {
64
- general: [
65
- "site:0xdf.gitlab.io",
66
- "site:ippsec.rocks",
67
- "site:medium.com",
68
- "site:infosecwriteups.com",
69
- "site:hackingarticles.in"
70
- ],
71
- htb: [
72
- "site:0xdf.gitlab.io",
73
- "site:ippsec.rocks",
74
- "site:app.hackthebox.com",
75
- '"HackTheBox" OR "HTB"'
76
- ],
77
- thm: [
78
- "site:tryhackme.com",
79
- '"TryHackMe" OR "THM"'
80
- ],
81
- ctf: [
82
- "site:ctftime.org",
83
- "site:ctf.zeyu2001.com",
84
- "site:github.com CTF writeup"
85
- ],
86
- vulnhub: [
87
- "site:vulnhub.com",
88
- '"VulnHub" writeup'
89
- ]
90
- };
91
- var SCENARIO_KEYWORDS = {
92
- ad: "Active Directory Kerberos LDAP BloodHound",
93
- windows: "Windows privilege escalation PowerShell",
94
- linux: "Linux privilege escalation GTFOBins SUID",
95
- web: "web exploitation XSS SQLi SSTI RCE",
96
- crypto: "cryptography RSA AES cipher",
97
- forensics: "forensics memory dump volatility",
98
- pwn: "binary exploitation buffer overflow ROP",
99
- reversing: "reverse engineering IDA Ghidra",
100
- misc: "miscellaneous steganography OSINT"
101
- };
102
- async function searchGoogle(query, options = {}) {
103
- const { maxResults = 10, timeout = 3e4 } = options;
104
- const results = [];
105
- let page = null;
106
- try {
107
- const context = await getFreshContext();
108
- page = await context.newPage();
109
- if (!page) throw new Error("Failed to create page");
110
- page.setDefaultTimeout(timeout);
111
- await page.goto("https://www.google.com/?hl=en", {
112
- waitUntil: "domcontentloaded"
113
- });
114
- let searchBox = await page.waitForSelector('textarea[name="q"], input[name="q"]', { timeout: 5e3 }).catch(() => null);
115
- if (!searchBox) {
116
- const acceptButton = await page.$('button#L2AGLb, button:has-text("Accept all"), button:has-text("I agree"), button:has-text("Agree")');
117
- if (acceptButton) {
118
- await acceptButton.click();
119
- await page.waitForSelector('textarea[name="q"], input[name="q"]', { timeout: 5e3 }).catch(() => null);
120
- searchBox = await page.$('textarea[name="q"], input[name="q"]');
121
- }
122
- }
123
- if (searchBox) {
124
- await searchBox.fill(query);
125
- await page.keyboard.press("Enter");
126
- } else {
127
- await page.goto("https://www.google.com/search?q=" + encodeURIComponent(query) + "&hl=en", {
128
- waitUntil: "domcontentloaded"
129
- });
130
- }
131
- await page.waitForSelector("h3", { timeout: 1e4 }).catch(() => {
132
- });
133
- const searchResults = await page.$$eval("div.g, div.tF2Cxc, div.MjjYud", (elements) => {
134
- return elements.map((el) => {
135
- const titleEl = el.querySelector("h3");
136
- const linkEl = el.querySelector("a");
137
- const snippetEl = el.querySelector("[data-sncf], .VwiC3b, [data-snf], .VwiC3b");
138
- return {
139
- title: titleEl?.textContent?.trim() || "",
140
- url: linkEl?.href || "",
141
- snippet: snippetEl?.textContent?.trim() || ""
142
- };
143
- }).filter((r) => r.title && r.url);
144
- });
145
- if (searchResults.length === 0) {
146
- const title = await page.title();
147
- console.log(`Debug: Empty results for Google. Page title: "${title}"`);
148
- const body = await page.evaluate(() => document.body.innerText.slice(0, 500));
149
- console.log(`Debug: Body snippet: ${body}`);
150
- }
151
- results.push(...searchResults.slice(0, maxResults).map((r) => ({ ...r, source: "google" })));
152
- } catch (error) {
153
- console.error("Google search error:", error);
154
- } finally {
155
- if (page) await page.close();
156
- }
157
- return results;
158
- }
159
- async function searchDuckDuckGo(query, options = {}) {
160
- const { maxResults = 10, timeout = 3e4 } = options;
161
- const results = [];
162
- let page = null;
163
- try {
164
- const context = await getFreshContext();
165
- page = await context.newPage();
166
- if (!page) throw new Error("Failed to create page");
167
- page.setDefaultTimeout(timeout);
168
- await page.goto("https://html.duckduckgo.com/html/?q=" + encodeURIComponent(query), {
169
- waitUntil: "domcontentloaded"
170
- });
171
- const searchResults = await page.$$eval(".result", (elements) => {
172
- return elements.map((el) => {
173
- const titleEl = el.querySelector(".result__a");
174
- const snippetEl = el.querySelector(".result__snippet");
175
- return {
176
- title: titleEl?.textContent?.trim() || "",
177
- url: titleEl?.href || "",
178
- snippet: snippetEl?.textContent?.trim() || ""
179
- };
180
- }).filter((r) => r.title && r.url);
181
- });
182
- if (searchResults.length === 0) {
183
- const title = await page.title();
184
- console.log(`Debug: Empty results for DuckDuckGo. Page title: "${title}"`);
185
- const body = await page.evaluate(() => document.body.innerText.slice(0, 500));
186
- console.log(`Debug: Body snippet: ${body}`);
187
- }
188
- results.push(...searchResults.slice(0, maxResults).map((r) => ({ ...r, source: "duckduckgo" })));
189
- } catch (error) {
190
- console.error("DuckDuckGo search error:", error);
191
- } finally {
192
- if (page) await page.close();
193
- }
194
- return results;
195
- }
196
- async function searchBing(query, options = {}) {
197
- const { maxResults = 10, timeout = 3e4 } = options;
198
- const results = [];
199
- let page = null;
200
- try {
201
- const context = await getFreshContext();
202
- page = await context.newPage();
203
- if (!page) throw new Error("Failed to create page");
204
- page.setDefaultTimeout(timeout);
205
- await page.goto("https://www.bing.com/search?q=" + encodeURIComponent(query) + "&setlang=en&cc=US", {
206
- waitUntil: "domcontentloaded"
207
- });
208
- const searchResults = await page.$$eval(".b_algo", (elements) => {
209
- return elements.map((el) => {
210
- const titleEl = el.querySelector("h2 a");
211
- const snippetEl = el.querySelector(".b_caption p, .b_snippet");
212
- return {
213
- title: titleEl?.textContent?.trim() || "",
214
- url: titleEl?.href || "",
215
- snippet: snippetEl?.textContent?.trim() || ""
216
- };
217
- }).filter((r) => r.title && r.url);
218
- });
219
- if (searchResults.length === 0) {
220
- const title = await page.title();
221
- console.log(`Debug: Empty results for Bing. Page title: "${title}"`);
222
- const body = await page.evaluate(() => document.body.innerText.slice(0, 500));
223
- console.log(`Debug: Body snippet: ${body}`);
224
- }
225
- results.push(...searchResults.slice(0, maxResults).map((r) => ({ ...r, source: "bing" })));
226
- } catch (error) {
227
- console.error("Bing search error:", error);
228
- } finally {
229
- if (page) await page.close();
230
- }
231
- return results;
232
- }
233
- async function searchBrave(query, options = {}) {
234
- const { maxResults = 10, timeout = 3e4 } = options;
235
- const results = [];
236
- let page = null;
237
- try {
238
- const context = await getFreshContext();
239
- page = await context.newPage();
240
- if (!page) throw new Error("Failed to create page");
241
- page.setDefaultTimeout(timeout);
242
- await page.goto("https://search.brave.com/search?q=" + encodeURIComponent(query), {
243
- waitUntil: "domcontentloaded"
244
- });
245
- await page.waitForSelector(".snippet", { timeout: 1e4 }).catch(() => {
246
- });
247
- const searchResults = await page.$$eval("#results .snippet, .result, article, div.snippet", (elements) => {
248
- return elements.map((el) => {
249
- const titleEl = el.querySelector("h1, h2, h3, h4, .heading-serp, .snippet-title, .title");
250
- const linkEl = el.querySelector("a");
251
- const snippetEl = el.querySelector(".snippet-content, .snippet-description, .res-snippet, .description");
252
- return {
253
- title: titleEl?.textContent?.trim() || "",
254
- url: linkEl?.href || "",
255
- snippet: snippetEl?.textContent?.trim() || ""
256
- };
257
- }).filter((r) => r.title && r.url);
258
- });
259
- if (searchResults.length === 0) {
260
- const title = await page.title();
261
- console.log(`Debug: Empty results for Brave. Page title: "${title}"`);
262
- const body = await page.evaluate(() => document.body.innerText.slice(0, 500));
263
- console.log(`Debug: Body snippet: ${body}`);
264
- }
265
- results.push(...searchResults.slice(0, maxResults).map((r) => ({ ...r, source: "brave" })));
266
- } catch (error) {
267
- console.error("Brave search error:", error);
268
- } finally {
269
- if (page) await page.close();
270
- }
271
- return results;
272
- }
273
- async function searchYahoo(query, options = {}) {
274
- const { maxResults = 10, timeout = 3e4 } = options;
275
- const results = [];
276
- let page = null;
277
- try {
278
- const context = await getFreshContext();
279
- page = await context.newPage();
280
- if (!page) throw new Error("Failed to create page");
281
- page.setDefaultTimeout(timeout);
282
- await page.goto("https://search.yahoo.com/search?p=" + encodeURIComponent(query), {
283
- waitUntil: "domcontentloaded"
284
- });
285
- const consent = await page.$('button[name="agree"], .consent-form button');
286
- if (consent) await consent.click().catch(() => {
287
- });
288
- const searchResults = await page.$$eval(".algo, .ovr, .relsrch", (elements) => {
289
- return elements.map((el) => {
290
- const titleEl = el.querySelector("h3 a");
291
- const snippetEl = el.querySelector(".compText, .compText p, p, .fc-secondary");
292
- return {
293
- title: titleEl?.textContent?.trim() || "",
294
- url: titleEl?.href || "",
295
- snippet: snippetEl?.textContent?.trim() || ""
296
- };
297
- }).filter((r) => r.title && r.url);
298
- });
299
- results.push(...searchResults.slice(0, maxResults).map((r) => ({ ...r, source: "yahoo" })));
300
- } catch (error) {
301
- console.error("Yahoo search error:", error);
302
- } finally {
303
- if (page) await page.close();
304
- }
305
- return results;
306
- }
307
- async function unifiedSearch(query, options = {}) {
308
- const { maxResults = 10 } = options;
309
- const results = [];
310
- const yahooResults = await searchYahoo(query, options);
311
- results.push(...yahooResults);
312
- if (results.length < 5) {
313
- const bingResults = await searchBing(query, options);
314
- results.push(...bingResults);
315
- }
316
- if (results.length < 8) {
317
- const braveResults = await searchBrave(query, options);
318
- results.push(...braveResults);
319
- }
320
- if (results.length < 10) {
321
- const googleResults = await searchGoogle(query, options);
322
- results.push(...googleResults);
323
- }
324
- const uniqueResults = Array.from(new Map(results.map((item) => [item.url, item])).values());
325
- return uniqueResults.slice(0, maxResults);
326
- }
327
- async function deepSearch(query, options = {}) {
328
- const { maxResults = 5, timeout = 3e4, depth = 1 } = options;
329
- const results = [];
330
- const searchResults = await unifiedSearch(query, { maxResults, timeout });
331
- for (const result of searchResults.slice(0, Math.min(depth * 3, maxResults))) {
332
- let page = null;
333
- try {
334
- const context = await getFreshContext();
335
- page = await context.newPage();
336
- if (!page) continue;
337
- page.setDefaultTimeout(timeout);
338
- await page.goto(result.url, { waitUntil: "domcontentloaded" });
339
- const content = await page.evaluate(() => {
340
- document.querySelectorAll("script, style, nav, footer, header, aside").forEach((el) => el.remove());
341
- const main = document.querySelector("main, article, .content, #content, .post-content") || document.body;
342
- return main.textContent?.replace(/\s+/g, " ").trim().slice(0, 5e3) || "";
343
- });
344
- const links = await page.$$eval("a[href]", (anchors) => {
345
- return anchors.map((a) => a.href).filter((href) => href.startsWith("http")).slice(0, 10);
346
- });
347
- results.push({
348
- ...result,
349
- content,
350
- links,
351
- depth: 0
352
- });
353
- } catch (error) {
354
- results.push({ ...result, content: "", links: [], depth: 0 });
355
- } finally {
356
- if (page) await page.close();
357
- }
358
- }
359
- return results;
360
- }
361
- async function fetchUrlContent(url, options = {}) {
362
- const { timeout = 3e4 } = options;
363
- let page = null;
364
- try {
365
- const context = await getFreshContext();
366
- page = await context.newPage();
367
- if (!page) throw new Error("Failed to create page");
368
- page.setDefaultTimeout(timeout);
369
- await page.goto(url, { waitUntil: "domcontentloaded" });
370
- const content = await page.evaluate(() => {
371
- document.querySelectorAll("script, style, nav, footer, header").forEach((el) => el.remove());
372
- return document.body.textContent?.replace(/\s+/g, " ").trim() || "";
373
- });
374
- return content;
375
- } catch (error) {
376
- return "";
377
- } finally {
378
- if (page) await page.close();
379
- }
380
- }
381
- async function searchCVE(query) {
382
- return unifiedSearch(`${query} site:cve.mitre.org OR site:nvd.nist.gov`);
383
- }
384
- async function searchExploits(query) {
385
- return unifiedSearch(`${query} site:exploit-db.com OR site:github.com exploit POC`);
386
- }
387
- async function searchWriteups(query, platform = "general") {
388
- const sources = WRITEUP_SOURCES[platform] || WRITEUP_SOURCES.general;
389
- const siteQuery = sources.join(" OR ");
390
- return unifiedSearch(`${query} writeup walkthrough ${siteQuery}`);
391
- }
392
- async function searchMachineWriteup(machineName) {
393
- const [writeups, videos] = await Promise.all([
394
- unifiedSearch(`"${machineName}" HackTheBox OR TryHackMe writeup walkthrough site:0xdf.gitlab.io OR site:medium.com`),
395
- unifiedSearch(`"${machineName}" ippsec site:youtube.com OR site:ippsec.rocks`)
396
- ]);
397
- return { writeups, videos };
398
- }
399
- async function searchByScenario(query, scenario) {
400
- const keywords = SCENARIO_KEYWORDS[scenario] || "";
401
- return unifiedSearch(`${query} ${keywords} writeup walkthrough exploit`);
402
- }
403
- async function searchADWriteups(query) {
404
- return unifiedSearch(
405
- `${query} Active Directory Kerberos LDAP BloodHound GetNPUsers AS-REP Roasting Kerberoasting DCSync Pass-the-Hash writeup`
406
- );
407
- }
408
- async function searchLinuxPrivesc(query) {
409
- return unifiedSearch(
410
- `${query} Linux privilege escalation SUID GTFOBins sudo capabilities cronjob kernel exploit writeup`
411
- );
412
- }
413
- async function searchWindowsPrivesc(query) {
414
- return unifiedSearch(
415
- `${query} Windows privilege escalation SeImpersonate JuicyPotato PrintSpoofer token impersonation UAC bypass writeup`
416
- );
417
- }
418
- async function securityResearch(query) {
419
- const [general, cves, exploits, writeups] = await Promise.all([
420
- unifiedSearch(query),
421
- searchCVE(query),
422
- searchExploits(query),
423
- searchWriteups(query)
424
- ]);
425
- return { general, cves, exploits, writeups };
426
- }
427
- async function ctfResearch(boxName, scenario) {
428
- const [machine, scenarioResults, exploits, deepContent] = await Promise.all([
429
- searchMachineWriteup(boxName),
430
- scenario ? searchByScenario(boxName, scenario) : Promise.resolve([]),
431
- searchExploits(boxName),
432
- deepSearch(`${boxName} HackTheBox writeup`, { maxResults: 3, depth: 1 })
433
- ]);
434
- return { machine, scenario: scenarioResults, exploits, deepContent };
435
- }
436
-
437
- export {
438
- closeBrowser,
439
- searchGoogle,
440
- searchDuckDuckGo,
441
- searchBing,
442
- searchBrave,
443
- searchYahoo,
444
- unifiedSearch,
445
- deepSearch,
446
- fetchUrlContent,
447
- searchCVE,
448
- searchExploits,
449
- searchWriteups,
450
- searchMachineWriteup,
451
- searchByScenario,
452
- searchADWriteups,
453
- searchLinuxPrivesc,
454
- searchWindowsPrivesc,
455
- securityResearch,
456
- ctfResearch
457
- };