summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorSebastien Blot2017-09-20 10:11:01 +0200
committerSebastien Blot2017-09-20 10:11:01 +0200
commit868f96c759b6650d88ff9f4fbc5c048302134248 (patch)
treec0de0af318bf77a8959164ef11aeeeb2b7bab294 /doc
Initial import
Diffstat (limited to 'doc')
-rw-r--r--doc/Makefile20
-rw-r--r--doc/source/_static/custom.css4
-rw-r--r--doc/source/_static/sp.jpgbin0 -> 36559 bytes
-rw-r--r--doc/source/conf.py178
-rw-r--r--doc/source/config.rst283
-rw-r--r--doc/source/download.rst16
-rw-r--r--doc/source/faq.rst196
-rw-r--r--doc/source/features.rst352
-rw-r--r--doc/source/index.rst30
-rw-r--r--doc/source/installation.rst33
-rw-r--r--doc/source/papers.rst16
11 files changed, 1128 insertions, 0 deletions
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..7355011
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,20 @@
1# Minimal makefile for Sphinx documentation
2#
3
4# You can set these variables from the command line.
5SPHINXOPTS =
6SPHINXBUILD = sphinx-build
7SPHINXPROJ = Snuffleupagus
8SOURCEDIR = source
9BUILDDIR = build
10
11# Put it first so that "make" without argument is like "make help".
12help:
13 @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14
15.PHONY: help Makefile
16
17# Catch-all target: route all unknown targets to Sphinx using the new
18# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19%: Makefile
20 @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file
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 @@
1blockquote {
2 border-left: 2px solid #999;
3 padding-left: 20px;
4} \ 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
--- /dev/null
+++ b/doc/source/_static/sp.jpg
Binary files 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 @@
1# -*- coding: utf-8 -*-
2#
3# Snuffleupagus documentation build configuration file, created by
4# sphinx-quickstart on Tue Jun 27 14:15:46 2017.
5#
6# This file is execfile()d with the current directory set to its
7# containing dir.
8#
9# Note that not all possible configuration values are present in this
10# autogenerated file.
11#
12# All configuration values have a default; values that are commented out
13# serve to show the default.
14
15# If extensions (or modules to document with autodoc) are in another directory,
16# add these directories to sys.path here. If the directory is relative to the
17# documentation root, use os.path.abspath to make it absolute, like shown here.
18#
19# import os
20# import sys
21# sys.path.insert(0, os.path.abspath('.'))
22from datetime import datetime
23
24
25# -- General configuration ------------------------------------------------
26
27# If your documentation needs a minimal Sphinx version, state it here.
28#
29# needs_sphinx = '1.0'
30
31# Add any Sphinx extension module names here, as strings. They can be
32# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
33# ones.
34#extensions = ['sphinx.ext.githubpages']
35
36# Add any paths that contain templates here, relative to this directory.
37templates_path = ['_templates']
38
39# The suffix(es) of source filenames.
40# You can specify multiple suffix as a list of string:
41#
42# source_suffix = ['.rst', '.md']
43source_suffix = '.rst'
44
45# The master toctree document.
46master_doc = 'index'
47
48# General information about the project.
49project = u'Snuffleupagus'
50copyright = u'%d, NBS System' % datetime.now().year
51author = u'Sebastien Blot & Julien Voisin'
52
53# The version info for the project you're documenting, acts as replacement for
54# |version| and |release|, also used in various other places throughout the
55# built documents.
56#
57# The short X.Y version.
58version = u'0.1'
59# The full version, including alpha/beta/rc tags.
60release = u'Public Alpha'
61
62# The language for content autogenerated by Sphinx. Refer to documentation
63# for a list of supported languages.
64#
65# This is also used if you do content translation via gettext catalogs.
66# Usually you set "language" from the command line for these cases.
67language = None
68
69# List of patterns, relative to source directory, that match files and
70# directories to ignore when looking for source files.
71# This patterns also effect to html_static_path and html_extra_path
72exclude_patterns = []
73
74# The name of the Pygments (syntax highlighting) style to use.
75pygments_style = 'manni'
76
77# If true, `todo` and `todoList` produce output, else they produce nothing.
78todo_include_todos = False
79
80
81# -- Options for HTML output ----------------------------------------------
82
83# The theme to use for HTML and HTML Help pages. See the documentation for
84# a list of builtin themes.
85#
86html_theme = 'alabaster'
87
88# Theme options are theme-specific and customize the look and feel of a theme
89# further. For a list of options available for each theme, see the
90# documentation.
91#
92
93html_sidebars = {
94 '**': [
95 'about.html',
96 'navigation.html',
97 'relations.html',
98 'searchbox.html',
99 #'donate.html',
100 ]
101}
102html_theme_options = {
103 'logo': './sp.jpg',
104 #'description': '<br>Killing bug-classes in PHP 7, virtual-patching the rest.',
105 #'fixed_sidebar': True,
106 'page_width': '60%',
107 'show_powered_by': False,
108 }
109
110sidebar_collapse = True
111
112# Add any paths that contain custom static files (such as style sheets) here,
113# relative to this directory. They are copied after the builtin static files,
114# so a file named "default.css" will overwrite the builtin "default.css".
115html_static_path = ['_static']
116
117#html_logo = './sp.png'
118
119html_show_sphinx = False
120
121# -- Options for HTMLHelp output ------------------------------------------
122
123# Output file base name for HTML help builder.
124htmlhelp_basename = 'Snuffleupagusdoc'
125
126
127# -- Options for LaTeX output ---------------------------------------------
128
129latex_elements = {
130 # The paper size ('letterpaper' or 'a4paper').
131 #
132 # 'papersize': 'letterpaper',
133
134 # The font size ('10pt', '11pt' or '12pt').
135 #
136 # 'pointsize': '10pt',
137
138 # Additional stuff for the LaTeX preamble.
139 #
140 # 'preamble': '',
141
142 # Latex figure (float) alignment
143 #
144 # 'figure_align': 'htbp',
145}
146
147# Grouping the document tree into LaTeX files. List of tuples
148# (source start file, target name, title,
149# author, documentclass [howto, manual, or own class]).
150latex_documents = [
151 (master_doc, 'Snuffleupagus.tex', u'Snuffleupagus Documentation',
152 u'Sebastien Blot \\& Julien Voisin', 'manual'),
153]
154
155
156# -- Options for manual page output ---------------------------------------
157
158# One entry per manual page. List of tuples
159# (source start file, name, description, authors, manual section).
160man_pages = [
161 (master_doc, 'snuffleupagus', u'Snuffleupagus Documentation',
162 [author], 1)
163]
164
165
166# -- Options for Texinfo output -------------------------------------------
167
168# Grouping the document tree into Texinfo files. List of tuples
169# (source start file, target name, title, author,
170# dir menu entry, description, category)
171texinfo_documents = [
172 (master_doc, 'Snuffleupagus', u'Snuffleupagus Documentation',
173 author, 'Snuffleupagus', 'One line description of project.',
174 'Miscellaneous'),
175]
176
177
178
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 @@
1Configuration
2=============
3
4Since PHP *ini-like* configuration model isn't flexible enough,
5Snuffleupagus is using its own format.
6
7Options are chainable by using dots (``.``), and string parameters
8**must** be quoted, while booleans and integers aren't.
9
10Comments are prefixed either with ``#``, or ``;``.
11
12Some rules applies in a specific ``function`` (context), on a specific ``variable``
13(data), like ``disable_functions``, others can only be enabled/disabled, like
14``harden_random``.
15
16.. warning::
17
18 Careful, a wrongly configured Snuffleupagus might break your website.
19 It's up to you to understand its :doc:`features <features>`,
20 read the present documentation about how to configure them,
21 evaluate your threat model, and write your configuration file accordingly.
22
23The rules are evaluated in the order that they are written, and the **first** one
24to match will terminate the evaluation (except for rules in simulation mode).
25
26Bugclass-killer features
27------------------------
28
29global_strict
30^^^^^^^^^^^^^
31`default: disabled`
32
33``global_strict`` will enable the `strict <https://secure.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration.strict>`_ mode globally,
34forcing PHP to throw a `TypeError <https://secure.php.net/manual/en/class.typeerror.php>`_
35exception if an argument type being passed to a function does not match its corresponding declared parameter type.
36
37It can either be ``enabled`` or ``disabled``
38
39::
40
41 sp.global_strict.disable();
42 sp.global_strict.enable();
43
44harden_random
45^^^^^^^^^^^^^
46 * `default: enabled`
47 * `more <features.html#weak-prng-via-rand-mt-rand>`__
48
49``harden_random`` will silently replace the insecure `rand <https://secure.php.net/manual/en/function.rand.php>`_
50and `mt_rand <https://secure.php.net/manual/en/function.mt-rand.php>`_ functions with
51the secure PRNG `random_int <https://secure.php.net/manual/en/function.random-int.php>`_.
52
53It can either be ``enabled`` or ``disabled``.
54
55::
56
57 sp.harden_random.enable();
58 sp.harden_random.disable();
59
60.. _config_global:
61
62global
63^^^^^^
64
65This configuration variable contain parameters that are used by other ones:
66
67- ``secret_key``: A secret key used by various cryptographic features,
68 like `cookies protection <features.html#session-cookie-stealing-via-xss>`__ or `unserialize protection <features.html#unserialize-related-magic>`__,
69 so do make sure that it's random and long enough.
70 You can generate it with something like this: ``head -c 256 /dev/urandom | tr -dc 'a-zA-Z0-9'``.
71
72::
73
74 sp.global.secret_key("44239bd400aa82e125337c9d4eb8315767411ccd");
75
76unserialize_hmac
77^^^^^^^^^^^^^^^^
78 * `default: disabled`
79 * `more <features.html#unserialize-related-magic>`__
80
81``unserialize_hmac`` will add integrity check to ``unserialize`` calls, preventing
82abritrary code execution in their context.
83
84::
85
86 sp.unserialize_hmac.enable();
87 sp.unserialize_hmac.disable();
88
89
90auto_cookie_secure
91^^^^^^^^^^^^^^^^^^
92 * `default: disabled`
93 * `more <features.html#session-cookie-stealing-via-xss>`__
94
95``auto_cookie_secure`` will automatically mark cookies as `secure <https://en.wikipedia.org/wiki/HTTP_cookie#Secure_cookie>`_
96when the web page is requested over HTTPS.
97
98It can either be ``enabled`` or ``disabled``.
99
100::
101
102 sp.auto_cookie_secure.enable();
103 sp.auto_cookie_secure.disable();
104
105cookie_encryption
106^^^^^^^^^^^^^^^^^
107 * `default: disabled`
108 * `more <features.html#session-cookie-stealing-via-xss>`__
109
110.. warning::
111
112 To use this feature, you **must** set the :ref:`global.secret_key <config_global>` variable.
113 This design decision prevents attacker from
114 `trivially bruteforcing <https://www.idontplaydarts.com/2011/11/decrypting-suhosin-sessions-and-cookies/>`_
115 session cookies.
116
117``cookie_secure`` will activate transparent encryption of specific cookies.
118
119It can either be ``enabled`` or ``disabled``.
120
121::
122
123 sp.cookie_encryption.cookie("my_cookie_name");
124 sp.cookie_encryption.cookie("another_cookie_name");
125
126
127readonly_exec
128^^^^^^^^^^^^^
129 * `default: disabled`
130
131``readonly_exec`` will prevent the execution of writable PHP files.
132
133It can either be ``enabled`` or ``disabled``.
134
135::
136
137 sp.readonly_exec.enable();
138
139upload_validation
140^^^^^^^^^^^^^^^^^
141 * `default: disabled`
142 * `more <features.html#remote-code-execution-via-file-upload>`__
143
144``upload_validation`` will call a given script upon a file upload, with the path
145to the file being uploaded as argument, and various information about it in the environment:
146
147* ``SP_FILENAME``: the name of the uploaded file
148* ``SP_FILESIZE``: the size of the file being uploaded
149* ``SP_REMOTE_ADDR``: the ip address of the uploader
150* ``SP_CURRENT_FILE``: the current file being executed
151
152This feature can be used, for example, to check if an uploaded file contains php
153code, with something like `vld <https://derickrethans.nl/projects.html#vld>`_
154(``php -d vld.execute=0 -d vld.active=1 -d extension=vld.so yourfile.php``).
155
156The upload will be **allowed** if the script return the value ``0``. Every other
157value will prevent the file from being uploaded.
158
159::
160
161 sp.upload_validation.script("/var/www/is_valid_php.py").enable();
162
163
164disable_xxe
165^^^^^^^^^^^
166 * `default: enabled`
167 * `more <features.html#xxe>`__
168
169``disable_xxe`` will prevent XXE attacks by disabling the loading of external entities (``libxml_disable_entity_loader``) in the XML parser.
170
171::
172
173 sp.disable_xxe.enable();
174
175
176Virtual-patching
177----------------
178
179Snuffleupagus provides virtual-patching, via the ``disable_functions`` directive, allowing you to stop or control dangerous behaviours.
180Admitting you have a call to ``system()`` that lacks proper user-input validation, thus leading to an **RCE**, this might be the right tool.
181
182::
183
184 # Allow `id.php` to restrict system() calls to `id`
185 sp.disable_functions.function("system").filename("id.php").param("cmd").value("id").allow();
186 sp.disable_functions.function("system").filename("id.php").drop()
187
188Of course, this is a trivial example, and a lot can be achieved with this feature, as you will see below.
189
190
191Filters
192^^^^^^^
193
194- ``alias(:str)``: human-readable description of the rule
195- ``cidr(ip/mask:str)``: match on the client's `cidr <https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing>`_
196- ``filename(name:str)``: match in the file ``name``
197- ``filename_r(regexp:str)``: the file name matching the ``regexp``
198- ``function(name:str)``: match on function ``name``
199- ``function_r(regexp:str)``: the function matching the ``regexp``
200- ``hash(:str)``: match on the file's `sha256 <https://en.wikipedia.org/wiki/SHA-2>`_ sum
201- ``param(name:str)``: match on the function's parameter ``name``
202- ``param_r(regexp:str)``: match on the function's parameter ``regexp``
203- ``param_type(type:str)``: match on the function's parameter ``type``
204- ``ret(value:str)``: match on the function's return ``value``
205- ``ret_r(regexp:str)``: match with a ``regexp`` on the function's return
206- ``ret_type(type_name:str)``: match on the ``type_name`` of the function's return value
207- ``value(:str)``: match on a litteral value
208- ``value_r(:regexp)``: match on a value matching the ``regexp``
209- ``var(name:str)``: match on a **local variable** ``name``
210
211The ``type`` must be one of the following values:
212
213- ``FALSE``: for boolean false
214- ``TRUE``: for boolean true
215- ``NULL``: for the **null** value
216- ``LONG``: for a long (also know as ``integer``) value
217- ``DOUBLE``: for a **double** (also known as ``float``) value
218- ``STRING``: for a string
219- ``OBJECT``: for a object
220- ``ARRAY``: for an array
221- ``RESOURCE``: for a resource
222
223Actions
224^^^^^^^
225
226- ``allow()``: **allow** the request if the rule matches
227- ``drop()``: **drop** the request if the rule matches
228- ``dump(directory:str)``: dump the request in the ``directory`` if it matches the rule
229- ``simulation()``: enabled the simulation mode
230
231Details
232^^^^^^^
233
234The ``function`` filter is able to do various dereferencing:
235
236- ``function("AwesomeClass::my_method")`` will match in the method ``my_method`` in the class ``AwesomeClass``
237
238The ``param`` filter is also able to do some dereferencing:
239
240- ``param(foo[bar])`` will get match on the value corresponding to the ``bar`` key in the hashtable ``foo``.
241 Remember that in PHP, almost every data structure is a hashtable. You can of course nest this like
242 ``param(foo[bar][baz][batman])``.
243- The ``var`` filter will walk the calltrace until it finds the variable's name, or the end of it,
244 allowing to match on global variables: ``.var("_GET[param]")`` will match on the GET parameter ``param``.
245
246For clarity's sake, the presence of the ``allow`` or ``drop`` action is **mandatory**.
247
248.. warning::
249
250 When you're writing rules, please do keep in mind that the **order matters**.
251 For example, if you're denying a call to ``system()`` and then allowing it in a
252 more narrowed way later, the call will be denied,
253 because it'll match the deny first.
254
255If you're paranoid, we're providing a php script to automatically generate
256hash of files containing dangerous functions,
257and blacklisting them everywhere else.
258
259Examples
260^^^^^^^^
261
262Evaluation order of rules
263"""""""""""""""""""""""""
264
265The following rules will:
266
2671. Allow calls to ``system("id")``
2682. Issue a trace in the logs on calls to ``system`` with its parameters starting with ``ping``,
269 and pursuing evaluation of the remaining rules.
2703. Drop calls to ``system``.
271
272
273::
274
275 sp.disable_functions.function("system").param("cmd").value("id").allow();
276 sp.disable_functions.function("system").param("cmd").value_r("^ping").drop().simulation();
277 sp.disable_functions.function("system").param("cmd").drop();
278
279Miscellaneous examples
280""""""""""""""""""""""
281
282.. literalinclude:: ../../config/examples.ini
283 :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 @@
1Download
2========
3
4Debian
5------
6
7
8Ubuntu
9------
10
11
12Source code
13-----------
14
15::
16 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 @@
1FAQ
2===
3
4General
5-------
6
7What is Snuffleupagus?
8""""""""""""""""""""""
9
10Snuffleupagus is a `PHP7+ <http://php.net/manual/en/migration70.php>`_
11module designed to drastically raising the cost of attacks against website,
12by killing entire bug classes, and also providing a powerful virtual-patching system,
13allowing administrator to fix specific vulnerabilities without having to touch the PHP code.
14
15
16Where does the name *Snuffeupagus* comes from?
17""""""""""""""""""""""""""""""""""""""""""""""
18
19 Aloysius Snuffleupagus, more commonly known as Mr. Snuffleupagus, Snuffleupagus
20 or Snuffy for short, is one of the characters on Sesame Street,
21 the educational television program for young children.
22
23 He was created as a woolly mammoth, without tusks or (visible) ears,
24 and has a long thick pointed tail, similar in shape to that of a dinosaur
25 or other reptile. He has long thick brown hair and a trunk, or "snuffle",
26 that drags along the ground. He is Big Bird's best friend and
27 has a baby sister named Alice. He also attends "Snufflegarten".
28
29 --- `Wikipedia <https://en.wikipedia.org/wiki/Mr._Snuffleupagus>`_
30
31
32Why is Snuffleupagus called Snuffleupagus?
33""""""""""""""""""""""""""""""""""""""""""
34
35Like PHP's `ElePHPant <https://secure.php.net/elephpant.php>`_,
36we thought that using an elephant as a mascot would be a great idea.
37
38
39Why did you write Snuffleupagus?
40""""""""""""""""""""""""""""""""
41
42We're working for `NBS System <https://nbs-system.com/en/>`__,
43a web hosting company (meaning that we're dealing with PHP code all day long),
44with a strong focus on security. We do have hardening
45(kernel, `WAF <https://naxsi.org>`_, `IDS <https://en.wikipedia.org/wiki/Intrusion_detection_system>`_, …)
46below the web stack, but most of the time, when a website is compromised,
47it's either to send ads, spam, deface it, steal data, …
48This is why we need to harden the website itself too, but we can't touch its
49source code.
50
51Why not Suhosin?
52""""""""""""""""
53
54We're huge fans of `Suhosin <https://suhosin.org>`_, unfortunately:
55
56- it doesn't work very well on PHP 7
57- it has some oudated features and misses new ones
58- it doesn't cope very well with our various industrialization needs
59- it has some shortcomings by design
60
61We're using the `disable_function <https://secure.php.net/manual/en/ini.core.php#ini.disable-functions>`_
62directive, but unfortunately, it doesn't provide enough usable granularity (guess how many CMS are using
63``system`` to do various mandatory maintenance tasks…).
64
65This is why we decided to write our own hardening module, in the spirit of Suhosin,
66via virtual-patching support, and other cool new features.
67
68What license is Snuffleupagus under and why?
69""""""""""""""""""""""""""""""""""""""""""""
70
71Snuffleupagus is licensed under the `LGPL <https://www.gnu.org/copyleft/lesser.html>`_,
72and is developed by the fine people from `NBS System <https://nbs-system.com/>`__.
73
74We chose the LGPL because we don't care that much how you're using Snuffleupagus,
75but we'd like to force people to make their improvements/contributions
76available to everyone.
77
78Should I use Snuffleupagus?
79"""""""""""""""""""""""""""
80
81Yes.
82
83Even if you're not using the virtual-patching capabilities, Snuffleupagus comes
84with various passive features that won't break your website while killing numerous vulnerabilities.
85
86Please keep in mind that you are not only protecting yourself and your users/customers,
87but also other people on the internet that might be attacked by your server if
88it becomes compromised.
89
90How mature is this project?
91"""""""""""""""""""""""""""
92
93This project was floating around since early 2016, and we did the first commit
94the 28ᵗʰ of December of the same year. We're currently in a private alpha phase,
95finding and fixing as much bugs as possible with the help of friends.
96
97Are you saying that PHP isn't secure?
98"""""""""""""""""""""""""""""""""""""
99
100We don't like PHP's approach of security; namely (sometimes) adding warnings
101in the documentation and trusting the developer to not do any mistake,
102instead of focusing on the root cause, and killing the
103bug class one for all.
104
105Moreover, it seems that the current attitude toward security in the PHP world
106is to `blame the user <https://externals.io/message/100147>`_ instead of acknowledging
107issues, as stated in their `documentation <https://wiki.php.net/security#not_a_security_issue>`_.
108We do think that an security issue that "requires the use of code or settings known to be insecure"
109is still a security issue, and should be treated as such.
110
111Installation and configuration
112------------------------------
113
114Can snuffleupagus break my application?
115"""""""""""""""""""""""""""""""""""""""
116Yes.
117
118Some options won't break anything, like ``harden_rand``, but some like ``global_strict``
119or overly-restrictives virtual-patching rules might pretty well break your website.
120It's up to you to configure Snuffleupaggus accordingly to your needs.
121
122You can also enable the ``simulation`` mode on features that you're not sure about,
123to see what would snuffleupagus do to your application, before activating them for good.
124
125How can I find out the problem when my application breaks?
126""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
127
128By checking the logs; Snuffleupagus systematically prefix them with ``[snuffleupagus]``.
129
130
131Does Snuffleupagus run on Windows?
132""""""""""""""""""""""""""""""""""
133No idea.
134
135
136Will Snuffleupagus run on my old PHP 5?
137"""""""""""""""""""""""""""""""""""""""
138No.
139
140Since PHP5 `will be deprecated at the end of 2018 <http://php.net/supported-versions.php>`_,
141you should think about moving to PHP7 anyway. You can (and should) use
142`Suhosin <https://suhosin.org>`_ in the meantime.
143
144Help and support
145----------------
146
147I found a security issue
148""""""""""""""""""""""""
149If you believe you have found a security issue affecting Snuffleupagus,
150then we would be more than happy to hear from you!
151
152We promise to treat any reported issue seriously and,
153if the investigation confirms it affects Snuffleupagus,
154to patch it within a reasonable time,
155release a public announcement that describes the issue,
156discuss potential impact of the vulnerability,
157reference applicable patches or workarounds,
158and credit the discoverer.
159
160Please send it us a mail to the ``snuffleupagus`` user,
161on ``nbs-system.com``.
162
163I found a bug. How can I report it?
164"""""""""""""""""""""""""""""""""""
165We do have an issue tracker on `Github <https://github.com/nbs-system/snuffleupagus/issues>`_.
166Please make sure to include as much information as possible when reporting your issue,
167such as your operating system, your version of PHP 7, your version of snuffleupagus,
168your logs, the problematic php code, the request, a brief description, … long story short,
169give us everything that you can.
170
171Where can I find even more help?
172""""""""""""""""""""""""""""""""
173The :doc:`configuration page <config>` might be what you're looking for.
174If you're adventurous, you can also check the `issue tracker <https://github.com/nbs-system/snuffleupagus/issues/?q=is%3Aissue>`_
175(make sure to check the closed issues too).
176
177I need professional support for my company.
178"""""""""""""""""""""""""""""""""""""""""""
179Contact `NBS System <https://nbs-system.com>`_.
180
181Unimplemented mitigations and abandoned ideas
182---------------------------------------------
183
184Contant time comparisons
185""""""""""""""""""""""""
186We didn't manage to perform time-based side-channel attacks on strings
187against real world PHP application, and the results that we gathered on
188tailored test cases weren't concluding: for simplicity's sake, we chose
189to not implement a mitigation against this class of attacks.
190
191We would be happy to be proven wrong, and reconsider implementing this feature,
192if someone can manage to get better results than us.
193
194The possibility of having this natively in PHP has
195`been discussed <https://marc.info/?l=php-internals&m=141692988212413&w=2>`_,
196but 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 @@
1Features
2========
3
4Snuffleupagus has a lot of features that can be divided in two main categories: bug-classes
5killers and virtual-patching. The first category provides primitives to kill various
6bug families (like arbitrary code execution via ``unserialize`` for example) or rise the
7cost of exploitation, the second one is a highly configurable system to patch functions in php itself.
8
9Bug classes killed
10------------------
11
12``system`` injections
13^^^^^^^^^^^^^^^^^^^^^
14
15The ``system`` function execute an external program and displays the output.
16It's used to interract with various external tools, like file-format converters for example.
17Unfortunately, passing user-controlled parameters to it often leads to an arbitrary command execution.
18
19 When allowing user-supplied data to be passed to this function,
20 use `escapeshellarg()` or `escapeshellcmd()` to ensure that users cannot trick
21 the system into executing arbitrary commands.
22
23 --- `The PHP documentation about system <https://secure.php.net/manual/en/function.system.php>`_
24
25We're kind of killing it by filtering the ``$``, ``|``, ``;``, ````` and ``&`` chars in our
26default configuration, making it a lot harder for an attacker to inject arbitrary commands.
27
28This family of vulnerabilities lead to various CVE, like:
29
30- `CVE-2017-7981 <https://tuleap.net/plugins/tracker/?aid=10159>`_: Authenticated remote code execution on Tuleap
31- `CVE-2014-4688 <https://www.pfsense.org/security/advisories/pfSense-SA-14_10.webgui.asc>`_: Authenticated remote code execution on pfSense
32- `CVE-2014-1610 <https://www.rapid7.com/db/modules/exploit/multi/http/mediawiki_thumb>`_: Unauthenticated remote code execution on DokuWiki
33- `CVE-2013-3630 <https://www.rapid7.com/db/modules/exploit/multi/http/moodle_cmd_exec>`_: Authenticated remote code execution on Moodle
34- Every single shitty `modem/router/switch/IoT <https://twitter.com/internetofshit>`_.
35
36
37``mail``-related injections
38^^^^^^^^^^^^^^^^^^^^^^^^^^^
39
40This vulnerability is known `since 2011 <http://esec-pentest.sogeti.com/posts/2011/11/03/using-mail-for-remote-code-execution.html>`_,
41and was popularized by `RIPS <https://www.ripstech.com/blog/2016/roundcube-command-execution-via-email/>`_ in 2016.
42The last flag of the `mail` function can be used to pass various parameters to
43the underlying binary used to send emails: this can lead to an arbitrary file write,
44often meaning an arbitrary code execution.
45
46 The ``additional_parameters`` parameter can be used to pass additional flags
47 as command line options to the program configured to be used when sending mail
48
49 --- `The PHP documentation about mail <https://secure.php.net/manual/en/function.mail.php>`_
50
51We're killing it by preventing any extra options in additional_parameters.
52
53This family of vulnerabilities lead to various CVE, like:
54
55- `CVE-2017-7692 <https://legalhackers.com/advisories/SquirrelMail-Exploit-Remote-Code-Exec-CVE-2017-7692-Vuln.html>`_: Authenticated remote code execution in SquirrelMail
56- `CVE-2016-10074 <https://legalhackers.com/advisories/SwiftMailer-Exploit-Remote-Code-Exec-CVE-2016-10074-Vuln.html>`_: remote code execution in SwiftMailer
57- `CVE-2016-10033 <https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html>`_: remote code execution in PHPMailer
58- `CVE-2016-9920 <https://www.ripstech.com/blog/2016/roundcube-command-execution-via-email/>`_: Unauthenticated remote code execution in Roundcube
59
60Session-cookie stealing via XSS
61^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62
63The goto payload for XSS is often to steal cookies.
64Like *Suhosin*, we are encrypting the cookies with a secret key, the IP of the user
65and its user-agent. This means that an attacker with an XSS won't be able to use
66the stolen cookie, since he (often) can't spoof the IP address of the user.
67
68This feature is roughly the same than the `Suhosin one <https://suhosin.org/stories/configuration.html#transparent-encryption-options>`_.
69
70Users behind the same IP address but with different browsers won't be able to use each other stolen cookies,
71except if they can manage to guess the user agent. This isn't especially difficult,
72but an invalid decryption will leave a trace in the logs.
73
74Finally, having a secret server-side key will prevent anyone (even the user himself)
75from reading the content of the cookie, reducing the impact of an application storing sensitive data client-side.
76
77The encryption is done via the [tweetnacl library](https://tweetnacl.cr.yp.to/),
78thus using curve25519, xsalsa20 and poly1305 for the encryption. We chose this
79library because of its portability, simplicity and reduced size (a single `.h` and
80`.c` file.).
81
82Remote code execution via file-upload
83^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
84
85Some PHP applications allows users to upload contents, like avatars for a forum.
86Unfortunately, sometimes, content validation isn't implemented properly (if at all),
87meaning arbitrary file upload, often leading, contrary to what the documentation is saying,
88to an arbitrary code execution.
89
90 Not validating which file you operate on may mean that users can *access sensitive information* in other directories.
91
92 --- `The PHP documentation about file uploads <https://secure.php.net/manual/en/features.file-upload.common-pitfalls.php>`_
93
94We're killing it, like Suhosin, by automatically calling a script upon file upload,
95if it returns something else than ``0``, the file will be removed (or stored in a quarantine,
96for further analysis).
97
98We're recommending to use the `vld <https://derickrethans.nl/projects.html#vld>`_ project
99inside the script to ensure the file doesn't contain any valid PHP code, with something like this:
100
101::
102
103 $ php -d vld.execute=0 -d vld.active=1 -d extension=vld.so $file
104
105Unserialize-related magic
106^^^^^^^^^^^^^^^^^^^^^^^^^
107
108PHP is able to *serialize* arbitrary objects, to easily store them.
109Unfortunately, it's often possible to gain arbitrary code execution upon deserialization
110of user-supplied serialized objects.
111
112 Do not pass untrusted user input to ``unserialize()`` regardless of the options value of allowed_classes.
113 Unserialization can result in code being loaded and executed due to object instantiation and autoloading,
114 and a malicious user may be able to exploit this.
115
116 --- `The PHP documentation about serialize <https://secure.php.net/manual/en/function.serialize.php>`_
117
118We're killing it by exploiting the fact that PHP will discard any garbage found at the end of a serialized object,
119allowing us to simply append a `HMAC <https://en.wikipedia.org/wiki/Hash-based_message_authentication_code>`_
120at the end of strings generated by the ``serialize``,
121hence guaranteeing that any object deserialized came from the application,
122and wasn't tampered with,
123
124We're not encrypting it, like we do with the cookies,
125allowing this feature to be disabled (or switch into leaning mode)
126without the need to invalidate any data.
127
128.. warning::
129
130 This feature can't be deployed on websites that already stored serialized
131 objects (ie. in database), since they are missing the HMAC, and thus will be detected as
132 an attack. If you're in this situation, you should use this feature with the
133 ``simulation`` mode, and switch it off once you don't have any messages in your
134 logs.
135
136A nice side-effect of this feature is that it'll defeat various memory corruption
137issues related to the complexity of ``unserialize``'s implementation,
138and the amount of control if provides to an attacker, like `CVE-2016-9137, CVE-2016-9138 <https://bugs.php.net/bug.php?id=73147>`_,
139`2016-7124 <https://bugs.php.net/bug.php?id=72663>`_, `CVE-2016-5771 and CVE-2016-5773 <https://www.evonide.com/how-we-broke-php-hacked-pornhub-and-earned-20000-dollar/>`_, …
140
141This family of vulnerabilities lead to various CVE, like:
142
143- `CVE-2016-???? <https://www.computest.nl/advisories/CT-2016-1110_Observium.txt>`_: Unauthenticated remote code execution in Observium (leading to remote root)
144- `CVE-2016-5726 <http://seclists.org/oss-sec/2016/q2/521>`_: Unauthenticated remote code execution in Simple Machines Forums
145- `CVE-2016-4010 <http://netanelrub.in/2016/05/17/magento-unauthenticated-remote-code-execution/>`_: Unauthenticated remote code execution in Magento
146- `CVE-2017-2641 <http://netanelrub.in/2017/03/20/moodle-remote-code-execution/>`_: Unauthenticated remote code execution in Moodle
147- `CVE-2015-8562 <https://www.rapid7.com/db/modules/exploit/multi/http/joomla_http_header_rce>`_: Unauthenticated remote code execution in Joomla
148- `CVE-2015-7808 <https://www.rapid7.com/db/modules/exploit/multi/http/vbulletin_unserialize>`_: Unauthenticated remote code execution in vBulletin
149- `CVE-2014-1691 <http://seclists.org/oss-sec/2014/q1/153>`_: Unauthenticated remote code execution in Horde
150- `CVE-2012-5692 <https://www.rapid7.com/db/modules/exploit/unix/webapp/invision_pboard_unserialize_exec>`_: Unauthenticated remote code execution in IP.Board
151
152
153
154Weak-PRNG via rand/mt_rand
155^^^^^^^^^^^^^^^^^^^^^^^^^^
156
157The functions ``rand`` and ``mt_rand`` are often used to generate random numbers used
158in sensitive context, like password generation, token creation, …
159Unfortunately, as said in the documentation, the quality of their entropy is low,
160leading to the generation of guessable values.
161
162 This function does not generate cryptographically secure values, and should not be used for cryptographic purposes.
163
164 --- `The PHP documentation about rand <https://secure.php.net/manual/en/function.rand.php>`_
165
166We're addressing this issue by replacing every call to ``rand`` and ``mt_rand`` with
167a call to the ``random_int``, a `CSPRNG <https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator>`_.
168
169It's worth noting that the PHP documentation contains the following warning:
170
171 ``min`` ``max`` range must be within the range ``getrandmax()``. i.e. ``(max - min) <= getrandmax()``.
172 Otherwise, ``rand()`` may return poor-quality random numbers.
173
174 --- `The PHP documentation about rand <https://secure.php.net/manual/en/function.rand.php>`_
175
176This is of course addressed as well by the ``harden_rand`` feature.
177
178.. warning::
179
180 Activating this feature will raise an `Error <https://secure.php.net/manual/en/class.error.php>`_
181 exception if ``min`` is superior to ``max``, while the default dehaviour is simply to swap them.
182
183This family of vulnerabilities lead to various CVE, like:
184
185- `CVE-2015-5267 <https://moodle.org/mod/forum/discuss.php?d=320291>`_: Unauthenticated accounts takeover in in Moodle
186- `CVE-2014-9624 <https://www.mantisbt.org/bugs/view.php?id=17984>`_: Captcha bypass in MantisBT
187- `CVE-2014-6412 <https://core.trac.wordpress.org/ticket/28633>`_: Unauthenticated account takeover in Wordpress
188- `CVE-2015-???? <https://hackerone.com/reports/31171>`_: Unauthenticated accounts takeover in Concrete5
189- `CVE-2013-6386 <https://www.drupal.org/SA-CORE-2013-003>`_: Unauthenticated accounts takeover in Drupal
190- `CVE-2010-???? <http://www.sektioneins.com/advisories/advisory-022010-mybb-password-reset-weak-random-numbers-vulnerability.html>`_: Unauthenticated accounts takeover in MyBB
191- `CVE-2008-4102 <https://sektioneins.de/en/advisories/advisory-042008-joomla-weak-random-password-reset-token-vulnerability.html>`_: Unauthenticated accounts takeover in Joomla
192- `CVE-2006-0632 <https://www.cvedetails.com/cve/CVE-2006-0632/>`_: Unauthenticated account takeover in phpBB
193
194XXE
195^^^
196
197Despite the documentation saying nothing about this class of vulnerabilities,
198`XML eXternal Entitiy <https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing>`_ (XXE) are often leading to arbitrary file reading, SSRF, and sometimes even arbitrary
199code execution.
200
201XML documents can contain a `Document Type Definition <https://www.w3.org/TR/REC-xml/#sec-prolog-dtd>`_ (DTD),
202enabling definition of XML entities. It's possible to define an (external) entity by an
203URI, that the parser will access, and embed its content back into the document
204for further processing.
205
206For example, providing an url like ``file:///etc/passwd`` will read
207this file's content, and since it's not valid XML, the application
208will spit it out in an error message, thus leaking its content.
209
210We're killing this class of vulnerabilities by calling
211the `libxml_disable_entity_loader <https://secure.php.net/manual/en/function.libxml-disable-entity-loader.php>`_
212function with its parameter set to ``true`` at startup,
213and then *nop'ing* it, so it won't do anything if ever called again.
214
215This family of vulnerabilities lead to various CVE, like:
216
217- `CVE-2015-5161 <https://legalhackers.com/advisories/eBay-Magento-XXE-Injection-Vulnerability.html>`_: Unauthenticated arbitrary file disclosure on Magento
218- `CVE-2014-8790 <https://github.com/GetSimpleCMS/GetSimpleCMS/issues/944>`_: Unauthenticated remote code execution in GetSimple CMS
219- `CVE-2011-4107 <https://www.phpmyadmin.net/security/PMASA-2011-17/>`_: Authenticated local file disclosure in PHPMyAdmin
220
221
222Cookie stealing via HTTP MITM
223^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
224
225While it's possible to set the ``secure`` flag on cookies to prevent them from being
226transmitted over HTTP, and only allow its transmission over HTTPS.
227Snuffleupagus can automatically set this flag if the client is accessing the
228website over a secure connection.
229
230This behaviour is suggested in the documentation:
231
232 On the server-side, it's on the programmer to send this kind of cookie only
233 on secure connection (e.g. with respect to ``$_SERVER["HTTPS"]``).
234
235 --- `The PHP documentation about setcookie <https://secure.php.net/manual/en/function.setcookie.php>`_
236
237
238Exploitation, post-exploitation and general hardening
239-----------------------------------------------------
240
241Virtual-patching
242^^^^^^^^^^^^^^^^
243
244PHP itself exposes a number of functions that might be considered **dangerous** and that have limited legitimate use cases.
245``system()``, ``exec()``, ``dlopen()`` - for example - fall into this category. By default, PHP only allows to globally disable some functions.
246
247
248However, (ie. ``system()``) they might have legitimate use cases in processes such as self upgrade etc., making it impossible to effectively
249disable them - at the risk of breaking critical features.
250
251SnuffleuPagus allows the user to restrict usage of specific functions per files, or per
252files with a matching (sha256) hash, thus allowing the use of such functions **only** in the intended places.
253
254Furthermore, running the `following script <FIXME>`_ will generate an hash and line-based whitelist
255of dangerous functions, droping them everywhere else:
256
257
258.. literalinclude:: ../../scripts/generate_rules.php
259 :language: php
260
261
262The intent is to make post-exploitation process (such as backdooring of legitimate code, or RAT usage) a lot harder for the attacker.
263
264
265Global strict mode
266^^^^^^^^^^^^^^^^^^
267
268By default, PHP will coerce values of the wrong type into the expected one
269if possible. For example, if a function expecting an integer is given a string,
270it will be coerced in an integer.
271
272PHP7 introduced a **strict mode**, in which variables won't be coerced anymore,
273and a `TypeError <https://php.net/manual/en/class.typeerror.php>`_ exception will
274be raised if the types aren't matching.
275`Scalar type declarations <https://secure.php.net/manual/en/migration70.new-features.php#migration70.new-features.scalar-type-declarations>`_
276are optional, but you don't have to used them in your code to benefit from them,
277since every internal function from php has them.
278
279This option provide a switch to globally activate this strict mode,
280helping to uncover vulnerabilities like the classical
281`strcmp bypass <https://danuxx.blogspot.fr/2013/03/unauthorized-access-bypassing-php-strcmp.html>`_,
282and various other types mismatch.
283
284This feature is largely inspired from the
285`autostrict <https://github.com/krakjoe/autostrict>`_ module from `krakjoe <krakjoe.ninja>`_.
286
287
288Preventing execution of writable PHP files
289^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
290
291If an attacker manages to upload an arbitrary file or to modify an existing one,
292odds are that (thanks to the default `umask <https://en.wikipedia.org/wiki/Umask>`_)
293this file is writable by the PHP process.
294
295Snuffleupagus can prevent the execution of this kind of files. A good practise
296would be to use a different user to run PHP than for administrating the website,
297and using this feature to lock this up.
298
299
300
301Dumping capabilities
302^^^^^^^^^^^^^^^^^^^^
303It's possible to apply the ``dump(:str)`` filter to any virtual-patching rule,
304to dump the complete web request, along with the filename and the corresponding
305line number. By using the *right* set of restrictive rules (or by using the
306*overly* restrictives ones in ``simulation`` mode), you might be able
307to gather interesting vulnerabilities used against your website.
308
309
310Misc low-hanging fruits in the default configuration file
311^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
312
313Snuffleupagus is shipping with a default configuration file, containing
314various examples and ideas of things that you might want to enable (or not).
315
316Available functions recon
317"""""""""""""""""""""""""
318
319After compromising a website, most of the time, the attacker does some recon
320within its webshell, to check which functions are available to execute arbitrary code,
321since it's not uncommon for some web-hoster to disable things like ``system`` or ``passthru``,
322or to check if mitigations are enabled, like ``open_basedir``.
323This behaviour can be detected by preventing the execution of functions like ``ini_get``
324or ``is_callable`` with *suspicious* parameters.
325
326``chmod`` hardening
327"""""""""""""""""""
328
329Some PHP applications are using broad rights when using the ``chmod`` function,
330like the infamous ``chmod(777)`` command, effectively making the file writable by everyone.
331Snuffleupagus is preventing this kind of behaviour by restricting the parameters
332than can be passer to ``chmod``.
333
334Arbitrary file inclusion hardening
335""""""""""""""""""""""""""""""""""
336
337Arbitrary file inclusion is a common vulnerability, that might be detected
338by preventing the use of anything else than a whitelist of extensions in calls
339to ``include`` or ``require``.
340
341*Cheap* SQL injections detection
342""""""""""""""""""""""""""""""""
343
344In some SQL injections, attackers might need to use comments, a feature that is
345often not used in production system, so it might be a good idea to filter
346queries that contains some. The same filtering idea can be used against
347SQL functions that are frequently used in SQL injections, like ``sleep``, ``benchmark``
348or strings like ``version_info``.
349
350Still about SQL injections, if a function performing a query returns ``FALSE``
351(indicating an error), it might be useful to dump the request for further analysis.
352
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 @@
1Snuffleupagus
2=============
3
4Snuffleupagus is a `PHP 7+ <https://secure.php.net/>`_ module designed to drastically raising the cost of
5attacks against website, by killing entire bug classes, and also providing a
6powerful virtual-patching system, allowing administrator to fix specific
7vulnerabilities and audit suspicious behaviours without having to touch the PHP code.
8
9Documentation
10-------------
11
12.. toctree::
13 :maxdepth: 2
14
15 features
16 installation
17 config
18 download
19 faq
20 papers
21
22Greetings
23---------
24We would like to thank the following people:
25
26- `Suhosin <http://suhosin.org>`_, for paving the way.
27- The people behind the `RIPS <https://www.ripstech.com/>`_ scanner for their ground breaking work
28- `NBS System <https://nbs-system.com>`_, for creating and open-sourcing this piece of software
29- `Websec.fr <https://websec.fr>`_, for keeping our interesting vulnerabilities alive
30- 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 @@
1Installation
2============
3
4Snuffleupagus is tested against various PHP 7+ versions: XXX
5
6Manual installation
7-------------------
8
9Depending on the system, we might already offer binary packages.
10You can check our :doc:`download`. In that case you only need to activate
11the extension inside your ``php.ini`` and to configure it.
12
13
14Quickstart
15^^^^^^^^^^
16
17::
18
19 git clone https://github.com/nbs-system/snuffleupagus
20 cd snuffleupagus
21 phpize
22 ./configure
23 make
24 make install
25
26This should install ``snuffleupagus.so`` file in your extension directory. The final step is adding a load directive to ``php.ini``::
27
28 extension=snuffleupagus.so
29
30Upgrading
31---------
32
33Upgrading 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 @@
1Propaganda
2==========
3
4This pages lists various mentions, articles and presentations about Snuffleupagus.
5
6Talks
7-----
8
9- `BerlinSide0x08 <https://berlinsides.org/?page_id=2168>`_ - `Php7 Nightmares <slides.pdf>`_ - 2017-05-28
10- `Hack.lu <https://2017.hack.lu/talks/>`_ - soon™ - 2017-10-18
11- `BlackAlps <https://blackalps.ch/2017program.php>`_ - soon™ - 2017-11-16
12
13Articles
14--------
15
16- `Killing php bug classes at berlinsides <https://dustri.org/b/killing-php-bug-classes-at-berlinsides.html>`_ - 2017-06-05 \ No newline at end of file