Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
52 changes: 52 additions & 0 deletions frontend/src/data/softwareData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { graphqlRequest } from "../api/graphql";
import { mockSoftware, type SoftwareEntry } from "./softwareMockData";

export type { SoftwareEntry } from "./softwareMockData";

export const USE_SOFTWARE_MOCK_DATA = true; // ENDRE DENNE FOR Å IKKE BRUKE MOCK!!!

export type SoftwareCatalogEntry = Omit<SoftwareEntry, "associatedTechniques" | "usedByThreatActors">;

export async function getSoftwareCatalog(): Promise<SoftwareCatalogEntry[]> {
if (USE_SOFTWARE_MOCK_DATA) return mockSoftware;

const data = await graphqlRequest<{ software: SoftwareCatalogEntry[] }>(`
query SoftwareCatalog {
software {
id
mitreId
name
description
type
aliases
platforms
}
}
`);

return data.software;
}

export async function getSoftwareByMitreId(mitreId: string): Promise<SoftwareEntry | null> {
if (USE_SOFTWARE_MOCK_DATA) {
return mockSoftware.find((entry) => entry.mitreId === mitreId) ?? null;
}

const data = await graphqlRequest<{ softwareByMitreId: SoftwareEntry | null }>(`
query SoftwareDetail($mitreId: String!) {
softwareByMitreId(mitreId: $mitreId) {
id
mitreId
name
description
type
aliases
platforms
associatedTechniques { id mitreId name }
usedByThreatActors { id mitreId name }
}
}
`, { mitreId });

return data.softwareByMitreId;
}
128 changes: 128 additions & 0 deletions frontend/src/data/softwareMockData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
export type RelatedSoftwareEntry = {
id: string;
mitreId: string;
name: string;
};

export type SoftwareEntry = {
id: string;
mitreId: string;
name: string;
type: "TOOL" | "MALWARE";
summary: string;
description: string;
aliases: string[];
platforms: string[];
associatedTechniques: RelatedSoftwareEntry[];
usedByThreatActors: RelatedSoftwareEntry[];
};

export const mockSoftware: SoftwareEntry[] = [
{
id: "S0002",
mitreId: "S0002",
name: "Mimikatz",
type: "TOOL",
summary: "Extracts credentials from memory using LSASS dumping and other techniques.",
description: "Mimikatz is an open-source tool used to extract credentials from Windows memory, including passwords, hash values, Kerberos tickets, and other authentication material. It is widely used by adversaries for post-exploitation and credential theft, and can also be used to perform pass-the-hash, pass-the-ticket, and other credential-related attacks. Mimikatz is commonly employed in red team operations and malicious campaigns due to its flexibility and extensive feature set for interacting with Windows security internals.",
aliases: ["mimikatz", "kiwi", "gentilkiwi", "mimilb"],
platforms: ["Windows"],
associatedTechniques: [
{ id: "T1003", mitreId: "T1003", name: "OS Credential Dumping" },
{ id: "T1555", mitreId: "T1555", name: "Credentials from Password Stores" },
{ id: "T1078", mitreId: "T1078", name: "Valid Accounts" },
{ id: "T1059", mitreId: "T1059", name: "Command and Scripting Interpreter" },
{ id: "T1110", mitreId: "T1110", name: "Brute Force" },
],
usedByThreatActors: [
{ id: "G0016", mitreId: "G0016", name: "APT28" },
{ id: "apt29", mitreId: "G0016", name: "APT29" },
{ id: "G0032", mitreId: "G0032", name: "Lazarus Group" },
{ id: "G0034", mitreId: "G0034", name: "Sandworm Team" },
],
},
{
id: "S0154",
mitreId: "S0154",
name: "Cobalt Strike",
type: "TOOL",
summary: "Adversary emulation framework for post-exploitation, C2, and lateral movement.",
description: "Adversary emulation framework for post-exploitation, C2, and lateral movement.",
aliases: ["CobaltStrike"],
platforms: ["Windows", "Linux", "macOS"],
associatedTechniques: [],
usedByThreatActors: [],
},
{
id: "S0363",
mitreId: "S0363",
name: "PowerShell Empire",
type: "TOOL",
summary: "Post-exploitation framework using PowerShell for C2 and lateral movement.",
description: "Post-exploitation framework using PowerShell for C2 and lateral movement.",
aliases: ["Empire", "PowerShell Empire"],
platforms: ["Windows", "Linux", "macOS"],
associatedTechniques: [],
usedByThreatActors: [],
},
{
id: "S0498",
mitreId: "S0498",
name: "WellMess",
type: "MALWARE",
summary: "Modular backdoor used for espionage and data theft.",
description: "Modular backdoor used for espionage and data theft.",
aliases: ["WellMess"],
platforms: ["Windows", "Linux"],
associatedTechniques: [],
usedByThreatActors: [],
},
{
id: "S0521",
mitreId: "S0521",
name: "SeaDuke",
type: "MALWARE",
summary: "Modular malware platform used for long-term espionage operations.",
description: "Modular malware platform used for long-term espionage operations.",
aliases: ["SeaDuke"],
platforms: ["Windows"],
associatedTechniques: [],
usedByThreatActors: [],
},
{
id: "S0580",
mitreId: "S0580",
name: "SUNBURST",
type: "MALWARE",
summary: "Supply chain malware used to gain long-term access to target environments.",
description: "Supply chain malware used to gain long-term access to target environments.",
aliases: ["SUNBURST", "Solorigate"],
platforms: ["Windows"],
associatedTechniques: [],
usedByThreatActors: [],
},
{
id: "S0619",
mitreId: "S0619",
name: "DarkHalo",
type: "MALWARE",
summary: "Backdoor used for privilege escalation and persistent access.",
description: "Backdoor used for privilege escalation and persistent access.",
aliases: ["DarkHalo"],
platforms: ["Windows"],
associatedTechniques: [],
usedByThreatActors: [],
},
{
id: "S0689",
mitreId: "S0689",
name: "PlugX",
type: "MALWARE",
summary: "Modular remote access trojan used for espionage and data exfiltration.",
description: "Modular remote access trojan used for espionage and data exfiltration.",
aliases: ["PlugX", "Korplug"],
platforms: ["Windows"],
associatedTechniques: [],
usedByThreatActors: [],
},
];
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,13 @@ import {
Shield,
TerminalSquare,
} from "lucide-react";
import { graphqlRequest } from "../api/graphql";
import { getSoftwareCatalog, type SoftwareCatalogEntry } from "../../data/softwareData";
import "./Software.css";

type SoftwareEntry = {
id: string;
mitreId: string;
name: string;
type: "TOOL" | "MALWARE";
description: string;
aliases: string[];
platforms: string[];
};

const PAGE_SIZE = 10;
const PAGE_SIZE = 8;

function Software() {
const [softwareEntries, setSoftwareEntries] = useState<SoftwareEntry[]>([]);
const [softwareEntries, setSoftwareEntries] = useState<SoftwareCatalogEntry[]>([]);
const [loading, setLoading] = useState(true);
const [loadError, setLoadError] = useState("");
const [search, setSearch] = useState("");
Expand All @@ -39,21 +29,9 @@ function Software() {

useEffect(() => {
let cancelled = false;
graphqlRequest<{ software: SoftwareEntry[] }>(`
query SoftwareCatalog {
software {
id
mitreId
name
description
type
aliases
platforms
}
}
`)
.then((data) => {
if (!cancelled) setSoftwareEntries(data.software);
getSoftwareCatalog()
.then((entries) => {
if (!cancelled) setSoftwareEntries(entries);
})
.catch((error: unknown) => {
if (!cancelled) {
Expand Down Expand Up @@ -221,7 +199,7 @@ function Software() {
<div className="software-empty-state" role="status">
<Database aria-hidden="true" />
<h2>Loading software</h2>
<p>Connecting to the threat intelligence database.</p>
<p>Preparing the software catalog.</p>
</div>
) : loadError ? (
<div className="software-empty-state" role="alert">
Expand Down Expand Up @@ -251,15 +229,15 @@ function Software() {
</span>
</div>
<h2>{entry.name}</h2>
<p className="software-card-description">{entry.description}</p>
<p className="software-card-description">{("summary" in entry && entry.summary) || entry.description}</p>
<p className="software-platforms">
{entry.platforms.join(" · ")}
</p>
<Link
className="software-profile-link"
to={`/software/${encodeURIComponent(entry.mitreId)}`}
to="/software/S0002"
>
View details <ArrowRight aria-hidden="true" />
Open profile <ArrowRight aria-hidden="true" />
</Link>
<ArrowRight className="software-card-chevron" aria-hidden="true" />
</article>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
import { useEffect, useState } from "react";
import { ArrowLeft, ArrowRight, Bug, Database, Network, Radio, TerminalSquare } from "lucide-react";
import { Link, useParams } from "react-router-dom";
import { graphqlRequest } from "../api/graphql";
import { getSoftwareByMitreId } from "../../data/softwareData";
import type { SoftwareEntry } from "../../data/softwareData";
import "./SoftwareDetail.css";

type RelatedEntry = {
id: string;
mitreId: string;
name: string;
};

type SoftwareDetailRecord = {
id: string;
mitreId: string;
name: string;
description: string;
type: "TOOL" | "MALWARE";
aliases: string[];
platforms: string[];
associatedTechniques: RelatedEntry[];
usedByThreatActors: RelatedEntry[];
};

function cleanDescription(description: string): string {
return description
.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
Expand All @@ -37,36 +20,17 @@ function SoftwareDetail() {
const [detailState, setDetailState] = useState<{
mitreId: string;
status: "loading" | "loaded" | "error";
software: SoftwareDetailRecord | null;
software: SoftwareEntry | null;
error: string;
}>({ mitreId: "", status: "loading", software: null, error: "" });

useEffect(() => {
let cancelled = false;

graphqlRequest<{ softwareByMitreId: SoftwareDetailRecord | null }>(`
query SoftwareDetail($mitreId: String!) {
softwareByMitreId(mitreId: $mitreId) {
id
mitreId
name
description
type
aliases
platforms
associatedTechniques { id mitreId name }
usedByThreatActors { id mitreId name }
}
}
`, { mitreId })
.then((data) => {
getSoftwareByMitreId(mitreId)
.then((software) => {
if (!cancelled) {
setDetailState({
mitreId,
status: "loaded",
software: data.softwareByMitreId,
error: "",
});
setDetailState({ mitreId, status: "loaded", software, error: "" });
}
})
.catch((requestError: unknown) => {
Expand Down Expand Up @@ -95,7 +59,7 @@ function SoftwareDetail() {
<div className="software-detail-state" role="status">
<Database aria-hidden="true" />
<h1>Loading software details</h1>
<p>Connecting to the threat intelligence database.</p>
<p>Preparing the software profile.</p>
</div>
</main>
);
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/routes/AppRoutes.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "../pages/Home";
import Home from "../pages/Home/Home";
import ThreatActors from "../pages/ThreatActors/ThreatActors";
import Software from "../pages/Software";
import SoftwareDetail from "../pages/SoftwareDetail";
import Software from "../pages/Software/Software";
import SoftwareDetail from "../pages/Software/SoftwareDetail";
import Tactics from "../pages/Tactics/Tactics";
import SavedItems from "../pages/SavedItems";
import SavedItems from "../pages/SavedItems/SavedItems";
import Techniques from "../pages/Techniques/Techniques";
import AppLayout from "../components/layout/AppLayout";
import TacticDetailed from "../pages/Tactics/TacticDetailed";
Expand Down