Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
I used PyLint and Django-Lint on an internal engagement recently and wanted to show how simple they are to use.
If you prefer video and audio over just reading the text, then you can find the YouTube version of this post below.
That said, don’t forget to hit those like and subscribe buttons to help support the blog and channel!
While testing the Django application, I decided to try out django-lint for some static analysis.
First, I installed the django-lint module using pip.
doyler@mbp:~/Documents/demo_tool$ pip install django-lint DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Collecting django-lint
Next, I tried to run the tool against the application, but I was in the wrong folder.
doyler@mbp:~/Documents/demo_tool/source$ django-lint demo-tool-develop Usage: django-lint [options] target Django Lint is a tool that statically analyses Django projects and applications, checking for programming errors and bad code smells. For example, it reports nullable "CharField" fields, as well as reporting for unspecified options in settings.py. The `target` argument is mandatory and can specify either a directory containing a Django project, a single application or a single file. django-lint: error: The specified target ('/Users/doyler/Documents/demo_tool/source/demo-tool-develop') does not appear to be part of a Django application
When I went to the correct folder, I learned that I was missing the django module.
doyler@mbp:~/Documents/demo_tool/source/demo-tool-develop$ django-lint LearningDjango E: Cannot import `django' module, exiting..
Finally, I installed Django, and was ready to start.
doyler@mbp:~/Documents/demo_tool/source/demo-tool-develop$ pip install django DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Collecting django Downloading https://files.pythonhosted.org/packages/49/49/178daa8725d29c475216259eb19e90b2aa0b8c0431af8c7e9b490ae6481d/Django-1.11.29-py2.py3-none-any.whl (6.9MB)
With Django and django-lint installed, it was time to see if I could find any vulnerabilities using static analysis.
First, I ran the application against my demo source, but received an error about a missing __init__.py file.
doyler@mbp:~/Documents/demo_tool/source/demo-tool-develop$ django-lint LearningDjango ************* Module LearningDjango F: 1,0: error while code parsing: Unable to load file '/Users/doyler/Documents/demo_tool/source/demo-tool-develop/LearningDjango/__init__.py' ([Errno 2] No such file or directory: '/Users/doyler/Documents/demo_tool/source/demo-tool-develop/LearningDjango/__init__.py')
After finally going to the correct app directory, I was able to successfully run django-lint! Unfortunately, there was nothing of note, and I just had a few errors and style issues that I could fix.
doyler@mbp:~/Documents/demo_tool/source/demo-tool-develop/LearningDjango/BasicApp$ django-lint -p . ************* Module BasicApp.Demo_Module C: 1,0: Invalid name "Demo_Module" for type module (should match (([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$) F: 1,0: Unable to import 'pyodbc'
With nothing fruitful coming from django-lint during my engagement, I decided to give PyLint a try on my personal repositories.
First, I installed PyLint using pip.
doyler@mbp:~/tools$ pip install pylint DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Requirement already satisfied: pylint in /usr/local/lib/python2.7/site-packages (0.28.0)
This was the only package that I needed to install, so I was ready to try out the application.
First, when I ran the application, I only received errors about missing __init__.py files.
doyler@mbp:~/tools/SecurityTools$ pylint ./* No config file found, using default configuration ************* Module AlexaPortScanner F: 1,0: error while code parsing: Unable to load file 'AlexaPortScanner/__init__.py' ([Errno 2] No such file or directory: 'AlexaPortScanner/__init__.py') ************* Module AndroidCloseTabs F: 1,0: error while code parsing: Unable to load file 'AndroidCloseTabs/__init__.py' ([Errno 2] No such file or directory: 'AndroidCloseTabs/__init__.py') ... <snip> ... ************* Module ZipCracker F: 1,0: error while code parsing: Unable to load file 'ZipCracker/__init__.py' ([Errno 2] No such file or directory: 'ZipCracker/__init__.py')
Next, I ran a quick one-liner to add an init file to every directory that wasn’t named ‘.git’.
doyler@mbp:~/tools/SecurityTools$ find . -type d -not -iwholename '*.git*' -exec touch {}/__init__.py \;
As you can see, this made quite the fun commit to my repository.
Finally, I was able to run the application and check my errors.
As you can see, I received a ton of messages about my repositories, and a few useful errors! I know that this is a wall of text, but I wanted to show some of the common issues that you might run across, as well as leave it here for me to reference in the future.
doyler@mbp:~/tools/SecurityTools$ pylint ./* No config file found, using default configuration ************* Module AlexaPortScanner C: 1,0: Missing docstring ************* Module AlexaPortScanner.alexaPortScanner C:142,0: Line too long (84/80) C: 1,0: Invalid name "alexaPortScanner" for type module (should match (([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$) C: 1,0: Missing docstring C: 6,0:build_speechlet_response: Missing docstring ... <snip> ... ************* Module DNSRickroll.dnsRickroll W: 12,4: Redefining built-in 'hex' C: 1,0: Invalid name "dnsRickroll" for type module (should match (([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$) C: 1,0: Missing docstring E: 2,0: No name 'request' in module 'urllib' E: 2,0: No name 'parse' in module 'urllib' E: 2,0: No name 'error' in module 'urllib' ... <snip> ... ************* Module ECBPlaintextAttack.ecbServer W: 18,0: Found indentation with tabs instead of spaces ... <snip> ... E: 65,14:main: Instance of '_socketobject' has no 'recv' member E: 73,8:main: Instance of '_socketobject' has no 'send' member W: 61,17:main: Unused variable 'client_address' ... <snip> ... ************* Module FileIntegrity.fileintegrity C: 1,0: Missing docstring E: 9,0: No name 'parse' in module 'urllib' F: 9,0: Unable to import 'urllib.parse' ... <snip> ... ************* Module IpExpander.ipExpander C: 1,0: Invalid name "ipExpander" for type module (should match (([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$) ... <snip> ... E: 6,13:isIP: Undefined variable 'IPAddress' E: 13,18:isCIDR: Undefined variable 'IPNetwork' E: 19,16:expandCIDR: Undefined variable 'IPNetwork' E: 30,18:expandRange: Undefined variable 'IPAddress' E: 39,25:expandRange: Undefined variable 'IPNetwork' E: 45,20:expandRange: Undefined variable 'IPAddress' E: 49,16:expandRange: Undefined variable 'iter_iprange' E: 70,29:main: Undefined variable 'IPAddress' W: 2,0: Unused import pprint ... <snip> ... Report ====== 729 statements analysed. Duplication ----------- +-------------------------+------+---------+-----------+ | |now |previous |difference | +=========================+======+=========+===========+ |nb duplicated lines |0 |NC |NC | +-------------------------+------+---------+-----------+ |percent duplicated lines |0.000 |NC |NC | +-------------------------+------+---------+-----------+ Statistics by type ------------------ +---------+-------+-----------+-----------+------------+---------+ |type |number |old number |difference |%documented |%badname | +=========+=======+===========+===========+============+=========+ |module |35 |NC |NC |0.00 |37.14 | +---------+-------+-----------+-----------+------------+---------+ |class |3 |NC |NC |0.00 |0.00 | +---------+-------+-----------+-----------+------------+---------+ |method |24 |NC |NC |8.33 |87.50 | +---------+-------+-----------+-----------+------------+---------+ |function |39 |NC |NC |15.38 |41.03 | +---------+-------+-----------+-----------+------------+---------+ Raw metrics ----------- +----------+-------+------+---------+-----------+ |type |number |% |previous |difference | +==========+=======+======+=========+===========+ |code |785 |72.69 |NC |NC | +----------+-------+------+---------+-----------+ |docstring |99 |9.17 |NC |NC | +----------+-------+------+---------+-----------+ |comment |72 |6.67 |NC |NC | +----------+-------+------+---------+-----------+ |empty |124 |11.48 |NC |NC | +----------+-------+------+---------+-----------+ Messages by category -------------------- +-----------+-------+---------+-----------+ |type |number |previous |difference | +===========+=======+=========+===========+ |convention |395 |NC |NC | +-----------+-------+---------+-----------+ |refactor |9 |NC |NC | +-----------+-------+---------+-----------+ |warning |112 |NC |NC | +-----------+-------+---------+-----------+ |error |16 |NC |NC | +-----------+-------+---------+-----------+ % errors / warnings by module ----------------------------- +----------------------------------+------+--------+---------+-----------+ |module |error |warning |refactor |convention | +==================================+======+========+=========+===========+ |IpExpander.ipExpander |50.00 |6.25 |0.00 |10.89 | +----------------------------------+------+--------+---------+-----------+ |DNSRickroll.dnsRickroll |18.75 |1.79 |0.00 |1.52 | +----------------------------------+------+--------+---------+-----------+ |ECBPlaintextAttack.ecbServer |12.50 |46.43 |0.00 |4.81 | +----------------------------------+------+--------+---------+-----------+ |BurpVERBalyzer.VERBalyzer |6.25 |7.14 |88.89 |24.81 | +----------------------------------+------+--------+---------+-----------+ |FileIntegrity.fileintegrity |6.25 |1.79 |0.00 |8.86 | +----------------------------------+------+--------+---------+-----------+ |README |6.25 |0.00 |0.00 |0.00 | +----------------------------------+------+--------+---------+-----------+ |BinToHex.binToHex |0.00 |9.82 |0.00 |1.27 | +----------------------------------+------+--------+---------+-----------+ |PyDHCPDiscover.dhcpdiscover |0.00 |8.93 |11.11 |16.46 | +----------------------------------+------+--------+---------+-----------+ |AlexaPortScanner.alexaPortScanner |0.00 |4.46 |0.00 |2.03 | +----------------------------------+------+--------+---------+-----------+ |ReverseShell.reverseShell |0.00 |4.46 |0.00 |1.27 | +----------------------------------+------+--------+---------+-----------+ |ZipCracker.zipCracker |0.00 |3.57 |0.00 |2.53 | +----------------------------------+------+--------+---------+-----------+ |ImageExtract.imgExtract |0.00 |2.68 |0.00 |2.03 | +----------------------------------+------+--------+---------+-----------+ |RSAGenKey.genKey |0.00 |0.89 |0.00 |7.34 | +----------------------------------+------+--------+---------+-----------+ |ECBPlaintextAttack.ecbAttack |0.00 |0.89 |0.00 |7.09 | +----------------------------------+------+--------+---------+-----------+ |PortScanner.portScanner |0.00 |0.89 |0.00 |1.52 | +----------------------------------+------+--------+---------+-----------+ Messages -------- +-----------+------------+ |message id |occurrences | +===========+============+ |C0103 |277 | +-----------+------------+ |C0111 |93 | +-----------+------------+ |W0312 |56 | +-----------+------------+ |C0301 |21 | +-----------+------------+ |F0401 |12 | +-----------+------------+ |E0602 |9 | +-----------+------------+ |W0702 |7 | +-----------+------------+ |W0622 |7 | +-----------+------------+ |W0611 |7 | +-----------+------------+ |R0201 |7 | +-----------+------------+ |W0621 |6 | +-----------+------------+ |W0612 |6 | +-----------+------------+ |W0311 |4 | +-----------+------------+ |E0611 |4 | +-----------+------------+ |C0324 |4 | +-----------+------------+ |W0703 |3 | +-----------+------------+ |W0613 |3 | +-----------+------------+ |W1401 |2 | +-----------+------------+ |W0511 |2 | +-----------+------------+ |W0402 |2 | +-----------+------------+ |W0201 |2 | +-----------+------------+ |W0105 |2 | +-----------+------------+ |E1101 |2 | +-----------+------------+ |W0232 |1 | +-----------+------------+ |W0122 |1 | +-----------+------------+ |W0107 |1 | +-----------+------------+ |R0913 |1 | +-----------+------------+ |R0912 |1 | +-----------+------------+ |E0001 |1 | +-----------+------------+ Global evaluation ----------------- Your code has been rated at 1.82/10 External dependencies --------------------- :: Crypto \-Cipher \-AES (ECBPlaintextAttack.ecbServer) bs4 (ImageExtract.imgExtract) dns \-resolver (DNSRickroll.dnsRickroll) requests (AndroidCloseTabs.androidCloseTabs,ImageExtract.imgExtract,FileIntegrity.fileintegrity)
I know that I initially set out to perform static analysis on the security of these applications, but I was not successful.
That said, I found a few tools that I would like to try in the future. Stay tuned for a potential blog post but let me know if you have any recommendations!
I think a great first test for these would be my Python code injection demo, so I look forward to trying them out.
While static analysis didn’t find me any vulnerabilities, it did help to get a little more familiar with these tools.
I think that Bandit will be the first security-based scanner that I try, but let me know if you have any other suggestions.
I hope to update my SecurityTools repository for all the errors at the very least, but feel free to submit pull requests for me!
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he’s done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!
He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.
This page contains links to products that I may receive compensation from at no additional cost to you. View my Affiliate Disclosure page here. As an Amazon Associate, I earn from qualifying purchases.