From 868f96c759b6650d88ff9f4fbc5c048302134248 Mon Sep 17 00:00:00 2001 From: Sebastien Blot Date: Wed, 20 Sep 2017 10:11:01 +0200 Subject: Initial import --- doc/source/_static/custom.css | 4 + doc/source/_static/sp.jpg | Bin 0 -> 36559 bytes doc/source/conf.py | 178 +++++++++++++++++++++ doc/source/config.rst | 283 +++++++++++++++++++++++++++++++++ doc/source/download.rst | 16 ++ doc/source/faq.rst | 196 +++++++++++++++++++++++ doc/source/features.rst | 352 ++++++++++++++++++++++++++++++++++++++++++ doc/source/index.rst | 30 ++++ doc/source/installation.rst | 33 ++++ doc/source/papers.rst | 16 ++ 10 files changed, 1108 insertions(+) create mode 100644 doc/source/_static/custom.css create mode 100644 doc/source/_static/sp.jpg create mode 100644 doc/source/conf.py create mode 100644 doc/source/config.rst create mode 100644 doc/source/download.rst create mode 100644 doc/source/faq.rst create mode 100644 doc/source/features.rst create mode 100644 doc/source/index.rst create mode 100644 doc/source/installation.rst create mode 100644 doc/source/papers.rst (limited to 'doc/source') diff --git a/doc/source/_static/custom.css b/doc/source/_static/custom.css new file mode 100644 index 0000000..1c47d04 --- /dev/null +++ b/doc/source/_static/custom.css @@ -0,0 +1,4 @@ +blockquote { + border-left: 2px solid #999; + padding-left: 20px; +} \ No newline at end of file diff --git a/doc/source/_static/sp.jpg b/doc/source/_static/sp.jpg new file mode 100644 index 0000000..0575ca7 Binary files /dev/null and b/doc/source/_static/sp.jpg differ diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 0000000..b2af5f2 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +# +# Snuffleupagus documentation build configuration file, created by +# sphinx-quickstart on Tue Jun 27 14:15:46 2017. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) +from datetime import datetime + + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +#extensions = ['sphinx.ext.githubpages'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Snuffleupagus' +copyright = u'%d, NBS System' % datetime.now().year +author = u'Sebastien Blot & Julien Voisin' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'0.1' +# The full version, including alpha/beta/rc tags. +release = u'Public Alpha' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'manni' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# + +html_sidebars = { + '**': [ + 'about.html', + 'navigation.html', + 'relations.html', + 'searchbox.html', + #'donate.html', + ] +} +html_theme_options = { + 'logo': './sp.jpg', + #'description': '
Killing bug-classes in PHP 7, virtual-patching the rest.', + #'fixed_sidebar': True, + 'page_width': '60%', + 'show_powered_by': False, + } + +sidebar_collapse = True + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +#html_logo = './sp.png' + +html_show_sphinx = False + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Snuffleupagusdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'Snuffleupagus.tex', u'Snuffleupagus Documentation', + u'Sebastien Blot \\& Julien Voisin', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'snuffleupagus', u'Snuffleupagus Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'Snuffleupagus', u'Snuffleupagus Documentation', + author, 'Snuffleupagus', 'One line description of project.', + 'Miscellaneous'), +] + + + diff --git a/doc/source/config.rst b/doc/source/config.rst new file mode 100644 index 0000000..8318e7d --- /dev/null +++ b/doc/source/config.rst @@ -0,0 +1,283 @@ +Configuration +============= + +Since PHP *ini-like* configuration model isn't flexible enough, +Snuffleupagus is using its own format. + +Options are chainable by using dots (``.``), and string parameters +**must** be quoted, while booleans and integers aren't. + +Comments are prefixed either with ``#``, or ``;``. + +Some rules applies in a specific ``function`` (context), on a specific ``variable`` +(data), like ``disable_functions``, others can only be enabled/disabled, like +``harden_random``. + +.. warning:: + + Careful, a wrongly configured Snuffleupagus might break your website. + It's up to you to understand its :doc:`features `, + read the present documentation about how to configure them, + evaluate your threat model, and write your configuration file accordingly. + +The rules are evaluated in the order that they are written, and the **first** one +to match will terminate the evaluation (except for rules in simulation mode). + +Bugclass-killer features +------------------------ + +global_strict +^^^^^^^^^^^^^ +`default: disabled` + +``global_strict`` will enable the `strict `_ mode globally, +forcing PHP to throw a `TypeError `_ +exception if an argument type being passed to a function does not match its corresponding declared parameter type. + +It can either be ``enabled`` or ``disabled`` + +:: + + sp.global_strict.disable(); + sp.global_strict.enable(); + +harden_random +^^^^^^^^^^^^^ + * `default: enabled` + * `more `__ + +``harden_random`` will silently replace the insecure `rand `_ +and `mt_rand `_ functions with +the secure PRNG `random_int `_. + +It can either be ``enabled`` or ``disabled``. + +:: + + sp.harden_random.enable(); + sp.harden_random.disable(); + +.. _config_global: + +global +^^^^^^ + +This configuration variable contain parameters that are used by other ones: + +- ``secret_key``: A secret key used by various cryptographic features, + like `cookies protection `__ or `unserialize protection `__, + so do make sure that it's random and long enough. + You can generate it with something like this: ``head -c 256 /dev/urandom | tr -dc 'a-zA-Z0-9'``. + +:: + + sp.global.secret_key("44239bd400aa82e125337c9d4eb8315767411ccd"); + +unserialize_hmac +^^^^^^^^^^^^^^^^ + * `default: disabled` + * `more `__ + +``unserialize_hmac`` will add integrity check to ``unserialize`` calls, preventing +abritrary code execution in their context. + +:: + + sp.unserialize_hmac.enable(); + sp.unserialize_hmac.disable(); + + +auto_cookie_secure +^^^^^^^^^^^^^^^^^^ + * `default: disabled` + * `more `__ + +``auto_cookie_secure`` will automatically mark cookies as `secure `_ +when the web page is requested over HTTPS. + +It can either be ``enabled`` or ``disabled``. + +:: + + sp.auto_cookie_secure.enable(); + sp.auto_cookie_secure.disable(); + +cookie_encryption +^^^^^^^^^^^^^^^^^ + * `default: disabled` + * `more `__ + +.. warning:: + + To use this feature, you **must** set the :ref:`global.secret_key ` variable. + This design decision prevents attacker from + `trivially bruteforcing `_ + session cookies. + +``cookie_secure`` will activate transparent encryption of specific cookies. + +It can either be ``enabled`` or ``disabled``. + +:: + + sp.cookie_encryption.cookie("my_cookie_name"); + sp.cookie_encryption.cookie("another_cookie_name"); + + +readonly_exec +^^^^^^^^^^^^^ + * `default: disabled` + +``readonly_exec`` will prevent the execution of writable PHP files. + +It can either be ``enabled`` or ``disabled``. + +:: + + sp.readonly_exec.enable(); + +upload_validation +^^^^^^^^^^^^^^^^^ + * `default: disabled` + * `more `__ + +``upload_validation`` will call a given script upon a file upload, with the path +to the file being uploaded as argument, and various information about it in the environment: + +* ``SP_FILENAME``: the name of the uploaded file +* ``SP_FILESIZE``: the size of the file being uploaded +* ``SP_REMOTE_ADDR``: the ip address of the uploader +* ``SP_CURRENT_FILE``: the current file being executed + +This feature can be used, for example, to check if an uploaded file contains php +code, with something like `vld `_ +(``php -d vld.execute=0 -d vld.active=1 -d extension=vld.so yourfile.php``). + +The upload will be **allowed** if the script return the value ``0``. Every other +value will prevent the file from being uploaded. + +:: + + sp.upload_validation.script("/var/www/is_valid_php.py").enable(); + + +disable_xxe +^^^^^^^^^^^ + * `default: enabled` + * `more `__ + +``disable_xxe`` will prevent XXE attacks by disabling the loading of external entities (``libxml_disable_entity_loader``) in the XML parser. + +:: + + sp.disable_xxe.enable(); + + +Virtual-patching +---------------- + +Snuffleupagus provides virtual-patching, via the ``disable_functions`` directive, allowing you to stop or control dangerous behaviours. +Admitting you have a call to ``system()`` that lacks proper user-input validation, thus leading to an **RCE**, this might be the right tool. + +:: + + # Allow `id.php` to restrict system() calls to `id` + sp.disable_functions.function("system").filename("id.php").param("cmd").value("id").allow(); + sp.disable_functions.function("system").filename("id.php").drop() + +Of course, this is a trivial example, and a lot can be achieved with this feature, as you will see below. + + +Filters +^^^^^^^ + +- ``alias(:str)``: human-readable description of the rule +- ``cidr(ip/mask:str)``: match on the client's `cidr `_ +- ``filename(name:str)``: match in the file ``name`` +- ``filename_r(regexp:str)``: the file name matching the ``regexp`` +- ``function(name:str)``: match on function ``name`` +- ``function_r(regexp:str)``: the function matching the ``regexp`` +- ``hash(:str)``: match on the file's `sha256 `_ sum +- ``param(name:str)``: match on the function's parameter ``name`` +- ``param_r(regexp:str)``: match on the function's parameter ``regexp`` +- ``param_type(type:str)``: match on the function's parameter ``type`` +- ``ret(value:str)``: match on the function's return ``value`` +- ``ret_r(regexp:str)``: match with a ``regexp`` on the function's return +- ``ret_type(type_name:str)``: match on the ``type_name`` of the function's return value +- ``value(:str)``: match on a litteral value +- ``value_r(:regexp)``: match on a value matching the ``regexp`` +- ``var(name:str)``: match on a **local variable** ``name`` + +The ``type`` must be one of the following values: + +- ``FALSE``: for boolean false +- ``TRUE``: for boolean true +- ``NULL``: for the **null** value +- ``LONG``: for a long (also know as ``integer``) value +- ``DOUBLE``: for a **double** (also known as ``float``) value +- ``STRING``: for a string +- ``OBJECT``: for a object +- ``ARRAY``: for an array +- ``RESOURCE``: for a resource + +Actions +^^^^^^^ + +- ``allow()``: **allow** the request if the rule matches +- ``drop()``: **drop** the request if the rule matches +- ``dump(directory:str)``: dump the request in the ``directory`` if it matches the rule +- ``simulation()``: enabled the simulation mode + +Details +^^^^^^^ + +The ``function`` filter is able to do various dereferencing: + +- ``function("AwesomeClass::my_method")`` will match in the method ``my_method`` in the class ``AwesomeClass`` + +The ``param`` filter is also able to do some dereferencing: + +- ``param(foo[bar])`` will get match on the value corresponding to the ``bar`` key in the hashtable ``foo``. + Remember that in PHP, almost every data structure is a hashtable. You can of course nest this like + ``param(foo[bar][baz][batman])``. +- The ``var`` filter will walk the calltrace until it finds the variable's name, or the end of it, + allowing to match on global variables: ``.var("_GET[param]")`` will match on the GET parameter ``param``. + +For clarity's sake, the presence of the ``allow`` or ``drop`` action is **mandatory**. + +.. warning:: + + When you're writing rules, please do keep in mind that the **order matters**. + For example, if you're denying a call to ``system()`` and then allowing it in a + more narrowed way later, the call will be denied, + because it'll match the deny first. + +If you're paranoid, we're providing a php script to automatically generate +hash of files containing dangerous functions, +and blacklisting them everywhere else. + +Examples +^^^^^^^^ + +Evaluation order of rules +""""""""""""""""""""""""" + +The following rules will: + +1. Allow calls to ``system("id")`` +2. Issue a trace in the logs on calls to ``system`` with its parameters starting with ``ping``, + and pursuing evaluation of the remaining rules. +3. Drop calls to ``system``. + + +:: + + sp.disable_functions.function("system").param("cmd").value("id").allow(); + sp.disable_functions.function("system").param("cmd").value_r("^ping").drop().simulation(); + sp.disable_functions.function("system").param("cmd").drop(); + +Miscellaneous examples +"""""""""""""""""""""" + +.. literalinclude:: ../../config/examples.ini + :language: python \ No newline at end of file diff --git a/doc/source/download.rst b/doc/source/download.rst new file mode 100644 index 0000000..161937f --- /dev/null +++ b/doc/source/download.rst @@ -0,0 +1,16 @@ +Download +======== + +Debian +------ + + +Ubuntu +------ + + +Source code +----------- + +:: + git clone https://github.com/nbs-system.com/snuffleupagus diff --git a/doc/source/faq.rst b/doc/source/faq.rst new file mode 100644 index 0000000..07aba33 --- /dev/null +++ b/doc/source/faq.rst @@ -0,0 +1,196 @@ +FAQ +=== + +General +------- + +What is Snuffleupagus? +"""""""""""""""""""""" + +Snuffleupagus is a `PHP7+ `_ +module designed to drastically raising the cost of attacks against website, +by killing entire bug classes, and also providing a powerful virtual-patching system, +allowing administrator to fix specific vulnerabilities without having to touch the PHP code. + + +Where does the name *Snuffeupagus* comes from? +"""""""""""""""""""""""""""""""""""""""""""""" + + Aloysius Snuffleupagus, more commonly known as Mr. Snuffleupagus, Snuffleupagus + or Snuffy for short, is one of the characters on Sesame Street, + the educational television program for young children. + + He was created as a woolly mammoth, without tusks or (visible) ears, + and has a long thick pointed tail, similar in shape to that of a dinosaur + or other reptile. He has long thick brown hair and a trunk, or "snuffle", + that drags along the ground. He is Big Bird's best friend and + has a baby sister named Alice. He also attends "Snufflegarten". + + --- `Wikipedia `_ + + +Why is Snuffleupagus called Snuffleupagus? +"""""""""""""""""""""""""""""""""""""""""" + +Like PHP's `ElePHPant `_, +we thought that using an elephant as a mascot would be a great idea. + + +Why did you write Snuffleupagus? +"""""""""""""""""""""""""""""""" + +We're working for `NBS System `__, +a web hosting company (meaning that we're dealing with PHP code all day long), +with a strong focus on security. We do have hardening +(kernel, `WAF `_, `IDS `_, …) +below the web stack, but most of the time, when a website is compromised, +it's either to send ads, spam, deface it, steal data, … +This is why we need to harden the website itself too, but we can't touch its +source code. + +Why not Suhosin? +"""""""""""""""" + +We're huge fans of `Suhosin `_, unfortunately: + +- it doesn't work very well on PHP 7 +- it has some oudated features and misses new ones +- it doesn't cope very well with our various industrialization needs +- it has some shortcomings by design + +We're using the `disable_function `_ +directive, but unfortunately, it doesn't provide enough usable granularity (guess how many CMS are using +``system`` to do various mandatory maintenance tasks…). + +This is why we decided to write our own hardening module, in the spirit of Suhosin, +via virtual-patching support, and other cool new features. + +What license is Snuffleupagus under and why? +"""""""""""""""""""""""""""""""""""""""""""" + +Snuffleupagus is licensed under the `LGPL `_, +and is developed by the fine people from `NBS System `__. + +We chose the LGPL because we don't care that much how you're using Snuffleupagus, +but we'd like to force people to make their improvements/contributions +available to everyone. + +Should I use Snuffleupagus? +""""""""""""""""""""""""""" + +Yes. + +Even if you're not using the virtual-patching capabilities, Snuffleupagus comes +with various passive features that won't break your website while killing numerous vulnerabilities. + +Please keep in mind that you are not only protecting yourself and your users/customers, +but also other people on the internet that might be attacked by your server if +it becomes compromised. + +How mature is this project? +""""""""""""""""""""""""""" + +This project was floating around since early 2016, and we did the first commit +the 28ᵗʰ of December of the same year. We're currently in a private alpha phase, +finding and fixing as much bugs as possible with the help of friends. + +Are you saying that PHP isn't secure? +""""""""""""""""""""""""""""""""""""" + +We don't like PHP's approach of security; namely (sometimes) adding warnings +in the documentation and trusting the developer to not do any mistake, +instead of focusing on the root cause, and killing the +bug class one for all. + +Moreover, it seems that the current attitude toward security in the PHP world +is to `blame the user `_ instead of acknowledging +issues, as stated in their `documentation `_. +We do think that an security issue that "requires the use of code or settings known to be insecure" +is still a security issue, and should be treated as such. + +Installation and configuration +------------------------------ + +Can snuffleupagus break my application? +""""""""""""""""""""""""""""""""""""""" +Yes. + +Some options won't break anything, like ``harden_rand``, but some like ``global_strict`` +or overly-restrictives virtual-patching rules might pretty well break your website. +It's up to you to configure Snuffleupaggus accordingly to your needs. + +You can also enable the ``simulation`` mode on features that you're not sure about, +to see what would snuffleupagus do to your application, before activating them for good. + +How can I find out the problem when my application breaks? +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +By checking the logs; Snuffleupagus systematically prefix them with ``[snuffleupagus]``. + + +Does Snuffleupagus run on Windows? +"""""""""""""""""""""""""""""""""" +No idea. + + +Will Snuffleupagus run on my old PHP 5? +""""""""""""""""""""""""""""""""""""""" +No. + +Since PHP5 `will be deprecated at the end of 2018 `_, +you should think about moving to PHP7 anyway. You can (and should) use +`Suhosin `_ in the meantime. + +Help and support +---------------- + +I found a security issue +"""""""""""""""""""""""" +If you believe you have found a security issue affecting Snuffleupagus, +then we would be more than happy to hear from you! + +We promise to treat any reported issue seriously and, +if the investigation confirms it affects Snuffleupagus, +to patch it within a reasonable time, +release a public announcement that describes the issue, +discuss potential impact of the vulnerability, +reference applicable patches or workarounds, +and credit the discoverer. + +Please send it us a mail to the ``snuffleupagus`` user, +on ``nbs-system.com``. + +I found a bug. How can I report it? +""""""""""""""""""""""""""""""""""" +We do have an issue tracker on `Github `_. +Please make sure to include as much information as possible when reporting your issue, +such as your operating system, your version of PHP 7, your version of snuffleupagus, +your logs, the problematic php code, the request, a brief description, … long story short, +give us everything that you can. + +Where can I find even more help? +"""""""""""""""""""""""""""""""" +The :doc:`configuration page ` might be what you're looking for. +If you're adventurous, you can also check the `issue tracker `_ +(make sure to check the closed issues too). + +I need professional support for my company. +""""""""""""""""""""""""""""""""""""""""""" +Contact `NBS System `_. + +Unimplemented mitigations and abandoned ideas +--------------------------------------------- + +Contant time comparisons +"""""""""""""""""""""""" +We didn't manage to perform time-based side-channel attacks on strings +against real world PHP application, and the results that we gathered on +tailored test cases weren't concluding: for simplicity's sake, we chose +to not implement a mitigation against this class of attacks. + +We would be happy to be proven wrong, and reconsider implementing this feature, +if someone can manage to get better results than us. + +The possibility of having this natively in PHP has +`been discussed `_, +but as 2017, nothing has been merged yet. diff --git a/doc/source/features.rst b/doc/source/features.rst new file mode 100644 index 0000000..89cd756 --- /dev/null +++ b/doc/source/features.rst @@ -0,0 +1,352 @@ +Features +======== + +Snuffleupagus has a lot of features that can be divided in two main categories: bug-classes +killers and virtual-patching. The first category provides primitives to kill various +bug families (like arbitrary code execution via ``unserialize`` for example) or rise the +cost of exploitation, the second one is a highly configurable system to patch functions in php itself. + +Bug classes killed +------------------ + +``system`` injections +^^^^^^^^^^^^^^^^^^^^^ + +The ``system`` function execute an external program and displays the output. +It's used to interract with various external tools, like file-format converters for example. +Unfortunately, passing user-controlled parameters to it often leads to an arbitrary command execution. + + When allowing user-supplied data to be passed to this function, + use `escapeshellarg()` or `escapeshellcmd()` to ensure that users cannot trick + the system into executing arbitrary commands. + + --- `The PHP documentation about system `_ + +We're kind of killing it by filtering the ``$``, ``|``, ``;``, ````` and ``&`` chars in our +default configuration, making it a lot harder for an attacker to inject arbitrary commands. + +This family of vulnerabilities lead to various CVE, like: + +- `CVE-2017-7981 `_: Authenticated remote code execution on Tuleap +- `CVE-2014-4688 `_: Authenticated remote code execution on pfSense +- `CVE-2014-1610 `_: Unauthenticated remote code execution on DokuWiki +- `CVE-2013-3630 `_: Authenticated remote code execution on Moodle +- Every single shitty `modem/router/switch/IoT `_. + + +``mail``-related injections +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This vulnerability is known `since 2011 `_, +and was popularized by `RIPS `_ in 2016. +The last flag of the `mail` function can be used to pass various parameters to +the underlying binary used to send emails: this can lead to an arbitrary file write, +often meaning an arbitrary code execution. + + The ``additional_parameters`` parameter can be used to pass additional flags + as command line options to the program configured to be used when sending mail + + --- `The PHP documentation about mail `_ + +We're killing it by preventing any extra options in additional_parameters. + +This family of vulnerabilities lead to various CVE, like: + +- `CVE-2017-7692 `_: Authenticated remote code execution in SquirrelMail +- `CVE-2016-10074 `_: remote code execution in SwiftMailer +- `CVE-2016-10033 `_: remote code execution in PHPMailer +- `CVE-2016-9920 `_: Unauthenticated remote code execution in Roundcube + +Session-cookie stealing via XSS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The goto payload for XSS is often to steal cookies. +Like *Suhosin*, we are encrypting the cookies with a secret key, the IP of the user +and its user-agent. This means that an attacker with an XSS won't be able to use +the stolen cookie, since he (often) can't spoof the IP address of the user. + +This feature is roughly the same than the `Suhosin one `_. + +Users behind the same IP address but with different browsers won't be able to use each other stolen cookies, +except if they can manage to guess the user agent. This isn't especially difficult, +but an invalid decryption will leave a trace in the logs. + +Finally, having a secret server-side key will prevent anyone (even the user himself) +from reading the content of the cookie, reducing the impact of an application storing sensitive data client-side. + +The encryption is done via the [tweetnacl library](https://tweetnacl.cr.yp.to/), +thus using curve25519, xsalsa20 and poly1305 for the encryption. We chose this +library because of its portability, simplicity and reduced size (a single `.h` and +`.c` file.). + +Remote code execution via file-upload +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some PHP applications allows users to upload contents, like avatars for a forum. +Unfortunately, sometimes, content validation isn't implemented properly (if at all), +meaning arbitrary file upload, often leading, contrary to what the documentation is saying, +to an arbitrary code execution. + + Not validating which file you operate on may mean that users can *access sensitive information* in other directories. + + --- `The PHP documentation about file uploads `_ + +We're killing it, like Suhosin, by automatically calling a script upon file upload, +if it returns something else than ``0``, the file will be removed (or stored in a quarantine, +for further analysis). + +We're recommending to use the `vld `_ project +inside the script to ensure the file doesn't contain any valid PHP code, with something like this: + +:: + + $ php -d vld.execute=0 -d vld.active=1 -d extension=vld.so $file + +Unserialize-related magic +^^^^^^^^^^^^^^^^^^^^^^^^^ + +PHP is able to *serialize* arbitrary objects, to easily store them. +Unfortunately, it's often possible to gain arbitrary code execution upon deserialization +of user-supplied serialized objects. + + Do not pass untrusted user input to ``unserialize()`` regardless of the options value of allowed_classes. + Unserialization can result in code being loaded and executed due to object instantiation and autoloading, + and a malicious user may be able to exploit this. + + --- `The PHP documentation about serialize `_ + +We're killing it by exploiting the fact that PHP will discard any garbage found at the end of a serialized object, +allowing us to simply append a `HMAC `_ +at the end of strings generated by the ``serialize``, +hence guaranteeing that any object deserialized came from the application, +and wasn't tampered with, + +We're not encrypting it, like we do with the cookies, +allowing this feature to be disabled (or switch into leaning mode) +without the need to invalidate any data. + +.. warning:: + + This feature can't be deployed on websites that already stored serialized + objects (ie. in database), since they are missing the HMAC, and thus will be detected as + an attack. If you're in this situation, you should use this feature with the + ``simulation`` mode, and switch it off once you don't have any messages in your + logs. + +A nice side-effect of this feature is that it'll defeat various memory corruption +issues related to the complexity of ``unserialize``'s implementation, +and the amount of control if provides to an attacker, like `CVE-2016-9137, CVE-2016-9138 `_, +`2016-7124 `_, `CVE-2016-5771 and CVE-2016-5773 `_, … + +This family of vulnerabilities lead to various CVE, like: + +- `CVE-2016-???? `_: Unauthenticated remote code execution in Observium (leading to remote root) +- `CVE-2016-5726 `_: Unauthenticated remote code execution in Simple Machines Forums +- `CVE-2016-4010 `_: Unauthenticated remote code execution in Magento +- `CVE-2017-2641 `_: Unauthenticated remote code execution in Moodle +- `CVE-2015-8562 `_: Unauthenticated remote code execution in Joomla +- `CVE-2015-7808 `_: Unauthenticated remote code execution in vBulletin +- `CVE-2014-1691 `_: Unauthenticated remote code execution in Horde +- `CVE-2012-5692 `_: Unauthenticated remote code execution in IP.Board + + + +Weak-PRNG via rand/mt_rand +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The functions ``rand`` and ``mt_rand`` are often used to generate random numbers used +in sensitive context, like password generation, token creation, … +Unfortunately, as said in the documentation, the quality of their entropy is low, +leading to the generation of guessable values. + + This function does not generate cryptographically secure values, and should not be used for cryptographic purposes. + + --- `The PHP documentation about rand `_ + +We're addressing this issue by replacing every call to ``rand`` and ``mt_rand`` with +a call to the ``random_int``, a `CSPRNG `_. + +It's worth noting that the PHP documentation contains the following warning: + + ``min`` ``max`` range must be within the range ``getrandmax()``. i.e. ``(max - min) <= getrandmax()``. + Otherwise, ``rand()`` may return poor-quality random numbers. + + --- `The PHP documentation about rand `_ + +This is of course addressed as well by the ``harden_rand`` feature. + +.. warning:: + + Activating this feature will raise an `Error `_ + exception if ``min`` is superior to ``max``, while the default dehaviour is simply to swap them. + +This family of vulnerabilities lead to various CVE, like: + +- `CVE-2015-5267 `_: Unauthenticated accounts takeover in in Moodle +- `CVE-2014-9624 `_: Captcha bypass in MantisBT +- `CVE-2014-6412 `_: Unauthenticated account takeover in Wordpress +- `CVE-2015-???? `_: Unauthenticated accounts takeover in Concrete5 +- `CVE-2013-6386 `_: Unauthenticated accounts takeover in Drupal +- `CVE-2010-???? `_: Unauthenticated accounts takeover in MyBB +- `CVE-2008-4102 `_: Unauthenticated accounts takeover in Joomla +- `CVE-2006-0632 `_: Unauthenticated account takeover in phpBB + +XXE +^^^ + +Despite the documentation saying nothing about this class of vulnerabilities, +`XML eXternal Entitiy `_ (XXE) are often leading to arbitrary file reading, SSRF, and sometimes even arbitrary +code execution. + +XML documents can contain a `Document Type Definition `_ (DTD), +enabling definition of XML entities. It's possible to define an (external) entity by an +URI, that the parser will access, and embed its content back into the document +for further processing. + +For example, providing an url like ``file:///etc/passwd`` will read +this file's content, and since it's not valid XML, the application +will spit it out in an error message, thus leaking its content. + +We're killing this class of vulnerabilities by calling +the `libxml_disable_entity_loader `_ +function with its parameter set to ``true`` at startup, +and then *nop'ing* it, so it won't do anything if ever called again. + +This family of vulnerabilities lead to various CVE, like: + +- `CVE-2015-5161 `_: Unauthenticated arbitrary file disclosure on Magento +- `CVE-2014-8790 `_: Unauthenticated remote code execution in GetSimple CMS +- `CVE-2011-4107 `_: Authenticated local file disclosure in PHPMyAdmin + + +Cookie stealing via HTTP MITM +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While it's possible to set the ``secure`` flag on cookies to prevent them from being +transmitted over HTTP, and only allow its transmission over HTTPS. +Snuffleupagus can automatically set this flag if the client is accessing the +website over a secure connection. + +This behaviour is suggested in the documentation: + + On the server-side, it's on the programmer to send this kind of cookie only + on secure connection (e.g. with respect to ``$_SERVER["HTTPS"]``). + + --- `The PHP documentation about setcookie `_ + + +Exploitation, post-exploitation and general hardening +----------------------------------------------------- + +Virtual-patching +^^^^^^^^^^^^^^^^ + +PHP itself exposes a number of functions that might be considered **dangerous** and that have limited legitimate use cases. +``system()``, ``exec()``, ``dlopen()`` - for example - fall into this category. By default, PHP only allows to globally disable some functions. + + +However, (ie. ``system()``) they might have legitimate use cases in processes such as self upgrade etc., making it impossible to effectively +disable them - at the risk of breaking critical features. + +SnuffleuPagus allows the user to restrict usage of specific functions per files, or per +files with a matching (sha256) hash, thus allowing the use of such functions **only** in the intended places. + +Furthermore, running the `following script `_ will generate an hash and line-based whitelist +of dangerous functions, droping them everywhere else: + + +.. literalinclude:: ../../scripts/generate_rules.php + :language: php + + +The intent is to make post-exploitation process (such as backdooring of legitimate code, or RAT usage) a lot harder for the attacker. + + +Global strict mode +^^^^^^^^^^^^^^^^^^ + +By default, PHP will coerce values of the wrong type into the expected one +if possible. For example, if a function expecting an integer is given a string, +it will be coerced in an integer. + +PHP7 introduced a **strict mode**, in which variables won't be coerced anymore, +and a `TypeError `_ exception will +be raised if the types aren't matching. +`Scalar type declarations `_ +are optional, but you don't have to used them in your code to benefit from them, +since every internal function from php has them. + +This option provide a switch to globally activate this strict mode, +helping to uncover vulnerabilities like the classical +`strcmp bypass `_, +and various other types mismatch. + +This feature is largely inspired from the +`autostrict `_ module from `krakjoe `_. + + +Preventing execution of writable PHP files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If an attacker manages to upload an arbitrary file or to modify an existing one, +odds are that (thanks to the default `umask `_) +this file is writable by the PHP process. + +Snuffleupagus can prevent the execution of this kind of files. A good practise +would be to use a different user to run PHP than for administrating the website, +and using this feature to lock this up. + + + +Dumping capabilities +^^^^^^^^^^^^^^^^^^^^ +It's possible to apply the ``dump(:str)`` filter to any virtual-patching rule, +to dump the complete web request, along with the filename and the corresponding +line number. By using the *right* set of restrictive rules (or by using the +*overly* restrictives ones in ``simulation`` mode), you might be able +to gather interesting vulnerabilities used against your website. + + +Misc low-hanging fruits in the default configuration file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Snuffleupagus is shipping with a default configuration file, containing +various examples and ideas of things that you might want to enable (or not). + +Available functions recon +""""""""""""""""""""""""" + +After compromising a website, most of the time, the attacker does some recon +within its webshell, to check which functions are available to execute arbitrary code, +since it's not uncommon for some web-hoster to disable things like ``system`` or ``passthru``, +or to check if mitigations are enabled, like ``open_basedir``. +This behaviour can be detected by preventing the execution of functions like ``ini_get`` +or ``is_callable`` with *suspicious* parameters. + +``chmod`` hardening +""""""""""""""""""" + +Some PHP applications are using broad rights when using the ``chmod`` function, +like the infamous ``chmod(777)`` command, effectively making the file writable by everyone. +Snuffleupagus is preventing this kind of behaviour by restricting the parameters +than can be passer to ``chmod``. + +Arbitrary file inclusion hardening +"""""""""""""""""""""""""""""""""" + +Arbitrary file inclusion is a common vulnerability, that might be detected +by preventing the use of anything else than a whitelist of extensions in calls +to ``include`` or ``require``. + +*Cheap* SQL injections detection +"""""""""""""""""""""""""""""""" + +In some SQL injections, attackers might need to use comments, a feature that is +often not used in production system, so it might be a good idea to filter +queries that contains some. The same filtering idea can be used against +SQL functions that are frequently used in SQL injections, like ``sleep``, ``benchmark`` +or strings like ``version_info``. + +Still about SQL injections, if a function performing a query returns ``FALSE`` +(indicating an error), it might be useful to dump the request for further analysis. + diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 0000000..8a9c340 --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,30 @@ +Snuffleupagus +============= + +Snuffleupagus is a `PHP 7+ `_ module designed to drastically raising the cost of +attacks against website, by killing entire bug classes, and also providing a +powerful virtual-patching system, allowing administrator to fix specific +vulnerabilities and audit suspicious behaviours without having to touch the PHP code. + +Documentation +------------- + +.. toctree:: + :maxdepth: 2 + + features + installation + config + download + faq + papers + +Greetings +--------- +We would like to thank the following people: + +- `Suhosin `_, for paving the way. +- The people behind the `RIPS `_ scanner for their ground breaking work +- `NBS System `_, for creating and open-sourcing this piece of software +- `Websec.fr `_, for keeping our interesting vulnerabilities alive +- Web developers around the world, for being so imaginative diff --git a/doc/source/installation.rst b/doc/source/installation.rst new file mode 100644 index 0000000..779008d --- /dev/null +++ b/doc/source/installation.rst @@ -0,0 +1,33 @@ +Installation +============ + +Snuffleupagus is tested against various PHP 7+ versions: XXX + +Manual installation +------------------- + +Depending on the system, we might already offer binary packages. +You can check our :doc:`download`. In that case you only need to activate +the extension inside your ``php.ini`` and to configure it. + + +Quickstart +^^^^^^^^^^ + +:: + + git clone https://github.com/nbs-system/snuffleupagus + cd snuffleupagus + phpize + ./configure + make + make install + +This should install ``snuffleupagus.so`` file in your extension directory. The final step is adding a load directive to ``php.ini``:: + + extension=snuffleupagus.so + +Upgrading +--------- + +Upgrading the Snuffleupagus is as simple as recompiling it (or using a binary), replacing the file and restarting your webserver. diff --git a/doc/source/papers.rst b/doc/source/papers.rst new file mode 100644 index 0000000..d028b14 --- /dev/null +++ b/doc/source/papers.rst @@ -0,0 +1,16 @@ +Propaganda +========== + +This pages lists various mentions, articles and presentations about Snuffleupagus. + +Talks +----- + +- `BerlinSide0x08 `_ - `Php7 Nightmares `_ - 2017-05-28 +- `Hack.lu `_ - soon™ - 2017-10-18 +- `BlackAlps `_ - soon™ - 2017-11-16 + +Articles +-------- + +- `Killing php bug classes at berlinsides `_ - 2017-06-05 \ No newline at end of file -- cgit v1.3