Security Considerations
Securing applications that are accessible to the Internet is not a trivial task. This page outlines some of the issues, and offers best-practices and tips to help you secure your application using Embedthis ESP.
Contents
- Updating ESP
- Sandboxing
- ESP User Account
- Chroot Jail
- Securing SSL
- Authentication
- Log Files
- Common Security Threats
- High Profile Threats
Updates
Even the best application or web framework can experience some security vulnerabilities that are discovered after being deployed in the field. It is highly recommended that you stay up to date with the latest version of ESP.
Embedthis provides security protection as part of the ESP commercial license that will proactively notify you of any security flaws and will expedite fixes or workarounds to minimize any vulnerabilities.
Sandboxing
Sandboxing is the term applied to running ESP in a confined environment. When embedding, the profile of client access is often well known, and the profile of malicious attacks are often well outside the bounds of this expected profile. The profile includes the rate of accesses, the length of URLs and the size of data submitted by the user.
ESP has a set of configuration properties that allow you to define a sandbox which specifies how ESP must be used for a request to be serviced. By using a well defined sandbox, you can help ensure that your application will not be compromised by malicious requests. You should customize the sandbox limits to use minimum values and thus provide the most protection.
Security Limit Directives
The ESP security limits can be used to effectively block some denial of service attacks. Limits should be set as low as possible while still permitting all valid requests and workloads.
Setting the http.limits.requests to a low value can restrict the ability of a malicious client to monopolize the server. One attack method for denial of service attacks is to initiate requests, but not conclude the request headers. The server is then forced to wait for the client to complete the request before it can act. However, setting the http.timeouts.parse property to a low value will abort such requests and prevent such attacks.
ESP can monitor sandbox limits and trigger defensive responses if access is outside defined norms. See the Denial of Service section for more details.
Sandbox Limit Properties
Property | Description |
---|---|
http.limits.connections | Maximum number of network connections. Note a client can open many network connections. A browser session will typically open 4-6 connections. |
http.limits.clients | Maximum number of simultaneous clients |
http.limits.cache | Maximum size of the response cache |
http.limits.cacheItem | Maximum size of a single item in the response cache |
http.limits.keepAlive | Maximum number of requests to serve using a single TCP/IP connection |
http.limits.memory | Maximum memory the server can allocate |
http.limits.processes | Maximum number of simultaneous CGI processes the server will start |
http.limits.requestBody | Maximum size of the incoming request body. Does not include file upload size. |
http.limits.requestForm | Maximum size of request form data (POST data) |
http.limits.requestHeader | Maximum size of the request header |
http.limits.requests | Maximum number of simultaneous requests from a single client IP |
http.limits.uri | Maximum size of a URI |
http.limits.upload | Maximum size of a file upload request |
http.limits.workers | Maximum number of worker threads to service requests. A single worker may service many requests as ESP will typically not block when serving a request. Workers are assigned to service network events and are then returned to a worker pool to service the next event. |
Sandbox Timeout Properties
Property | Description |
---|---|
http.timeouts.inactivity | Maximum request and connection inactivity duration. This can be defined per route, so if you have a long running request, create a dedicated route for that request. |
http.timeouts.parse | Maximum duration to parse the request headers. This should be set very short. Typically a browser will send all the request headers in one network packet. Recommended value is 5 secs. |
http.timeouts.request | Maximum request duration. Set this to the maximum time a request can take. This can be defined per route, so if you have a long running request, create a dedicated route and RequestTimeout for it. |
See the Configuring ESP for further details.
Defensive Countermeasures
ESP includes a monitoring and defensive response framework to mitigate against denial-of-service (DOS) attacks and vulnerability probing. This framework monitors the security sandbox and triggers defenses should any sandbox metric be outside anticipated norms. Monitored metrics can also include the number of requests that result in an error, the number of SSL errors and the total number of requests.
For example, to ban any client that requests more than 50 unknown URIs per minute:
defenses: { block: { "remedy": "ban", "status": 406, "message": "Client banned", "period": "1hour", }, }, monitors: { missing: { "expression": "NotFoundErrors > 50", "period": "1min", "defenses": [ "block" ], }, },
See the Monitoring and Defending for further details.
ESP User Account
It is important that you run ESP with the lowest system privilege that will get the job done. If any application is compromised, including ESP, then the system will be safest if the compromised application has as few privileges as possible.
Unix Account
On Unix, ESP initially runs as root or administrator and then changes to the user account defined in the ESP configuration file via the http.server.account.user property.
Chroot Jail
One of the best forms of isolation for the server is to run inside a chroot jail. A chroot jail is when an application changes its root directory to be isolated from the real file system root directory. Any access then to files outside the jail is protected and impossible. ESP supports chroot jails via the http.server.chroot property.
Securing SSL
Cipher Selection
It is important to select a sufficiently long key length and strong cipher to protect SSL communications. It is recommended to use the AES cipher and avoid the older RC4 cipher suite. See the section below regarding High Profile Threats for threats against the RC4 ciphers.
SSL Forms
A common practice is to use HTTP for regular communications and to post login forms using SSL. However, this approach is flawed. The web form itself must be served using SSL as well as the URL receiving the login information. This prevents attackers injecting code into the login form and hijacking login credentials.
Authentication
It is important to adequately secure all passwords stored at the server. Simply hashing the passwords with MD5 is now insufficient as MD5 and other "fast" hashing techniques can be quickly compromised by dedicated password cracking and hashing tools.
ESP includes the blowfish cipher as an alternative that is more secure than MD5. The Blowfish cipher is especially well suited for password hashing partly. Partly because it is slow, it does not easily succumb to brute-force cracking.
If you wish to use the Digest authentication scheme, unfortunately you cannot use blowfish as the browser uses MD5 to encrypt the password before transmitting over the wire. This and other shortcomings of Digest authentication should encourage you to select other schemes. A better alternative is Basic authentication over SSL using blowfish to encrypt the passwords. Alternatively, use web form authentication with blowfish for password storage.
If using a web page for users to submit their credentials, it is strongly recommended that you use SSL for both the web form page and for the request validating the user credentials.
Log Files
ESP will log errors to the error log and request trace to the trace log. These It is recommended that you regularly review these logs for suspicious activity.
Common Security Threats
This section details some common security threats and issues and the steps you can take to mitigate them.
Server Information Disclosure
HTTP responses often disclose information that an attacker can use to refine their attack. At a minimum, too much information enables the attack to proceed faster. ESP includes a stealth directive that suppresses unnecessary information. Here is a typical HTTP response from ESP
HTTP/1.1 200 OK Content-Type: text/html Server: Embedthis-http Date: Thu, 15 Aug 2014 22:10:25 GMT ETag: "cf4ce71-54-51c64a0b" Content-Length: 84 Last-Modified: Sun, 23 Jun 2014 01:06:19 GMT Connection: close Accept-Ranges: bytes
Note that by default, ESP does not disclose the web server version number in HTTP headers. You can further restrict information disclosure by defining the http.stealth property.
stealth: true
HTTP/1.1 200 OK Content-Type: text/html Date: Thu, 15 Aug 2014 22:11:46 GMT ETag: "cf4ce71-54-51c64a0b" Content-Length: 84 Last-Modified: Sun, 23 Jun 2014 01:06:19 GMT Connection: close Accept-Ranges: bytes
Notice that the stealth property has suppressed the Server header altogether. Attackers will need to work a little harder to know what kind of web server is responding to their requests — they may move onto another target.
Session Hijacking
Cookies are used to identify authenticated user sessions. As such, they are a prized piece of information by attackers. The HTTP Set-Cookie response header has an option to prevent client side scripts from ascertaining the session cookie value. This can greatly reduce the risk of session hijacking via cross-site scripting.
auth: { session: { visible: false } }
The visible session property appends the "httpOnly" value to the Set-Cookie response so the cookie will only be accessible to HTTP requests.
Set-Cookie: key=value; httpOnly
Mixed Transports
Is is a bad idea to mix secure and non-secure content in one page. This means a web page should be totally served by HTTP or by HTTPS but not mix transports on one page. The reason is that a page served by HTTP can be compromised and the guarantee of HTTPS and that green-browser https logo is diminished if the form page from which the user enters there data is not 100% trust-worthy.
Denial of Service
Denial of service attacks can be difficult to detect and defend against. However, Embedded devices typically have a well defined, understood and anticipated work load. Unlike enterprise system, which have highly variable work loads, embedded systems typically serve a specific purpose with known clients that follow a more predictable access pattern. This allows an embedded system to define a range of operation that is considered "normal" and to trigger alerts and defenses if access is outside of this "normal" operation.
ESP provides a Monitor and Defending framework that can detect many denial of service attacks. The defensive policies can alert and mitigate the attack and help maintain service. It is recommended that all systems consider this framework.
Cross Site Scripting
Cross-site vulnerabilities have ballooned over recent years. Unfortunately, there is no, single complete cure. However, ESP supports the Content Security Policy (CSP) scheme that can go a long way to reduce the exposure. It does this by exactly specifying and restricting what cross-site access is permitted.
The following ESP directive enables the Content Security Policy and restricts all access to the origin site. This is a good starting point.
headers: { add: { "Content-Security-Policy: "default-src 'self' } }
See An introduction to Content Security Policy for more information.
For Microsoft IE, there is another step specific for IE that is useful. The following ESP directive invokes some additional IE cross site protections.
headers: { add: { "X-XSS-Protection": "1; mode=block" } }
Cross-Site Request Forgery
Cross site requires forgery or XSRF is an exploit where unauthorized commands are sent from a user that the website trusts. Unlike cross-site scripting, which exploits the trust a user has for a site, XSRF exploits the trust that a site has in a user. See Wikipedia for more details.
ESP can generate mitigate the XSRF threat by generating an XSRF token that is required in all POST forms. This token is dynamically generated on the server and saved in the ESP session. It is sent to the browser in the X-XSRF-TOKEN HTTP response headers and may also be optionally generated in form web pages as a hidden input field. When the form is posted, ESP checks that the token matches the token saved in the ESP session storage.
To enable XSRF token checking, set http.xsrf to true. To generate an XSRF token in an ESP form page, use the inputSecurityToken API. This generates a hidden input field containing the XSRF token.
<% inputSecurityToken(); %>
This generates:
<input name='-xsrf-' type='hidden' value='TOKEN-VALUE'>
If using Ajax to issue POST requests, you will need to add the security token to the posted data fields manually. You can call securityToken to add the token to the page HTTTP headers. For example:
<script> securityToken(); </script>Then you can extract the security token from the HTTP headers and add to any POST request form fields. If you need to access the token value directly in Javascript client-side code, use:
<script> var token = "<%= getSecurityToken(); %>" </script>
Hidden Frames
Hidden frames may be inserted by attackers to provide a launch-pad for running malicious scripts. Denying the ability to run frames can close of this attack vector.
The following ESP directive will prevent frames or iframes from running in the web page.
Header set X-Frame-Options deny
headers: { add: { "X-Frame-Options": "deny" } }
High Profile Threats
There have been several high profile exploits that pose specific risks and have captured media attention. These are addressed specifically below with details on how to mitigate their effects.
Crime Exploit
The Crime Security Exploit attacks and exploits leakage of information due to the varying effectiveness of TLS compression.
- Access to intercept and redirect client communications
- Ability to initiate requests from the client
- Encrypted communications SSL/TLS
- TLS level compression
By default, ESP does not use TLS with TLS compression and is thus not vulnerable to this exploit. The OpenSSL SSL_COMP_add_compression_method will enable TLS compression, so it is important not to use this OpenSSL API.
Breach Exploit
The Breach exploit is a variant of the Crime exploit. It attacks and discovers private server information, such as CSRF tokens, by observing the compression of HTTP responses over SSL. This exploit requires the following to be effective:
- Access to intercept and redirect client communications
- Ability to initiate requests from the client
- Encrypted communications SSL/TLS
- Server-side encryption of dynamic responses
- Unmodified inclusion in the response body of client specified query or form data
ESP does not dynamically compress response content and so is not vulnerable to this exploit.
Beast Exploit
The Beast Security Exploit attacks block ciphers used by TLS to access encrypted packets. This exploit requires the following to be effective:
- Use of TLS 1.0. This exploit has been addressed in TLS 1.1 and later.
- Ability to position attacker as man-in-the-middle between server and client
- Encrypted communications SSL/TLS
- Using a block cipher.
Notes:
- OpenSSL 0.9.6d and later are not vulnerable.
- ESP 3.3 and later have shipped with fixed OpenSSL libraries.
- Using RC4 will mitigate the attack if upgrading OpenSSL is not feasible, however this cipher is vulnerable to the Luck 13 exploit described below.
Lucky 13 Exploit
The Lucky 13 exploit attacks TLS by using varying padding for block ciphers.
This exploit requires the following to be effective:
- Ability to position attacker as man-in-the-middle between server and client
- Encrypted communications SSL/TLS
- Using a block cipher.
- Use of the RC4 cipher.
Notes:
- Mitigate by not using an RC4 cipher
- RC4 was not the default cipher in any ESP release
Documented Vulnerabilities
ESP documents discovered security errors in its GitHub issue database at
https://github.com/embedthis/esp/issues?state=open
Specific issue reports are created for all confirmed or erroneous security reports that receive a CVE classification. You can search for specific CVE numbers or see all via:
https://github.com/embedthis/esp/search?q=CVE-&type=Issues
Unfortunately some security researchers publish poorly diagnosed security alerts and sometimes do not contact the vendor for confirmation of the report. Consequently there exist some security CVE reports which are bogus. ESP creates parallel CVE issues in the ESP GitHub issue database to comment on these reports and provide accurate resolution information.
Other Security References
Some of these articles may provide good background regarding security web servers.
- http://www.isg.rhul.ac.uk/tls/TLStiming.pdf
- http://html5sec.org/
- https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
- https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
- https://www.owasp.org/images/b/be/Cracking-into-embedded-devices-and-beyond.pdf
- http://media.blackhat.com/bh-ad-11/Sutton/bh-ad-11-Sutton_Embeded_Web_Servers_WP.pdf
- http://www.imperialviolet.org/2012/07/19/hope9talk.html
- https://www.owasp.org/images/b/be/Cracking-into-embedded-devices-and-beyond.pdf
C Code
ESP applications are not immune to security flaws. It is highly recommended that you use the MPR services for all your ESP code. This portable runtime has been extensively tested and includes routines to guard against common buffer overflows and other such exploits.
ESP Secure By Default
ESP is designed to be secure by default. This means that the default configuration enables security best-practices to limit cross-site-scripting vulnerabilities. It also implies a fairly restrictive security sandbox. This default configuration may be a little too restrictive for your application. In that case, you can easily remove or override these defaults by the relevant ESP directives.
ESP uses the following built-in configuration for the default route.
SessionCookie invisible app: { http: { auth: { session: { visible: false }, }, stealth: true, limits: { buffer: "32KB", /* Default buffer size */ cache: "10MB", /* Max response cache size */ cacheItem: "200KB", /* Per-item max cache size */ chunk: "64KB", /* Default chunk encoding size */ clients: 100, /* Max simultaneous clients */ connections: 50, /* Max simultaneous connections */ files: "unlimited",/* Max open files */ keepAlive: 200, /* Max requests per socket connection */ processes: "unlimited",/* Max processes to run */ requestBody: 100K, /* Max request body data */ requestForm: 32K, /* Max request form body data */ requestHeader: 32K, /* Max request HTTP headers size */ responseBody: "2GB", /* Max response body size */ memory: "200MB", /* Max memory heap usage */ requests: 20, /* Max simultaneous requests */ sessions: 100, /* Max client sessions */ upload: "2GB", /* Max file upload size */ uri: "8K", /* Max URL size */ webSockets: 20, /* Max Web Sockets */ webSocketsMessage: "50K", /* Max WebSockets message size */ webSocketsPacket: "50K", /* Max WebSockets packet size */ webSocketsFrame: "4K", /* Max Websockets frame size */ workers: 4, /* Max worker threads */ }, timeouts: { exit: "30secs", /* Max time for app to exit */ parse: "20secs", /* Max time to receive request headers */ inactivity: "300secs", /* Max I/O inactivity for connections */ request: "infinite", /* Max request duration */ session: "30mins", /* Max user session duration */ }, headers: { add: { "X-XSS-Protection": "1; mode=block", "X-Frame-Options": "deny", "X-Content-Type-Options": "nosniff", }, }, } }