CINXE.COM
Analyze - Pulsedive
<!DOCTYPE html> <html lang='en' data-theme='dark' data-uid='0' data-username='' data-email='' data-key='' data-role='0' data-pro='0' data-api='0' data-feed='0' data-enterprise='0' data-integrations='W10=' data-services='eyJhcGkiOnsicGxhbiI6InZpc2l0b3IiLCJkaXNwbGF5IjpudWxsLCJsaW1pdHMiOnsic29mdCI6ZmFsc2UsInJlcXVlc3RzIjp7InNlY29uZCI6MSwiZGF5IjoxMCwibW9udGgiOjEwMH0sImV4cGxvcmUiOjEwLCJhbmFseXplIjpmYWxzZSwibmV3cyI6ZmFsc2V9LCJjdXN0b21lciI6ZmFsc2V9LCJmZWVkIjp7InBsYW4iOiJmcmVlIiwiZGlzcGxheSI6IlNhbXBsZSBPbmx5IiwibGltaXRzIjp7InNhbXBsZSI6dHJ1ZX0sImN1c3RvbWVyIjpmYWxzZX19' data-crawler='0' data-throttle='0' data-customer='0' data-maintenance='0' > <head> <!-- charset --> <meta charset='utf-8'> <!-- fetch all resources from here by default --> <base href='https://pulsedive.com'> <!-- page title --> <title>Analyze - Pulsedive</title> <!-- canonical URL --> <link rel='canonical' href='https://pulsedive.com/analyze/'> <!-- favicon --> <link rel='shortcut icon' href='https://pulsedive.com/img/favicon.png'> <link rel='icon' type='image/x-icon' href='https://pulsedive.com/img/favicon.png'> <!-- OpenSearch --> <link rel='search' type='application/opensearchdescription+xml' title='Pulsedive' href='https://pulsedive.com/opensearch.php?v=6.3.09'> <!-- version --> <meta name='version' content='6.3.09'> <!-- assets URL --> <meta name='assets' content='https://pulsedive.com'> <!-- viewport --> <meta name='viewport' content='width=device-width, initial-scale=1'> <!-- SEO --> <meta name='author' content='Pulsedive'> <meta name='description' content="Upload a list of indicators in bulk to retrieve information from our data set or via on-demand passive scans with Pulsedive's powerful scanning engine."> <meta name='keywords' content="threat intelligence,feed,ioc"> <!-- Twitter card --> <meta name='twitter:card' content='summary_large_image'> <meta name='twitter:site' content='@pulsedive'> <meta name='twitter:creator' content='@pulsedive'> <meta name='twitter:title' content='Analyze - Pulsedive'> <meta name='twitter:description' content='Upload a list of indicators in bulk to retrieve information from our data set or via on-demand passive scans with Pulsedive's powerful scanning engine.'> <meta name='twitter:image' content='https://pulsedive.com/img/opengraph/analyze.jpg'> <!-- Open Graph card --> <meta property='og:url' content='https://pulsedive.com/analyze/'> <meta property='og:title' content='Analyze - Pulsedive'> <meta property='og:description' content='Upload a list of indicators in bulk to retrieve information from our data set or via on-demand passive scans with Pulsedive's powerful scanning engine.'> <meta property='og:image' content='https://pulsedive.com/img/opengraph/analyze.jpg'> <!-- fonts --> <link rel='preload' href='https://pulsedive.com/fonts/fontawesome.css?v=6.3.09' as='style'><link rel='stylesheet' href='https://pulsedive.com/fonts/fontawesome.css?v=6.3.09'><link rel='preload' href='https://pulsedive.com/fonts/montserrat.css?v=6.3.09' as='style'><link rel='stylesheet' href='https://pulsedive.com/fonts/montserrat.css?v=6.3.09'><link rel='preload' href='https://pulsedive.com/fonts/varelaround.css?v=6.3.09' as='style'><link rel='stylesheet' href='https://pulsedive.com/fonts/varelaround.css?v=6.3.09'> <!-- CSS --> <link rel='preload' href='https://pulsedive.com/css/page.css?v=6.3.09' as='style'><link rel='stylesheet' href='https://pulsedive.com/css/page.css?v=6.3.09'><link rel='preload' href='https://pulsedive.com/css/layout.css?v=6.3.09' as='style'><link rel='stylesheet' href='https://pulsedive.com/css/layout.css?v=6.3.09'><link rel='preload' href='https://pulsedive.com/css/cards.css?v=6.3.09' as='style'><link rel='stylesheet' href='https://pulsedive.com/css/cards.css?v=6.3.09'><link rel='preload' href='https://pulsedive.com/css/elem.css?v=6.3.09' as='style'><link rel='stylesheet' href='https://pulsedive.com/css/elem.css?v=6.3.09'><link rel='preload' href='https://pulsedive.com/css/dark.css?v=6.3.09' as='style'><link rel='stylesheet' href='https://pulsedive.com/css/dark.css?v=6.3.09'> </head> <body data-schema='eyJpbmRpY2F0b3JzIjp7ImlwdjYiOnsiZGlzcGxheSI6IklQdjYiLCJhdHRyaWJ1dGVzIjpbInByb3RvY29sIiwicG9ydCIsImhvc3R0eXBlIiwidGVjaG5vbG9neSIsInRhY3RpYyIsInRlY2huaXF1ZSJdfSwiZG9tYWluIjp7ImRpc3BsYXkiOiJEb21haW4iLCJhdHRyaWJ1dGVzIjpbInByb3RvY29sIiwicG9ydCIsImhvc3R0eXBlIiwidGVjaG5vbG9neSIsInRhY3RpYyIsInRlY2huaXF1ZSJdfSwiYXJ0aWZhY3QiOnsiZGlzcGxheSI6IkFydGlmYWN0IiwiYXR0cmlidXRlcyI6WyJmaWxlbmFtZSIsImZpbGV0eXBlIiwieWFyYSIsInRhY3RpYyIsInRlY2huaXF1ZSJdfSwiaXAiOnsiZGlzcGxheSI6IklQIiwiYXR0cmlidXRlcyI6WyJwcm90b2NvbCIsInBvcnQiLCJob3N0dHlwZSIsInRlY2hub2xvZ3kiLCJ0YWN0aWMiLCJ0ZWNobmlxdWUiXX0sInVybCI6eyJkaXNwbGF5IjoiVVJMIiwiYXR0cmlidXRlcyI6WyJwcm90b2NvbCIsInBvcnQiLCJ0ZWNobm9sb2d5IiwidGFjdGljIiwidGVjaG5pcXVlIl19fSwidGhyZWF0cyI6eyJhdHRyaWJ1dGVzIjpbInRhY3RpYyIsInRlY2huaXF1ZSIsInRlY2hub2xvZ3kiLCJpbmR1c3RyeSIsImNvdW50cnljb2RlIl0sImNhdGVnb3JpZXMiOnsiYXR0YWNrIjoiQXR0YWNrIiwidGVycm9yaXNtIjoiVGVycm9yaXNtIiwic3BhbSI6IlNwYW0iLCJleHBsb2l0a2l0IjoiRXhwbG9pdCBLaXQiLCJyYW5zb213YXJlIjoiUmFuc29td2FyZSIsInJhdCI6IlJBVCIsImJvdG5ldCI6IkJvdG5ldCIsInBoaXNoaW5nIjoiUGhpc2hpbmciLCJnZW5lcmFsIjoiR2VuZXJhbCIsIm1hbHdhcmUiOiJNYWx3YXJlIiwiZnJhdWQiOiJGcmF1ZCIsInByb3h5IjoiUHJveHkiLCJncm91cCI6Ikdyb3VwIiwiZmFtaWx5IjoiTWFsd2FyZSBGYW1pbHkiLCJwdXAiOiJQVVAiLCJ0b29sIjoiVG9vbCIsImNyaW1lIjoiQ3JpbWUiLCJ2dWxuZXJhYmlsaXR5IjoiVnVsbmVyYWJpbGl0eSIsInJlY29ubmFpc3NhbmNlIjoiUmVjb25uYWlzc2FuY2UiLCJjYW1wYWlnbiI6IkNhbXBhaWduIiwiYWJ1c2UiOiJBYnVzZSIsInNweXdhcmUiOiJTcHl3YXJlIn19LCJhdHRyaWJ1dGVzIjp7InByb3RvY29sIjoiUHJvdG9jb2wiLCJwb3J0IjoiUG9ydCIsInRhY3RpYyI6IlRhY3RpYyIsInRlY2hub2xvZ3kiOiJUZWNobm9sb2d5IiwidGVjaG5pcXVlIjoiVGVjaG5pcXVlIiwieWFyYSI6IllBUkEgUnVsZSIsImhvc3R0eXBlIjoiSG9zdCBUeXBlIiwiZmlsZW5hbWUiOiJGaWxlIE5hbWUiLCJmaWxldHlwZSI6IkZpbGUgVHlwZSIsImNvdW50cnljb2RlIjoiQ291bnRyeSBDb2RlIiwiaW5kdXN0cnkiOiJJbmR1c3RyeSJ9LCJ2YWxpZGF0aW9uIjp7ImNvdW50cnljb2RlIjoiXC9eW0EtWl17Mn0kXC8ifX0='> <!--header--> <header data-hide="0"> <!-- logo --> <a class='logo' data-enterprise=0 href='https://pulsedive.com'> <img style='max-height:35px; max-width:10em;' class='logo bigscreen' src='https://pulsedive.com/img/logo_community_light.svg?v=6.3.09' alt="Pulsedive logo"> <img style='max-height:35px;' class='logo smallscreen midscreen' src='https://pulsedive.com/img/heart.svg?v=6.3.09' alt="Pulsedive logo"> </a> <a class='logo' data-enterprise=1 href='/dashboard/'> <img style='max-height:35px; max-width:10em;' class='logo bigscreen' src='https://pulsedive.com/img/logo_community_light.svg?v=6.3.09' alt="Pulsedive logo"> <img style='max-height:35px;' class='logo smallscreen midscreen' src='https://pulsedive.com/img/heart.svg?v=6.3.09' alt="Pulsedive logo"> </a> <!-- top nav --> <nav class='bigscreen'> <a href='/dashboard/'><i class='fas fa-stream'></i>Dashboard</a> <div class='dropdown'> <a href='/explore/'><i class='fas fa-explore'></i>Explore</a> <div> <a href='/explore/'><i class='fas fa-indicator'></i>Indicators</a> <a href='/explore/threats/'><i class='fas fa-threat'></i>Threats</a> <!--<a data-auth=1 href='/explore/?q=user%3D'><i class='fas fa-upload'></i>Your Submissions</a>--> <a href='/api/explore' class='sep-top'><i class='fas fa-product-api'></i>API</a> </div> </div> <a href='/analyze/'><i class='fas fa-code-branch'></i>Analyze</a> <div class='dropdown'> <a href='/api/'><i class='fas fa-product-api'></i>API</a> <div> <a href='/api/'><i class='fas fa-info-circle'></i>Overview</a> <a href='/api/indicators' class='sep-top'><i class='fas fa-indicator'></i>Indicators</a> <a href='/api/threats'><i class='fas fa-threat'></i>Threats</a> <a href='/api/explore'><i class='fas fa-explore'></i>Explore</a> <a data-enterprise=0 href='/about/api' class='sep-top'><i class='fas fa-clock'></i>Rate Limits</a> <a href='/api/taxii'><i class='fas fa-taxii'></i>STIX/TAXII 2.1</a> <a data-enterprise=0 href='/about/feed'><i class='fas fa-product-feed'></i>Bulk Export</a> </div> </div> <div data-enterprise=1 class='dropdown'> <a onclick="Form.feedDownload().modal(true);" data-enterprise=1 data-auth=1><i class='fas fa-product-feed'></i>Export</a> <div> <a onclick="Form.feedDownload().modal(true);" data-enterprise=1 data-auth=1><i class='fas fa-product-feed'></i>Configure CSV</a> <a href='/api/taxii'><i class='fas fa-taxii'></i>STIX/TAXII 2.1</a> </div> </div> <div data-enterprise=0 class='dropdown'> <a href='/about/'><i class='fas fa-info-circle'></i>About</a> <div> <a href='/about/'><i class='fas fa-info-circle'></i>Overview</a> <a href='/pro' class='sep-top' style='min-width:10em;'><i class='fas fa-product-pro'></i>Pro<span style='opacity:0.5; float:right;'>$29/mo</span></a> <a href='/about/api'><i class='fas fa-product-api'></i>API</a> <a href='/about/feed'><i class='fas fa-product-feed'></i>Feed</a> <a href='/enterprise'><i class='fas fa-product-enterprise'></i>Enterprise TIP</a> <a href='/addon' class='sep-top'><i class='fab fa-chrome'></i>Add-On</a> <a href='/integrations'><i class='fas fa-puzzle-piece'></i>Integrations</a> <a href='/company'><i class='fas fa-copyright'></i>Company</a> <a href='https://blog.pulsedive.com' target='_blank'><i class='fas fa-rss'></i>Blog</a> </div> </div> </nav> <nav class='midscreen'> <a href='/explore/' alt="Explore"><i class='fas fa-explore'></i></a> <a href='/analyze/' alt="Analyze"><i class='fas fa-code-branch'></i></a> <a href='/api/' alt="API"><i class='fas fa-product-api'></i></a> <a href='/about/pro' alt='Pro' data-enterprise=0 data-pro=0 data-admin=0><i class='fas fa-product-pro'></i></a> <a href='/about/feed' alt="Feed" data-enterprise=0 data-pro=1 data-admin=0><i class='fas fa-product-feed'></i></a> <a onclick="Form.feedDownload().modal(true);" alt="Feed" data-enterprise=1 data-auth=1><i class='fas fa-product-feed'></i></a> <a href='/configuration/' alt="Admin" data-admin=1><i class='fas fa-cogs'></i></a> <a href='/about/' data-enterprise=0 alt="About"><i class='fas fa-info-circle'></i></a> </nav> <aside> <!-- account menu --> <span class='bigscreen'> <div data-auth=0 data-enterprise=0 class='dropdown'> <a href='/register' class='success'><i class='fas fa-user-plus'></i>Sign Up</a> <div> <a data-action='login'><i class='fas fa-sign-in-alt'></i>Sign In</a> <a data-action='theme'><i class='fas fa-adjust'></i>Change Theme</a> <a data-action='contact'><i class='fas fa-envelope'></i>Contact Us</a> </div> </div> <div data-auth=1 class='dropdown'> <a href='/account/'><i class='fas fa-user-cog' data-pro=0 data-admin=0></i><i class='fas fa-user-shield' data-pro=1 data-admin=0></i><i class='fas fa-users-cog' data-admin=1></i><span style='display:inline-block; text-overflow:ellipsis; overflow:hidden; vertical-align:bottom; max-width:5em;'></span></a> <div> <a href='/account/'><i class='fas fa-user'></i>Account</a> <a data-enterprise=1 onclick="window.page.forms.keys.modal(true);"><i class='fas fa-puzzle-piece'></i>Third-Party API Keys</a> <a data-enterprise=0 data-pro=1 onclick="window.page.forms.keys.modal(true);"><i class='fas fa-product-pro'></i>Pro Integrations</a> <a data-action='theme'><i class='fas fa-adjust'></i>Change Theme</a> <a data-action='contact' data-enterprise=0 data-admin=0><i class='fas fa-envelope'></i>Contact Us</a> <a data-action='contact' data-enterprise=1><i class='fas fa-life-ring'></i>Support</a> <a data-enterprise=0 data-admin=0 data-pro=0 data-api=0 data-feed=0 href='/purchase' class='success'><i class='fa fa-plus-circle'></i>Upgrade</a> <a href='/pulsedive/data.php?get=indicators' target='_blank' class='sep-top'><i class='fas fa-upload'></i>Export Submissions</a> <a data-feed=1 data-enterprise=0 onclick="Form.feedDownload().modal(true);"><i class='fas fa-product-feed'></i>Download Feed</a> <a data-feed=0 data-enterprise=0 onclick="Form.feedDownload().modal(true);"><i class='fas fa-product-feed'></i>Feed Sample</a> <a onclick="window.page.forms.threat.modal(true);" data-contributor=1 data-enterprise=0 class='sep-top'><i class='fas fa-threat'></i>Add a threat</a> <a onclick="window.page.forms.threat.modal(true);" data-enterprise=1 class='sep-top'><i class='fas fa-threat'></i>Add a threat</a> <!--<a href='/configuration/feed.php' data-admin=1><i class='fas fa-feed'></i>Add a feed</a>--> <a href='/configuration/' data-admin=1><i class='fas fa-cogs'></i>Admin</a> <a data-action='logout' class='error sep-top'><i class='fas fa-sign-out-alt'></i>Sign Out</a> </div> </div> <a data-action='toolbox' alt="Toolbox"><i class='fas fa-hammer'></i></a> </span> <!-- top nav, right side --> <span class='midscreen'> <a data-action='login' data-auth=0 data-enterprise=0 class='success' alt="Sign In"><i class='fas fa-user-plus'></i></a> <a data-action='account' data-auth=1 href='/account/' alt="Account"><i class='fas fa-user-cog' data-pro=0 data-admin=0></i><i class='fas fa-user-shield' data-pro=1 data-admin=0></i><i class='fas fa-users-cog' data-admin=1></i></a> <a data-action='toolbox' alt="Toolbox"><i class='fas fa-hammer'></i></a> <a data-action='theme' alt="Toggle theme"><i class='fas fa-adjust'></i></a> <a data-action='contact' class='bigscreen' data-enterprise=0 alt="Contact"><i class='fas fa-envelope'></i></a> <a data-action='contact' data-enterprise=1 alt="Support"><i class='fas fa-life-ring'></i></a> </span> <!-- globalsearch --> <div class='text-wrapper'> <i class='fas fa-search' onclick="this.parentElement.querySelector('input[type=text]').focus();"></i><input name='search' type='text' autocomplete='none' aria-label='search'> </div> <!-- top hamburger menu for small screens --> <span class='smallscreen'> <a onclick="document.querySelector('header nav.mobile').style.display = 'block'; window.page.url('nav', { anchor:true });"><i class='fas fa-bars'></i></a> </span> </aside> <!-- mobile nav --> <nav class='mobile'> <a name='closeNav' onclick="this.parentElement.style.display = 'none'; window.page.url('', { anchor:true });"><i class='fas fa-times'></i></a> <a href='/dashboard/'><i class='fas fa-stream'></i>Dashboard</a> <a href='/explore/'><i class='fas fa-explore'></i>Explore</a> <a href='/analyze/'><i class='fas fa-code-branch'></i>Analyze</a> <a href='/api/' data-enterprise=1><i class='fas fa-product-api'></i>API</a> <a href='/about/api' data-enterprise=0 data-admin=0><i class='fas fa-product-api'></i>API</a> <a href='/about/pro' data-enterprise=0 data-admin=0><i class='fas fa-product-pro'></i>Pro</a> <a href='/about/feed' data-enterprise=0 data-admin=0><i class='fas fa-product-feed'></i>Feed</a> <a onclick="Form.feedDownload().modal(true);" data-enterprise=1 data-auth=1><i class='fas fa-product-feed'></i>Feed</a> <a href='/configuration/' data-admin=1><i class='fas fa-cogs'></i>Admin</a> <a class='sep-bottom' href='/about/' data-enterprise=0><i class='fas fa-info-circle'></i>About</a> <a data-action='register' data-auth=0 data-enterprise=0><i class='fas fa-user-plus'></i>Register</a> <a data-action='login' data-auth=0 data-enterprise=0><i class='fas fa-sign-in-alt'></i>Sign In</a> <a data-action='account' data-auth=1 href='/account/'><i class='fas fa-user-cog' data-pro=0 data-admin=0></i><i class='fas fa-user-shield' data-pro=1 data-admin=0></i><i class='fas fa-users-cog' data-admin=1></i>Account</a> <a data-action='logout' data-auth=1><i class='fas fa-sign-out-alt'></i>Sign Out</a> <a data-action='theme' onclick="this.parentElement.style.display = 'none';"><i class='fas fa-adjust'></i>Toggle Theme</a> <a data-action='contact' onclick="this.parentElement.style.display = 'none';"><i class='fas fa-envelope'></i>Contact</a> </nav> </header> <!-- scripts --> <script defer src='https://pulsedive.com/js/events.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/functions.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/page.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/docs.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/forms.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/preview.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/data.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/premium.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/integrations.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/suggestions.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/api/api.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/api/explore.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/api/indicator.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/api/threat.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/api/feed.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/api/action.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/api/submit.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/api/search.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/ui/ui.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/ui/card.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/ui/autocomplete.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/ui/stamp.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/ui/taglist.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/ui/table.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/ui/grid.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/ui/tree.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/ui/cloner.js?v=6.3.09'></script><script defer src='https://pulsedive.com/js/ui/regex.js?v=6.3.09'></script> <!-- side menu --> <aside data-show=0 class=''> </aside> <!-- main content --> <main> <!-- Unsupported browser warning --> <div id='unsupported-browser-warning' class='sep-bottom error' style='padding:10px; display:none;'> <div class='inline' style='margin-left:5px;'> <i class='fas fa-exclamation-circle'></i> </div> <div class='inline' style='width:calc(100% - 40px);'> We detected an unsupported browser. Some features and functionality might not work properly. We strongly recommend you upgrade your browser. </div> </div> <section> <script> // remaining scans (checks done server-side as well - don't waste your time hackers) var remaining = 0; var remaining_month; // action object var action; // indicator queue var queue = []; var queueElement; // indicator deduplication and order tracking var unique = {}; var count = 0; // parsed and expanded CIDR strings var cidr = []; // results table var results; // pause and resume buttons var pause; var resume; window.addEventListener('load', function(event) { // check API status getStatus(); // initialize action object action = new Action(); // add header window.page.header("Analyze"); // analysis section outputAnalyze(); // results outputResults(); // actions outputActions(); window.addEventListener('popstate', function(event) { // expire previous results if applicable pageChange(); }); // expire previous results pageChange(); // analysis text provided if (window.page.qs.s !== undefined && window.page.qs.s !== null) { window.page.cards.analyze.ui.inputs.text.value = window.page.qs.s.trim(); update(); } // always add notice for smaller screens window.page.notice("Use a larger screen for an optimal experience.", { type:'warning', class:'smallscreen midscreen' }); }); function getStatus() { // ignore Enterprise user limits if (window.page.user.enterprise > 0) { return; } // ignore admin limits if (window.page.user.role >= 2) { return; } // get API status Action.status(function(data) { // update remaining requests remaining = data.day && data.day.remaining ? data.day.remaining : 1; if (remaining < 0) { remaining = 0; } if (data.month) { remaining_month = data.month.remaining; if (remaining_month < 0) { remaining_month = 0; } } // remove previous queue notes var prev = window.page.cards.queue.card.querySelectorAll('div.sep-bottom'); for (var i = 0; i < prev.length; i++) { window.page.cards.queue.card.removeChild(prev[i]); } // informational daily and monthly limit notices var note = UI.div(); if (remaining < 5000 && (remaining_month !== undefined ? remaining_month > 0 : true)) { note.add(UI.p(window.page.user.uid <= 0 ? "You can scan one indicator at a time." : "You have " + remaining + " scan" + (remaining > 1 || remaining <= 0 ? 's' : '') + " left today.", { icon:'info-circle', class:remaining <= 0 ? 'error' : '' })); } if (window.page.user.uid > 0 && remaining_month !== undefined && remaining_month < 5000) { note.add(UI.p("You have " + remaining_month + " scan" + (remaining_month > 1 || remaining_month <= 0 ? 's' : '') + " left this month.", { icon:'info-circle', class:remaining_month <= 0 ? 'error' : '' })); } if (note.children.length > 0) { window.page.cards.queue.note(note); } // monthly notices if (window.page.user.uid > 0 && remaining_month !== undefined) { // limit reached if (remaining_month <= 0) { window.page.notice("Your monthly indicator scan limit has been reached. Upgrade to increase your limits.", { type:'error', button:UI.button('View Limits', '/about/api', { newTab:true, class:'calltoaction' }) }); // not many remaining } else if (remaining_month <= 50) { window.page.notice("You have " + remaining_month + " indicator scan" + (remaining_month > 1 || remaining_month <= 0 ? 's' : '') + " left this month. Upgrade to increase your limits.", { type:'warning', button:UI.button('View Limits', '/about/api', { newTab:true, class:'calltoaction' }) }); } } // limit reached if (remaining <= 0) { window.page.notice("Your daily indicator scan limit has been reached. Upgrade to increase your limits.", { type:'error', button:UI.button('View Limits', '/about/api', { newTab:true, class:'calltoaction' }) }); // not a registered user } else if (window.page.user.uid <= 0) { window.page.notice("Non-registered users can scan one indicator at a time. Create an account to increase your limits.", { type:'warning', button:UI.button('Sign Up', function() { window.page.forms.login.modal(true).tab('register'); }, { newTab:true, class:'calltoaction' }) }); // not many remaining } else if (remaining <= 25) { window.page.notice("You have " + remaining + " indicator scan" + (remaining > 1 || remaining <= 0 ? 's' : '') + " left today. Upgrade to increase your limits.", { type:'warning', button:UI.button('View Limits', '/about/api', { newTab:true, class:'calltoaction' }) }); } // adjust queue card height adjust(); }); } function adjust() { // keep queue height the same as input card try { // get top of queue element var top = queueElement.getBoundingClientRect().top; // calculate offset from top of queue card var offset = top - window.page.cards.queue.card.getBoundingClientRect().top; // calculate max height var height = (parseInt(window.getComputedStyle(window.page.cards.analyze.card).height) - offset - 30) + 'px'; // set max height of queue element if (queueElement.style.maxHeight != height) { queueElement.style.maxHeight = height; } } catch (err) { } } function pageChange() { // analysis in progress if ((results && results.data.length > 0) || (action && action.counts && action.counts.total > 0)) { // going back to main input section if (window.page.page != 'results') { // hide preview pane if (window.page) { window.page.preview.show(false); } // back button var button = UI.button('Return to results', function(done) { window.scrollTo(0, 0); window.page.sections.switch('results'); }, { class:'calltoaction' }); // analysis in progress var notice; if (action.counts.total > 0 && action.counts.completed < action.counts.total) { window.page.notice("Analysis in progress.", { type:'warning', button:button, clear:true }); } else { window.page.notice("Analysis complete.", { type:'success', button:button, clear:true }); } // update API status getStatus(); } // not initialized } else { // trying to access previous results if (window.page.page == 'results') { window.page.sections.switch('main', true); window.page.notice("Previous results expired.", { type:'error' }); } // load input section window.page.sections.switch('main', true); } } function excluded(input) { // iterate through list of exclusions var exclusions = window.page.cards.analyze.ui.inputs.exclude.selection(); for (var i = 0, len = exclusions.length; i < len; i++) { // input matches exclusion if (input.toLowerCase().indexOf(exclusions[i].toLowerCase()) >= 0) { return true; } } return false; } function normalize(text) { // remove trailing periods and ellipses text = text.replace(/\.+$/, ''); text = text.replace(/\u2026/, ''); // too short if (text.length <= 2) { return; } // too long if (text.length > 1000) { return; } // get inclusions var includes = window.page.cards.analyze.ui.inputs.include.selection() || []; if (includes.length <= 0) { return; } // possible IP, domain, URL, email if (text.indexOf('.') >= 0 && text.lastIndexOf('.') < text.length - 1) { // filter timestamps if (/^\d\d\d\d\-\d\d\-\d\dt\d\d:\d\d:\d\d\.000z$/i.test(text)) { return; } // refang before validating text = refang(text); // unescape backslashes text = text.replace(/\\\//g, '/'); // URL if (/.+:\/\/.+\..+/.test(text)) { // clean up start of URL text = text.replace(/^[^a-z0-9\-]+/i, ''); // add trailing slash for pathless domains if (/.+:\/\/[^\/]+$/.test(text)) { text += '/'; } // parse URLs if (includes.indexOf('url') >= 0) { return text; } return; } // email if (/^[^@]+@.+\..+$/.test(text)) { // don't parse email domains if ((window.page.cards.analyze.ui.inputs.options.selection() || []).indexOf('email') >= 0) { return normalize((text.split('@', 2))[1]); } return; } // IP:port if (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}$/.test(text)) { text = text.split(':')[0]; } // IP if (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(text)) { // parse IPs if (includes.indexOf('ipv4') >= 0) { return text; } return; } // don't parse domains if (includes.indexOf('domain') < 0) { return; } // remove wildcards or periods from the start of the string text = text.replace(/^\*/, ''); text = text.replace(/^\./, ''); // convert to lowercase text = text.toLowerCase(); // domain if (text.indexOf('.') > 0 && text.lastIndexOf('.') < text.length - 2) { // invalid characters if (!/^[a-z0-9\-.:\u00df-\u2b81d]+$/.test(text)) { return; } // numbers in non-punycode TLD const tld = text.split('.').pop(); if (/[0-9]+/.test(tld) && !/^xn\-\-/i.test(tld)) { return; } // colon if (text.indexOf(':') > 0) { var parts = text.split(':'); // too many colons if (parts.length > 2) { return; } // second part is not a port if (!/^\d{1,5}$/.test(parts[1])) { return; } return parts[0]; } return text; } return; } // possible IPv6 if (text.indexOf(':') >= 0 && text.lastIndexOf(':') < text.length) { // string does not contain minimum number of octets if (text.split(':').length < 8) { // no abbreviation if (!/::/.test(text)) { return; } } // convert to lowercase text = text.toLowerCase(); // IPv6 if (text.match(/:/g).length > 1 && /^[a-f0-9:]+$/.test(text.toLowerCase())) { if (includes.indexOf('ipv6') >= 0) { return text; } return; } return; } // Enterprise users only if (window.page.user.enterprise > 0) { // possible hash if ([32, 40, 64].indexOf(text.length) >= 0) { // md5 if (/^[0-9a-f]{32}$/i.test(text)) { if (includes.indexOf('md5') >= 0) { return text; } return; } // sha1 if (/^[0-9a-f]{40}$/i.test(text)) { if (includes.indexOf('sha1') >= 0) { return text; } return; } // sha256 if (/^[0-9a-f]{64}$/i.test(text)) { if (includes.indexOf('sha256') >= 0) { return text; } return; } } } } function parse(text) { // add terminating character text += "\n"; // indicator buffer var buffer = ''; // iterate through each character for (var i = 0, len = text.length; i < len; i++) { // hit max indicators if (count > 1000000) { break; } // determine action based on character switch (text[i]) { // separator characters case '\n': case '\r': case '\t': case ' ': case ',': case '<': case '>': case '"': case "'": case '?': // no value present if (buffer.length <= 0) { break; } // validate and expand CIDR var ips = Indicator.expandCidr(buffer); if (ips) { // include CIDR expansion if parsing IPs if ((window.page.cards.analyze.ui.inputs.include.selection() || []).indexOf('ipv4') >= 0 && (window.page.cards.analyze.ui.inputs.options.selection() || []).indexOf('cidr') >= 0) { // keep raw CIDR cidr.push(buffer); // add IPs to queue for (var j = 0, ipc = ips.length; j < ipc; j++) { // does not match exclusion if (!excluded(ips[j])) { // add indicator to queue if (unique[ips[j]] === undefined) { unique[ips[j]] = count++; } } } } } else { // normalize and validate indicator var ioc = normalize(buffer); // valid indicator does not match exclusions if (ioc && !excluded(ioc)) { // add indicator to queue if (unique[ioc] === undefined) { unique[ioc] = count++; } } } // reset buffer buffer = ''; break; // add character to buffer default: buffer += text[i]; } } } function download() { // no indicators to download if (queue.length <= 0) { // flash queue element queueElement.style.animation = "flash 0.4s linear 3"; return; } // create blob with queue data var blob = new Blob([queue.join("\n")], { type:'text/plain' }); // create object URL var url = URL.createObjectURL(blob); // create link element var a = document.createElement('a'); a.href = url; a.download = 'pulsedive_parsediocs.csv'; // download a.click(); // revoke URL URL.revokeObjectURL(url); } function update(done) { // clear result window.page.cards.analyze.result('', ''); // adjust queue height adjust(); // clear queue and caches queue = []; unique = {}; count = 0; cidr = []; // clear download button window.page.cards.queue.update({ header:{ title:'Queue', icon:'list-alt', aside:UI.div('loader') } }); // update status queueElement.style.animation = 'none'; queueElement.textContent = ''; queueElement.appendChild(UI.element('span', "Parsing input", { class:'loader', style:{ whiteSpace:'normal' } })); // parse data on separate thread setTimeout(function() { // parse text parse(window.page.cards.analyze.ui.inputs.text.value); // get file objects from tags var files = window.page.cards.analyze.ui.inputs.upload.files.selection(true).map(function(tag) { return tag.file }); // no files to read if (files.length <= 0) { // preview indicators preview(); } // track files read var filesRead = 0; // parse files for (var i = 0, len = files.length; i < len; i++) { // initialize file reader var reader = new FileReader(); // reader finished reading file reader.onload = function(event) { // parse indicators parse(event.target.result); // increment read counter filesRead++; // all files read if (filesRead >= files.length) { // preview indicators preview(); } }; // start reading file try { reader.readAsText(files[i]); } catch(err) { } } if (done) { done(); } }, 1); } function preview() { // insert unique indicators into queue and preserve order for (var ioc in unique) { queue[unique[ioc]] = ioc; // preserve memory delete unique[ioc]; } // re-add download button window.page.cards.queue.update({ header:{ title:'Queue', icon:'list-alt', aside:UI.a('Download', function(done) { download(); done(); }, { icon:'download', alt:"Download list of parsed indicators." }) } }); // clear preview queueElement.textContent = ''; // no indicators parsed if (queue.length <= 0) { queueElement.textContent += "No indicators parsed."; queueElement.appendChild(UI.element('span', " (" + window.page.cards.analyze.ui.inputs.include.selection().join(', ') + ")", { class:'note' })); // active exclusions var exclusions = (window.page.cards.analyze.ui.inputs.exclude.selection() || []).length; if (exclusions > 0) { queueElement.appendChild(UI.element('div', exclusions + " parsing exclusions.", { class:'note', style:{ marginTop:'2em' } })); } // add indicators to queue preview } else { // queue is too big to show all if (queue.length > 1000) { queueElement.textContent += "Showing 1000 indicators out of " + queue.length + "."; // hit max if (queue.length >= 1000000) { queueElement.textContent += " (max: 1M)"; } queueElement.textContent += "\n\n"; } else { queueElement.textContent += "Parsed " + queue.length + " indicators.\n\n"; } // CIDRs were expanded if (cidr.length > 0) { queueElement.textContent += "The following CIDR strings were expanded into IPs:\n"; // preview expanded strings for (var i = 0, len = cidr.length; i < len; i++) { // limit preview if (i >= 4 && cidr.length > i + 1) { queueElement.textContent += "and " + (cidr.length - i) + " more.\n\n"; break; } // list CIDR string queueElement.textContent += cidr[i] + "\n"; } queueElement.textContent += "\n"; } // preview indicators for (var i = 0, len = queue.length; i < len; i++) { // don't display entire queue if (i > 1000) { break; } // list indicator queueElement.textContent += queue[i] + "\n"; } } // adjust queue height adjust(); } function clear(done) { // reset includes window.page.cards.analyze.ui.inputs.include.select('all', true); // clear input text window.page.cards.analyze.ui.inputs.text.value = ''; // clear files window.page.cards.analyze.ui.inputs.upload.files.clear(); // clear indicator queue update(); // callback done(); } function analyze(done, submit, input) { // no values parsed if (queue.length <= 0) { window.page.cards.analyze.result("No indicators.parsed.", 'error'); if (done) { done(); } return; } // cut queue to limit if (window.page.user.enterprise <= 0 && window.page.user.role < 2) { queue.splice(window.page.user.uid ? remaining : 1); } // hide results header, actions, and sort menu window.page.cards.results.header().dataset.hide = 1; window.page.cards.results.actions().dataset.hide = 1; window.page.cards.results.sort().dataset.hide = 1; // initial status window.page.cards.analyze.result(UI.div('loader').add('Processing'), ''); // clear results results.clear(); // reset action data action.reset(); // get status labels var status = { progress:window.page.cards.status.card.querySelector('[name=progress]'), errors:window.page.cards.status.card.querySelector('[name=errors]') }; // add progress bar var progress = UI.progress(0, 1, "Initializing..."); status.progress.textContent = ''; status.progress.appendChild(progress); // update totals window.page.cards.results.update({ header:{ title:'Indicators', icon:'indicator', aside:new Taglist({ toggle:true, radio:true }, [ { name:'all', selected:true, display:'All', alt:"Show all results.", callback:function() { // show all results results.show(); } }, { name:'success', display:'Successful', alt:"Show successful results only.", callback:function() { // show successful results only results.show(function(row) { return row._raw.error ? false : true; }); } }, { name:'errors', display:'Errors', class:'error', alt:"Show errors only.", callback:function() { // show successful results only results.show(function(row) { return row._raw.error ? true : false; }); } } ]).taglist } }); // show pause button pause.disabled = false; resume.disabled = true; // whether analysis has started var started = false; // scan or submit data and get results var form = window.page.cards.submit.ui.inputs; action.update(submit ? { value:queue, type:'auto', stamp_seen:1, activate:1, risk:form.risk ? form.risk.selection() : 'recommended', comment:form.comment && form.comment.value.trim().length > 0 ? form.comment.value.trim() : null, threat:form.threats ? form.threats.selection() : [], probe:function() { switch (form.scan ? form.scan.selection() : 'active') { case 'passive': return 0; case 'active': return 1; case 'never': return 'never'; } }(), attributes:Object.keys(form).reduce(function(form, attributes, input) { // valid attribute input if (/^attribute_/.test(input)) { // add attribute tags try { attributes[input.replace(/^attribute_/, '')] = form[input].selection(); } catch (err) { } } return attributes; }.bind(this, form), {}) } : { value:queue, type:'auto' }).process('indicator', submit ? 'submit' : 'analyze', function(err) { // show error window.page.cards.analyze.result(err.message, 'error'); // complete if (done) { done(); } }, function() { // analysis has started if (started == false) { started = true; // switch to results window.scrollTo(0, 0); window.page.sections.switch('results'); // clear input page result window.page.cards.analyze.result(''); // complete if (done) { done(); } // add notice if submitting if (submit) { window.page.notice("Submissions in progress. You can leave this page if you wish."); } } }, function(completed, total, errors) { // update progress progress.update(completed, total, completed + '/' + total); // update errors status.errors.textContent = errors; if (errors > 0) { status.errors.classList.add('error'); } else { status.errors.classList.remove('error'); } }, function() { // show results printResults(); // update status status.progress.textContent = submit ? "Submission complete." : "Analysis complete."; // hide pause and resume buttons pause.disabled = true; resume.disabled = true; // reparse input and finish update(done); }); } function submit(done) { // reset action data action.reset(); // get status label var status = window.page.cards.status.card.querySelector('[name=progress]'); // add progress bar var progress = UI.progress(0, 1, "Submitting"); status.textContent = ''; status.appendChild(progress); // add values to submit var values = []; for (var i = 0, len = results.data.length; i < len; i++) { // skip errors if (results.data[i]._raw.error) { continue; } values.push(results.data[i].indicator); } // submit data var form = window.page.cards.submit.ui.inputs; action.update({ value:values, type:'auto', stamp_seen:1, activate:1, risk:form.risk ? form.risk.selection() : 'recommended', comment:form.comment && form.comment.value.trim().length > 0 ? form.comment.value.trim() : null, threat:form.threats ? form.threats.selection() : [], probe:function() { switch (form.scan ? form.scan.selection() : 'active') { case 'passive': return 0; case 'active': return 1; case 'never': return 'never'; } }(), attributes:Object.keys(form).reduce(function(form, attributes, input) { // valid attribute input if (/^attribute_/.test(input)) { // add attribute tags try { attributes[input.replace(/^attribute_/, '')] = form[input].selection(); } catch (err) { } } return attributes; }.bind(this, form), {}) }).process('indicator', 'submit', function(err) { // show error window.page.cards.submit.result(err.message, 'error'); // hide progress bars and update status status.textContent = err.message; done(); }, function() { // hide submit form Card.hideOverlay(); // successfully uploaded submissions done(); // no need to stay window.page.notice("Submissions in progress. You can leave this page if you wish."); }, function(completed, total, errors) { // update progress progress.update(completed, total, "Submitting: " + completed + '/' + total); }, function() { // update status status.textContent = "Submission complete."; // print latest data printResults(); done(); }); } function printResults() { // clear data results.clear(); // show results header, actions, and sort menu window.page.cards.results.header().dataset.hide = 0; window.page.cards.results.actions().dataset.hide = 0; window.page.cards.results.sort().dataset.hide = 0; // add requests to results table for (var qid in action.requests) { // skip pending requests if (action.requests[qid].constructor !== Object) { continue; } // create and add indicator object results.add(new Indicator(action.requests[qid])); } // remove error filters results.filter = null; // print results results.print(); } function formatRow(row, indicator) { // qid row.dataset.qid = indicator.qid; // clear row row.textContent = ''; // completed but error if (indicator._raw.error) { // error icon row.appendChild(UI.div().add(UI.icon('exclamation-circle', { class:'error' }))); // request value and error message row.appendChild(UI.div('grow').add(UI.heading(indicator.indicator)).add(UI.div('error').add(indicator._raw.error))); return row; } // set URL row.href = indicator.url(); // risk row.appendChild(UI.div().add(UI.icon('risk-' + indicator.risk.score))); // retired if (indicator.stamp.retired) { row.classList.add('retired'); } // subtext var subtext = UI.div(); // PTR record var ptr = indicator.properties.get('dns', 'ptr'); if (ptr.constructor === Array) { ptr = ptr[0]; } if (ptr && ptr.trim().indexOf(';;') < 0) { subtext.add(UI.p(indicator.properties.get('dns', 'ptr'), { icon:'location-arrow', class:'note' })); } // location var cc = indicator.countrycode(); if (cc) { subtext.add(UI.p([UI.flag(cc), indicator.location()], { class:'note' })); } // indicator name row.appendChild(UI.div('grow').add(UI.heading(indicator.display())).add(subtext)); // last scan if (indicator.stamp.added) { row.appendChild(UI.div('right').add(UI.p(UI.stamp(indicator.stamp.probed), { icon:'barcode', alt:"Last active scan" }))); // not in database } else { row.appendChild(UI.div('right').add(UI.p("Not in database", { class:'note', icon:'info-circle' }))); } return row; } function handleUpdate() { // handling key presses window.page.cards.analyze.ui.inputs.text.addEventListener('keypress', function(event) { // determine key pressed switch (event.key) { // analyze shortcut case 'Enter': if (event.shiftKey) { // update and analyze update(function() { // count is higher than user's limit if (window.page.user.enterprise <= 0 && window.page.user.role < 2 && count > remaining) { // prompt user prompt(); return; } // analyze indicators analyze(); }); // prevent default action event.preventDefault(); } break; } }); // handling pasting text window.page.cards.analyze.ui.inputs.text.addEventListener('paste', function(event) { // fetch clipboard data and update raw text input var text = (event.clipboardData || window.clipboardData).getData('text'); // lengthy paste if (text.length > 10000) { // create file object var file = new Blob([text], { type:'text/plain' }); // add to files window.page.cards.analyze.ui.inputs.upload.taglist.add({ name:"PASTE-" + Math.random().toString(36).substring(0, 10), icon:'clone', description:(text.length / 1024).toFixed(1) + ' KB - pasted text', file:file, class:'flash' }); // prevent default handling of event event.preventDefault(); return; } }); // handle clicks on text input (for add-on) window.page.cards.analyze.ui.inputs.text.addEventListener('click', function(event) { // parse data update(); }); // handle any other type of text input window.page.cards.analyze.ui.inputs.text.addEventListener('input', debounce(function(event) { // parse data update(); }, 300)); // file list changed window.page.cards.analyze.ui.inputs.upload.taglist.onchange = debounce(function(tag) { // parse data update(); // adjust queue element card height adjust(); }, 300); } function handleFileDrop() { // create file drop overlay var overlay; // track enter/leave events var counter = 0; // handle file dragging document.body.addEventListener('dragenter', function(event) { // unsupported if (!event.dataTransfer || !event.dataTransfer.types) { return; } // no files dragged if (event.dataTransfer.types.indexOf('Files') < 0) { return; } // prevent default handling of event event.preventDefault(); // track event counter++; // switch back to input if results section is showing window.page.sections.switch('main'); // overlay displaying already if (overlay) { return; } // create overlay overlay = UI.div('overlay'); // add overlay to card window.page.cards.analyze.card.appendChild(overlay); }); document.body.addEventListener('dragleave', function(event) { // unsupported if (!event.dataTransfer || !event.dataTransfer.types) { return; } // no files dragged if (event.dataTransfer.types.indexOf('Files') < 0) { return; } // prevent default handling of event event.preventDefault(); // no overlay if (!overlay) { return; } counter--; // remove overlay if (counter <= 0) { if (overlay) { window.page.cards.analyze.card.removeChild(overlay); overlay = null; } counter = 0; } }); // must define dragover event for drop event to fire document.body.addEventListener('dragover', function(event) { // prevent default handling of event event.preventDefault(); }); // handle file drops document.body.addEventListener('drop', function(event) { // prevent default handling of event event.preventDefault(); // remove overlay if (overlay) { window.page.cards.analyze.card.removeChild(overlay); overlay = null; } counter = 0; // get files from drop var files = event.dataTransfer.items; // add files to upload for (var i = 0, len = files.length; i < len; i++) { // not a file if (files[i].kind !== 'file') { continue; } // get File object var file = files[i].getAsFile(); // add to upload window.page.cards.analyze.ui.inputs.upload.files.add(files[i].getAsFile(), 'text'); } }); } function exportUrl(format, sid) { // unsupported format format = format.toLowerCase(); if (['csv', 'json', 'stix'].indexOf(format) < 0) { return; } // create base URL var url = window.page.root.trim('/') + '/api/scan.php?'; // add format url += 'format=' + format; // pretty-print JSON if (['json', 'stix'].indexOf(format) >= 0) { url += '&pretty=1'; } // add submission ID url += '&sid=' + (sid || action.sids[0]); return url; } function handleExport(format, sid) { // no submissions if (action.sids.length <= 0) { return; } // multiple submissions if (!sid && action.sids.length > 1) { promptExport(format); return; } // export var url = exportUrl(format, sid); if (url) { window.open(url, '_blank'); } } function promptExport(format) { // prompt user new Card({ name:'promptExport', header:{ title:'Export', icon:'file-export', aside:new Taglist({ toggle:true, radio:true, select:format, callback:function(tag) { promptExport(tag.getAttribute('name')); } }, [{ name:'csv', display:'CSV' }, { name:'stix', display:'STIX 2.1' }, { name:'json', display:'JSON' }]).taglist }, modal:true }).append().form({ note:"Your analysis was composed of multiple submissions. You can export each individual submission below." }, action.sids.map(function(sid) { // get export URL var url = exportUrl(format, sid); if (!url) { return; } return { type:UI.div('flex', { marginBottom:'2em' }).add(UI.div().add(UI.copy(url, url))).add(UI.button("Export", function(sid, done) { // export submission handleExport(format, sid); }.bind(null, sid), { class:'calltoaction' })) }; }), [{ text:"Close", click:function(done) { // hide modal Card.hideOverlay(); done(); } }]).modal(true); } function prompt() { // ignore Enterprise user limits if (window.page.user.enterprise > 0) { return; } // ignore admin limits if (window.page.user.role >= 2) { return; } // create modal var prompt = new Card({ name:'prompt', header:{ title:remaining <= 0 ? "Scan Limit Reached" : "Scan Limits", icon:'exclamation-triangle' }, modal:true }).form({ cancel:true }, [{ type:'p', value:window.page.user.uid > 0 ? ("You have " + remaining + " indicator scans left today. Upgrade to increase your limits.") : "You can scan one indicator at a time. Sign up to increase your limits." }], [window.page.user.uid <= 0 ? { name:'register', text:'Sign Up', click:function(done, event) { done(); window.page.forms.login.modal(true).tab('register'); } } : { name:'upgrade', text:'View Limits', class:'calltoaction', click:function(done, event) { done(); // go to API limits window.open('/about/api', '_blank'); } }, remaining > 0 ? { name:'continue', text:'Scan ' + (remaining == 1 ? 'first indicator' : 'first ' + remaining + ' indicators'), class:'calltoaction', click:function(done, event) { Card.hideOverlay(); analyze(done); } } : null]); // show modal prompt.append().modal(true); } function outputAnalyze() { // create split form section var section = window.page.sections.main.appendChild(UI.div('flex', { width:'100%' })); // create card for text or file input new Card({ name:'analyze', full:true, header:{ title:'Input', icon:'file-medical-alt' } }).append(section).note("Paste text or upload files containing IPs, URLs, and domains. Large pasted text will be added as a virtual file. Pulsedive will parse, refang, and deduplicate indicators automatically.").inputs({}, [{ name:'include', label:'Include', type:new Taglist({ selectAll:true, select:'all', deconstruct:true, callback:function(tag) { update(); } }, [{ name:'ipv4', display:'IPv4' }, { name:'ipv6', display:'IPv6' }, { name:'domain', display:'Domains' }, { name:'url', display:'URLs' }].concat(window.page.user.enterprise > 0 ? [{ name:'md5', display:'MD5' }, { name:'sha1', display:'SHA-1' }, { name:'sha256', display:'SHA-256' }] : [])).taglist }, { name:'text', label:'Text Input', type:UI.element('textarea', '', { style:{ height:'15em', minHeight:'8em' }, attribute:{ placeholder:"Paste text containing indicators here.", autofocus:true } }) }, { name:'upload', label:'Upload Files', type:UI.upload() }, { type:UI.div('', { marginTop:'2em' }), }, { name:'options', label:'Parsing Options', type:new Taglist({ select:['cidr', 'email'], deconstruct:true, callback:function(tag) { update(); } }, [{ name:'cidr', display:'IPv4 CIDR expansion', alt:"Parse and expand IPv4 ranges into individual IPs" }, { name:'email', display:'Email domains', alt:"Parse domains from email addresses" }]).taglist }, { name:'exclude', label:'Parsing Exclusions' }]).buttons({ result:true }, [{ name:'clear', text:'Reset', click:function(done, event) { clear(done); } }, window.page.user.enterprise > 0 || window.page.user.role >= 1 ? { name:'submit', text:'Submit', alt:"Submit indicators instead of scanning them.", click:function(done, event) { // show submit form window.page.cards.submit.modal(true); done(); } } : null, { name:'analyze', text:'Analyze', class:'calltoaction', click:function(done, event) { // count is higher than user's limit if (window.page.user.enterprise <= 0 && window.page.user.role < 2 && count > remaining) { // prompt user prompt(); done(); return; } // analyze indicators analyze(done); } }]); // adjust queue height when resizing textbox window.page.cards.analyze.card.onmousemove = adjust; // add taglist to exclusions new Taglist({ textbox:window.page.cards.analyze.ui.inputs.exclude, onchange:function() { update(); } }); // handle file drag events handleFileDrop(); // handle text input and file upload events handleUpdate(); // create card to preview raw content new Card({ name:'queue', class:'bigscreen', header:{ title:'Queue', icon:'list-alt', aside:UI.a('Download', function(done) { download(); done(); }, { icon:'download', alt:"Download list of parsed indicators." }) } }).append(section); window.page.cards.queue.card.style.paddingBottom = 0; // create queue element queueElement = UI.p(["No indicators parsed.", UI.element('span', " (" + window.page.cards.analyze.ui.inputs.include.selection().join(', ') + ")", { class:'note' })], { name:'queue', class:'code', style:{ maxHeight:'100%', maxWidth:'20em', overflow:'auto', overflowWrap:'normal' } }); window.page.cards.queue.add(queueElement); // adjust queue height adjust(); } function outputResults() { // add results section window.page.sections.add('results', 'results'); // add header window.page.header("Results", { section:'results' }); // add status card outputStatus(); // results card with table new Card({ name:'results', full:true, header:{ title:'Results', icon:'indicator' } }).append(window.page.sections.results); // add sorting and bulk selection window.page.cards.results.sort([{ key:'indicator', display:'Indicator' }, { key:'domain', display:'Domain' }, { key:'risk', display:'Risk' }]); // add results table window.page.cards.results.add(new Table([], formatRow, { name:'results', preview:true, loading:true, empty:"No results.", more:'scroll', sort:window.page.cards.results.sort() })); // save results table for easier referencing results = window.page.cards.results.ui.objects.results; } function outputActions() { // add submit form outputSubmit(); // submit window.page.cards.results.actions(UI.a('Submit All', function(done, event) { window.page.cards.submit.modal(true); done(); }, { icon:'upload', alt:"Submit indicators to Pulsedive and update existing indicators with fresh active scans." })); // export menu if (window.page.user.uid > 0) { window.page.cards.results.actions(UI.dropdown(UI.a('Export', '', { icon:'file-export' }), [ UI.a('CSV via API', function(done) { // export CSV file handleExport('csv'); done(); }, { icon:'product-api' }), UI.a('JSON via API', function(done) { // pretty-print JSON handleExport('json'); done(); }, { icon:'product-api' }), UI.a('STIX 2.1 via API', function(done) { // pretty-print JSON handleExport('stix'); done(); }, { icon:'product-api' }) ])); // not logged in } else { window.page.cards.results.actions(UI.a('Export', function(done) { // show login form window.page.forms.login.modal(true); done(); }, { icon:'file-export', alt:"Log in to export to CSV, JSON, and STIX 2.1." })); } } function outputSubmit() { // create submit form new Form('submit', "Submit").add({ cancel:outputSubmit, result:true }, (window.page.user.role > 0 || window.page.user.enterprise > 0 ? [{ type:UI.p("If Recommended is not selected, only indicators with a lower risk score will be updated.", { class:'note', icon:'info-circle', style:{ padding:0 } }), marginBottom:'1em' }, { name:'risk', label:'Risk', type:new Taglist({ radio:true, select:'recommended' }, [{ name:'recommended', display:'Recommended', icon:'heartbeat' }, { name:'unknown', display:'Unknown', icon:'risk-unknown' }, { name:'none', display:'Very Low', icon:'risk-none' }, { name:'low', display:'Low', icon:'risk-low' }, { name:'medium', display:'Medium', icon:'risk-medium' }, { name:'high', display:'High', icon:'risk-high' }, { name:'critical', display:'Critical', icon:'risk-critical' }]).taglist, marginBottom:'1em' }, { name:'scan', label:'Scan Type', type:new Taglist({ radio:true, select:'active' }, [{ name:'active', display:'Active', icon:'barcode' }, { name:'passive', display:'Passive', icon:'eye-slash' }, { name:'never', display:'Always Passive', icon:'user-secret', alt:"Prevent automated active scans of these indicators. You can reset this flag for each indicator by manually performing an active scan." }]).taglist, marginBottom:'1em' }] : []).concat([{ label:'Comment', type:UI.a("Add a comment", function(done, event) { // reset link in case replacement doesn't work done(); // replace this link with a textarea for the comment if (event.target.parentElement) { window.page.cards.submit.inputs({}, [{ name:'comment', type:'textarea', replace:event.target }], true); } }, { icon:'plus', style:{ display:'inline-block', border:'none', marginBottom:'1em' } }) }]).concat(window.page.user.role > 0 || window.page.user.enterprise > 0 ? [{ label:'Threats', name:'threats', type:'text', taglist:{ autocomplete:'threats' }, marginTop:'1em' }] : []).concat(window.page.user.enterprise > 0 || window.page.user.role > 0 ? [{ type:UI.p("Attributes will be added only to indicators that support them. If not supported, the attributes will be silently ignored.", { class:'note', icon:'info-circle', style:{ padding:0 } }), marginTop:'1em', marginBottom:'2em' }] : []).concat(window.page.user.role > 0 || window.page.user.enterprise > 0 ? Object.keys(window.page.data.schema.attributes).reduce(function(attributes, type) { // indicators support attribute for (var itype in window.page.data.schema.indicators) { // exclude some types if (['artifact'].indexOf(itype) >= 0) { continue; } if (window.page.data.schema.indicators[itype].attributes.indexOf(type) >= 0) { attributes.push(type); break; } } return attributes; }, []).sort().map(function(type) { return { name:'attribute_' + type, label:UI.descriptor(UI.descriptor(window.page.data.schema.attributes[type], window.page.data.schema.validation[type] ? 'Regex validation' : ''), Object.keys(window.page.data.schema.indicators).sort().reduce(function(supported, itype) { if (window.page.data.schema.indicators[itype].attributes.indexOf(type) >= 0) { supported.push(window.page.data.schema.indicators[itype].display); } return supported; }, []).join(', ')), type:'text', taglist:{ autocomplete:type, validation:window.page.data.schema.validation[type] } }; }) : []).concat(window.page.user.enterprise <= 0 ? [{ type:UI.p([UI.icon('exclamation-circle'), "By submitting any content to Pulsedive, you confirm that ", UI.element('b', "you are the original owner of such content"), ", or that you have the necessary rights and permissions to authorize us to use your content as we see fit."], { class:'note center', style:{ padding:0 } }), marginTop:'2em', marginBottom:'1em' }, { type:UI.p([UI.icon('exclamation-circle'), "By submitting content to Pulsedive, ", UI.element('b', "you hereby grant us and those we work with the rights to use such content as we see fit.")], { class:'note center', style:{ padding:0 } }), marginBottom:'1em' }, { type:UI.p(["Please read the full text of our ", UI.a('Terms of Service', '/terms', { newTab:true }), " to understand more."], { class:'note center', style:{ padding:0, maxWidth:'525px' } }), marginBottom:'1em' }] : []), [{ name:'submit', text:'Submit', click:function(done, event) { // on results page if (window.page.page == 'results') { // submit indicators without clearing analysis results submit(function() { done(); Card.hideOverlay(); // clear form outputSubmit(); }); // on input page } else { // submit indicators, handle like regular analyze request analyze(function() { done(); Card.hideOverlay(); // clear form outputSubmit(); }, true); } } }]); } function outputStatus() { // add status card new Card({ name:'status', full:true }).append(window.page.sections.results); // note about expiring results window.page.cards.status.note(UI.p("Results will expire once you leave this page.", { icon:'info-circle', class:'note' })); // container var container = UI.div('flex'); window.page.cards.status.add(container); // progress container.add(UI.div('info', { maxWidth:'12em', margin:'0 10px 10px 10px' }).add(UI.heading('Progress', { level:2, style:{ padding:0, margin:0 } })).add(UI.element('span', "Initializing...", { name:'progress' }))); // errors container.add(UI.div('info', { minWidth:'8em', maxWidth:'10em', margin:'0 10px 10px 10px' }).add(UI.heading('Errors', { level:2, style:{ padding:0, margin:0 } })).add(UI.element('span', 0, { name:'errors' }))); // add buttons container var buttons = UI.div('', { margin:'10px 0 0 0', padding:'15px' }); container.add(buttons); // add edit button buttons.add(UI.button('Edit Input', function() { // switch back to input section window.page.sections.switch('main'); // trigger page change event pageChange(); }, { name:'edit' })); // add pause button pause = UI.button('Pause', function() { // pause submitting new data action.pause(); // show resume button pause.disabled = true; resume.disabled = false; // show results printResults(); results.note("Analysis paused. Showing completed results."); }, { name:'pause', class:'danger' }); buttons.add(pause); // add resume button resume = UI.button('Resume', function() { // resume analysis action.resume(); // hide results header, actions, and sort menu window.page.cards.results.header().dataset.hide = 1; window.page.cards.results.actions().dataset.hide = 1; window.page.cards.results.sort().dataset.hide = 1; // show pause button pause.disabled = false; resume.disabled = true; // clear results results.clear(); }, { name:'resume', class:'calltoaction', }); buttons.add(resume); // hide resume button resume.disabled = true; } </script> </section> <!-- footer --> <footer data-hide="0"> <a href='https://pulsedive.com' target='_blank'>©2025 Pulsedive LLC | v6.3.09 | January 6</a> <!-- links --> <aside> <a data-crawler=1 href='/recent' target='_blank'><i class='fas fa-history'></i>Recent</a> <a name='slack' href='https://join.slack.com/t/pulsedive/shared_invite/enQtMzI3NDQyMjEzMTY4LTBhNmE1NWIyMjdhNjVkYTc5OWMxZGExNWM3OWIxYzYyZGNlMGMwODBjNTZlNjc0M2RhOGQ3MjQwYjQ1Nzk3ZGE' target='_blank'><i class='fab fa-slack inline'></i></a> <a name='linkedin' href='https://linkedin.com/company/pulsedive' target='_blank'><i class='fab fa-linkedin inline'></i></a> <a name='blog' href='https://blog.pulsedive.com' target='_blank'><i class='fas fa-rss inline'></i></a> <span>|</span> <a name='company' href='https://pulsedive.com/about/company' target='_blank'><i class='fas fa-copyright'></i>Company</a> <a data-action='contact'><i class='fas fa-envelope'></i>Contact</a> <a href='/terms' target='_blank'><i class='fas fa-file'></i>Terms</a> <a data-enterprise=0 href='/privacy' target='_blank'><i class='fas fa-user-secret'></i>Privacy</a> <a data-enterprise=1 href='/enterprise-privacy' target='_blank'><i class='fas fa-user-secret'></i>Privacy</a> </aside> </footer> </main> </body> </html>