Security Considerations

An example of deployment for production is available here (wiki) using NGINX/Apache and python virtual environment. This example respect all security considerations defined in this page.

Installations

Secure server and connection

  • I recommend using a HTTPS proxy or HTTPS Server with WSGI module on production environments (to protect against MiM attacks and protect the WebScripts Server).
  • Set webproxy_number to the number of HTTP proxy used, it's important for IP Spoofing protection.

Virtual environments

  • I recommend using a python virtual environment

Configurations

Interface

  • The WebScripts Server is not secure enough to be used directly on public interface (the proxy is very important). It should not use an interface other than 127.0.0.1.

HTTP headers

  • To protect your WEB clients (against XSS, CSRF, MiM and other threats) the configuration named security of the WebScripts Server sends HTTP headers. This configuration should be true. The headers are:
    • Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
    • Content-Security-Policy: default-src 'self'; form-action 'none'
    • X-Frame-Options: deny
    • X-XSS-Protection: 1; mode=block
    • X-Content-Type-Options: nosniff
    • Referrer-Policy: origin-when-cross-origin
    • Cache-Control: no-store
    • Clear-Site-Data: *
    • Feature-Policy: payment 'none'; geolocation 'none'; microphone 'none'; camera 'none'
    • Permissions-Policy: microphone=(),camera=(),payment=(),geolocation=()
    • Cross-Origin-Embedder-Policy: require-corp
    • Cross-Origin-Opener-Policy: same-origin
    • Cross-Origin-Resource-Policy: same-origin

Debugging

  • The debug configuration should be false, if set to true some scripts, modules and configurations will no longer be protected.

Bruteforce

  • auth_failures_to_blacklist and blacklist_time configuration should be set, to protect your passwords againts bruteforce attacks.

SMTP password

  • In the production environment, you must be notified from your WebScripts server, configure SMTP (server, email addresses...) to receive notifications.
  • Do not use SMTP password (smtp_password != None) without StartTLS (smtp_starttls == True) or SSL (smtp_ssl == True). If connection is not secure the password may be sniffed.

Script configurations

Logs

  • You should set to true the no_password configuration when you don't have a password in command lines arguments to logs command line.

Content type

  • You should never set stderr_content_type to text/html because it may be used for XSS (HTML and javascript injection).
  • Some script required the text/html as content_type, i should use specific function for XSS protection.
  • Don't unescape HTML special characters in console scripts (when content_type is text/plain), the javascript does it for you.

Timeout

  • You should set the timeout configuration.

Credentials

Change the password of the Admin user and the API key or use custom authentication script, database and system.

System

Files rigths and access

Some files and directories must be protected by the system, to avoid privilege escalation, RCE (Remote Code Execution) or other attacks.

READ-ONLY: scripts, executables and configurations

  1. Scripts, executables and configurations should never have setuid, setgid, sticky bit or other special permissions.
  2. Scripts, executables and configurations should never have the write permissions and any permissions for group and other
    • Use this command to protect your executables: chmod 100 <file>
    • Use this command to protect your scripts and configurations: chmod 400 <file>
  3. The directories of scripts, executables and configurations should always have root as owner and never write permissions for group and other
    1. Use this command to change the owner as root: chown root:root <directory>
    2. Use this command to change permissions: chmod 755 <directory>

READ and WRITE: data and logs

To protect your files the read and write files, you need to change permissions on group and other (on Linux run this command: chmod -R 600 <directory or file>) and make sure the owner is the user who is launching the WebScript Server (on Linux run this command: chown -R <user>:<user> <directory or file>).

The files and directories that need protection:

  • ./data/, <lib path>/data/: encrypted or hashed passwords are stored here, user permissions are also set here
  • ./logs/, <lib path>/logs/: logs contains informations about configurations

Delete files

  • ./export_Configuration.json is useful for debugging but it should be removed on production environments.

System administration

The WebScripts is a tool that can help you administer other system (using SSH or WinRM scripts for example) but never the WebScripts Server system. If your scripts can change the system configurations, an attacker can also use it. The principle is as follow: the system protects your WebScripts server and the WebScripts server must not change the system.

Remote Code Excution

You should never use a function to execute string as code on users inputs. A remote code execution is very dangerous.

  • I show some examples here but these are not exhaustive.
  • You can use other languages, read the documentation and pay attention to the functions exec, shell, eval, ....

Python

Some examples of Remote Code Execution on WebScripts custom module:

import os, pickle

def page(environ, user, configuration, filename, arguments, inputs, *args, csrf_token=None):

    """
    Some examples of remote code executions are shown in this function, 
    you should never use this example or an equivalent.
    """

    eval(environ["HTTP_COMMAND"]) # Run the Command HTTP headers as python code
    exec(filename)                # Run the URL parameter as python code
    os.system(arguments[0])       # Run the first argument as a command line
    pickle.loads(inputs[0])       # De-serailize a pickle payload (Pickle contains weakness don't use it on user inputs)

    # Don't execute a (encrypted) cookie !

    return "200 OK", {}, "Response"

Some examples of Remote Code Execution on python script:

import pickle, sys, os

eval(environ["HTTP_COMMAND"])        # Run the Command HTTP headers as python code
eval(sys.argv[1])                    # Run the first argument as python code
eval(input())                        # Run stdin as python code

exec(environ["HTTP_COMMAND"])        # Run the Command HTTP headers as python code
exec(sys.argv[1])                    # Run the first argument as python code
exec(input())                        # Run stdin as python code

os.system(environ["HTTP_COMMAND"])   # Run the Command HTTP headers as a command line
os.system(sys.argv[1])               # Run the first argument as a command line
os.system(input())                   # Run stdin as a command line

pickle.loads(environ["HTTP_COMMAND"])# De-serailize the Command HTTP headers as a pickle payload (Pickle contains weakness don't use it on user inputs)
pickle.loads(sys.argv[1])            # De-serailize the Command HTTP headers as a pickle payload (Pickle contains weakness don't use it on user inputs)
pickle.loads(input())                # De-serailize the Command HTTP headers as a pickle payload (Pickle contains weakness don't use it on user inputs)

Bash

Some examples of Remote Code Execution in bash script:

eval $1                           # Run the first argument as a command line
$1                                # Run the first argument as a command line

python3 -c "${1}"                 # Run the first argument as python code
php -r "${1}"                     # Run the first argument as php code

PHP

Some examples of Remote Code Execution in php script:

<?php 
  shell_exec($argv[1]);           // Run the first argument as a command line
  eval($argv[1]);                 // Run the first argument as php code
?>

XSS

You should never print a user entry (headers, arguments, inputs, URLs, content, username, cookie, ...), when the output content-type is set to text/html, without escape HTML scpecial characters.

Python

import html
print(html.escape(user.name))

PHP

<?php
    echo(htmlspecialchars(cookie));
?>

WebScripts Web Security

Session

The WebScripts Server use HTTP Cookies for session. The session are generated with secrets.token_hex(64). The cookie is set with this HTTP header: Set-Cookie: SessionID=<user id>:<64 random byte hexadecimal>; Path=/; SameSite=Strict; Max-Age=3600; Secure; HttpOnly. Sessions can be used with only one IP address and expire after one hours and there is an IP spoofing protection.

CSRF token

The server uses CSRF tokens for POST requests when a session is used. The CSRF tokens are generated with b64encode(secrets.token_bytes(48)).decode(). Tokens can only be used once, for one session and they expire after 300 seconds (5 minutes).

Cautions:

  • BasicAuth and API keys should never be used with a web browser because CSRF protections is not enabled with these methods.