Esempio n. 1
0
    public function getResultIterator($path)
    {
        if (Environment::hasAtLeastJavaVersion(5) !== true) {
            $this->log(['FindBugs requires JRE 1.5 or later.', \Yasca\Logs\Level::ERROR]);
            return new \EmptyIterator();
        }
        try {
            $process = new Process('"' . __DIR__ . '/bin/findbugs' . (Environment::isWindows() ? '.bat' : '') . '"' . ' -home "' . __DIR__ . '" ' . ' -include "' . __DIR__ . '/filter.xml" ' . '-textui -xml:withMessages -xargs -quiet');
        } catch (ProcessStartException $e) {
            $this->log(['FindBugs failed to start', \Yasca\Logs\Level::ERROR]);
            return new \EmptyIterator();
        }
        $this->log(['FindBugs launched', \Yasca\Logs\Level::INFO]);
        (new \Yasca\Core\FunctionPipe())->wrap($path)->pipe([Operators::_class, '_new'], '\\RecursiveDirectoryIterator')->toIteratorBuilder()->where(function ($fileinfo) {
            return $this->supportsExtension($fileinfo->getExtension());
        })->select(static function ($fileinfo, $filepath) {
            return "{$filepath}\n";
        })->forAll([$process, 'writeToStdin']);
        $process->closeStdin();
        return $process->continueWith(function ($async) use($path) {
            list($stdout, $stderr) = $async->result();
            $this->log(['FindBugs completed', \Yasca\Logs\Level::INFO]);
            $dom = new \DOMDocument();
            try {
                $success = $dom->loadXML($stdout);
            } catch (\ErrorException $e) {
                $success = false;
            }
            if ($success !== true) {
                if ($stdout === '') {
                    $this->log(['FindBugs did not return any data', \Yasca\Logs\Level::ERROR]);
                } else {
                    $this->log(['FindBugs did not return valid XML', \Yasca\Logs\Level::ERROR]);
                    $this->log(["FindBugs returned {$stdout}", \Yasca\Logs\Level::ERROR]);
                }
                return Async::fromResult(new \EmptyIterator());
            }
            $bugPatterns = (new \Yasca\Core\IteratorBuilder())->from($dom->getElementsByTagName('BugPattern'))->selectKeys(static function ($patternNode) {
                return ["{$pattern->getElementsByTagName('Details')->item(0)->nodeValue}", "{$pattern->getAttribute('type')}"];
            })->toArray(true);
            return (new \Yasca\Core\IteratorBuilder())->from($dom->getElementsByTagName('BugInstance'))->select(static function ($bugInstance) use(&$bugPatterns, $path) {
                $type = $bugInstance->getAttribute('type');
                $sourceLine = $bugInstance->getElementsByTagName('SourceLine')->item(0);
                $shortMessage = $bugInstance->getElementsByTagName('ShortMessage')->item(0)->nodeValue;
                return (new \Yasca\Result())->setOptions(['pluginName' => 'FindBugs', 'severity' => "{$bugInstance->getAttribute('priority')}", 'category' => (new \Yasca\Core\FunctionPipe())->wrap($bugInstance->getAttribute('category'))->pipeLast('\\str_replace', '_', ' ')->pipe('\\strtolower')->pipe('\\ucwords')->unwrap(), 'lineNumber' => "{$sourceLine->getAttribute('start')}", 'filename' => "{$path}/{$sourceLine->getAttribute('sourcepath')}", 'references' => ['http://findbugs.sourceforge.net/bugDescriptions.html#' . \urlencode($type) => 'FindBugs Bug Description'], 'message' => "{$shortMessage}", 'description' => <<<EOT
{$shortMessage}

{$bugPatterns[$type]}
EOT
]);
            })->toFunctionPipe()->pipe([Async::_class, 'fromResult']);
        });
    }
Esempio n. 2
0
 public function getResultIterator($path)
 {
     if (Environment::hasAtLeastJavaVersion(4) !== true) {
         $this->log(['PMD requires JRE 1.4 or later.', \Yasca\Logs\Level::ERROR]);
         return new \EmptyIterator();
     }
     try {
         $process = new Process('java -cp "' . (new \Yasca\Core\FunctionPipe())->wrap(__DIR__)->pipe([Operators::_class, '_new'], '\\FilesystemIterator')->toIteratorBuilder()->select(static function ($u, $key) {
             return $key;
         })->whereRegex('`\\.jar$`ui')->join(PATH_SEPARATOR) . '" net.sourceforge.pmd.PMD "' . $path . '"' . ' xml' . ' "' . __DIR__ . '/yasca-rules.xml"');
         //    ' "' . __DIR__ . '/yasca-rules.xml"'
         //);
     } catch (ProcessStartException $e) {
         $this->log(['PMD failed to start', \Yasca\Logs\Level::ERROR]);
         return new \EmptyIterator();
     }
     $this->log(['PMD launched', \Yasca\Logs\Level::INFO]);
     return $process->continueWith(function ($async) {
         list($stdout, $stderr) = $async->result();
         $this->log(['PMD completed', \Yasca\Logs\Level::INFO]);
         //$this->log([$stdout, \Yasca\Logs\Level::ERROR]);
         $dom = new \DOMDocument();
         try {
             $success = $dom->loadXML($stdout);
         } catch (\ErrorException $e) {
             $success = false;
         }
         if ($success !== true) {
             if ($stdout === '') {
                 $this->log(['PMD did not return any data', \Yasca\Logs\Level::ERROR]);
                 $this->log([$stderr, \Yasca\Logs\Level::ERROR]);
             } else {
                 $this->log(['PMD did not return valid XML', \Yasca\Logs\Level::ERROR]);
                 $this->log(["PMD returned {$stdout}", \Yasca\Logs\Level::ERROR]);
             }
             return Async::fromResult(new \EmptyIterator());
         }
         return (new \Yasca\Core\IteratorBuilder())->from($dom->getElementsByTagName('file'))->selectMany(static function ($fileNode) {
             return (new \Yasca\Core\IteratorBuilder())->from($fileNode->getElementsByTagName('violation'))->select(static function ($violationNode) use($fileNode) {
                 return (new \Yasca\Result())->setOptions(['pluginName' => 'PMD', 'filename' => "{$fileNode->getAttribute('name')}", 'lineNumber' => "{$violationNode->getAttribute('beginline')}", 'category' => "{$violationNode->getAttribute('rule')}", 'severity' => "{$violationNode->getAttribute('priority')}", 'description' => "", 'message' => "", 'references' => ["{$violationNode->getAttribute('externalInfoUrl')}" => 'PMD Reference']]);
             });
         })->toFunctionPipe()->pipe([Async::_class, 'fromResult']);
     });
 }
Esempio n. 3
0
    public function getResultIterator($filepath)
    {
        if (Environment::hasAtLeastJavaVersion(6) !== true) {
            if ($this->firstRun === true) {
                $this->log(['Pixy requires JRE 1.6 or later.', \Yasca\Logs\Level::ERROR]);
            }
            $this->firstRun = false;
            return new \EmptyIterator();
        }
        try {
            $process = new Process('"' . __DIR__ . '/pixy' . (Environment::isWindows() ? '.bat' : '') . '"' . ' "' . $filepath . '"');
        } catch (ProcessStartException $e) {
            if ($this->firstRun === true) {
                $this->log(['Unable to start Pixy', \Yasca\Logs\Level::ERROR]);
            }
            $this->firstRun = false;
            return new \EmptyIterator();
        }
        $this->log(['Pixy launched', \Yasca\Logs\Level::DEBUG]);
        return $process->continueWith(function ($async) {
            list($stdout, $stderr) = $async->result();
            $this->log(['Pixy completed', \Yasca\Logs\Level::DEBUG]);
            $matches = [];
            \preg_match_all(<<<'EOT'
`(*ANY)(?xim)
	^ (?<analysis>
		XSS		|
		SQL 	|
		File
	)
	\s Analysis \s BEGIN \R

	(^ .* (?<! Analysis \s BEGIN | \d ) \R)*

	(?<results>
		(^ 	-	\d*	.* \: \d+ $ \R?)+
	)
`u
EOT
, $stdout, $matches, PREG_SET_ORDER);
            return (new \Yasca\Core\IteratorBuilder())->from($matches)->selectKeys(static function ($analysisMatch) {
                return [$analysisMatch['results'], $analysisMatch['analysis']];
            })->whereRegex(<<<'EOT'
`(*ANY)(?xim)
	^ - \d* (?<filename> .* ) : (?<lineNumber> \d+ ) $.
`u
EOT
, \RegexIterator::ALL_MATCHES, 0, PREG_SET_ORDER)->selectMany(function ($results, $analysis) {
                if ($analysis === 'XSS') {
                    $result = $this->newXssResult();
                } elseif ($analysis === 'SQL') {
                    $result = $this->newSqliResult();
                } else {
                    $result = (new \Yasca\Result())->setOptions(['description' => 'Generic File Vulnerability']);
                }
                return (new \Yasca\Core\IteratorBuilder())->from($results)->select(static function ($match) use($result) {
                    $r = clone $result;
                    return $r->setOptions(['pluginName' => 'Pixy', 'lineNumber' => "{$match['lineNumber']}", 'filename' => "{$match['filename']}", 'message' => "{$match['filename']}"]);
                });
            })->toFunctionPipe()->pipe([Async::_class, 'fromResult']);
        });
    }