From 80919f66ba3eeb099f9b9e5ed7645059bb6e66ba Mon Sep 17 00:00:00 2001 From: Yazan Essam Date: Thu, 25 Apr 2024 02:19:50 +0200 Subject: [PATCH 1/2] Attacks UI --- src/renderer/App.tsx | 5 +- src/renderer/components/sidebar.tsx | 5 +- src/renderer/views/project/JsLeaks.tsx | 6 +- src/renderer/views/project/attacks.tsx | 61 +++++++++++++++++++ .../views/project/attacks/exposures.tsx | 23 +++++++ .../views/project/attacks/missingHeaders.tsx | 23 +++++++ .../views/project/attacks/potentialXss.tsx | 23 +++++++ .../views/project/attacks/sqlInjection.tsx | 23 +++++++ 8 files changed, 161 insertions(+), 8 deletions(-) create mode 100644 src/renderer/views/project/attacks.tsx create mode 100644 src/renderer/views/project/attacks/exposures.tsx create mode 100644 src/renderer/views/project/attacks/missingHeaders.tsx create mode 100644 src/renderer/views/project/attacks/potentialXss.tsx create mode 100644 src/renderer/views/project/attacks/sqlInjection.tsx diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 3e35156..86abb64 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -9,7 +9,8 @@ import { ProjectLayout } from './layout/projectLayout'; import Status from './views/project/status'; import Recon from './views/project/recon'; import { ReconResults } from './views/project/results/recon-results'; -import JsLeaks from './views/project/JsLeaks.1'; +import JsLeaks from './views/project/JsLeaks'; +import Attacks from './views/project/attacks'; function Home() { return ( @@ -31,7 +32,7 @@ export default function App() { } /> } /> } /> - } /> + } /> } /> diff --git a/src/renderer/components/sidebar.tsx b/src/renderer/components/sidebar.tsx index e50e4e8..63896eb 100644 --- a/src/renderer/components/sidebar.tsx +++ b/src/renderer/components/sidebar.tsx @@ -30,9 +30,8 @@ const dashboardMenu: DashboardMenu[] = [ icon: , }, { - href: 'attack', - title: 'Attack', - Disabled: true, + href: 'attacks', + title: 'Attacks', icon: , }, { diff --git a/src/renderer/views/project/JsLeaks.tsx b/src/renderer/views/project/JsLeaks.tsx index b3ad068..0a4b824 100644 --- a/src/renderer/views/project/JsLeaks.tsx +++ b/src/renderer/views/project/JsLeaks.tsx @@ -5,13 +5,13 @@ import { CardHeader, CardTitle, } from '../../components/ui/card'; -import Secrets from './JsLeaks Jobs/secrets'; -import EndPoints from './JsLeaks Jobs/EndPoints'; +import Secrets from './jsLeaksJob/secrets'; +import EndPoints from './jsLeaksJob/Endpoint'; export default function JsLeaks() { return (
-

Initiate Recon Attacks

+

JsLeaks

diff --git a/src/renderer/views/project/attacks.tsx b/src/renderer/views/project/attacks.tsx new file mode 100644 index 0000000..9291ad4 --- /dev/null +++ b/src/renderer/views/project/attacks.tsx @@ -0,0 +1,61 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '../../components/ui/card'; +import Exposures from './attacks/exposures'; +import MissingHeaders from './attacks/missingHeaders'; +import PotentialXss from './attacks/potentialXss'; +import SqlInjection from './attacks/sqlInjection'; + +export default function Attacks() { + return ( +
+

Attacks

+
+
+ + + Scan for exposures + wanna find exposures ? + + + + + + + + Scan for missing headers + wanna find more ? + + + + + + + + Scan the URLs + wanna catch potential XSS + + + + + + + + Scan for SQL Injection + + SSTI, Open Redirect & CRLF Injection + + + + + + +
+
+
+ ); +} diff --git a/src/renderer/views/project/attacks/exposures.tsx b/src/renderer/views/project/attacks/exposures.tsx new file mode 100644 index 0000000..538635b --- /dev/null +++ b/src/renderer/views/project/attacks/exposures.tsx @@ -0,0 +1,23 @@ +import { Loader2 } from 'lucide-react'; +import { useState } from 'react'; +import { Button } from '../../../components/ui/button'; + +export default function Exposures() { + const [Loading, setLoading] = useState(false); + const RunExposures = async () => { + setLoading(true); + }; + return ( + // eslint-disable-next-line react/jsx-no-useless-fragment + <> + {!Loading ? ( + + ) : ( + + )} + + ); +} diff --git a/src/renderer/views/project/attacks/missingHeaders.tsx b/src/renderer/views/project/attacks/missingHeaders.tsx new file mode 100644 index 0000000..7d9dbb8 --- /dev/null +++ b/src/renderer/views/project/attacks/missingHeaders.tsx @@ -0,0 +1,23 @@ +import { Loader2 } from 'lucide-react'; +import { useState } from 'react'; +import { Button } from '../../../components/ui/button'; + +export default function MissingHeaders() { + const [Loading, setLoading] = useState(false); + const RunMissingHeaders = async () => { + setLoading(true); + }; + return ( + // eslint-disable-next-line react/jsx-no-useless-fragment + <> + {!Loading ? ( + + ) : ( + + )} + + ); +} diff --git a/src/renderer/views/project/attacks/potentialXss.tsx b/src/renderer/views/project/attacks/potentialXss.tsx new file mode 100644 index 0000000..a4d518a --- /dev/null +++ b/src/renderer/views/project/attacks/potentialXss.tsx @@ -0,0 +1,23 @@ +import { Loader2 } from 'lucide-react'; +import { useState } from 'react'; +import { Button } from '../../../components/ui/button'; + +export default function PotentialXss() { + const [Loading, setLoading] = useState(false); + const RunPotentialXss = async () => { + setLoading(true); + }; + return ( + // eslint-disable-next-line react/jsx-no-useless-fragment + <> + {!Loading ? ( + + ) : ( + + )} + + ); +} diff --git a/src/renderer/views/project/attacks/sqlInjection.tsx b/src/renderer/views/project/attacks/sqlInjection.tsx new file mode 100644 index 0000000..f4c9156 --- /dev/null +++ b/src/renderer/views/project/attacks/sqlInjection.tsx @@ -0,0 +1,23 @@ +import { Loader2 } from 'lucide-react'; +import { useState } from 'react'; +import { Button } from '../../../components/ui/button'; + +export default function SqlInjection() { + const [Loading, setLoading] = useState(false); + const RunSqlInjection = async () => { + setLoading(true); + }; + return ( + // eslint-disable-next-line react/jsx-no-useless-fragment + <> + {!Loading ? ( + + ) : ( + + )} + + ); +} From 1f3ddf12da22ebeac14962d4f8fbd75f57851398 Mon Sep 17 00:00:00 2001 From: Yazan Essam Date: Sat, 27 Apr 2024 16:40:52 +0300 Subject: [PATCH 2/2] jsleak is ready to work --- src/main/jsleak/jsleak.ts | 17 +++-- src/main/main.ts | 2 +- src/main/preload.ts | 2 + src/renderer/views/project/JsLeaks.tsx | 68 ++++++++++++------- .../views/project/jsLeaksJob/Endpoint.tsx | 17 ++++- .../views/project/jsLeaksJob/secrets.tsx | 15 +++- 6 files changed, 89 insertions(+), 32 deletions(-) diff --git a/src/main/jsleak/jsleak.ts b/src/main/jsleak/jsleak.ts index 2140c3c..8736120 100644 --- a/src/main/jsleak/jsleak.ts +++ b/src/main/jsleak/jsleak.ts @@ -1,5 +1,6 @@ import { execSync } from 'child_process'; import path from 'path'; +import fs from 'fs'; import { CurrentOS, toolPath } from '../util'; import { PROJECT_DIR } from '../api/project'; import { connectJson } from '../db/connect'; @@ -11,10 +12,12 @@ export async function findSecret(outputDir: string = PROJECT_DIR): Promise<{ error: any; }> { const jsleak = toolPath('jsleak'); - const command = `${CurrentOS() === 'win32' ? 'type' : 'cat'} ${path.join(outputDir, 'httpx_live_domains.txt')} | ${jsleak} -s - >> ${path.join(outputDir, 'secrets.txt')}`; + const command = `${CurrentOS() === 'win32' ? 'type' : 'cat'} ${path.join(outputDir, 'httpx_live_domains.txt')} | ${jsleak} -s`; try { - execSync(command); + fs.writeFileSync( + `${path.join(outputDir, 'secrets.txt')}`, + execSync(command).toString('utf-8'), + ); const numberOfUrls = await countLines(path.join(outputDir, 'secrets.txt')); const db = connectJson(path.join(`${outputDir}/details.json`)); await db.update({ @@ -38,10 +41,12 @@ export async function extraLinks(outputDir: string = PROJECT_DIR): Promise<{ error: any; }> { const jsleak = toolPath('jsleak'); - const command = `${CurrentOS() === 'win32' ? 'type' : 'cat'} ${path.join(outputDir, 'httpx_live_domains.txt')} | ${jsleak} -l | findstr ".js" - >> ${path.join(outputDir, 'extra_links.txt')}`; + const command = `${CurrentOS() === 'win32' ? 'type' : 'cat'} ${path.join(outputDir, 'httpx_live_domains.txt')} | ${jsleak} -l | findstr ".js"`; try { - execSync(command); + fs.writeFileSync( + `${path.join(outputDir, 'extra_links.txt')}`, + execSync(command).toString('utf-8'), + ); const numberOfUrls = await countLines( path.join(outputDir, 'extra_links.txt'), ); diff --git a/src/main/main.ts b/src/main/main.ts index 89e01f4..65036a0 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -26,7 +26,7 @@ import { import { liveSubDomains, screenwin } from './recon/httpx'; import { fetchJs, parameter, wwayback } from './recon/waybackurls'; import { returnFile } from './api/serve'; -import { findSecret, extraLinks } from './jsleak/jsleak'; +import { extraLinks, findSecret } from './jsleak/jsleak'; class AppUpdater { constructor() { diff --git a/src/main/preload.ts b/src/main/preload.ts index 3ae3315..4780754 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts @@ -14,6 +14,8 @@ export type Channels = | 'waybackurls-parameter' | 'get-project-details' | 'api-call' + | 'find-secrets' + | 'extra-links' | 'open-link'; const electronHandler = { diff --git a/src/renderer/views/project/JsLeaks.tsx b/src/renderer/views/project/JsLeaks.tsx index 0a4b824..1d06f86 100644 --- a/src/renderer/views/project/JsLeaks.tsx +++ b/src/renderer/views/project/JsLeaks.tsx @@ -1,3 +1,7 @@ +/* eslint-disable react/jsx-props-no-spreading */ +/* eslint-disable react-hooks/exhaustive-deps */ +import { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; import { Card, CardContent, @@ -7,35 +11,53 @@ import { } from '../../components/ui/card'; import Secrets from './jsLeaksJob/secrets'; import EndPoints from './jsLeaksJob/Endpoint'; +import { ProjectDetails } from '../../types'; export default function JsLeaks() { + const [details, setDetails] = useState(); + const { projectSlug } = useParams(); + + const getDetails = async () => { + const res = await window.electron.ipcRenderer.invoke( + 'get-project-details', + projectSlug, + ); + setDetails(res); + console.log(res); + }; + + useEffect(() => { + getDetails(); + }, []); return (

JsLeaks

-
-
- - - Find Secrets - wanna find secrets ? - - - - - - - - Find EndPoints - - Unveiling extra and hidden endpoints - - - - - - + {details && ( +
+
+ + + Find Secrets + wanna find secrets ? + + + + + + + + Find EndPoints + + Unveiling extra and hidden endpoints + + + + + + +
-
+ )}
); } diff --git a/src/renderer/views/project/jsLeaksJob/Endpoint.tsx b/src/renderer/views/project/jsLeaksJob/Endpoint.tsx index 205df3f..b2f151f 100644 --- a/src/renderer/views/project/jsLeaksJob/Endpoint.tsx +++ b/src/renderer/views/project/jsLeaksJob/Endpoint.tsx @@ -1,11 +1,26 @@ import { Loader2 } from 'lucide-react'; import { useState } from 'react'; import { Button } from '../../../components/ui/button'; +import { useToast } from '../../../components/ui/use-toast'; +import { ProjectDetails } from '../../../types'; -export default function EndPoints() { +export default function EndPoints(details: ProjectDetails) { + const { name } = details; const [Loading, setLoading] = useState(false); + const { toast } = useToast(); const RunEndPoints = async () => { setLoading(true); + if (details) { + const res = await window.electron.ipcRenderer.invoke('extra-links', { + projectName: name, + }); + if (res) { + toast({ + title: 'Endpoints are ready', + }); + } + } + setLoading(false); }; return ( // eslint-disable-next-line react/jsx-no-useless-fragment diff --git a/src/renderer/views/project/jsLeaksJob/secrets.tsx b/src/renderer/views/project/jsLeaksJob/secrets.tsx index 865aea9..41d2ea5 100644 --- a/src/renderer/views/project/jsLeaksJob/secrets.tsx +++ b/src/renderer/views/project/jsLeaksJob/secrets.tsx @@ -1,11 +1,24 @@ import { Loader2 } from 'lucide-react'; import { useState } from 'react'; import { Button } from '../../../components/ui/button'; +import { useToast } from '../../../components/ui/use-toast'; +import { ProjectDetails } from '../../../types'; -export default function Secrets() { +export default function Secrets(details: ProjectDetails) { + const { name } = details; const [Loading, setLoading] = useState(false); + const { toast } = useToast(); const RunSecrets = async () => { setLoading(true); + const res = await window.electron.ipcRenderer.invoke('find-secrets', { + projectName: name, + }); + if (res) { + toast({ + title: 'your Secrets are ready', + }); + } + setLoading(false); }; return ( // eslint-disable-next-line react/jsx-no-useless-fragment