diff --git a/src/components/Results/Malware.tsx b/src/components/Results/Malware.tsx new file mode 100644 index 0000000..1b681a8 --- /dev/null +++ b/src/components/Results/Malware.tsx @@ -0,0 +1,70 @@ + +import styled from 'styled-components'; +import colors from 'styles/colors'; +import { Card } from 'components/Form/Card'; +import Row, { ExpandableRow } from 'components/Form/Row'; + +const Expandable = styled.details` +margin-top: 0.5rem; +cursor: pointer; +summary::marker { + color: ${colors.primary}; +} +`; + +const getExpandableTitle = (urlObj: any) => { + let pathName = ''; + try { + pathName = new URL(urlObj.url).pathname; + } catch(e) {} + return `${pathName} (${urlObj.id})`; +} + +const convertToDate = (dateString: string): string => { + const [date, time] = dateString.split(' '); + const [year, month, day] = date.split('-').map(Number); + const [hour, minute, second] = time.split(':').map(Number); + const dateObject = new Date(year, month - 1, day, hour, minute, second); + if (isNaN(dateObject.getTime())) { + return dateString; + } + return dateObject.toString(); +} + +const MalwareCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => { + const urlHaus = props.data.urlHaus; + return ( + + { urlHaus.query_status === 'no_results' && } + { urlHaus.query_status === 'ok' && ( + <> + + + + + )} + {urlHaus.urls && ( + + Expand Results + { urlHaus.urls.map((urlResult: any, index: number) => { + const rows = [ + { lbl: 'ID', val: urlResult.id }, + { lbl: 'Status', val: urlResult.url_status }, + { lbl: 'Date Added', val: convertToDate(urlResult.date_added) }, + { lbl: 'Threat Type', val: urlResult.threat }, + { lbl: 'Reported By', val: urlResult.reporter }, + { lbl: 'Takedown Time', val: urlResult.takedown_time_seconds }, + { lbl: 'Larted', val: urlResult.larted }, + { lbl: 'Tags', val: (urlResult.tags || []).join(', ') }, + { lbl: 'Reference', val: urlResult.urlhaus_reference }, + { lbl: 'File Path', val: urlResult.url }, + ]; + return () + })} + + )} + + ); +} + +export default MalwareCard; diff --git a/src/components/misc/ProgressBar.tsx b/src/components/misc/ProgressBar.tsx index 210d342..0164dfc 100644 --- a/src/components/misc/ProgressBar.tsx +++ b/src/components/misc/ProgressBar.tsx @@ -218,6 +218,7 @@ const jobNames = [ 'rank', 'archives', 'block-lists', + 'malware', ] as const; export const initialJobs = jobNames.map((job: string) => { diff --git a/src/pages/Results.tsx b/src/pages/Results.tsx index f0d5b72..a8027a4 100644 --- a/src/pages/Results.tsx +++ b/src/pages/Results.tsx @@ -53,6 +53,7 @@ import FirewallCard from 'components/Results/Firewall'; import ArchivesCard from 'components/Results/Archives'; import RankCard from 'components/Results/Rank'; import BlockListsCard from 'components/Results/BlockLists'; +import MalwareCard from 'components/Results/Malware'; import keys from 'utils/get-keys'; import { determineAddressType, AddressType } from 'utils/address-type-checker'; @@ -448,6 +449,14 @@ const Results = (): JSX.Element => { fetchRequest: () => fetch(`${api}/block-lists?url=${address}`).then(res => parseJson(res)), }); + // Check if a host is present on the URLHaus malware list + const [malwareResults, updateMalwareResults] = useMotherHook({ + jobId: 'malware', + updateLoadingJobs, + addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, + fetchRequest: () => fetch(`${api}/malware?url=${address}`).then(res => parseJson(res)), + }); + /* Cancel remaining jobs after 10 second timeout */ useEffect(() => { const checkJobs = () => { @@ -503,6 +512,7 @@ const Results = (): JSX.Element => { { id: 'linked-pages', title: 'Linked Pages', result: linkedPagesResults, Component: ContentLinksCard, refresh: updateLinkedPagesResults }, { id: 'txt-records', title: 'TXT Records', result: txtRecordResults, Component: TxtRecordCard, refresh: updateTxtRecordResults }, { id: 'block-lists', title: 'Block Lists', result: blockListsResults, Component: BlockListsCard, refresh: updateBlockListsResults }, + { id: 'malware', title: 'Malware', result: malwareResults, Component: MalwareCard, refresh: updateMalwareResults }, { id: 'features', title: 'Site Features', result: siteFeaturesResults, Component: SiteFeaturesCard, refresh: updateSiteFeaturesResults }, { id: 'sitemap', title: 'Pages', result: sitemapResults, Component: SitemapCard, refresh: updateSitemapResults }, { id: 'carbon', title: 'Carbon Footprint', result: carbonResults, Component: CarbonFootprintCard, refresh: updateCarbonResults }, diff --git a/src/utils/docs.ts b/src/utils/docs.ts index 9db788c..ea4cbd8 100644 --- a/src/utils/docs.ts +++ b/src/utils/docs.ts @@ -470,6 +470,17 @@ const docs: Doc[] = [ resources: [], screenshot: '', }, + { + id: 'malware', + title: 'Malware & Phishing Detection', + description: '', + use: '', + resources: [ + { title: 'URLHaus', link: 'https://urlhaus-api.abuse.ch/'}, + { title: 'PhishTank', link: 'https://www.phishtank.com/'}, + ], + screenshot: '', + }, // { // id: '', // title: '',