diff --git a/frontend/src/_nav.js b/frontend/src/_nav.js index 628f53d759144692a765b588ff88da6de110849f..f059e987a0e9ecf419a6d6885d3c673784449a9e 100644 --- a/frontend/src/_nav.js +++ b/frontend/src/_nav.js @@ -59,6 +59,16 @@ const _nav = [ to: '/password-breaches/view', icon: <CIcon icon={cilShieldAlt} customClassName="nav-icon" />, }, + { + component: CNavTitle, + name: 'SHODAN SCAN', + }, + { + component: CNavItem, + name: 'Scan IPs', + to: '/scan', + icon: <CIcon icon={cilShieldAlt} customClassName="nav-icon" />, + }, { component: CNavTitle, name: 'Theme', diff --git a/frontend/src/routes.js b/frontend/src/routes.js index b30af16d621b32fe31aa87d11c7b948aabe85f20..ab66997bb48d1093ad90b85ea8bffc4b50c97afe 100644 --- a/frontend/src/routes.js +++ b/frontend/src/routes.js @@ -55,6 +55,7 @@ const TrackedEmails = React.lazy(() => import('./views/emails/BreachesEmails')) const PasswordBreaches = React.lazy(() => import('./views/passwords/Breaches')) const TrackedPasswords = React.lazy(() => import('./views/passwords/BreachesPasswords')) const Profile = React.lazy(() => import('./views/pages/profile/Profile')) +const shodan_scan = React.lazy(() => import('./views/shodan/shodanscan')) const routes = [ { path: '/', exact: true, name: 'Home' }, @@ -106,6 +107,7 @@ const routes = [ { path: '/password-breaches/add', name: 'Password Breaches', element: PasswordBreaches }, { path: '/password-breaches/view', name: 'View Breached Passwords', element: TrackedPasswords }, { path: '/profile', name: 'Profile', element: Profile }, + { path: '/scan', name: 'Shodan Scan', element: shodan_scan }, ] export default routes diff --git a/frontend/src/views/shodan/shodanscan.js b/frontend/src/views/shodan/shodanscan.js new file mode 100644 index 0000000000000000000000000000000000000000..6cd53ec473d69fc09eeffbb559aec633841321d9 --- /dev/null +++ b/frontend/src/views/shodan/shodanscan.js @@ -0,0 +1,129 @@ +import React, { useState } from 'react' +import { + CButton, + CCard, + CCardBody, + CCardHeader, + CCol, + CForm, + CFormInput, + CInputGroup, + CInputGroupText, + CRow, +} from '@coreui/react' +import CIcon from '@coreui/icons-react' +import { cilTrash, cilPlus } from '@coreui/icons' + +const ShodanScanner = () => { + const [ipAddresses, setIpAddresses] = useState([{ address: '' }]) + const [scanResults, setScanResults] = useState([]) + + const handleAddIpAddress = () => setIpAddresses([...ipAddresses, { address: '' }]) + + const handleRemoveIpAddress = (index) => { + const newIpAddresses = [...ipAddresses] + newIpAddresses.splice(index, 1) + setIpAddresses(newIpAddresses) + } + + const handleScan = async () => { + try { + const response = await fetch('http://127.0.0.1:8000/shodan-scan/', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ ips: ipAddresses.map((ip) => ip.address) }), + }) + + const data = await response.json() + + // Log or process the scan results from the backend + console.log('Scan results:', data) + setScanResults(data.scan_results) + } catch (error) { + console.error('Error scanning IP addresses:', error) + } + } + + return ( + <CRow> + <CCol lg={12}> + <CCard className={'mb-4'}> + <CCardHeader>Shodan Scanner</CCardHeader> + <CCardBody> + <CForm> + {ipAddresses.map((ip, index) => ( + <CInputGroup key={index} className="mb-3"> + <CFormInput + type="text" + placeholder="Enter IP Address" + value={ip.address} + onChange={(e) => { + const newIpAddresses = [...ipAddresses] + newIpAddresses[index].address = e.target.value + setIpAddresses(newIpAddresses) + }} + /> + <CButton + type="button" + color="danger" + variant="outline" + onClick={() => handleRemoveIpAddress(index)} + > + <CIcon icon={cilTrash} /> + </CButton> + </CInputGroup> + ))} + <CButton color="primary" className="mb-3" onClick={handleAddIpAddress}> + <CIcon icon={cilPlus} /> Add Another IP Address + </CButton> + + <div className="d-grid gap-2"> + <CButton color="info" onClick={handleScan}> + Scan + </CButton> + </div> + </CForm> + {scanResults.length > 0 && ( + <div className="scan-results"> + <h3>Scan Results</h3> + {scanResults.map((result, index) => ( + <div key={index} className="result"> + <h4>IP Address: {result.ip_address}</h4> + <div> + Geolocation: {result.geolocation.country}, {result.geolocation.city} + </div> + <div> + Latitude: {result.geolocation.latitude}, Longitude: {''} + {result.geolocation.longitude} + </div> + <div> + <h5>Open Ports</h5> + {result.open_ports.map((port, portIndex) => ( + <p key={portIndex}> + {port.port}/{port.protocol} - {port.banner} + </p> + ))} + </div> + <div> + <h5>Vulnerabilities</h5> + {result.vulnerabilities && + result.vulnerabilities.map((vuln, vulnIndex) => ( + <p key={vulnIndex}> + {Object.keys(vuln)[0]}: {Object.values(vuln)[0]} + </p> + ))} + </div> + </div> + ))} + </div> + )} + </CCardBody> + </CCard> + </CCol> + </CRow> + ) +} + +export default ShodanScanner