common-vulnerability-entry.pl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #!/usr/bin/perl
  2. ###############################################################################
  3. ##
  4. ## Functions for downloading and parsing Common Vulnerability DB data
  5. ##
  6. ###############################################################################
  7. use strict;
  8. use warnings;
  9. use LWP::UserAgent;
  10. use Time::ParseDate; # libtime-modules-perl
  11. use POSIX qw(mktime);
  12. use HTML::Parser;
  13. ## Get details of given CVE entry from NIST DB
  14. sub fetchCVE {
  15. my $cve_id = shift;
  16. my $cve_base_url = shift;
  17. my $cvss_base_url = shift;
  18. my $url;
  19. trace " Fetching $cve_id\n";
  20. $cve_id =~ s/^CAN/CVE/;
  21. ##
  22. ## get CVE Scores from NVD
  23. ##
  24. $url = $cvss_base_url . $cve_id;
  25. my $cvss = get $url;
  26. #die " Unable to fetch CVE $cve_id" unless defined $cve;
  27. unless (defined $cvss) {
  28. error "Failed to download CVE: $url\n";
  29. #return ""; # Don't die, we might still get proper date info from the CVE at MITRE..
  30. $cvss = "";
  31. }
  32. # Check for error pages: referenced but unpublished CVEs :-/
  33. if ($cvss =~ /is\ valid\ CVE\ format,\ but\ CVE\ was\ not\ found/) {
  34. error " $cve_id does not exist in NIST DB\n";
  35. #return ""; # Don't die, we might still get proper date info from the CVE at MITRE..
  36. }
  37. ##
  38. ## get CVE from MITRE
  39. ##
  40. $url = $cve_base_url . $cve_id;
  41. my $cve = get $url;
  42. unless (defined $cve) {
  43. error "Failed to download CVE: $url\n";
  44. return "";
  45. }
  46. # Check for error pages: referenced but unpublished CVEs :-/
  47. if ($cvss =~ /Could\ not\ find\ a\ CVE\ entry\ or\ candidate\ named/) {
  48. error " $cve_id does not exist in MITRE DB\n";
  49. return "";
  50. }
  51. return (join ("",$cvss, $cve));
  52. }
  53. ## Get CVE severity rating and report date and return
  54. ## (date base-score impact-score exploit-score)
  55. sub parseCVE($$) {
  56. my $cve_id = shift;
  57. my $cve = shift;
  58. # use worst-case info as defaults
  59. my $cve_date = parsedate("today");
  60. my $cve_base = 10;
  61. my $cve_impact = 10;
  62. my $cve_exploit = 10;
  63. if ($cve eq "") {
  64. # No details means we assume worst-case (highest score, recent bug)
  65. if ($cve_id =~ /LOCAL-(.*)/) {
  66. note " Assuming worst-case ratings for LOCAL CVE $cve_id..";
  67. $cve_date = parsedate("$1", NO_RELATIVE => 1, VALIDATE =>1);
  68. } else {
  69. error " Got bad data for CVE/CVSS $cve_id, using worst-case defaults..";
  70. }
  71. return ($cve_date, $cve_base, $cve_impact, $cve_exploit);
  72. }
  73. # Reporting Date -> $cve_date
  74. unless ($cve =~ /<td colspan="2">Assigned:?\s+\((\d{4})(\d{2})(\d{2})\)<\/td>/ ||
  75. $cve =~ /<div class="smaller">CVE Version:\s+(\d{4})(\d{2})(\d{2})<\/div>/ ||
  76. $cve =~ /<td colspan="3" class="note">Candidate assigned on\s+(\d{4})(\d{2})(\d{2})/) {
  77. error "\n\n$cve\nUnable to extract date from above CVE, assume worst-case (today)\n";
  78. } else {
  79. $cve_date = parsedate("$2/$3/$1", NO_RELATIVE => 1, VALIDATE =>1);
  80. }
  81. # Base Score -> $cve_base
  82. unless ($cve =~ /CVSS\sv2\sBase\sScore:<\/span><a\shref=".*>(.*)<\/a>\s\(\w+\)/) {
  83. error " Unable to parse CVSSv2 Base Score for $cve_id, assume worst-case\n";
  84. } else {
  85. $cve_base = $1;
  86. }
  87. # Impact Subscore -> $cve_impact
  88. unless ($cve =~ /<div\ class="row"><span\ class="label">Impact\ Subscore:<\/span>\s+(.*)<\/div>/) {
  89. error " Unable to parse CVSSv2 Impact Score for $cve_id, assume worst-case\n";
  90. } else {
  91. $cve_impact = $1;
  92. }
  93. # Exploitability Subscore -> $cve_exploit
  94. unless ($cve =~ /<div\ class="row"><span\ class="label">Exploitability\ Subscore:<\/span>\s+(.*)<\/div>/) {
  95. error " Unable to parse CVSSv2 Exploitability Score for $cve_id, assume worst-case\n";
  96. } else {
  97. $cve_exploit = $1;
  98. }
  99. #print "$cve_base\n";
  100. #print "$cve_impact\n";
  101. #print "$cve_exploit\n";
  102. return ($cve_date, $cve_base, $cve_impact, $cve_exploit);
  103. }
  104. 1;