Security

Main principles

For Versions 7 and above platform, security is governed by following rules:
* Standard web browsers and 'https' protocol are used. The web technology provides a first level insulation between the web server and the workstation.
* Passwords are not transferred on the network. The authentication system is based on standards. The following options are available:
1. The Windows login that is controlled in an LDAP directory,
2. An Oauth2 authentication (a redirection is done to the authentication server).
* The connection between the Sage X3 Web Server and the Sage X3 server is based on certificates that are created at installation time by a private certificate authority.
* Rights managements are done at service level and are based on function profiles associated with the user.
* The access of the Sage X3 processes to the server is restricted by a white list of authorized directories.
* On the Sage X3 Web Server, the processes and/or the services that 'node.js' and 'mongodb' do not require to be root or have administrator privileges.

One of the consequences of this is that the management of passwords that was handled by Sage X3 is now obsolete and no more used; the security rules for passwords are now managed by the security providers (google, LDAP rules) you choose.

Note: For simplicity reasons or for autonomous demo servers), a fallback solution based on users and encrypted passwords stored in the Sage X3 Web Server is available, but is not to be used for production environments.

Security parameters

The syracuse web server has different parameters to tune the security. The configuration is based on a dedicated security section in the nodelocale.js file.

HTTP headers

clickjacking

The server is protected against clickjacking by adding the x-frame-options: DENY http header.

If for any reason you need to be able to put the site into an iframe, you can do it ***at your own risk*** by overriding the default as follows:
CODECODE CODEjsexports.config = {security: {http: {headers: {// set 'x-frame-options' to enable embedding into another site via iframe// 'x-frame-options': 'allow-from http://other-site','x-frame-options': 'SAMEORIGIN', // default value is 'DENY'},},},};

Before U9.0.3

The header was directly under the httpas follows:

CODECODE CODEjsexports.config = {security: {http: {// set 'x-frame-options' to enable embedding into another site via iframe// 'x-frame-options': 'allow-from http://other-site',// 'x-frame-options': 'SAMEORIGIN','x-frame-options': 'DENY' // default value},},};

XSS and other defense headers

Any headers in the headers property will be added in the response. By default, the following are added:

The content-security-policy has many directives you can use to control what the browser can render. Among all directives we can mention:

Note on child-src, frame-src and worker-src

The directive frame-src was deprecated by CSP version 2 but has recently been undeprecated in favour to child-src.
The web standard defines frame-src and worker-src to be used in the future. In conclusion, it's best so specify frame-src and worker-src since these allow more fine grained control when using up to date browsers. Still setting child-srcto be there as a fallback for old browsers

These directives can be modified as sub-properties of content-security-policy as follows:

CODECODE CODEjsexports.config = {security: {http: {headers: {"content-security-policy": {"frame-src": ["'self'", "www.w3schools.com"]},},},},};

HTML5 rocks provides a good tutorial

Debugging content-security-policyissues. While hardening the security configuration it may happen to many resources get blocked and make the system unusable. To avoid this, it is possible to only report potential violations but not block them effectively.
To report violations, set the property content-security-policy-report-only instead of content-security-policy.

The above configuration would look like:

CODECODE CODEjsexports.config = {security: {http: {headers: {"content-security-policy-report-only": {"frame-src": ["'self'", "www.w3schools.com"]},},},},};

It is also possible to set both content-security-policy and content-security-policy-report-only. This will block access to resources as defined in content-security-policy while only reporting additional violations caused by directives put in content-security-policy-report-only without blocking them.

content-security-policy-report-only will only report access violations but not block them in any way so it's very important to replace it with content-security-policy once the configuration was successfully tested

Content security

The user interface can include some external contents by using iframe. Including such contents may corrupt the security of the site, but by adding the sandbox attribute to the iframe HTML tags we can reduce the risk.

iframe sandbox

HTML vignettes support 3 levels (low, medium, high) of security.
Per default, these levels define the sandbox attribute as follows:

As of today, the medium level is selected per default to compute the sandbox attribute.

Customizing the sandbox attribute

You can change the default authorization of the 3 levels by editing the security section in nodelocal.js.
Each of the 3 levels can consist of one or more of the supported elements of the sandbox attribute:
* allow-formsEnables form submission
* allow-pointer-lockEnables pointer APIs (for example pointer position)
* allow-popupsEnables popups
* allow-same-originAllows the iframe content to be treated as being from the same origin
* allow-scriptsEnables scripts
* allow-top-navigationAllows the iframe content to navigate its top-level browsing context

Examples

CODECODE CODEjsexports.config = {security: {client: {iframe: {sandbox: {// low: null, // if null no sandbox attribute will be added (not recommended)// medium: null, // if null no sandbox attribute will be added (not recommended)low: "allow-same-origin allow-forms allow-popups allow-scripts",medium: "allow-same-origin allow-forms allow-scripts",high: ""}}},},};

Be aware that there is a difference in setting a sandbox level to null or setting it to "" (empty)
* null: Do not put the sandbox attribute. This means there is no restriction at all and everything is allowed.
* "": Put the sandbox attribute with no additional elements. This means nothing is allowed.

It's highly recommended to not set any of the security levels to null. In case of doing so please make sure to at least restrict access to resources by setting the content-security-policy accordingly.

In general, combining the sandbox attribute and the frame-src and child-src directive of the content-security-policy provide a better control of what can be rendered in the browser.

Examples

Example 1 - Control web page gadgets

Setup

Create 2 external links with the following url:

  1. http://www.w3schools.com/tags/demo_iframe_sandbox_origin.htm
  2. http://www.w3schools.com/tags/demo_iframe_sandbox_form.htm

Create a new landing page

Add a web gadgets for both external links above

Test

By default your 2 gadgets are displayed and you can submit the form data.

For web gadgets, the medium level is used, so in the nodelocale.js file, change the security.client.iframe.sandbox.medium property as follows:

CODECODE CODEjsmedium: "allow-same-origin allow-scripts",

Restart the server and now you no longer able to submit the form data.

Do the same by removing allow-same-origin, now the demo_iframe_sandbox_origin page cannot load the book list with the ajax request.

Finally, edit the security.http.headers property to add a content-security-policy header as follows:

CODECODE CODEjsexports.config = {security: {http: {headers: {"content-security-policy": {"frame-src": ["'self'"]},},},},};

Restart the server and now none of the iframes are rendered.

Example 2 - Block external resources except pendo.io

Edit the security.http.headers property to add a content-security-policy header as follows:

CODECODE CODEjsexports.config = {security: {http: {headers: {"content-security-policy": {"default-src": ["'self'", "'unsafe-inline'"],"connect-src": ["'self'", "ws:", "wss:"],"script-src": ["'self'", "'unsafe-inline'", "'unsafe-eval'", "cdn.pendo.io", "app.pendo.io"],"img-src": ["'self'", "data:", "app.pendo.io"],"child-src": ["self"], // Compatibility for older browsers"frame-src": ["'self'"]}},},},};

Restart the server and now no external resources like images or scripts will be downloaded by the browser except for pendo.io

Manage allowed protocol and encryption algorithm

Configuration

As an administrator and for security purposes, it is important to be able to set allowed or forbidden protocols and encryption algorithms.

The configuration of the options used to create a TLS server can be managed by editing the security section in the nodelocal.js file. This configuration ensures that the TLS V1.2 protocol is used and forbids RC4 and CBC encryption.

Example - nodelocal configuration for TLS

Edit the security.tls property to add renegotiation and context parameters as follows:

CODECODE CODEjsconst constants = require('constants');exports.config = {security: {tls: {// For up to date recommendations on TLS security// see https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Server_Protocol_and_Cipher_Configurationrenegotiation: {limit: 3, // default 3window: 600 // default 600 (10 minutes)},context: {// Cipher suite acceptedciphers: 'EDH+aRSA+AESGCM:EDH+aRSA+AES:EECDH+aRSA+AESGCM:EECDH+aRSA+AES:-SHA' +':ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:RSA+AESGCM:RSA+AES+SHA256:RSA+AES+SHA' +':DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA' +':!aNULL:!eNULL:!LOW:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:!ADH:!IDEA',// Use the server's cipher suite preferences instead of the client's one (recommended)honorCipherOrder: true,// Rejected protocols known as unsecured (SSL V2, V3, TLS V1.0, V1.1)secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_TLSv1 | constants.SSL_OP_NO_TLSv1_1}}},};

Note: It is important to declare the constants at the beginning of the file. Do not put a chain, this would false the result.

Verifying the expected behavior

Here are several tests you can run to ensure that the TLS security level meets the requirements.
These tests consider that an HTTPS server is running on port 8126. The standard port of an HTTPS server is 443.

Example 1 - Test TLS v1.0 protocol

CODECODE CODEsh$ openssl s_client -tls1 -connect localhost:8126CONNECTED(00000204)no peer certificate availableNo client certificate CA names sentSSL handshake has read 0 bytes and written 0 bytesNew, (NONE), Cipher is (NONE)Secure Renegotiation IS NOT supportedCompression: NONEExpansion: NONENo ALPN negotiatedSSL-Session:Protocol : TLSv1Cipher: 0000Session-ID:Session-ID-ctx:Master-Key:Key-Arg : NonePSK identity: NonePSK identity hint: NoneSRP username: NoneStart Time: 1529961360Timeout : 7200 (sec)Verify return code: 0 (ok)20556:error:1409E0E5:SSL routines:ssl3_write_bytes:ssl handshake failure:s3_pkt.c:659:

Example 2 - Test RC4 cipher suites

CODECODE CODEsh$ openssl s_client -cipher ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5:PSK-RC4-SHA -connect localhost:8126CONNECTED(00000220)no peer certificate availableNo client certificate CA names sentSSL handshake has read 7 bytes and written 150 bytesNew, (NONE), Cipher is (NONE)Secure Renegotiation IS NOT supportedCompression: NONEExpansion: NONENo ALPN negotiatedSSL-Session:Protocol : TLSv1.2Cipher: 0000Session-ID:Session-ID-ctx:Master-Key:Key-Arg : NonePSK identity: NonePSK identity hint: NoneSRP username: NoneStart Time: 1529961371Timeout : 300 (sec)Verify return code: 0 (ok)10480:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:802:

Example 3 - Test CBC cipher suites

CODECODE CODEsh$ openssl s_client -cipher SRP-DSS-AES-256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:SRP-AES-256-CBC-SHA:PSK-AES256-CBC-SHA:SRP-DSS-AES-128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:SRP-AES-128-CBC-SHA:IDEA-CBC-SHA:PSK-AES128-CBC-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:SRP-DSS-3DES-EDE-CBC-SHA:SRP-RSA-3DES-EDE-CBC-SHA:SRP-3DES-EDE-CBC-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DH-RSA-DES-CBC3-SHA:DH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA:PSK-3DES-EDE-CBC-SHA -connect localhost:8126CONNECTED(00000218)no peer certificate availableNo client certificate CA names sentSSL handshake has read 7 bytes and written 158 bytesNew, (NONE), Cipher is (NONE)Secure Renegotiation IS NOT supportedCompression: NONEExpansion: NONENo ALPN negotiatedSSL-Session:Protocol : TLSv1.2Cipher: 0000Session-ID:Session-ID-ctx:Master-Key:Key-Arg : NonePSK identity: NonePSK identity hint: NoneSRP username: NoneStart Time: 1529961383Timeout : 300 (sec)Verify return code: 0 (ok)16904:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:802:

Example 4 - Test including an accepted cipher (ECDHE-RSA-AES256-GCM-SHA384)

CODECODE CODEsh$ openssl s_client -cipher RC4-SHA:RC4-MD5:DES-CBC3-SHA:ECDHE-RSA-AES256-GCM-SHA384 -connect localhost:8126CONNECTED(00000208)Certificate chain0 s:/CN=....i:/C=....1 s:/C=....i:/C=...Server certificate-----BEGIN CERTIFICATE----------END CERTIFICATE-----subject=/CN=....issuer=/C=....No client certificate CA names sentPeer signing digest: SHA512Server Temp Key: ECDH, P-256, 256 bitsSSL handshake has read 2368 bytes and written 272 bytesNew, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384Server public key is 2048 bitSecure Renegotiation IS supportedCompression: NONEExpansion: NONENo ALPN negotiatedSSL-Session:Protocol : TLSv1.2Cipher: ECDHE-RSA-AES256-GCM-SHA384Session-ID: ....Session-ID-ctx:Master-Key: .....Key-Arg : NonePSK identity: NonePSK identity hint: NoneSRP username: NoneTLS session ticket lifetime hint: 300 (seconds)TLS session ticket:....Start Time: 1529961397Timeout : 300 (sec)Verify return code: 19 (self signed certificate in certificate chain)depth=1 C = ....verify error:num=19:self signed certificate in certificate chainread:errno=10093

Example 5 - Test with default connect

CODECODE CODEsh$ openssl s_client -connect localhost:8126CONNECTED(00000134)Certificate chain0 s:/CN=....i:/C=....1 s:/C=....i:/C=...Server certificate-----BEGIN CERTIFICATE----------END CERTIFICATE-----subject=/CN=....issuer=/C=....No client certificate CA names sentPeer signing digest: SHA512Server Temp Key: ECDH, P-256, 256 bitsSSL handshake has read 2368 bytes and written 434 bytesNew, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384Server public key is 2048 bitSecure Renegotiation IS supportedCompression: NONEExpansion: NONENo ALPN negotiatedSSL-Session:Protocol : TLSv1.2Cipher: ECDHE-RSA-AES256-GCM-SHA384Session-ID: ....Session-ID-ctx:Master-Key: .....Key-Arg : NonePSK identity: NonePSK identity hint: NoneSRP username: NoneTLS session ticket lifetime hint: 300 (seconds)TLS session ticket:....Start Time: 1529961553Timeout : 300 (sec)Verify return code: 19 (self signed certificate in certificate chain)depth=1 C = ....verify error:num=19:self signed certificate in certificate chainread:errno=10093