Parse: A Static Security Scanner

Overview

Parse: A PHP Security Scanner

Packagist Version Build Status

PLEASE NOTE: This tool is still in a very early stage. The work continues...

The Parse scanner is a static scanning tool to review your PHP code for potential security-related issues. A static scanner means that the code is not executed and tested via a web interface (that's dynamic testing). Instead, the scanner looks through your code and checks for certain markers and notifies you when any are found.

For example, you really shouldn't be using eval in your code anywhere if you can help it. When the scanner runs, it will parse down each of your files and look for any eval() calls. If it finds any, it adds that match to the file and reports it in the results.

Installation

Install as a development dependency in your project using composer:

composer require --dev psecio/parse

The path to the installed executable may vary depending on your bin-dir setting. With the default value parse is located at vendor/bin/psecio-parse.

For a system-wide installation use:

composer global require psecio/parse

Make sure you have ~/.composer/vendor/bin/ in your path.

Usage

NOTE: In version 0.6 the executable was renamed psecio-parse. In earlier versions the tool was simply named parse.

NOTE: In version 0.4 and earlier the --target option was used to specify the project path, this is no longer supported. Use the syntax below.

To use the scanner execute it from the command line:

psecio-parse scan /path/to/my/project

For more detailed information see the help and list commands.

psecio-parse help scan

Output formats

Currently console (dots), xml and json output formats are available. Set format with the --format option.

psecio-parse scan --format=xml /path/to/my/project
psecio-parse scan --format=dots /path/to/my/project
psecio-parse scan --format=json /path/to/my/project

The console formats supports setting the verbosity using the -v or -vv switch.

psecio-parse scan -vv /path/to/my/project

If your platform does not support ANSI codes, or if you want to redirect the console output to a file, use the --no-ansi option.

psecio-parse scan --no-ansi /path/to/my/project > filename

Listing the checks

You can also get a listing of the current checks being done with the rules command:

psecio-parse rules

Managing rules to run

There are several ways to control which rules are run. You can specifically include rules using the --include-rules option, specifically exclude them with --exclude-rules, turn them on and off on a case-by-case basis using annotations, and disable annotations using --disable-annotations.

Excluding and Including rules

By default, psecio-parse scan includes all available rules in its scan. By using --exclude-rules and --include-rules, the rules included can be reduced.

Any rules specified by --exclude-rules are explicitly excluded from the scan, regardless of any other options selected. These rules cannot be added back to the scan, short of re-running the scan with different options. Invalid rules are silently ignored.

If --include-rules is provided, only those rules specified can be used. No other rules are checked. Note that rules that aren't available (whether they do not exist or --excluded-rules is used to exclude them) cannot be included. Invalid rules are silently ignored.

Annotations

Rules can be enabled and disabled using DocBlock annotations. These are comments in the code being scanned that tells Parse to specifically enable or disable a rule for the block of code the DocBlock applies to.

  • @psecio\parse\disable <rule>: Tells Parse to ignore the given rule for the scope of the DocBlock.
  • @psecio\parse\enable <rule>: Tells Parse to enable the given rule for the scope of the DocBlock. This can be used to re-enable a particular rule when @psecio\parse\disable has been applied to the containing scope.

Note that annotations cannot enable tests that have been omitted via the command line options. If a test is disabled at the command line, it is disabled for the entire scan, regardless of any annotations.

Comments can be added after <rule> following a dobule-slash (//) comment separator. It is recommended that comments be used to indicate why the rule has been disabled or enabled.

To disable the use of annotations, use the --disable-annotations option.

See the examples directory for some examples of the use of annotations for Parse.

The Checks

Here's the current list of checks:

  • Warn when sensitive values are committed (as defined by a variable like "username" set to a string)
  • Warn when display_errors is enabled manually
  • Avoid the use of eval()
  • Avoid the use of exit or die()
  • Avoid the use of logical operators (ex. using and over &&)
  • Avoid the use of the ereg* functions (now deprecated)
  • Ensure that the second parameter of extract is set to not overwrite (not EXTR_OVERWRITE)
  • Checking output methods (echo, print, printf, print_r, vprintf, sprintf) that use variables in their options
  • Ensuring you're not using echo with file_get_contents
  • Testing for the system execution functions and shell exec (backticks)
  • Use of readfile, readlink and readgzfile
  • Using parse_str or mb_parse_str (writes values to the local scope)
  • Warn if a .phps file is found
  • Using session_regenerate_id either without a parameter or using false
  • Avoid use of $_REQUEST (know where your data is coming from)
  • Don't use mysql_real_escape_string
  • Avoiding use of import_request_variables
  • Avoid use of $GLOBALS
  • Ensure the use of type checking validating against booleans (===)
  • Ensure that the /e modifier isn't used in regular expressions (execute)
  • Using concatenation in header() calls
  • Avoiding the use of $http_raw_post_data

Plenty more to come... (yup, @todo)

TODO

See the current issues list for @todo items...

Parse is covered under the MIT license.

@author Chris Cornutt ([email protected])

Comments
  • Add rule suppression annotations

    Add rule suppression annotations

    This is a first pass at adding annotations to handle suppressing rules, as per #10. I do not consider it done, or even close to it. I expect there will be at least one or two refactoring passes, maybe more, as this is kind of brute force. I also expect that the annotation format might change.

    That said, it does work and implements ignore and no-ignore annotations (namespaced to @psecio\parse\ignore and @psecio\parse\no-ignore). The annotations can be applied to any code level as long as you are using a doc block. The annotation parsing is also case-insensitive at the moment. So the following should all be valid:

    /**
     * @psecio\parse\ignore DisplayErrors
     */
    class Foo
    {
        /**
         * @psecio\parse\ignore GlobalsUse
         */
        public function bar()
        {
            /** @Psecio\Parse\Ignore logicaloperators */
            if ($a and $b) {
                echo "BAZ!";
            }
        }
    }
    

    I've included a couple of files to test against in tests/testFiles/annotation-tests/. There's also in-code notes on how the annotation parser can be made more versatile.

    What's missing

    (that I'm aware of)

    • reporting errors on invalid annotations or bad rule names
    • unit tests
    • --ignore-annotations

    For rule names, I'd like to eventually have it complain if either of the following occur:

    • Disabled rule: rule exists but disabled on the command line
    • Invalid rule: rule does not exist

    Possible refactorings

    (in no particular order but numbered for reference):

    1. Pull annotation parsing into a helper class.
    2. Somehow "plug in" to CallbackVisitor rather than occupying it. This could be hooks, or additional callbacks added. It's a little tricky, because the visitor needs to know what the annotation parsing adds and removes.
    3. Something else?

    Conclusion

    I'm open to any and all suggestions. I'll probably be working on this again tomorrow night, but it's hard to say for sure.

    opened by redbeardcreator 33
  • Cleaned up version of readable-tests

    Cleaned up version of readable-tests

    This replaces PR #23. Please see discussion there, but continue here. The new PR was necessary because I bungled merging in #25. I might have been able to recover, but this was easier.

    This PR implements most of @hanneskod's suggestions for #23, with some modifications.

    I also flattened the tests directory structure a bit by switching to PSR-4 on the tests. I went ahead and applied this to all the tests, not just the ones created here. I'd recommend doing this for the whole project. Makes it much cleaner.

    opened by redbeardcreator 22
  • Parse php code before analysis. (Use Parser and other libraries)

    Parse php code before analysis. (Use Parser and other libraries)

    Hello. I research about analyzers. In them, parser not be able to recognize include, require and etc expression. I want to know, how dose your program recognize path? Did you use other library or tools? or did you develop this part in your app?

    Thank you.

    opened by Rivendall 18
  • Add

    Add "unit" tests that test against parsed code

    Implements Issue #22.

    Under tests/Psecio/Parse, implemented ParseTest.php, ParseTestVisitor.php and Tests/TestSessionRegenFalse_ParseTest.php (yeah, crazy name there. May need to figure out a better naming convention).

    • ParseTest.php implements an abstract base class for all the parsing-based tests.
    • ParseTestVisitor.php implements a simple parse tree visitor for use in testing.
    • Tests/TestSessionRegenFalse_ParseTest.php implements several parse string tests for TestSessionRegenFalse, including one for the problem I found and fixed in PR #15.
    • Tests/TestAvoidGlobalsUse_ParseTest.php implements parse string tests for TestAvoidGlobalsUse.

    Implementing a test is as simple as creating a test case that extends \tests\Psecio\Parse\ParseTest. It must implement parseSampleProvider() and buildTest(). The buildTest() method should return an instance of the unit under test (e.g. TestSessionRegenFalse). Then parseSampleProvider() should return a list of PHP code string (with initial <?php omitted) and result pairs. Each PHP code string will be parsed, with the results evaluated against the results of buildTest() via the PhpParser\NodeTraverser. If the results match the result value, the test passes. Otherwise, it fails.

    opened by redbeardcreator 13
  • Add support for error-supression annotations

    Add support for error-supression annotations

    Both phpcs and phpmd support special comments that suppress the reporting for certain files, checks or sections of a code.

    This would be a good addition for reducing 'noise' for cases where you know an error will be reported, but you are aware of its implications and see no way around it (for example, if the file is auo-generated by some tool).

    opened by anroots 13
  • Simplified and updated dependency versions

    Simplified and updated dependency versions

    I know in #87 you expressed some hesitation about using newer versions of dependencies, so allow me to explain what I've done.

    • ~~My first commit just removed the old version numbers where a newer one was already given as an option.~~
    • ~~You may wonder why I updated the PHP version requirement from 5.4 to 5.5.9; that's because some of the deps already required a minimum of 5.5.9 (for the newer versions), plus there's no need to support anything older if it's already been EOL for some time.~~
    • ~~Then in the next one, I updated php-parser and phpunit, ran the tests, and updated the code and tests to reflect the changes in php-parser ^3.0.~~
    • ~~Before I changed anything in composer.json, I ran the tests and noticed one test failing. After updating the versions, the code, and the tests, the same test was still failing.~~
    • ~~After making my updates, I did start having trouble with the integration test causing a fatal error. My dev environment did have xdebug enabled, but the error I was getting wasn't the one you documented. It seemed very odd to me, but I would be interested to see if it would still show up if xdebug were taken out of the picture.~~

    If there's anything you're not comfortable with, let me know and I'll change it back. ~~Also, if you have any ideas on why the integration test might be failing, I'd love to hear them. I spent a while trying to track it down and I didn't find any reason for the particular object being null at that point. What's weirder: when I added a line of debugging code, it went away. Makes no sense at all.~~

    opened by garrettw 10
  • Maximum function nesting level of '100' reached

    Maximum function nesting level of '100' reached

    I'm trying to run parse against my codebase, but after a while it stops with this:

    Fatal error: Maximum function nesting level of '100' reached, aborting! in /home/nick/testcomposer/vendor/psecio/parse/src/Psecio/Parse/TestCollection.php on line 45

    It spits out a stack trace, but doesn't give any idea to what file it was working on when it had the problem. Is there any way to debug this?

    opened by NoodlesNZ 10
  • Rename tests

    Rename tests

    A lot of renaming :smile:

    Some devitaions from @redbeardcreator's suggestion:

    • SessionRegenerateId instead of SessionRegen
    • A simple Eval was not possible as the name collides with the actual eval() function. I used EvalFunction instead.

    I put the naming convention in CONTRIBUTING.md, along with some other guidelines (see if you like).

    I also moved ParseTest to the Rule namespace as Rule\RuleTestCase and made some minor changes to comply with psr-2.

    Instead of changing the list-tests command to list-rules I opted for info. I have this idea that we could supply more educational help about to checks being made using the info command

    psecio-parse info logicaloperators
    

    I will describe this idea more clearly another day (now sleep!) :smile:

    Merging will close #49.

    opened by hanneskod 10
  • Add long description to rules

    Add long description to rules

    Adds getLongDescription to rules and displays said descriptions with RulesCommand.

    DocblockDescriptionTrait reads description and long description from the class level doc comment. Se src/Rule/DisplayErrors.php for a concrete example. And execute bin/psecio-parse rules displayerrors to view the generated output.

    eloquent/blox is used to parse the docblock.

    RuleCollection rewritten to be case insensitive.

    Merging will close #11.

    opened by hanneskod 9
  • Update TestLogicalOperatorsFound

    Update TestLogicalOperatorsFound

    If I understand the intent of TestLogicalOperatorsFound correctly this is how I think it should be written.

    The use of PhpParser\Node\Expr\BinaryOp\NotIdentical confused me, I don't think I understand what this test did before. It didn't really work though as it issued a warning when scanning this code (due to the or at the end of $operator):

    if (stristr($line, $operator) !== false) {
        // ...
    }
    

    With this pr this code pass the test

    if (true && true) {
       // ...
    }
    

    And this code fails the test

    if (true and true) {
       // ...
    }
    

    Is that how the test was intended?

    (Related to issue #27)

    opened by hanneskod 8
  • How do function comments relate to the function?

    How do function comments relate to the function?

    In #10 there's a discussion about adding annotations to functions to tell Parse to bypass them to not include them in the results. It needs to be determined how the comments (with the annotation) relates to the function and where the best place would be to check this.

    opened by enygma 8
  • Dependency not found: akamon/mockery-callable-mock

    Dependency not found: akamon/mockery-callable-mock

    $ composer install
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Package operations: 24 installs, 0 updates, 0 removals
      - Installing akamon/mockery-callable-mock (v1.0.0): Downloading (failed)    Failed to download akamon/mockery-callable-mock from dist: The "https://api.github.com/repos/Akamon/mockery-callable-mock/zipball/e11211690c940fe0b089fa26018faab0cf2e3a88" file could not be downloaded (HTTP/1.1 404 Not Found)
        Now trying to download from source
      - Installing akamon/mockery-callable-mock (v1.0.0): Username for 'https://github.com':
    
    opened by mnvx 0
  • Bump nikic/php-parser version

    Bump nikic/php-parser version

    Can't install this extension to my project since it's too new for it, I use nikic/php-parser 4.* in my code, but this package uses 2.0 version

    I think it'd be awesome to update all other packages too

    opened by vladyslavstartsev 1
  • Bump

    Bump "symfony/console" to allow 3.4.* instead of 3.2

    Hey,

    installation is failing for me due to the composer constraint "symfony/console": "2.5 - 3.2",

        "require":{
            "php": ">=5.4",
            "nikic/php-parser": "^2.0",
            "symfony/console": "2.5 - 3.2",
            "symfony/event-dispatcher": "2.4 - 3.4"
        },
    

    with

        - Installation request for psecio/parse ^0.8.0 -> satisfiable by psecio/parse[0.8].
        - Conclusion: remove symfony/console v3.4.20
        - Conclusion: don't install symfony/console v3.4.20
        - psecio/parse 0.8 requires symfony/console 2.5 - 3.2 -> satisfiable by symfony/console[...].
    

    Is there any reason to fixate the version on max 3.2. or can we move to 3.4?

    Cheers Pascal

    opened by paslandau 0
  • Syntax errors when running against PHP 7.1 codebase

    Syntax errors when running against PHP 7.1 codebase

    Hello,

    I'm discovering psecio-parse and I've just ran it on my codebase.

    I've opened this issue to report errors when running it against a PHP 7.1 codebase:

    private const MY_PRIVATE_CONST = 'hello';
    

    ^ this will throw an error "Syntax error, unexpected T_CONST, expecting T_FUNCTION"

    public function hello(?string $name): string
    

    ^ this will throw an error "unexpected ?, expecting T_VARIABLE

    I believe these errors come from nikic/php-parser, right? Your composer.json locks it to version 2.0 (resolving to 2.1.1 back from 2016) when version 4.0 is out and supports newer syntax. So maybe updating the parser would simply solve these issues.

    Also, it would be great if you could provide phar archives for releases and don't limit the symfony/console dependency to version 3.2 max ;)

    Cheers and I wish the best to this project! :)

    ~Nico

    opened by NicolasCARPi 5
  • Add check for non-strict checks against openssl_verify return

    Add check for non-strict checks against openssl_verify return

    The openssl_verify function has the unfortunate interface of returning 1 if the signature is correct, 0 if it is incorrect, and -1 on error. This means if you do a naive comparison like if (!openssl_verify(...)) then errors will make it seem as if verification succeeded. Ideally verification should be done with something like if (openssl_verify(...) !== 1).

    It'd be great if parse could detect this!

    opened by mschwager 0
Owner
psec.io
psec.io
A static analysis tool for security

progpilot A static analyzer for security purposes Only PHP language is currently supported Installation Option 1: use standalone phar Download the lat

null 271 Dec 27, 2022
PHP code scanner to use with gettext/gettext

PHP code scanner to use with gettext/gettext

Gettext 12 Nov 11, 2022
A project to add Psalm support for Drupal for security testing, focused only on taint analysis.

psalm-plugin-drupal A Drupal integration for Psalm focused on security scanning (SAST) taint analysis. Features Stubs for sinks, sources, and sanitize

Samuel Mortenson 38 Aug 29, 2022
PHP Static Analysis Tool - discover bugs in your code without running it!

PHPStan - PHP Static Analysis Tool PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even b

PHPStan 11.6k Dec 30, 2022
Phan is a static analyzer for PHP. Phan prefers to avoid false-positives and attempts to prove incorrectness rather than correctness.

Phan is a static analyzer for PHP that prefers to minimize false-positives. Phan attempts to prove incorrectness rather than correctness. Phan looks f

null 5.4k Jan 7, 2023
Beautiful and understandable static analysis tool for PHP

PhpMetrics PhpMetrics provides metrics about PHP project and classes, with beautiful and readable HTML report. Documentation | Twitter | Contributing

PhpMetrics 2.3k Dec 22, 2022
Static code analysis to find violations in a dependency graph

PhpDependencyAnalysis PhpDependencyAnalysis is an extendable static code analysis for object-oriented PHP-Projects to generate dependency graphs from

Marco Muths 546 Dec 7, 2022
Performs advanced static analysis on PHP code

PHP Analyzer Please report bugs or feature requests via our website support system ? in bottom right or by emailing [email protected]. Contri

Continuous Inspection 443 Sep 23, 2022
The Exakat Engine : smart static analysis for PHP

Exakat The Exakat Engine is an automated code reviewing engine for PHP. Installation Installation with the phar Phar is the recommended installation p

Exakat 370 Dec 28, 2022
A static php code analysis tool using the Graph Theory

Mondrian Ok guyz, you have a master degree in Graph Theory, you follow Law of Demeter and you live on S.O.L.I.D principles ? Let's have some Fun ! (^ω

Florent Genette 391 Nov 30, 2022
A static analyzer for PHP version migration

PHP Migration Readme in Chinese 中文 This is a static analyzer for PHP version migration and compatibility checking. It can suppose your current code ru

Yuchen Wang 194 Sep 27, 2022
A static analysis tool for finding errors in PHP applications

Psalm Psalm is a static analysis tool for finding errors in PHP applications. Installation To get started, check out the installation guide. Live Demo

Vimeo 5k Jan 2, 2023
Deptrac is a static code analysis tool for PHP that helps you communicate, visualize and enforce architectural decisions in your projects

Deptrac is a static code analysis tool for PHP that helps you communicate, visualize and enforce architectural decisions in your projects. You can freely define your architectural layers over classes and which rules should apply to them.

QOSSMIC GmbH 2.2k Dec 30, 2022
SonarPHP: PHP static analyzer for SonarQube & SonarLint

Code Quality and Security for PHP This SonarSource project is a static code analyser for PHP language used as an extension for the SonarQube platform.

SonarSource 343 Dec 25, 2022
Static Analysis Results Baseliner

Static Analysis Results Baseliner (SARB) Why SARB Requirements Installing Using SARB Examples Further reading Why SARB? If you've tried to introduce a

Dave Liddament 151 Jan 3, 2023
Infection Static Analysis Plugin

Static analysis on top of mutation testing - prevents escaped mutants from being invalid according to static analysis

Roave, LLC 108 Jan 2, 2023
A php.ini scanner for best security practices

Scanner for PHP.ini The Iniscan is a tool designed to scan the given php.ini file for common security practices and report back results. Currently it

psec.io 1.5k Dec 5, 2022
A PHP dependency vulnerabilities scanner based on the Security Advisories Database.

Enlightn Security Checker The Enlightn Security Checker is a command line tool that checks if your application uses dependencies with known security v

Enlightn 242 Dec 26, 2022
A multitool library offering access to recommended security related libraries, standardised implementations of security defences, and secure implementations of commonly performed tasks.

SecurityMultiTool A multitool library offering access to recommended security related libraries, standardised implementations of security defences, an

Pádraic Brady 131 Oct 30, 2022