├── .gitignore ├── LICENSE ├── README.md ├── change_hosts_to_specified_color_by_services_or_issues.js ├── change_service_regex_to_specified_color.js ├── change_service_to_specified_color.js ├── change_services_to_specified_color.js ├── count_host_ports_by_color.js ├── count_host_services_by_color.js ├── delete_host_services_by_tool.js ├── delete_hosts_by_positive_cidr.js ├── delete_hosts_by_status.js ├── delete_issues_by_status.js ├── delete_issues_with_no_hosts.js ├── delete_services_by_port_protocol_service.js ├── dump_issue_evidence.js ├── dump_service_notes.js ├── filter_hosts_no_services.js ├── find_note_by_regex.js ├── generate_port_string_from_service.js ├── generate_unique_port_string.js ├── generate_url_list.js ├── generate_webdisco_target_list.js ├── get_hosts_by_cidr.js ├── get_person_by_department_regex.js ├── get_person_email.js ├── grey_hosts_no_services_green.js ├── hostnames_to_nessus.js ├── iis_os_profiler.js ├── list_host_services_by_color.js ├── list_host_services_by_service_regex.js ├── list_hosts_by_issue_title.js ├── list_hosts_by_issue_title_regex.js ├── list_hosts_by_tag.js ├── list_unknown_open_services.js ├── merge_issues.js ├── merge_issues_by_title.js ├── negate_hosts_by_cidr.js ├── nikto_Host_List.js ├── nikto_Top_Findings.js ├── search_service_note_content.js ├── services_to_color_by_hosts.js ├── set_global_service_by_port.js ├── set_host_os_by_os_regex.js ├── set_host_service_by_port.js ├── tag_hosts_by_cidr.js └── unique_service_by_hosts_cidr.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 lair-framework 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial serviceions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | browser-scripts 2 | ==================== 3 | 4 | Collection of small JavaScript functions and scripts that can be used in the browser to interact with Lair 5 | 6 | ## Usage 7 | 8 | 1. Log into Lair. 9 | 2. If the script comments have "Requires client-side updates: true" you will need to turn on client updates, if not, you can skip this step. On the initial page under "Settings" ensure that you have enabled "client-side updates". 10 | 3. Load your desired project. 11 | 4. From within your browser, open your JavaScript console. How to do this is specific to your browser and/or plugins used. 12 | 5. Copy the script and/or function definition in its entirety; paste it into your JavaScript console. 13 | 6. Run the newly defined function, adhering to the usage defined in the comments of each script. 14 | 15 | ## Contributing 16 | 17 | 1. Fork it 18 | 2. Create your feature branch (`git checkout -b my-new-feature`) 19 | 3. Commit your changes (`git commit -am 'Add some feature'`) 20 | 4. Push to the branch (`git push origin my-new-feature`) 21 | 5. Create new Pull Request 22 | -------------------------------------------------------------------------------- /change_hosts_to_specified_color_by_services_or_issues.js: -------------------------------------------------------------------------------- 1 | /* globals Session Meteor Hosts Services Issues StatusMap */ 2 | /* eslint-disable no-unused-vars */ 3 | function changeHostsToSpecifiedColorByServicesOrIssues (servicesOrIssues, statusOption, lairColor) { 4 | // Changes host color based on services|issues of the host 5 | // 6 | // This is good for editing large chucks of hosts based on service or vuln color. 7 | // Example: You've marked a bunch of services green and want to change all hosts, whose services are now all 8 | // green, to green. You run: changeHostsToSpecifiedColorByServicesOrIssues('services', 'lair-green', 'lair-green') 9 | // 10 | // Created by Isaiah Sarju 11 | // 12 | // Services or Issues Options (servicesOrIssues) 13 | // 'services': Change hosts based on hosts' services 14 | // 'issues': Change hosts based on hosts' issues 15 | // 16 | // Status Options (statusOption) 17 | // 'all': Change all hosts to specified lairColor 18 | // 'none': Hosts with no services|issues associated with them are changed to specified lairColor 19 | // 'lair-color': If all services|issues of a host are 'lair-color' change host to specified lairColor. Number of services|issues for host must be > 0 20 | // 'same': If there are no services|issues or all services|issues are the same color, set host color to specified lairColor 21 | // 'diff': If there are > 1 services|issues and services|issues differ in color, set host color to specified lairColor 22 | // 23 | // Lair Color Options (lairColor): lair-grey, lair-blue, lair-green, lair-orange, lair-red 24 | // 25 | // Usage 26 | // changeHostsToSpecifiedColorByServicesOrIssues('doesnmatter', 'all', 'lair-green'); Change all hosts to lair-green 27 | // changeHostsToSpecifiedColorByServicesOrIssues('services', 'none', 'lair-green'); If host has no services change to lair-green 28 | // changeHostsToSpecifiedColorByServicesOrIssues('issues', 'lair-orange', 'lair-red'); If all issues are lair-orange change host to lair-red 29 | // changeHostsToSpecifiedColorByServicesOrIssues('issues', 'same', 'lair-blue'); If host has same colored issues change host to lair-blue 30 | // changeHostsToSpecifiedColorByServicesOrIssues('services', 'diff', 'lair-grey'); If host has different colored services change host to lair-grey 31 | 32 | var projectId = Session.get('projectId') 33 | var modifiedBy = Meteor.user().emails[0].address 34 | var statCount = 0 35 | var count = 0 36 | 37 | // Define allSameColor callback function for object.every() 38 | // Returns true if value's color is same as (value - 1)'s color 39 | function allSameColor (value, index, array) { 40 | // Base Case 41 | if (index === 0) { 42 | return true 43 | } 44 | 45 | // Return true if status is same as previous status 46 | // else return false 47 | return (value.status === array[index - 1].status) 48 | } 49 | 50 | // Define changeHostColor 51 | function changeHostColor (id, newColor) { 52 | Hosts.update({ 53 | '_id': id 54 | }, { 55 | $set: { 56 | 'status': newColor, 57 | 'lastModifiedBy': modifiedBy 58 | } 59 | }) 60 | 61 | } 62 | 63 | // Define getServices 64 | // Returns service array of given host id 65 | function getServices (id) { 66 | return Services.find({ 67 | 'projectId': projectId, 68 | 'hostId': id 69 | }).fetch() 70 | } 71 | 72 | // Define getIssues 73 | // Returns service array of given host id 74 | function getIssues (id) { 75 | var hostIpv4 = Hosts.findOne({ '_id': id }).ipv4 76 | return Issues.find({ 77 | 'projectId': projectId, 78 | 'hosts.ipv4': hostIpv4 79 | }).fetch() 80 | } 81 | 82 | // Define getServicesOrIssues 83 | // Returns array of Services or Issues for host based on servicesOrIssues 84 | function getServicesOrIssues (id) { 85 | if (servicesOrIssues === 'services') { 86 | return getServices(id) 87 | } else if (servicesOrIssues === 'issues') { 88 | return getIssues(id) 89 | } 90 | throw { 91 | name: 'Incorrect servicesOrIssues Selection', 92 | message: 'Incorrect servicesOrIssues selection: "' + servicesOrIssues + '" is not a valid servicesOrIssues for this function' 93 | } 94 | } 95 | 96 | if (StatusMap.indexOf(lairColor) === -1) { 97 | console.log('Lair Supserviceed colors: ' + StatusMap) 98 | throw { 99 | name: 'Wrong lairColor', 100 | message: 'Provided lairColor: "' + lairColor + '" is not Lair compliant' 101 | } 102 | } 103 | 104 | // Get all hosts 105 | var hosts = Hosts.find({ 106 | 'projectId': projectId 107 | }).fetch() 108 | 109 | // If statusOption === 'all' Change all services to specified lairColor 110 | if (statusOption === 'all') { 111 | hosts.forEach(function (host) { 112 | // Change host to lairColor 113 | changeHostColor(host._id, lairColor) 114 | }) 115 | 116 | // set count to hosts.length 117 | count = hosts.length 118 | } else if (statusOption === 'none') { 119 | hosts.forEach(function (host) { 120 | var hostid = host._id 121 | var arrayLen = getServicesOrIssues(hostid).length 122 | 123 | // If host has no services|issues update its color 124 | if (arrayLen <= 0) { 125 | // Change host to lairColor 126 | changeHostColor(hostid, lairColor) 127 | 128 | // Update Count 129 | statCount++ 130 | } 131 | }) 132 | 133 | // set count to statCount 134 | count = statCount 135 | } else if (StatusMap.indexOf(statusOption) !== -1) { 136 | // Iterate over each host 137 | hosts.forEach(function (host) { 138 | // changeColor starts as false 139 | var changeColor = false 140 | var hostid = host._id 141 | 142 | // Get array of services|issues for current host 143 | var obj = getServicesOrIssues(hostid) 144 | 145 | changeColor = (obj.length > 0 && obj[0].status === statusOption && obj.every(allSameColor)) 146 | 147 | // If changeColor value is true, meaning all services|issues of this host are the same color 148 | // and there are >= 1 services|issues, then change host to the specified lairColor 149 | if (changeColor) { 150 | // Change host to lairColor 151 | changeHostColor(hostid, lairColor) 152 | 153 | // Update Count 154 | statCount++ 155 | } 156 | 157 | // set count to statCount 158 | count = statCount 159 | }) 160 | } else if (statusOption === 'same') { 161 | hosts.forEach(function (host) { 162 | // changeColor starts as false 163 | var changeColor = false 164 | var hostid = host._id 165 | 166 | // Get array of services|issues for current host 167 | var obj = getServicesOrIssues(hostid) 168 | 169 | changeColor = (obj.every(allSameColor)) 170 | 171 | // If changeColor value is true, meaning all services|issues of this host are the same color 172 | // and there are >= 1 services|issues, then change host to the specified lairColor 173 | if (changeColor) { 174 | // Change host color 175 | changeHostColor(hostid, lairColor) 176 | 177 | // Update Count 178 | statCount++ 179 | } 180 | 181 | // set count to statCount 182 | count = statCount 183 | }) 184 | } else if (statusOption === 'diff') { 185 | hosts.forEach(function (host) { 186 | // changeColor starts as false 187 | var changeColor = false 188 | var hostid = host._id 189 | 190 | // Get array of services|issues for current host 191 | var obj = getServicesOrIssues(hostid) 192 | 193 | changeColor = !(obj.every(allSameColor)) 194 | 195 | // If changeColor value is true, services|issues of this host vary in color 196 | // and there are >= 1 services|issues, then change host to the specified lairColor 197 | if (changeColor) { 198 | // Change host color 199 | changeHostColor(hostid, lairColor) 200 | 201 | // Update Count 202 | statCount++ 203 | } 204 | 205 | // set count to statCount 206 | count = statCount 207 | }) 208 | } else { 209 | throw { 210 | name: 'Incorrect statusOption Selection', 211 | message: 'Incorrect statusOption selection: "' + statusOption + '" is not a valid statusOption for this function' 212 | } 213 | } 214 | 215 | console.log('Total of ' + count + ' host(s) updated') 216 | } 217 | -------------------------------------------------------------------------------- /change_service_regex_to_specified_color.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Meteor Services */ 3 | function changeServicesRegexToSpecifiedColor (lairServiceRegex, lairColor) { 4 | // Changes the status of a given service to the specified color 5 | // 6 | // Updated to include Regex by Isaiah Sarju 7 | // Created by: Dan Kottmann 8 | // Updated by: Ryan Dorey 9 | // Usage: changeServicesRegexToSpecifiedColor(/*.sql.*/, 'lair-blue') 10 | // Colors available: lair-grey, lair-blue, lair-green, lair-orange, lair-red 11 | // Requires client-side updates: true 12 | 13 | var projectId = Session.get('projectId') 14 | var modifiedBy = Meteor.user().emails[0].address 15 | 16 | if (lairColor !== 'lair-grey' && lairColor !== 'lair-blue' && lairColor !== 'lair-green' && lairColor !== 'lair-orange' && lairColor !== 'lair-red') { 17 | console.log('Invalid color specified') 18 | return 19 | } 20 | var services = Services.find({ 21 | 'projectId': projectId, 22 | 'service': { 23 | '$regex': lairServiceRegex 24 | } 25 | }).fetch() 26 | if (services.length < 1) { 27 | console.log('No services found') 28 | return 29 | } 30 | services.forEach(function (service) { 31 | Services.update({ 32 | '_id': service._id 33 | }, { 34 | $set: { 35 | 'status': lairColor, 36 | 'lastModifiedBy': modifiedBy 37 | } 38 | }) 39 | }) 40 | console.log('Total of ' + services.length + ' service(s) updated to ' + lairColor + '.') 41 | } 42 | -------------------------------------------------------------------------------- /change_service_to_specified_color.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Meteor Session Services */ 3 | function changeServicesToSpecifiedColor (lairService, lairColor) { 4 | // Changes the status of a given service to the specified color 5 | // 6 | // Created by: Dan Kottmann 7 | // Updated by: Ryan Dorey 8 | // Usage: changeServicesToSpecifiedColor('dce-rpc', 'lair-orange') 9 | // Colors available: lair-grey, lair-blue, lair-green, lair-orange, lair-red 10 | // Requires client-side updates: true 11 | 12 | var projectId = Session.get('projectId') 13 | var modifiedBy = Meteor.user().emails[0].address 14 | 15 | if (lairColor !== 'lair-grey' && lairColor !== 'lair-blue' && lairColor !== 'lair-green' && lairColor !== 'lair-orange' && lairColor !== 'lair-red') { 16 | console.log('Invalid color specified') 17 | return 18 | } 19 | var services = Services.find({ 20 | 'projectId': projectId, 21 | 'service': lairService 22 | }).fetch() 23 | if (services.length < 1) { 24 | console.log('No services found') 25 | return 26 | } 27 | services.forEach(function (service) { 28 | Services.update({ 29 | '_id': service._id 30 | }, { 31 | $set: { 32 | 'status': lairColor, 33 | 'last_modifiedBy': modifiedBy 34 | } 35 | }) 36 | }) 37 | console.log('Total of ' + services.length + ' service(s) updated to ' + lairColor + '.') 38 | } 39 | -------------------------------------------------------------------------------- /change_services_to_specified_color.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Meteor Services */ 3 | function changeServicesToSpecifiedColor (lairPort, lairColor) { 4 | // Changes the status of the given service number to the specified color 5 | // 6 | // Created by: Dan Kottmann 7 | // Updated by: Ryan Dorey 8 | // Usage: changeServicesToSpecifiedColor(80, 'lair-orange') 9 | // Colors available: lair-grey, lair-blue, lair-green, lair-orange, lair-red 10 | // Requires client-side updates: true 11 | 12 | var projectId = Session.get('projectId') 13 | var modifiedBy = Meteor.user().emails[0].address 14 | 15 | if (lairColor !== 'lair-grey' && lairColor !== 'lair-blue' && lairColor !== 'lair-green' && lairColor !== 'lair-orange' && lairColor !== 'lair-red') { 16 | console.log('Invalid color specified') 17 | return 18 | } 19 | var services = Services.find({ 20 | 'projectId': projectId, 21 | 'service': lairPort 22 | }).fetch() 23 | if (services.length < 1) { 24 | console.log('No services found') 25 | return 26 | } 27 | services.forEach(function (service) { 28 | console.log('Updating: ' + service.service + '/' + service.protocol) 29 | Services.update({ 30 | '_id': service._id 31 | }, { 32 | $set: { 33 | 'status': lairColor, 34 | 'last_modified_by': modifiedBy 35 | } 36 | }) 37 | }) 38 | console.log('Total of ' + services.length + ' service(s) updated') 39 | } 40 | -------------------------------------------------------------------------------- /count_host_ports_by_color.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals projectId Hosts Services Session StatusMap */ 3 | function countHostServicesBycolor (color) { 4 | // Logs a count of all service by color per host 5 | // 6 | // Created by: Matt Burch 7 | // Usage: countHostServicesBycolor('lair-grey') 8 | // Supserviceed colors: console.log(StatusMap) 9 | // 10 | var hosts = {} 11 | var projectId = Session.get('projectId') 12 | 13 | if (StatusMap.indexOf(color) === -1) { 14 | console.log('Lair Supserviceed colors: ' + StatusMap) 15 | throw { 16 | name: 'Wrong color', 17 | message: 'Provided color: "' + color + '" is not Lair compliant' 18 | } 19 | } 20 | 21 | var services = Services.find({ 22 | 'projectId': projectId, 23 | 'status': color 24 | }).fetch() 25 | services.forEach(function (service) { 26 | host = Hosts.findOne({ 27 | 'projectId': projectId, 28 | '_id': service.hostId 29 | }) 30 | if (hosts.hasOwnProperty(host.ipv4)) { 31 | hosts[host.ipv4]++ 32 | } else { 33 | hosts[host.ipv4] = 1 34 | } 35 | }) 36 | for (var host in hosts) { 37 | console.log(host + ' (' + hosts[host] + ')') 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /count_host_services_by_color.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals projectId Hosts Services Session StatusMap */ 3 | function countHostServicesBycolor (color) { 4 | // Logs a count of all service by color per host 5 | // 6 | // Created by: Matt Burch 7 | // Usage: countHostServicesBycolor('lair-grey') 8 | // Supserviceed colors: console.log(StatusMap) 9 | // 10 | var hosts = {} 11 | var projectId = Session.get('projectId') 12 | 13 | if (StatusMap.indexOf(color) === -1) { 14 | console.log('Lair Supserviceed colors: ' + StatusMap) 15 | throw { 16 | name: 'Wrong color', 17 | message: 'Provided color: "' + color + '" is not Lair compliant' 18 | } 19 | } 20 | 21 | var services = Services.find({ 22 | 'projectId': projectId, 23 | 'status': color 24 | }).fetch() 25 | services.forEach(function (service) { 26 | host = Hosts.findOne({ 27 | 'projectId': projectId, 28 | '_id': service.hostId 29 | }) 30 | if (hosts.hasOwnProperty(host.ipv4)) { 31 | hosts[host.ipv4]++ 32 | } else { 33 | hosts[host.ipv4] = 1 34 | } 35 | }) 36 | for (var host in hosts) { 37 | console.log(host + ' (' + hosts[host] + ')') 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /delete_host_services_by_tool.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Services Meteor */ 3 | 4 | function deleteHostServicesByTool (ipAddr, lastModBy) { 5 | // Looks at a provided host and deletes any service by 6 | // specified 'Last Modified By' value. 7 | // Useful if a scanner adds large sum of bad Services. 8 | // 9 | // 10 | // Usage: deleteHostServicesByTool('192.168.1.141', 'nexpose') 11 | // Created by: Ryan Dorey 12 | // Requires client-side updates: true 13 | 14 | var projectId = Session.get('projectId') 15 | 16 | var host = Hosts.findOne({ 17 | 'projectId': projectId, 18 | 'ipv4': ipAddr 19 | }) 20 | if (typeof host === 'undefined') { 21 | console.log('No matching host found') 22 | return 23 | } 24 | 25 | var services = Services.find({ 26 | 'projectId': projectId, 27 | 'hostId': host._id, 28 | 'lastModifiedBY': lastModBy 29 | }).fetch() 30 | if (services.length < 1) { 31 | console.log('No matching Services found') 32 | } 33 | 34 | services.forEach(function (service) { 35 | console.log('Removing ' + service.protocol + '/' + service.service) 36 | Meteor.call('removeService', projectId, service._id, function () {}) 37 | }) 38 | console.log('Total of ' + services.length + ' service(s) removed.') 39 | } 40 | -------------------------------------------------------------------------------- /delete_hosts_by_positive_cidr.js: -------------------------------------------------------------------------------- 1 | function deleteHostsByCIDR () { 2 | // Delete list of IPv4 targets from supplied CIDR range 3 | // 4 | // Created by: Matt Burch 5 | // Usage: deleteHostsByCIDR('x.x.x.x/x') or deleteHostsByCIDR('x.x.x.x/x','y.y.y.y/y') 6 | // 7 | 8 | var hostTargets = [] 9 | var projectId = Session.get('projectId') 10 | var nets = Array.prototype.slice.call(arguments, 0) 11 | var hosts = Hosts.find({ 12 | projectId: projectId 13 | }).fetch() 14 | var hostip = {} 15 | var hostid = {} 16 | var count = 0 17 | 18 | function dec2Bin (octet, cidr) { 19 | var pad = '00000000' 20 | var bin = parseInt(octet[0], 10).toString(2) 21 | var bincidr = (bin.length >= pad.length ? bin : pad.slice(0, pad.length - bin.length) + bin) 22 | 23 | for (var i = 1; i <= octet.length; i++) { 24 | bin = parseInt(octet[i], 10).toString(2) 25 | bincidr += (bin.length >= pad.length ? bin : pad.slice(0, pad.length - bin.length) + bin) 26 | } 27 | 28 | return bincidr.slice(0, parseInt(cidr, 10)) 29 | } 30 | 31 | hosts.forEach(function (host) { 32 | var ip = host.ipv4.split('.') 33 | hostip[dec2Bin(ip, 32)] = host.ipv4 34 | hostid[host.ipv4] = host._id 35 | }) 36 | 37 | nets.forEach(function (cidr) { 38 | cidr = cidr.split('/') 39 | var net = cidr[0].split('.') 40 | var netbin = dec2Bin(net, cidr[1]) 41 | 42 | for (var key in hostip) { 43 | if ((key.slice(0, parseInt(cidr[1], 10))) === netbin) { 44 | Meteor.call('removeHost', projectId, hostid[hostip[key]], function(err) { 45 | if (!err) { 46 | Meteor.call('removeHostFromIssues', projectId, hostip[key]) 47 | } 48 | }) 49 | count ++ 50 | } 51 | } 52 | console.log('Total of ' + count + ' host(s) removed.') 53 | }) 54 | } 55 | -------------------------------------------------------------------------------- /delete_hosts_by_status.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Meteor */ 3 | 4 | function deleteHostsByStatus (status) { 5 | // Deletes all hosts of a given status 6 | // 7 | // Usage: deleteHostsByStatus('lair-grey') 8 | // Created by: Dan Kottmann 9 | // Requires client-side updates: true 10 | 11 | var projectId = Session.get('projectId') 12 | var hosts = Hosts.find({ 13 | 'projectId': projectId, 14 | 'status': status 15 | }).fetch() 16 | if (hosts.length < 1) { 17 | console.log('No matching hosts found') 18 | return 19 | } 20 | hosts.forEach(function (host) { 21 | console.log('Removing ' + host.ipv4) 22 | Meteor.call('removeHost', projectId, host._id, function (err) { 23 | if (!err) { 24 | Meteor.call('removeHostFromIssues', projectId, host.ipv4) 25 | } 26 | }) 27 | }) 28 | console.log('Total of ' + hosts.length + ' host(s) removed.') 29 | } 30 | -------------------------------------------------------------------------------- /delete_issues_by_status.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Issues Meteor */ 3 | 4 | function deleteIssuesByStatus (status) { 5 | // Deletes all Issues of a given status 6 | // 7 | // Usage: deleteIssuesByStatus('lair-grey') 8 | // Created by: Isaiah Sarju 9 | // Requires client-side updates: true 10 | 11 | var projectId = Session.get('projectId') 12 | var issues = Issues.find({ 13 | 'projectId': projectId, 14 | 'status': status 15 | }).fetch() 16 | if (issues.length < 1) { 17 | console.log('No matching Issues found') 18 | return 19 | } 20 | issues.forEach(function (issue) { 21 | console.log('Removing ' + issue.title) 22 | Meteor.call('removeIssue', projectId, issue._id) 23 | }) 24 | console.log('Total of ' + issues.length + ' Issue(s) removed.') 25 | } 26 | -------------------------------------------------------------------------------- /delete_issues_with_no_hosts.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Issues Meteor */ 3 | 4 | function deleteIssuesWithNoHosts () { 5 | // Looks at all issues and deletes 6 | // any Issue that has a zero (0) host count. 7 | // Useful if a host was removed from the project 8 | // and left orphaned issues behind. 9 | // 10 | // 11 | // Usage: deleteIssuesNoHosts() 12 | // Created by: Ryan Dorey 13 | // Requires client-side updates: true 14 | 15 | var projectId = Session.get('projectId') 16 | var orphanedIssues = Issues.find({ 17 | 'projectId': projectId, 18 | 'hosts': { 19 | $size: 0 20 | } 21 | }).fetch() 22 | 23 | if (orphanedIssues.length < 1) { 24 | console.log('No orphaned issues present') 25 | return 26 | } 27 | orphanedIssues.forEach(function (issue) { 28 | console.log('Removing: ' + issue.title) 29 | Meteor.call('removeIssue', projectId, issue._id, function () {}) 30 | }) 31 | console.log('Total of ' + orphanedIssues.length + ' vuln(s) removed') 32 | } 33 | -------------------------------------------------------------------------------- /delete_services_by_port_protocol_service.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Services Meteor */ 3 | 4 | function deleteServices (port, protocol, service) { 5 | // Script to delete phantom services (mostly for UDP) 6 | // Examples: 7 | // deleteServices(4172, 'udp', 'unknown') 8 | // Usage: 9 | // deleteServices(port, protocol, service) 10 | // deleteServices(0, 'udp', 'general') 11 | // Author: Alex Lauerman 12 | // Requires client-side updates: false 13 | 14 | var projectId = Session.get('projectId') 15 | var services = Services.find({ 16 | 'projectId': projectId, 17 | 'port': port, 18 | 'protocol': protocol, 19 | 'service': service 20 | }) 21 | 22 | services.forEach(function (service) { 23 | console.log('Removing Service : ' + service._id + ' ' + service.port + '/' + service.protocol + ' ' + service.service) 24 | Meteor.call('removeService', projectId, service.hostId, service._id) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /dump_issue_evidence.js: -------------------------------------------------------------------------------- 1 | function dumpIssueEvidence () { 2 | // Dump the contents of issue evidence 3 | // 4 | // Usage: dumpIssueEvidence() 5 | // Created by: Matt Burch 6 | // Requires client-side updates: false 7 | 8 | var projectId = Session.get('projectId') 9 | var issues = Issues.find({ 10 | projectId, projectId 11 | }).fetch() 12 | 13 | issues.forEach( function(issue) { 14 | console.log(issue.title) 15 | console.log(issue.evidence) 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /dump_service_notes.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Services _ Hosts Meteor */ 3 | 4 | function dumpServiceNotes (noteRegex, ip) { 5 | // Dump the contents of service notes matching a specific regex (matches against note 'title') 6 | // By supplying an empty string for the 'ip' you can dump all notes. 7 | // Examples: 8 | // dumpServiceNotes('^SSL Self-Signed', '') 9 | // dumpServiceNotes('Software Enumeration', '192.168.1.1') 10 | // 11 | // Usage: dumpServiceNotes(regex, ip) 12 | // Created by: Dan Kottmann 13 | // Requires client-side updates: false 14 | 15 | var projectId = Session.get('projectId') 16 | var re = new RegExp(noteRegex, 'i') 17 | var services = Services.find({ 18 | 'projectId': projectId, 19 | 'notes': { 20 | $elemMatch: { 21 | 'title': { 22 | $regex: noteRegex, 23 | $options: 'i' 24 | } 25 | } 26 | } 27 | }, { 28 | notes: 1, 29 | hostId: 1 30 | }).fetch() 31 | var hostIds = _.pluck(services, 'hostId') 32 | var hosts = Hosts.find({ 33 | '_id': { 34 | $in: hostIds 35 | } 36 | }, { 37 | sort: { 38 | longIpv4Addr: 1 39 | }, 40 | ipv4: 1 41 | }).fetch() 42 | hosts.forEach(function (host) { 43 | if (ip !== '' && ip !== host.ipv4) { 44 | return 45 | } 46 | services = Services.find({ 47 | 'hostId': host._id 48 | }, { 49 | sort: { 50 | service: 1 51 | }, 52 | notes: 1, 53 | service: 1, 54 | protocol: 1 55 | }).fetch() 56 | services.forEach(function (service) { 57 | service.notes.forEach(function (note) { 58 | if (re.test(note.title)) { 59 | console.log(host.ipv4 + ':' + service.port + '/' + service.protocol + ' - ' + note.title + '\n' + note.content) 60 | } 61 | }) 62 | }) 63 | }) 64 | } 65 | -------------------------------------------------------------------------------- /filter_hosts_no_services.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Services Meteor */ 3 | 4 | function filterHostsNoServices () { 5 | // Removes hosts that don't have open services and vulns mapped to them (i.e., tcp/udp 0) 6 | // 7 | // Created by: Chris Patten 8 | // Usage: filterHostsNoServices() 9 | // 10 | // Requires client-side updates: false 11 | 12 | var projectId = Session.get('projectId') 13 | var servicearray = [] 14 | var delarray = [] 15 | 16 | var hosts = Hosts.find({ 17 | 'projectId': projectId 18 | }).fetch() 19 | 20 | hosts.forEach(function (host) { 21 | var hostid = host._id 22 | var services = Services.find({ 23 | 'projectId': projectId, 24 | 'hostId': host._id 25 | }).fetch() 26 | services.forEach(function (service) { 27 | // check if service is 0 and that notes are empty - add to service array 28 | if (service.port <= 0 && service.notes < 1) { 29 | servicearray.push(service.port) 30 | } 31 | if (service.port > 0) { 32 | servicearray.push(service.port) 33 | } 34 | }) 35 | // check last index for 0 element - add host to delete array 36 | if ((servicearray[servicearray.length - 1] <= 0) || (servicearray.length <= 0)) { 37 | delarray.push(hostid) 38 | } 39 | servicearray.length = 0 40 | }) 41 | 42 | for (var x = 0; x < delarray.length; x++) { 43 | console.log('Removing HostID: ' + delarray[x]) 44 | Meteor.call('removeHost', projectId, delarray[x], function (err) { 45 | if (!err) { 46 | Meteor.call('removeHostFromIssues', projectId, delarray[x]) 47 | } 48 | }) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /find_note_by_regex.js: -------------------------------------------------------------------------------- 1 | var findNoteByRegex = function (noteRegex, noteType) { 2 | // Performs case insensitive search of the appropriate notes (both the title and contents) for the given regex 3 | // noteType can be one of the following: 4 | // all 5 | // project 6 | // host 7 | // service 8 | // Issue - searches the evidence field and notes 9 | // 10 | // Usage: findNote('.*Linux.*', 'all') 11 | // Created by: Joey Belans 12 | // Requires client-side updates: false 13 | 14 | var projectId = Session.get('projectId') 15 | 16 | var noteRe = new RegExp(noteRegex, 'i') 17 | if (noteType === 'project' || noteType === 'all') { 18 | console.log('Project Notes') 19 | var curProj = Projects.findOne({ 20 | '_id': projectId 21 | }, { 22 | notes: 1 23 | }) 24 | curProj.notes.forEach(function (note) { 25 | if (noteRe.test(note.title) || noteRe.test(note.content)) { 26 | console.log('\t' + note.title) 27 | } 28 | }) 29 | } 30 | if (noteType === 'host' || noteType === 'all') { 31 | console.log('Host Notes') 32 | Hosts.find({ 33 | 'projectId': projectId, 34 | $or: [{ 35 | 'notes': { 36 | $elemMatch: { 37 | 'title': { 38 | $regex: noteRegex, 39 | $options: 'i' 40 | } 41 | } 42 | } 43 | }, { 44 | 'notes': { 45 | $elemMatch: { 46 | 'content': { 47 | $regex: noteRegex, 48 | $options: 'i' 49 | } 50 | } 51 | } 52 | }] 53 | }, { 54 | notes: 1 55 | }).fetch().forEach(function (host) { 56 | host.notes.forEach(function (note) { 57 | if (noteRe.test(note.title) || noteRe.test(note.content)) { 58 | console.log('\t' + host.ipv4 + ' -> ' + note.title) 59 | } 60 | }) 61 | }) 62 | } 63 | if (noteType === 'service' || noteType === 'all') { 64 | console.log('Service Notes') 65 | Services.find({ 66 | 'projectId': projectId, 67 | $or: [{ 68 | 'notes': { 69 | $elemMatch: { 70 | 'title': { 71 | $regex: noteRegex, 72 | $options: 'i' 73 | } 74 | } 75 | } 76 | }, { 77 | 'notes': { 78 | $elemMatch: { 79 | 'content': { 80 | $regex: noteRegex, 81 | $options: 'i' 82 | } 83 | } 84 | } 85 | }] 86 | }, { 87 | notes: 1 88 | }).fetch().forEach(function (service) { 89 | service.notes.forEach(function (note) { 90 | if (noteRe.test(note.title) || noteRe.test(note.content)) { 91 | var serviceHost = Hosts.findOne({ 92 | 'projectId': projectId, 93 | '_id': service.hostId 94 | }) 95 | console.log('\t' + serviceHost.ipv4 + ' -> ' + service.service.toString() + ' -> ' + note.title) 96 | } 97 | }) 98 | }) 99 | } 100 | if (noteType === 'Issue' || noteType === 'all') { 101 | console.log('Issue Notes') 102 | Issues.find({ 103 | 'projectId': projectId, 104 | $or: [{ 105 | 'evidence': { 106 | $regex: noteRegex, 107 | $options: 'i' 108 | } 109 | }, { 110 | 'notes': { 111 | $elemMatch: { 112 | 'title': { 113 | $regex: noteRegex, 114 | $options: 'i' 115 | } 116 | } 117 | } 118 | }, { 119 | 'notes': { 120 | $elemMatch: { 121 | 'content': { 122 | $regex: noteRegex, 123 | $options: 'i' 124 | } 125 | } 126 | } 127 | }] 128 | }, { 129 | notes: 1 130 | }).fetch().forEach(function (vuln) { 131 | if (noteRe.test(vuln.evidence)) { 132 | console.log('\t' + vuln.title + ' -> Evidence Field') 133 | } 134 | vuln.notes.forEach(function (note) { 135 | if (noteRe.test(note.title) || noteRe.test(note.content)) { 136 | console.log('\t' + vuln.title + ' -> ' + note.title) 137 | } 138 | }) 139 | }) 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /generate_port_string_from_service.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Services _ Meteor */ 3 | 4 | function generatePortStringFromService (service) { 5 | // Generates a comma separated unique list of open services for the current project that matches 6 | // the regular expression provided as 'service'. 7 | 8 | // Usage: generatePortStringFromService(/http/) 9 | // 10 | // Created by: Tom Steele 11 | // Requires client-side updates: false 12 | 13 | var projectId = Session.get('projectId') 14 | var query = { 15 | 'projectId': projectId, 16 | 'service': service 17 | } 18 | var services = Services.find(query).fetch() 19 | return _.uniq(_.pluck(services, 'port')).sort(function (a, b) { 20 | return a - b 21 | }).join(',') 22 | } 23 | -------------------------------------------------------------------------------- /generate_unique_port_string.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Services _ Meteor */ 3 | 4 | function generateUniquePortString (protocol) { 5 | // Generates a comma separate unique list of open services for the current project 6 | // 7 | // Usages: generateUniquePortString() 8 | // generateUniquePortString('tcp') 9 | // Created by: Tom Steele 10 | // Requires client-side updates: false 11 | 12 | var projectId = Session.get('projectId') 13 | var query = { 14 | 'projectId': projectId 15 | } 16 | if (typeof protocol !== 'undefined') { 17 | query.protocol = protocol 18 | } 19 | var services = Services.find(query).fetch() 20 | return _.uniq(_.pluck(services, 'port')).sort(function (a, b) { 21 | return a - b 22 | }).join(',') 23 | } 24 | -------------------------------------------------------------------------------- /generate_url_list.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Services Meteor */ 3 | 4 | function generateURLList () { 5 | // Generate a list of URLs for all http(s) services in the current project 6 | // 7 | // Created by: Dan Kottmann 8 | // Usage: generateURLList() 9 | // Requires client-side updates: false 10 | 11 | var projectId = Session.get('projectId') 12 | var q = { 13 | 'projectId': projectId 14 | } 15 | var hosts = Hosts.find(q).fetch() 16 | if (!hosts) { 17 | console.log('No hosts found') 18 | return 19 | } 20 | var c = 0 21 | hosts.forEach(function (host) { 22 | var names = host.hostnames 23 | var hostId = host._id 24 | var query = { 25 | 'projectId': projectId, 26 | 'hostId': hostId 27 | } 28 | query.service = { 29 | '$regex': 'web|www|ssl|http|https', 30 | '$options': 'i' 31 | } 32 | var services = Services.find(query).fetch() 33 | services.forEach(function (service) { 34 | var protocol = 'http://' 35 | if (service.service.match(/(ssl|https)/gi)) { 36 | protocol = 'https://' 37 | } 38 | c++ 39 | console.log(protocol + host.ipv4 + ':' + service.port) 40 | names.forEach(function (n) { 41 | c++ 42 | console.log(protocol + n + ':' + service.port) 43 | }) 44 | }) 45 | }) 46 | console.log(c + ' URL(s) generated') 47 | } 48 | -------------------------------------------------------------------------------- /generate_webdisco_target_list.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Services Meteor */ 3 | 4 | var generateWebDiscoTargetList = function () { 5 | // Generate a target list of URLs for webDisco.py 6 | // 7 | // Created by: Dan Kottmann (general URL exservice) 8 | // Updated by: Ryan Dorey (for use with webDisco.py) & Alex Lauerman 9 | // Usage: generateWebDiscoTargetList() 10 | // Requires client-side updates: false 11 | // Note: This only matches based on a few likely conditions and won't necessarily identify 12 | // 100% of SSL services, so please keep this mind as you run this. 13 | // Additionally, it could result in some false positives for non-http services that use SSL 14 | 15 | var projectId = Session.get('projectId') 16 | var q = { 17 | 'projectId': projectId 18 | } 19 | var hosts = Hosts.find(q).fetch() 20 | if (hosts.length < 1) { 21 | console.log('No hosts found') 22 | return 23 | } 24 | var c = 0 25 | hosts.forEach(function (host) { 26 | var names = host.hostnames 27 | var hostId = host._id 28 | var query = { 29 | 'projectId': projectId, 30 | 'hostId': hostId 31 | } 32 | query.service = { 33 | '$regex': 'web|www|ssl|http|https', 34 | '$options': 'i' 35 | } 36 | var services = Services.find(query).fetch() 37 | services.forEach(function (service) { 38 | var protocol = 'http' 39 | if (service.service.match(/(ssl|https)/g)) { 40 | protocol = 'https' 41 | } 42 | service.notes.forEach(function (note) { 43 | if (note.content.match(/SSL/)) { 44 | protocol = 'https' 45 | } 46 | }) 47 | c++ 48 | console.log(protocol + ',' + host.ipv4 + ',' + service.port + ',') 49 | names.forEach(function (n) { 50 | c++ 51 | console.log(protocol + ',' + host.ipv4 + ',' + service.port + ',' + n) 52 | }) 53 | }) 54 | }) 55 | console.log(c + ' URL(s) generated') 56 | } 57 | -------------------------------------------------------------------------------- /get_hosts_by_cidr.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Meteor */ 3 | 4 | function getHostsByCIDR () { 5 | // Generate a list of hostname[ipv4] targets from supplied CIDR range 6 | // 7 | // Created by: Matt Burch 8 | // Usage: getHostsByCIDR('x.x.x.x/x') or getHostsByCIDR('x.x.x.x/x','y.y.y.y/y') 9 | // 10 | 11 | var hostTargets = [] 12 | var nets = Array.prototype.slice.call(arguments, 0) 13 | var hosts = Hosts.find({ 14 | projectId: Session.get('projectId') 15 | }).fetch() 16 | var hostip = {} 17 | 18 | function dec2Bin (octet, cidr) { 19 | var pad = '00000000' 20 | var bin = parseInt(octet[0], 10).toString(2) 21 | var bincidr = (bin.length >= pad.length ? bin : pad.slice(0, pad.length - bin.length) + bin) 22 | 23 | for (var i = 1; i <= octet.length; i++) { 24 | bin = parseInt(octet[i], 10).toString(2) 25 | bincidr += (bin.length >= pad.length ? bin : pad.slice(0, pad.length - bin.length) + bin) 26 | } 27 | 28 | return bincidr.slice(0, parseInt(cidr, 10)) 29 | } 30 | 31 | hosts.forEach(function (host) { 32 | var ip = host.ipv4.split('.') 33 | hostip[dec2Bin(ip, 32)] = host.ipv4 34 | }) 35 | 36 | nets.forEach(function (cidr) { 37 | cidr = cidr.split('/') 38 | var net = cidr[0].split('.') 39 | var netbin = dec2Bin(net, cidr[1]) 40 | 41 | for (var key in hostip) { 42 | if ((key.slice(0, parseInt(cidr[1], 10))) === netbin) { 43 | console.log(hostip[key]) 44 | } 45 | } 46 | }) 47 | } 48 | -------------------------------------------------------------------------------- /get_person_by_department_regex.js: -------------------------------------------------------------------------------- 1 | function getPersonByDepartmentRegex (dep) { 2 | // Generate a of email addresses based on person department regex by Principal, Department, Email 3 | // 4 | // Created by: Matt Burch 5 | // Usage: getPersonByDepartmentRegex(/CIO/) 6 | // 7 | 8 | if (dep && typeof dep !== 'object') { 9 | return console.log('Department regex can not be a string, must be an object') 10 | } 11 | var projectId = Session.get('projectId') 12 | 13 | var people = People.find({ 14 | projectId: projectId, 15 | department: { 16 | $regex: dep 17 | } 18 | }).fetch() 19 | 20 | people.forEach( function(p) { 21 | console.log("'" + p.principalName + "','" + p.department + "','" + p.emails.join(" ") + "'") 22 | }) 23 | console.log("returned: " + people.len() + " results") 24 | } 25 | -------------------------------------------------------------------------------- /get_person_email.js: -------------------------------------------------------------------------------- 1 | function getPersonEmail () { 2 | // Generate a list of defined people by Principal, Department, Email 3 | // 4 | // Created by: Matt Burch 5 | // Usage: getPersonEmail() 6 | // 7 | 8 | var projectId = Session.get('projectId') 9 | 10 | var people = People.find({ 11 | projectId: projectId 12 | }).fetch() 13 | 14 | people.forEach( function(p) { 15 | console.log("'" + p.principalName + "','" + p.department + "','" + p.emails.join(" ") + "'") 16 | }) 17 | console.log("returned: " + people.length + " results") 18 | } 19 | -------------------------------------------------------------------------------- /grey_hosts_no_services_green.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Meteor Services */ 3 | 4 | function greyHostsNoServicesGreen () { 5 | // Loops through each host from the selected project 6 | // and changes the status of any gray hosts with no open services 7 | // to green 8 | // 9 | // Usage: greyHostsNoServicesGreen() 10 | // Created by: Dan Kottmann 11 | // Requires client-side updates: true 12 | 13 | var projectId = Session.get('projectId') 14 | var modifiedBy = Meteor.user().emails[0].address 15 | var hosts = Hosts.find({ 16 | 'projectId': projectId, 17 | 'status': 'lair-grey' 18 | }).fetch() 19 | if (typeof hosts === 'undefined' || hosts.length === 0) { 20 | console.log('No hosts found') 21 | return 22 | } 23 | var c = 0 24 | hosts.forEach(function (host) { 25 | var serviceCount = Services.find({ 26 | 'hostId': host._id, 27 | 'port': { 28 | $gt: 0 29 | } 30 | }).count() 31 | if (serviceCount === 0) { 32 | c++ 33 | console.log('Updating: ' + host.ipv4) 34 | Hosts.update({ 35 | '_id': host._id 36 | }, { 37 | $set: { 38 | 'status': 'lair-green', 39 | 'last_modified_by': modifiedBy 40 | } 41 | }) 42 | } 43 | }) 44 | console.log(c + ' host(s) updated') 45 | } 46 | -------------------------------------------------------------------------------- /hostnames_to_nessus.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Meteor */ 3 | 4 | function hostnamesToNessus () { 5 | // Generate a list of hostname[ipv4] targets suitable for input into Nessus. 6 | // 7 | // Created by: Tom Steele 8 | // Usage: hostnamesToNessus() 9 | // Requires client-side updates: false 10 | 11 | var hosts = Hosts.find({ 12 | projectId: Session.get('projectId') 13 | }).fetch() 14 | var vhostTargets = [] 15 | hosts.forEach(function (host) { 16 | var ip = host.ipv4 17 | host.hostnames.forEach(function (name) { 18 | var item = name + '[' + ip + ']' 19 | vhostTargets.push(item) 20 | }) 21 | }) 22 | vhostTargets.forEach(function (item) { 23 | console.log(item) 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /iis_os_profiler.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Services Meteor Models */ 3 | 4 | var iisOsProfiler = function () { 5 | // Loops over every service who's product matches IIS X.X and performs a 6 | // best guess at the operating system, inserting the guess into the 7 | // service's host's os array. 8 | // 9 | // Usage: iisOsProfiler() 10 | // Created by: Tom Steele 11 | // Requires client-side updates: false 12 | 13 | var projectId = Session.get('projectId') 14 | var weight = 90 15 | var tool = 'IIS OS Profiler' 16 | var services = Services.find({ 17 | 'projectId': projectId, 18 | 'product': { 19 | '$regex': /IIS\s(httpd\s)?\d+\.\d+/, 20 | '$options': 'i' 21 | } 22 | }).fetch() 23 | services.forEach(function (service) { 24 | var product = service.product 25 | var res = product.match(/\d+\.\d+/) 26 | if (res === null) { 27 | return 28 | } 29 | var version = parseFloat(res[0]) 30 | if (isNaN(version)) { 31 | return 32 | } 33 | var os = Models.os() 34 | os.tool = tool 35 | os.weight = weight 36 | if (version < 6) { 37 | os.fingerprint = 'Microsoft Windows Server 2000' 38 | } else if (version < 7) { 39 | os.fingerprint = 'Microsoft Windows Server 2003' 40 | } else if (version < 8) { 41 | os.fingerprint = 'Microsoft Windows Server 2008' 42 | } else if (version < 9) { 43 | os.fingerprint = 'Microsoft Windows Server 2012' 44 | } else if (version < 11) { 45 | os.fingerprint = 'Microsoft Windows Server 2016' 46 | } 47 | if (os.fingerprint !== '') { 48 | Meteor.call('setOs', projectId, service.hostId, os.tool, os.fingerprint, os.weight, function (err) { 49 | if (err) { 50 | console.log('Error generating OS for', service.hostId, err) 51 | } else { 52 | console.log('Created new OS', os.fingerprint, 'for', service.hostId) 53 | } 54 | }) 55 | } 56 | }) 57 | } 58 | -------------------------------------------------------------------------------- /list_host_services_by_color.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Services Hosts Meteor StatusMap */ 3 | 4 | function listHostServicesBycolor (color) { 5 | // Logs a list of all services by color per host 6 | // 7 | // Created by: Matt Burch 8 | // Usage: countHostServicesBycolor('lair-grey') 9 | // Supserviceed colors: console.log(StatusMap) 10 | // 11 | var projectId = Session.get('projectId') 12 | 13 | if (StatusMap.indexOf(color) === -1) { 14 | console.log('Lair Supserviceed colors: ' + StatusMap) 15 | throw { 16 | name: 'Wrong color', 17 | message: 'Provided color: "' + color + '" is not Lair compliant' 18 | } 19 | } 20 | 21 | var services = Services.find({ 22 | 'projectId': projectId, 23 | 'status': color 24 | }).fetch() 25 | services.forEach(function (service) { 26 | var host = Hosts.findOne({ 27 | 'projectId': projectId, 28 | '_id': service.hostId 29 | }) 30 | console.log(host.ipv4 + ':' + service.port + '/' + service.protocol) 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /list_host_services_by_service_regex.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Services Meteor */ 3 | 4 | function listHostServicesByServiceRegex (serviceRegex) { 5 | // Logs a list of all services by service regex per host 6 | // 7 | // Created by Isaiah Sarju 8 | // Based on listHostServicesByColor by Matt Burch & changeServicesToSpecifiedColor by Dan Kottmann 9 | // Usage: listHostServicesByServiceRegex(/.*sql.*/) 10 | 11 | var REGEX = serviceRegex 12 | var projectId = Session.get('projectId') 13 | var serviceServices = Services.find({ 14 | 'projectId': projectId, 15 | 'service': { 16 | '$regex': REGEX 17 | } 18 | }).fetch() 19 | 20 | if (serviceServices.length < 1) { 21 | console.log('No services found') 22 | return 23 | } 24 | 25 | serviceServices.forEach(function (service) { 26 | var host = Hosts.findOne({ 27 | 'projectId': projectId, 28 | '_id': service.hostId 29 | }) 30 | console.log(host.ipv4 + ':' + service.port + '/' + service.protocol) 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /list_hosts_by_issue_title.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Meteor Issues*/ 3 | 4 | function listHostsByIssueTitle (title) { 5 | // Retrieves all host, port, protocol instances afflicted by a certain Issue 6 | // 7 | // Created by: Dan Kottmann & updated by Alex Lauerman 8 | // Usage: listHostsByIssueTitle('Microsoft Windows SMB NULL Session Authentication') 9 | // Requires client-side updates: false 10 | 11 | var projectId = Session.get('projectId') 12 | var issue = Issues.findOne({ 13 | 'projectId': projectId, 14 | 'title': title 15 | }) 16 | var msfHostsOutput = '' 17 | if (!issue) { 18 | console.log('Issue not found') 19 | return 20 | } 21 | 22 | var hosts = issue.hosts 23 | hosts.forEach(function (host) { 24 | console.log(host.ipv4 + ':' + host.port + '/' + host.protocol) 25 | msfHostsOutput += host.ipv4 + ', ' 26 | }) 27 | console.log('RHOSTS: ' + msfHostsOutput.slice(0, -2)) 28 | } 29 | -------------------------------------------------------------------------------- /list_hosts_by_issue_title_regex.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Meteor Issues */ 3 | 4 | function listHostsByIssueTitleRegex (issueRegex) { 5 | // Retrieves all host, service, protocol instances afflicted by a certain Issue 6 | // 7 | // Created by: Isaiah Sarju 8 | // Based on listHostsByIssueTitle Dan Kottmann & updated by Alex Lauerman 9 | // Usage: listHostsByIssueTitleRegex(/^SSL.*/) 10 | // Requires client-side updates: false 11 | 12 | var projectId = Session.get('projectId') 13 | var issues = Issues.find({ 14 | 'projectId': projectId, 15 | 'title': { 16 | '$regex': issueRegex 17 | } 18 | }).fetch() 19 | var msfHostsOutput = '' 20 | if (issues.length < 1) { 21 | console.log('No issues found') 22 | return 23 | } 24 | issues.forEach(function (issue) { 25 | console.log(issue.title) 26 | var hosts = issue.hosts 27 | hosts.forEach(function (host) { 28 | console.log(host.ipv4 + ':' + host.port + '/' + host.protocol) 29 | msfHostsOutput += host.ipv4 + ', ' 30 | }) 31 | console.log('RHOSTS: ' + msfHostsOutput.slice(0, -2)) 32 | msfHostsOutput = '' 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /list_hosts_by_tag.js: -------------------------------------------------------------------------------- 1 | function listHostByTag (tag) { 2 | // Retrieves all host by a tag 3 | // 4 | // Created by: James Cook 5 | // Usage: list_host_ip_by_tag.js 6 | // Requires client-side updates: false 7 | var hosts = Hosts.find({ 8 | projectId: Session.get('projectId'), 9 | tags: tag 10 | }).fetch() 11 | 12 | hosts.forEach(function (host) { 13 | console.log(host.ipv4) 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /list_unknown_open_services.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Services Meteor */ 3 | 4 | function listUnknownOpenServices (scope, outputFormat) { 5 | // Prints a list of all 'unknown' open services for each host 6 | // to prepare for additional efforts to identify services 7 | // 8 | // Usage: listUnknownOpenServices(searchScope, outputFormat) 9 | // Example: listUnknownOpenServices('both', 'nmap') 10 | // searchScope: 11 | // product (search the 'product' field) 12 | // service (search the 'service' field) 13 | // both 14 | // outputFormat: 15 | // list (list of hosts followed by list of all unknown services) 16 | // nmap (individual host nmap cmdline with per-host services) 17 | // hostAndPort (list host:service combinations. WARNING: A long list will likely be output. 18 | // Recommend doing select all + copy or saving log to file. See http://goo.gl/C6tmgw) 19 | // 20 | // Created by: Alain Iamburg 21 | 22 | var projectId = Session.get('projectId') 23 | var hostlist = [] 24 | var tcpservices = [] 25 | var udpservices = [] 26 | 27 | // FOR each service of each host 28 | var hosts = Hosts.find({ 29 | 'projectId': projectId 30 | }).fetch() 31 | hosts.forEach(function (host) { 32 | var services = Services.find({ 33 | 'projectId': projectId, 34 | 'hostId': host._id 35 | }).fetch() 36 | services.forEach(function (service) { 37 | if (service.port > 0) { 38 | if (scope === 'product') { 39 | if (service.product.toLowerCase() === 'unknown') { 40 | hostlist.push(host.ipv4) 41 | if (service.protocol === 'tcp') { 42 | tcpservices.push(service.port) 43 | } else if (service.protocol === 'udp') { 44 | udpservices.push(service.port) 45 | } 46 | } 47 | } else if (scope === 'service') { 48 | if (service.service.toLowerCase() === 'unknown') { 49 | hostlist.push(host.ipv4) 50 | if (service.protocol === 'tcp') { 51 | tcpservices.push(service.port) 52 | } else if (service.protocol === 'udp') { 53 | udpservices.push(service.port) 54 | } 55 | } 56 | } else if (scope === 'both') { 57 | if (service.service.toLowerCase() === 'unknown' || service.product.toLowerCase() === 'unknown') { 58 | hostlist.push(host.ipv4) 59 | if (service.protocol === 'tcp') { 60 | tcpservices.push(service.port) 61 | } else if (service.protocol === 'udp') { 62 | udpservices.push(service.port) 63 | } 64 | } 65 | } 66 | } 67 | }) 68 | 69 | // Output nmap command line format for each host and its unknown open services 70 | if (outputFormat === 'nmap') { 71 | if (tcpservices.length > 0 && udpservices.length > 0) { 72 | console.log('nmap -v -sV --version-all -sS -sU ' + host.ipv4 + ' -p T:' + tcpservices.toString() + ',U:' + udpservices.toString()) 73 | } else if (tcpservices.length > 0) { 74 | console.log('nmap -v -sV --version-all -sS ' + host.ipv4 + ' -p ' + tcpservices.toString()) 75 | } else if (udpservices.length > 0) { 76 | console.log('nmap -v -sV --version-all -sU ' + host.ipv4 + ' -p ' + udpservices.toString()) 77 | } 78 | tcpservices = [] 79 | udpservices = [] 80 | } 81 | 82 | // Output host:service 83 | if (outputFormat === 'hostAndPort') { 84 | if (tcpservices.length > 0) { 85 | tcpservices.forEach(function (tcpservice) { 86 | console.log(host.ipv4 + ':' + tcpservice.toString()) 87 | }) 88 | } 89 | if (udpservices.length > 0) { 90 | udpservices.forEach(function (udpservice) { 91 | console.log(host.ipv4 + ':' + udpservice.toString()) 92 | }) 93 | } 94 | } 95 | 96 | }) 97 | 98 | if ((tcpservices.length > 0 || udpservices.length > 0) && outputFormat === 'list') { 99 | var tcpservicesUniq = tcpservices.filter(function (elem, pos) { 100 | return tcpservices.indexOf(elem) === pos 101 | }) 102 | var udpservicesUniq = udpservices.filter(function (elem, pos) { 103 | return udpservices.indexOf(elem) === pos 104 | }) 105 | 106 | // Output a list of all hosts and unknown open TCP/UDP services 107 | console.log('Hosts:') 108 | console.log(hostlist.toString()) 109 | console.log('TCP Services:') 110 | console.log(tcpservicesUniq.sort(function (a, b) { 111 | return a - b 112 | }).toString()) 113 | console.log('UDP Services:') 114 | console.log(udpservicesUniq.sort(function (a, b) { 115 | return a - b 116 | }).toString()) 117 | } 118 | } -------------------------------------------------------------------------------- /merge_issues.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Issues Meteor */ 3 | 4 | function mergeIssues (titleRegex, minCVSS, maxCVSS, hostsRegex, newTitle, newCVSS, update) { 5 | // Merges all issues identified by the regular expressions into a new or existing Issue 6 | // provided by newTitle. 7 | // 8 | // Usage: 9 | // mergeIssues(/Apache/i, 7, 10, /.*/, 'Apache 2.x servers are vulnerable to multiple high risk issues', 'max', false) 10 | // mergeIssues(/Apache/i, 7, 10, /.*/, 'Apache 2.x servers are vulnerable to multiple high risk issues', 'max', true) 11 | // 12 | // titleRegex - regex to search titles 13 | // minCVSS - minimum CVSS score to include 14 | // maxCVSS - maximum CVSS score to include 15 | // hostsRegex - host IPs to include in filter 16 | // newTitle - title of the new Issue 17 | // newCVSS - new CVSS score, or choose 'max' to pick the highest CVSS score of that group 18 | // update - The update parameter determines whether it's a 'dry run' with output, or an actual merge. update = true will delete old entries 19 | // 20 | // Created by: Alex Lauerman and Tom Steele 21 | // Requires client-side updates: false 22 | 23 | // Do some light variable checking, you're still pretty much on your own 24 | if (typeof titleRegex !== 'object') { 25 | return console.log('Issue regex can not be a string, must be a object') 26 | } 27 | if (typeof newTitle !== 'string') { 28 | return console.log('Invalid title') 29 | } 30 | if (typeof newCVSS !== 'string') { 31 | return console.log('Invalid cvss. Variable must be a string') 32 | } 33 | 34 | var projectId = Session.get('projectId') 35 | var issues = Issues.find({ 36 | 'projectId': projectId, 37 | 'title': { 38 | '$regex': titleRegex 39 | }, 40 | 'cvss': { 41 | '$gte': minCVSS, 42 | '$lte': maxCVSS 43 | }, 44 | 'hosts.ipv4': { 45 | '$regex': hostsRegex 46 | } 47 | }).fetch() 48 | if (issues.length < 1) { 49 | return console.log('Did not find any issues with the given regex') 50 | } 51 | 52 | var highestCVSS = 0 53 | 54 | // You can change the sort order here 55 | // issues.sort(sortByHostCount) 56 | // issues.sort(sortByTitle) 57 | issues.sort(sortByCVSS) 58 | issues.forEach(function (Issue) { 59 | console.log('CVSS: ' + Issue.cvss + ' - Hosts: ' + Issue.hosts.length + ' - Title: ' + Issue.title) 60 | if (Issue.cvss > highestCVSS) { 61 | highestCVSS = Issue.cvss 62 | } 63 | }) 64 | 65 | console.log('Total found: ' + issues.length + ' Highest CVSS: ' + highestCVSS) 66 | 67 | if (update) { 68 | if (newCVSS === 'max') { 69 | newCVSS = highestCVSS 70 | } 71 | 72 | // If the Issue given in newTitle already exists, then we push it onto the regex list so we can combine them 73 | // Remove the existing Issue first 74 | var existingIssue = Issues.findOne({ 75 | 'projectId': projectId, 76 | 'title': newTitle 77 | }) 78 | if (typeof existingIssue !== 'undefined') { 79 | issues.push(existingIssue) 80 | Meteor.call('removeIssue', projectId, existingIssue._id) 81 | } 82 | console.log('Going to merge ' + issues.length + ' issues') 83 | 84 | var newDescription = '' 85 | var newSolution = '' 86 | var newEvidence = '' 87 | var newNotes = [] 88 | var newReferences = [] 89 | var cves = [] 90 | var hostList = [] 91 | var newFiles = [] 92 | // Loop over each Issue and combine the data 93 | issues.forEach(function (Issue) { 94 | newDescription = newDescription + 'CVSS: ' + Issue.cvss + ' - Hosts: ' + Issue.hosts.length + ' - Title: ' + Issue.title + "\n" 95 | newSolution = '' 96 | newEvidence = '' 97 | newReferences = newReferences.concat(Issue.references) 98 | newNotes = newNotes.concat(Issue.notes) 99 | cves = cves.concat(Issue.cves) 100 | hostList = hostList.concat(Issue.hosts) 101 | newFiles = newFiles.concat(Issue.files) 102 | }) 103 | var newHostList = unique(hostList) 104 | var newCVEs = unique(cves) 105 | // Create the new Issue 106 | Meteor.call('createIssue', projectId, newTitle, newCVSS, newDescription, newEvidence, newSolution, function (err, res) { 107 | if (err) { 108 | console.log('Error: could not create new Issue', err.message) 109 | if (existingIssue) { 110 | console.log('Looks like you lost', existingIssue.title) 111 | } 112 | } else { 113 | addExistingContentToIssue(res) 114 | } 115 | }) 116 | 117 | return console.log('Complete') 118 | } 119 | 120 | function sortByHostCount (a, b) { 121 | if (a.hosts.length > b.hosts.length) { 122 | return -1 123 | } 124 | if (a.hosts.length < b.hosts.length) { 125 | return 1 126 | } 127 | return 0 128 | } 129 | 130 | function sortByTitle (a, b) { 131 | if (a.hosts.title > b.hosts.title) { 132 | return -1 133 | } 134 | if (a.hosts.title < b.hosts.title) { 135 | return 1 136 | } 137 | return 0 138 | } 139 | 140 | function sortByCVSS (a, b) { 141 | if (a.cvss > b.cvss) { 142 | return -1 143 | } 144 | if (a.cvss < b.cvss) { 145 | return 1 146 | } 147 | return 0 148 | } 149 | 150 | // Adds notes, hosts, and cves to new vulnerablity 151 | function addExistingContentToIssue (issueId) { 152 | newNotes.forEach(function (note) { 153 | Meteor.call('addIssueNote', projectId, issueId, note.title, note.content) 154 | }) 155 | newHostList.forEach(function (host) { 156 | Meteor.call('addHostToIssue', projectId, issueId, host.ipv4, host.port, host.protocol) 157 | }) 158 | newCVEs.forEach(function (cve) { 159 | Meteor.call('addCVE', projectId, issueId, cve) 160 | }) 161 | newReferences.forEach(function (ref) { 162 | Meteor.call('addReference', projectId, issueId, ref.link, ref.name) 163 | }) 164 | removeIssues() 165 | } 166 | 167 | // Loop over all issues and remove them 168 | function removeIssues () { 169 | console.log('Removing Issues') 170 | issues.forEach(function (Issue) { 171 | Meteor.call('removeIssue', projectId, Issue._id) 172 | }) 173 | } 174 | 175 | function unique (arr) { 176 | var hash = {} 177 | var result = [] 178 | for (var i = 0, l = arr.length; i < l; ++i) { 179 | var objString = JSON.stringify(arr[i]) 180 | if (!hash.hasOwnProperty(objString)) { 181 | hash[objString] = true 182 | result.push(arr[i]) 183 | } 184 | } 185 | return result 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /merge_issues_by_title.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Issues Meteor */ 3 | 4 | function getHostList(Issue){ 5 | var hosts = ''; 6 | for(var i=0;i= pad.length ? bin : pad.slice(0, pad.length - bin.length) + bin) 20 | 21 | for (var i = 1; i <= octet.length; i++) { 22 | bin = parseInt(octet[i], 10).toString(2) 23 | bincidr += (bin.length >= pad.length ? bin : pad.slice(0, pad.length - bin.length) + bin) 24 | } 25 | 26 | return bincidr.slice(0, parseInt(cidr, 10)) 27 | } 28 | 29 | hosts.forEach(function (host) { 30 | var ip = host.ipv4.split('.') 31 | hostip[dec2Bin(ip, 32)] = host.ipv4 32 | }) 33 | 34 | nets.forEach(function (cidr) { 35 | cidr = cidr.split('/') 36 | var net = cidr[0].split('.') 37 | var netbin = dec2Bin(net, cidr[1]) 38 | 39 | for (var key in hostip) { 40 | if ((key.slice(0, parseInt(cidr[1], 10))) === netbin) { 41 | delete hostip[key] 42 | } 43 | } 44 | }) 45 | 46 | for (var key in hostip) { 47 | console.log(hostip[key]) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /nikto_Host_List.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Hosts Meteor Services */ 3 | 4 | function niktoHostList (services, domain) { 5 | // Creates a list of hosts and/or hostnames for automated Nikto scan 6 | // 7 | // Created by: Matt Burch 8 | // Usage: niktoHostList([/http/,80,'8000-8015']) 9 | // Optional Usage: niktoHostList([/http/,80,'8000-8015'],/domain\.com/) 10 | // 11 | if (domain && typeof domain !== 'object') { 12 | return console.log('Domain regex can not be a string, must be an object') 13 | } 14 | var HostTargets = {} 15 | var projectId = Session.get('projectId') 16 | 17 | function getHosts (lpid, port) { 18 | var host = Hosts.findOne({ 19 | 'projectId': projectId, 20 | '_id': lpid 21 | }) 22 | 23 | if (!(host.ipv4 + ':' + port in HostTargets)) { 24 | HostTargets[host.ipv4 + ':' + port] = true 25 | } 26 | if (domain) { 27 | host.hostnames.forEach(function (hostname) { 28 | if (domain.test(hostname) && !(hostname + ':' + port in HostTargets)) { 29 | HostTargets[hostname + ':' + port] = true 30 | } 31 | }) 32 | } 33 | } 34 | 35 | services.forEach(function (service) { 36 | var foundServices = [] 37 | if (typeof service === 'object') { 38 | foundServices = Services.find({ 39 | 'projectId': projectId, 40 | 'service': { 41 | '$regex': service 42 | } 43 | }).fetch() 44 | foundServices.forEach(function (s) { 45 | getHosts(s.hostId, s.port) 46 | }) 47 | } else if (typeof service === 'string') { 48 | var list = service.split('-') 49 | for (var i = parseInt(list[0], 10); i <= parseInt(list[1], 10); i++) { 50 | foundServices = Services.find({ 51 | 'projectId': projectId, 52 | 'service': i 53 | }).fetch() 54 | foundServices.forEach(function (s) { 55 | getHosts(s.hostId, s.port) 56 | }) 57 | } 58 | } else { 59 | var s = Services.findOne({ 60 | 'projectId': projectId, 61 | 'service': service 62 | }) 63 | getHosts(s.hostId, service.port) 64 | } 65 | }) 66 | 67 | for (var key in HostTargets) { 68 | console.log(key) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /nikto_Top_Findings.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Services Hosts Meteor */ 3 | 4 | function niktoTopFindings (custom, filter) { 5 | // Lists Nikto Top Findings results per host/vhost 6 | // 7 | // Created by: Matt Burch 8 | // Usage: niktoTopFindings([], true) 9 | // Usage: niktoTopFindings(['(.*might be interesting.*)'], true) 10 | // Usage: niktoTopFindings([], false) 11 | 12 | var nikto = new RegExp('Nikto') 13 | var findings = {} 14 | var projectId = Session.get('projectId') 15 | var topFindings = [ 16 | '(.*might be interesting.*)', 17 | '(.*Public HTTP Methods:.*PUT.*)', 18 | '(.*[Ww]eb[Dd]av.*)', 19 | '(.*Directory indexing found.*)', 20 | '(.*default file found.*)', 21 | '(.*Server leaks.*IP.*)', 22 | '(.*OSVDBID:.*)' 23 | ] 24 | if (custom.length > 0) { 25 | topFindings = custom 26 | } 27 | 28 | var services = Services.find({ 29 | 'projectId': projectId 30 | }).fetch() 31 | services.forEach(function (service) { 32 | var host = Hosts.findOne({ 33 | 'projectId': projectId, 34 | '_id': service.hostId 35 | }) 36 | service.notes.forEach(function (note) { 37 | if (nikto.test(note.title)) { 38 | var title = note.title.match(/\(.*\)/) 39 | 40 | if (filter) { 41 | var search = new RegExp(topFindings.join('|') + '\\n', 'g') 42 | var f = note.content.match(search) 43 | if (f) { 44 | if (!(findings[host.ipv4 + ' ' + title])) { 45 | findings[host.ipv4 + ' ' + title] = [] 46 | } 47 | findings[host.ipv4 + ' ' + title].push(f.join('')) 48 | } 49 | } else { 50 | console.log(host.ipv4 + ' ' + title) 51 | console.log(note.content) 52 | } 53 | 54 | 55 | } 56 | }) 57 | }) 58 | if (filter) { 59 | for (var key in findings) { 60 | console.log(key) 61 | console.log(findings[key].join('')) 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /search_service_note_content.js: -------------------------------------------------------------------------------- 1 | function searchServiceNoteContent (noteRegex, searchString) { 2 | // Search the contents of service notes for specific regex content, matching a note regex title 3 | // 4 | // Examples: 5 | // searchServiceNoteContent('Weak Cipher', '\\D\\D\\D-\\D.*') 6 | // 7 | // Usage: searchServiceNoteContent(title, search) 8 | // Created by: Matt Burch 9 | // Requires client-side updates: false 10 | 11 | var projectId = Session.get('projectId') 12 | var re = new RegExp(noteRegex, 'i') 13 | var search = new RegExp(searchString, 'g') 14 | var ciphers = [] 15 | var services = Services.find({ 16 | 'projectId': projectId, 17 | 'notes': { 18 | $elemMatch: { 19 | 'title': { 20 | $regex: noteRegex, 21 | $options: 'i' 22 | } 23 | } 24 | } 25 | }, { 26 | notes: 1, 27 | hostId: 1 28 | }).fetch() 29 | 30 | function unique(arr) { 31 | var u = {}, a = []; 32 | for(var i = 0, l = arr.length; i < l; ++i){ 33 | if(!u.hasOwnProperty(arr[i])) { 34 | a.push(arr[i]); 35 | u[arr[i]] = 1; 36 | } 37 | } 38 | return a; 39 | } 40 | services.forEach(function (service) { 41 | service.notes.forEach(function (note) { 42 | if (re.test(note.title)) { 43 | ciphers.push.apply(ciphers, note.content.match(search)) 44 | } 45 | }) 46 | }) 47 | console.log(unique(ciphers).join("\n")) 48 | } 49 | -------------------------------------------------------------------------------- /services_to_color_by_hosts.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* globals Session Services StatusMap Hosts Meteor */ 3 | 4 | function servicesToColorByHosts (hosts, port, color) { 5 | // Changes the status of provided service to provided color by Array of hosts 6 | // for lair-blue, lair-orange, lair-red; Host status is updated to color also 7 | // 8 | // Created by: Matt Burch 9 | // Usage: servicesToColorByHosts(['192.168.1.1','192.168.1.2'],80,'lair-blue') 10 | // Supserviceed Colors: console.log(StatusMap) 11 | // 12 | // Requires client-side updates: true 13 | 14 | var projectId = Session.get('projectId') 15 | var modifiedBy = Meteor.user().emails[0].address 16 | var count = 0 17 | var status = { 18 | 'lair-red': 4, 19 | 'lair-orange': 3, 20 | 'lair-blue': 2, 21 | 'lair-green': 0, 22 | 'lair-grey': 0 23 | } 24 | 25 | if (StatusMap.indexOf(color) === -1) { 26 | console.log('Lair Supserviceed colors: ' + StatusMap) 27 | throw { 28 | name: 'Wrong Color', 29 | message: 'Provided color: "' + color + '" is not Lair compliant' 30 | } 31 | } 32 | hosts.forEach(function (target) { 33 | var host = Hosts.findOne({ 34 | projectId: projectId, 35 | 'ipv4': target 36 | }) 37 | var hostServices = Services.find({ 38 | 'hostId': host._id, 39 | 'port': port 40 | }).fetch() 41 | if (hostServices.length < 1) { 42 | return 43 | } 44 | 45 | hostServices.forEach(function (service) { 46 | console.log('Updating: ' + target + ':' + service.port + '/' + service.protocol) 47 | Meteor.call('setPortStatus', projectId, service._id, color) 48 | if (status[color] > status[host.status]) { 49 | console.log('Updating: ' + target + ' status "' + color + '"') 50 | Meteor.call('setHostStatus', projectId, host._id, color) 51 | } 52 | count++ 53 | }) 54 | }) 55 | console.log(count + ' service(s) updated') 56 | } 57 | -------------------------------------------------------------------------------- /set_global_service_by_port.js: -------------------------------------------------------------------------------- 1 | var setGlobalServiceByPort = function (port, protocol, service) { 2 | // Set the service name for the specified service. 3 | // 4 | // Usage: setGlobalServiceByPort(443, 'tcp', 'https') 5 | // Created by: Jason Doyle 6 | // Requires client-side updates: false 7 | 8 | var projectId = Session.get('projectId') 9 | var services = Services.find({ 10 | 'projectId': projectId, 11 | 'port': port, 12 | 'protocol': protocol, 13 | 'service': { 14 | '$ne': service 15 | } 16 | }) 17 | services.forEach(function (s) { 18 | Meteor.call('setServiceService', projectId, s._id, service, function (err) { 19 | if (!err) { 20 | console.log('Modified service successfully') 21 | } 22 | }) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /set_host_os_by_os_regex.js: -------------------------------------------------------------------------------- 1 | /* globals Session Hosts sortWeight Meteor*/ 2 | /* eslint-disable no-unused-vars */ 3 | function setHostOsByOsRegex (osRegex, newOs, weight) { 4 | // Loops through each host from the selected project 5 | // and sets the Operating System value if the host's 6 | // Os matches the provided regex. Assigns the provided weight as well. 7 | // 8 | // Usage: setHostOsByOsRegex(/.*Linux.*/, 'Linux', 100) 9 | // Created by: Dan Kottmann 10 | // Requires client-side updates: false 11 | 12 | var projectId = Session.get('projectId') 13 | 14 | var query = { 15 | 'projectId': projectId, 16 | 'os.fingerprint': { 17 | $regex: osRegex 18 | } 19 | } 20 | var hosts = Hosts.find(query).fetch() 21 | 22 | if (hosts.length < 1) { 23 | console.log('No hosts found') 24 | return 25 | } 26 | 27 | hosts.forEach(function (host) { 28 | Meteor.call('setOs', projectId, host._id, 'Manual', newOs, weight, function (err) { 29 | if (err) { 30 | console.log('Unable to update host ' + host.ipv4) 31 | return 32 | } 33 | console.log('Updated host ' + host.ipv4) 34 | }) 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /set_host_service_by_port.js: -------------------------------------------------------------------------------- 1 | var setHostServiceByPort = function (host, port, protocol, service) { 2 | // Set the service name for a list of services per host. 3 | // 4 | // Usage: setHostServiceByPort('10.10.4.3', [7734,8824,10360], 'tcp', 'unknown') 5 | // Created by: Matt Burch 6 | // Requires client-side updates: false 7 | 8 | var projectId = Session.get('projectId') 9 | var host = Hosts.findOne({ 10 | 'projectId': projectId, 11 | 'ipv4': host, 12 | }) 13 | var services = Services.find({ 14 | 'projectId': projectId, 15 | 'hostId': host._id, 16 | 'port': { 17 | '$in': port 18 | }, 19 | 'protocol': protocol, 20 | 'service': { 21 | '$ne': service 22 | } 23 | }) 24 | services.forEach(function (s) { 25 | Meteor.call('setServiceService', projectId, s._id, service, function (err) { 26 | if (!err) { 27 | console.log('Modified service successfully') 28 | } 29 | }) 30 | }) 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tag_hosts_by_cidr.js: -------------------------------------------------------------------------------- 1 | function tagHostsByCIDR (tag, net) { 2 | // Add a tag to hosts in a given cidr. 3 | // 4 | // Created by: James Cook 5 | // borrowed a lot from: https://github.com/lair-framework/browser-scripts/blob/master/get_hosts_by_cidr.js 6 | // Usage: tagHostsByCIDR('tagname', 'x.x.x.x/x') 7 | // 8 | var hostTargets = [] 9 | var hosts = Hosts.find({ 10 | projectId: Session.get('projectId') 11 | }).fetch() 12 | var hostip = {} 13 | 14 | 15 | function addHostTag (hostId, tag) { 16 | check(hostId, Matchers.isObjectId) 17 | check(tag, Matchers.isNonEmptyString) 18 | return Hosts.update({ 19 | _id: hostId 20 | }, { 21 | $addToSet: { 22 | tags: tag 23 | }, 24 | $set: { 25 | lastModifiedBy: Meteor.user().emails[0].address 26 | } 27 | }) 28 | } 29 | 30 | function dec2Bin (octet, cidr) { 31 | var pad = '00000000' 32 | var bin = parseInt(octet[0], 10).toString(2) 33 | var bincidr = (bin.length >= pad.length ? bin : pad.slice(0, pad.length - bin.length) + bin) 34 | 35 | for (var i = 1; i <= octet.length; i++) { 36 | bin = parseInt(octet[i], 10).toString(2) 37 | bincidr += (bin.length >= pad.length ? bin : pad.slice(0, pad.length - bin.length) + bin) 38 | } 39 | 40 | return bincidr.slice(0, parseInt(cidr, 10)) 41 | } 42 | 43 | hosts.forEach(function (host) { 44 | var ip = host.ipv4.split('.') 45 | hostip[dec2Bin(ip, 32)] = host 46 | }) 47 | 48 | cidr = net.split('/') 49 | var net = cidr[0].split('.') 50 | var netbin = dec2Bin(net, cidr[1]) 51 | 52 | for (var key in hostip) { 53 | if ((key.slice(0, parseInt(cidr[1], 10))) === netbin) { 54 | addHostTag(hostip[key]._id, tag) 55 | console.log(hostip[key]._id, tag) 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /unique_service_by_hosts_cidr.js: -------------------------------------------------------------------------------- 1 | function uniqueServicesByHostsCIDR () { 2 | // Print a unique service list for hosts CIDR range 3 | // 4 | // Created by: Matt Burch 5 | // Usage: uniqueServicesByHostsCIDR('x.x.x.x/x') or uniqueServicesByHostsCIDR('x.x.x.x/x','y.y.y.y/y') 6 | // 7 | 8 | var hostTargets = [] 9 | var projectId = Session.get('projectId') 10 | var nets = Array.prototype.slice.call(arguments, 0) 11 | var hosts = Hosts.find({ 12 | projectId: projectId 13 | }).fetch() 14 | var hostip = {} 15 | var hostid = {} 16 | var ids = [] 17 | 18 | function dec2Bin (octet, cidr) { 19 | var pad = '00000000' 20 | var bin = parseInt(octet[0], 10).toString(2) 21 | var bincidr = (bin.length >= pad.length ? bin : pad.slice(0, pad.length - bin.length) + bin) 22 | 23 | for (var i = 1; i <= octet.length; i++) { 24 | bin = parseInt(octet[i], 10).toString(2) 25 | bincidr += (bin.length >= pad.length ? bin : pad.slice(0, pad.length - bin.length) + bin) 26 | } 27 | 28 | return bincidr.slice(0, parseInt(cidr, 10)) 29 | } 30 | 31 | hosts.forEach(function (host) { 32 | var ip = host.ipv4.split('.') 33 | hostip[dec2Bin(ip, 32)] = host.ipv4 34 | hostid[host.ipv4] = host._id 35 | }) 36 | 37 | nets.forEach(function (cidr) { 38 | cidr = cidr.split('/') 39 | var net = cidr[0].split('.') 40 | var netbin = dec2Bin(net, cidr[1]) 41 | 42 | for (var key in hostip) { 43 | if ((key.slice(0, parseInt(cidr[1], 10))) === netbin) { 44 | ids.push(hostid[hostip[key]]) 45 | } 46 | } 47 | }) 48 | 49 | var services = Services.find({projectId: projectId, hostId: {$in: ids}}).fetch() 50 | return _.uniq(_.pluck(services, 'port')).sort(function (a, b) { 51 | return a - b 52 | }).join(',') 53 | } 54 | --------------------------------------------------------------------------------