diff --git a/CSharpConfChecker.php b/CSharpConfChecker.php new file mode 100644 index 0000000..4ec4daf --- /dev/null +++ b/CSharpConfChecker.php @@ -0,0 +1,120 @@ +php CSharpConfChecker.php /path/to/src/ + * will output csv with status of packages (out of dat, known vulnerable) + */ + +$total = 0; + +function findConfFiles($folderPath) { + $confFiles = array(); + $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($folderPath)); + foreach($iterator as $file) { + //echo "$file \r"; + if ($file->isFile() && $file->getExtension() == 'config') { + $confFiles[] = $file->getPathname(); + } + } + return $confFiles; +} + +function parseConfFiles($confFiles) { + global $total; + $result = array(); + foreach($confFiles as $file) { + $lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + foreach($lines as $line) { + if(strpos($line, 'id=') !== false && strpos($line, 'version=') !== false) { + $id = ''; + $version = ''; + preg_match('/id=(\S+)/', $line, $idMatch); + if(!empty($idMatch)) { + $id = $idMatch[1]; + } + preg_match('/version=(\S+)/', $line, $versionMatch); + if(!empty($versionMatch)) { + $version = $versionMatch[1]; + } + if(!empty($id) && !empty($version)) { + if(empty($result[$id][$version])){ + $total++; + } + $result[$id][$version][] = $file; + } + } + } + } + + // sort by id and then by version number + uksort($result, function($a, $b) use ($result) { + $aVersions = array_keys($result[$a]); + $bVersions = array_keys($result[$b]); + $aVersion = $aVersions[count($aVersions) - 1]; + $bVersion = $bVersions[count($bVersions) - 1]; + $aVersion = preg_replace('/[^0-9.]/', '', $aVersion); + $bVersion = preg_replace('/[^0-9.]/', '', $bVersion); + if($a == $b) { + return version_compare($aVersion, $bVersion); + } else { + return strcmp($a, $b); + } + }); + return $result; +} + +function downloadUrls($parsedConf) { + global $total; + $count = 0; + foreach ($parsedConf as $id => $versions) { + foreach ($versions as $version => $files) { + $url = "https://www.nuget.org/packages/" . str_replace('"', '', trim($id)) . "/" . str_replace('"', '', trim($version)); + $count++; + echo "downloading: $count of $total \r"; + $response = getdataz($url); + + if (strpos($response, 'This package has at least one') !== false) { + $parsedConf[$id][$version]['status'] = 'vulnerable'; + } elseif (strpos($response, 'There is a newer version of this package') !== false) { + $parsedConf[$id][$version]['status'] = 'outdated'; + } + + } + } + echo "downloaded all\n"; + return $parsedConf; +} + +function getdataz($target){ + $ch = curl_init($target); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $result = curl_exec($ch); + curl_close($ch); + + return $result; +} + +$folderPath = isset($argv[1]) ? $argv[1] : ''; +if (!empty($folderPath)) { + echo "searching $folderPath\n"; + $confFiles = findConfFiles($folderPath); + echo "parsing\n"; + $parsedConfFiles = parseConfFiles($confFiles); + echo "found: $total\n"; + $parsedConfFiles = downloadUrls($parsedConfFiles); + + $csvString = "id, version, status, file\n"; + foreach ($parsedConfFiles as $id => $versions) { + + foreach ($versions as $version => $files) { + $status = isset($files['status']) ? $files['status'] : ''; + $file = isset($files[0]) ? $files[0] : ''; + + // Add a row to the CSV + $csvString .= "$id, $version, $status, $file\n"; + } + } + echo $csvString; +} +?>