About this document

About

This document once was a chapter within the Developers' Guide. We now converted this chapter into a stand alone document because the topic “security” is too important for being mentioned on “page 258” of some general documentation. ...and we added much more information.

This document is a “must-read” for:

Aspects covered

This guide concentrates on these aspects of security which are technical aspects.

Within an application there are a couple of aspects in addition that are application-related (e.g. authority management). These aspects are not treated in this document.

This is a “living” document. CaptainCasa actively takes part in security audits of applications that use CaptainCasa Enterprise Client as front-end architecture. Results of these audits are constantly added to this document.

Communication – https only!

All traffic between browser and server might go through infrastructures that you are not really aware of! Consequence: sending data without encryption and sending data without any technical authentication of the server is a 100% “no-go”!

Do never use “http://” in production environments. Always go through “https://”!

Define dedicated entrance pages

Overview

A “.risc” URL starts the corresponding page on server side.

Typically you want to define dedicated entrance pages into your application system – and you do not want to allow the user to “free-style” open any page that you provide.

Interface “IStartPageChecker”

To check this there is an own mechanism that is part of the CaptainCasa server runtime. There is an interface “IStartPageChecker”:

package org.eclnt.jsfserver.starter;

 

import javax.servlet.http.HttpServletRequest;

 

public interface IStartPageChecker

{

    public boolean checkIfPageCanBeDirectlyStarted(HttpServletRequest startRequest, String page);

}

 

Every time a “.risc” page is started then this interface called.

Default implementation by system.xml definition

There is a default implementation “DefaultStartPageChecker” that is always active.

This default implementation is checking for definitions inside the system.xml configuration file:

<system>

     <riscstarter

         ...

         >

        

        ...

        <allowstart page="/abc/*"/>

        <allowstart page="/*/index.*"/>

        <allowstart page="/xxx/yyy.jsp"/>

        ...

        <excludestart page="/abc/*"/>

        <excludestart page="/*/index.*"/>

        <excludestart page="/xxx/yyy.jsp"/>

        ...

        

     </riscstarter>

</system>

 

Here you have two options:

Of course: adding one “allowstart” definition will automatically over-rule all “excludestart” definitions! So you need to either do “allowstart” definitions or “excludestart” definitions – doing both does not make sense.

You can use the wildcard characters.

Please pay attention:

If developing your own checker – extend from default one

If you want to set up some own implementation of “IStartPageChecker” then you can do so – we recommend to extend your implementation from CaptainCasa's default implementation.

You need to register your implementation in system.xml:

<system>

      ...

     <riscstarter

        ...

        startpagecheckerclassname="<class name of IStartPageChecker implementation>"

        ...

        >

        ...

        ...

     </riscstarter>

</system>

 

Define pages that you allow to be embedded in IFRAMEs

Overview

By default a page (opened by a “.risc” URL) is not embed-able into IFRAMEs for security reasons. This is independent from the definition of entrance-pages which is explained in the previous part of this chapter.

The embedding of pages is ruled via http-header-attribute “x-frame-options”. This attribute can be explicitly defined within the CaptainCasa processing.

Definitions in system.xml

In system.xml there are the following configuration options:

     <riscstarter
       ...

        embedableasiframe="sameorigin"
       ...

        <allowiframeembedding page="/workplace/demohelloworld.jsp"/>

        <allowiframeembedding page="/*/index.*"/>

        ...

     </riscstarter>

 

Configuration in CaptainCasa tools

The tools of CaptainCasa allow to apply the definitions in system.xml in a more comfortable way than direct XML editing. Calling “start-able dialogs”...

...will show up a subsequent dialog, in which you can define the start-able and embed-able dialogs:

Session-id hijacking

All data of a user session is part of an normal http-session on server-side. The browser client passes the session-id with every call to the server, so that the server knows which data is addressed.

By accessing the session-id attackers can try to get into the session from an other browser (or program acting as browser). As consequence the session-id either needs to be part of the encrypted communication – or if not, then there must be additional functions in place to ensure that session-access from outside is not possible.

There are two areas of functions that are applied in this area:

“Session-id hijacking”

There are two types of session management (see chapter “Session Management” within the Developers' Guide):

Example:

 

https://xxx.yyy.com/appxyz/abc.def;jsessionid=4711

 

URL-based session management

In case of using the URL-based session management, the session-id is directly “steal-able”, because it is part of the URL. The URL itself is obviously not part of the https encryption – because it is the central address that defines the target of the communication. In other words: it is the information which is written onto the “envelope” of what is sent and needs to be seen by all communication parts that send the “envelope” across the network.

This means: attackers can directly read the session-id by observing the https-network traffic.

And this also means: some additional function is required to ensure that sessions, even if knowing their session-id, cannot be hijacked.

Additional Session-Security-Id as Cookie

The solution is quite simple: in addition to the session-id that is part of the URL, an additional “session-security-id” is communicated – but this time not as part of the URL, but as Cookie.

The cookie value is protected in the following way:

Filter “SecurityFilterGeneral”

The filter "SecurityFilterGeneral” is the one that exactly performs this management of an additional session-security-id. The name of the cookie holding this id is “”.

<system>

    ...

    <filterconfiguration

        active="false"

        classname="org.eclnt.jsfserver.util.SecurityFilterGeneral"/>

    ...

</system>

Only for users of the Java-Swing client

The Java-Swing client does not manage cookies, so the “SecurityFilterGeneral” is switched off for messages originating from this client. (The information of the client type is also inside the encrypted part of the communication.) The Java-Swing client can only be used with URL-encoding of the session id.

For this client there is a similar mechanism in place, that adds a security id to the communication, this time not as cookie but as extra parameter that is added to the http-post communication.

All internal communication between the Java-Swing client and the server is based on http-post communication – and as result is secured for session-hijacking. - Calls to external systems by http-get are not secured. Concrete scenario: the Java-Swing client can open up a browser by passing a URL. This URL is processed as http-get by the browser.

Only for users of Java-Swing client – Filter “SecurityFilter”

Preventing continuation of session on a different device

General information

The principles already were discussed in the introduction of this chapter: each request from a browser includes information about the browser itself. This information is collected and stored in the server-side session. Once a call into the session is not including exactly the same client-information as before must end in an error to prevent the take over of the session. - Sometimes people refer to a “fingerprint” that is sent with every request and that is always checked on server side against the “fingerprint” that initiated a session.

The browser does not send too much “fingerprint”-information, for good reason: in normal Internet-scenarios you do not want the server to exactly know who your are – otherwise it would be too easy to store information about you. So there is no MAC-address or equivalent that can be used...

Nevertheless: this information which comes from the browser side need to be used for checking.

Filter “SecurityFilterRemoteAddress”

Handling errors

When the filter “SecurityFilterRemoteAddress” detects some problem then it throws some error that is logged into the CaptainCasa log file:

java.lang.Error: Client that sends the request is not the one that created the session.

 

You should analyze the error and check the addition information in the CaptainCasa log file. The detailed information is output in front of the error message:

Client that sends the request is not the one that created the session. Aborting security check with error. ...URL...

Session information: ...

Request information: ...

...Stacktrace...

 

In the log you see the client information that is stored with the session and you can compare against the one that is coming with the request. You can see the three items which make the client information (remote address, x-forwarded-for, user-agent) separated by a slash “/” and you can check if there is a good reason for the difference between the session-information (originating from the first request opening the session) and the information for the current request.

If there is a good reason:

<system>

    ...

    <filterconfiguration

        active="false"

        classname="org.eclnt.jsfserver.util.SecurityFilterRemoteAddress"/>

    ...

</system>

 

Avoiding the Replaying of http - CLIENTSECID

There are security scenarios in which you have to explicitly avoid that the network activity of a certain http-request-processing is recorded and replayed somewhere after-wards.

To avoid this, CaptainCasa introduced a component CLIENTSECID that is bound to a server side object of type CLIENTSECIDBinding. The component requests from the CLIENTSECIDBinding a new id within each request-response processing on server side. This id is sent to the client side and re-sent to the server with the next request.

On server side a request is checked if the id that is received corresponds to the last id that was sent to the client. Then a new id is generated and sent with the response to the client.

The ids that are generated are random ids, that are not predictable to anyone trying to replay a certain recorded http-sequence against your server.

The CLIENTSECID component (arranged below the component BEANPROCESSING) should be placed on the outest page of your scenario, i.e. the one that is your starting page.

JavaScript Injection, “XSS”

General processing of text content - “Escaping”

With CaptainCasa no direct HTML content is sent from the server to the client side. The server transfers component data as XML to the client, which is there used to update corresponding components.

All CaptainCasa client side components that transfer data from the server into a text that is shown within the browser are programmed to avoid JavaScript injection. By default the HTML that is inserted is escaped – this means, that any HTML-character is converted into a safe variant before being passed into the the text of the corresponding HTML-element:

    var result = value.replace(/&/g, "&")

                      .replace(/>/g, ">")

                      .replace(/</g, "<")

                      .replace(/"/g, """)

                      .replace(/'/g, "'")

                      .replace(/\//g, "/");

 

This means: if e.g. assigning a BUTTON-TEXT with the value “Hal<b>lo</b>”, then the text that is shown in the button is not “Hallo” (i.e. “Hallo” with the “lo” being output with bold font weight) – but the text that is shown in the button is “Hal<b>lo</b>”.

Dedicated components - “Sanitizing”

Default

In some few cases and for dedicated controls only, the corresponding controls accept meaningful HTML code – this means the HTML is inserted “as is”, without escaping. These cases are:

In these cases the HTML is explicitly sanitized by default on client side before being passed into the HTML element. This sanitizing is done by using the corresponding algorithms from the Google-caja project – using an HTML4-based white list of allowed tags and attributes.

This algorithm is a quite restrictive one – and e.g. also removes images. But it is adequate to transfer formatted text content properly.

Avoiding sanitizing

All the components provide an attribute AVOIDSANITIZING. If you set to “true” then the client side sanitizing is not executed and the text that comes from your application is directly inserted into the corresponding HTML-element.

When using this attribute then you explicitly take over for passing correct HTML content! This means:

Places where direct browser content is created by CaptainCasa

Even though the base of CaptainCasa (as described in “General processing” at the begin of this chapter) is the communication of XML content between the client-side and the server, there are some places where direct browser content is created.

Starter page (“.risc”-page)

When calling a “.risc”-URL in the browser then the HTML-page that is responded to the browser is exactly the one that brings the JavaScript-Single-Page-Application into the browser that form the CaptainCasa client processing.

Servlet “RISCStarter”

Creation of images

Certain images are created by CaptainCasa dynamically. Examples:

Servlet “DynamicImageServlet”

Providing download content / content opened by URL

An application can create content that either should be downloaded by the user or that should be displayed in a new browser tab. Example: an application might create some HTML or PDF report.

CaptainCasa provides two mechanisms to publish dynamic content as URL:

Servlet “BufferedContentServlet” and “TempFileAccessServlet”

Error output in browser – hiding implementation details

Overview

In case of some sever application error situation it is super-nice for developers to directly see a browser page that e.g. list the full stack trace of the error.

But: this opens up the risk that internal information could be now published to the end user which might be usable to prepare some attack.

Examples:

Consequence: even though it make the process of analyzing errors more complex: detail of the error needs to be hidden in front of the user.

Filter “ErrorAnonymizerFilter”

Browser Cache control

Overview

Why should you take care of cache at all? Because the cache of the browser is something which is not protected to be abused. Imagine you are in an Internet cafe and you watch some nice PDF report that is generated by your business application. If this report is cached by the browser then the next user of the computer could open the cache and check what you left as information...

General statements

No caching of data that is transferred between CaptainCasa client in browser and server-side application

The main data communication inside CaptainCasa between the browser client and the server is based on a POST-processing – which by default is not cache-able.

Nevertheless (and after the experience of security audits...) we define a “no-cache/no-store” statement in the POST-responses... ;-)

Explicit area of caching are controlled by version-stamp

Special resources such as JavaScript and CSS-files are explicitly cached on client side, so that they do not have to be loaded every time you start the application. CaptainCasa appends a version-stamp to all the requests that are loading “.js” and “.css” files. In case the version of CaptainCasa changes (which means: updated “.js” files), the new versions will be automatically read because the URL now has a different version stamp.

Dynamically created content by default is set to be not cached

All content that is dynamically created (e.g. PDF created via BufferedContentMgr or by TempFileManager) is defined as being not-cache-able.

Caching of general resources

General resources of a web application (e.g. PNG images, SVG files, ...) are by default not explicitly treated. CaptainCasa provides filters which you might use to easily define...

Filters

Filter “NoCacheNoStoreFilter”

Filter “CacheFilter”

Filter configuration

You may extend both filters to include by updating the “system.xml” configuration:

...

    <filterconfiguration

        active="true"

        classname="org.eclnt.jsfserver.util.NoCacheNoStoreFilter"

        additionalmappings="...mapping...;...mapping...;...mapping..."

/>

...

 

The “mapping” definition is the one that is directly passed into the filter configuration. It is the same mapping that you would define in “web.xml” files and allows the positioning of a “*” either at the end or at the beginning. Examples:

Http-header fields that affect security

Overview

There are certain header-attributes of http-responses that affect the security because they tell the browser client what it is allowed to do in the context of the loaded content.

The ones that are currently treated by CaptainCasa's runtime are:

We do not explain the meaning of each of the http-header parameters in this documentation. Please refer to publicly available information.

The filter is applied to all extensions that are the ones to be directly loaded within the browser:

Filter “HttpHeaderAttributesForPagesFilter”

Filter configuration

You may configure the values that are set by some configuration in “system.xml”:

...

    <httpheaderattributesforpages

        x-xss-protection="1; mode=block"

        x-content-type-options="nosniff"

        content-security-policy="default-src 'self' data: 'unsafe-inline' 'unsafe-eval'; img-src * data:"

        referrer-policy="no-referrer"

        />

...

 

In the definition of the “httpheaderattributesforpages” element you only need to define these attributes that you want to explicitly control. Example: if you only want to update the content-security-policy, then you may define:

...

    <httpheaderattributesforpages

        content-security-policy="...your definition..."

        />

...

 

If explicitly defining an empty string (“”) then the http-header field is not set by the the filter. Example:

...

    <httpheaderattributesforpages

        content-security-policy=""

        />

...

 

Resource Access by Class Loader

Overview

There are certain areas in which resources can potentially be accessed by class loader:

Why does CaptainCasa allow access to resources that are loaded by class loader at all?

It's the possibility to distribute applications and components as self-containing .jar files. These .jar files not only contain the Java-programs (.class files) but also contain all the resources that these programs require for their processing.

Example: a component that requires some button images, needs to make these images available in way that the browser can access – i.e. by calling a URL. So a URL not only targets the “webcontent” of an application but also the resources that are part of the application's .jar file.

Risk

Of course your .jar file (and the resources you keep in the /classes directory) may contain a lot of information that must not be directly accessed by a URL!

So there must be a careful selection of resources that can directly be accessed by the browser.

Solution

Level 1 – Restriction of extensions

Only resources with an extension can be loaded that are part of white list of extensions. The extensions that by default are allowed to be accessed are:

bmp

css

eot

gif

giff

htm

html

jpg

jpeg

js

js.map

pdf

png

svg

tif

tiff

ttf

txt

woff

woff2

 

Level2 – Check of path by interface “IResourceSecurityChecker”

Every time CaptainCasa accesses a resource by class loader then interfaces of type “IResourceSeecurityChecker” are called:

public interface IResourceSecurityChecker

{

    /**

     * @param path

     * Access path into the classloader. String starting with "/" e.g.

     * "/com/xyz/resources/whatever.png"

     *

     * @return

     * true ==> access is allowed, false ==> access is not allowed,

     * null ==> path not relevant for this checker

     */

    public Boolean checkClassLoaderPathForOutsideUsage(String path);

}

 

Here the resources access can be explicitly checked by the application.

Implementations of the interface can be registered by either registering in system.xml configuration file...

<system>

    ...

    <resourcesecuritychecker name="...className..."/>

    ...

</system>

 

...or by directly registering by using the API:

ResourceSecurity.addResourceSecurityChecker(...);

 

Controlling values being sent and received – Interface “ICheckInboundAndOutboundValues”

The server side processing of CaptainCasa Enterprise Client provides some extra functions in order to check any outgoing or ingoing values.

The following interface is processed for each request and for each response:

package org.eclnt.jsfserver.injection;

 

public interface ICheckInboundAndOutboundValues

{

    public String checkInboundValue(String tagName,

                                    String attributeName, String value);

    public String checkOutboundValue(String tagName,

                                     String attributeName, String value);

}

 

The implementation of the interface is registered within the sytem.xml configuration file (webcontent/eclntjsfserver/config/server.xml):

<system>

    ...

    <checkinboundandoutboundvalues name="...className..."/>

    ...     

</system>

 

At runtime an instance of the class is created by using a constructor without parameters.

Internal file access

All file access within the CaptainCasa server processing is done through the class “FileManager” (org.eclnt.util.file.FileManager). The class is a public class so it may also be used by your application.

Restricted access via Java API

Inside the FileManager there is the possibility to restrict the access to the file system. There are two corresponding methods:

By default the FileManager starts without any restrictions, so it has full access to the file system. After calling one of the methods, the FileManager will run in restricted mode.

Restricted access via system.xml

You may define restrictions in addition by using the configuration file “system.xml” (<webcontent>/eclntjsfserver/config/system.xml). Example:

<system>

    ...

    ...     

    <filemanagerreadaccess directory="${servletwebapp}"/>

    <filemanagerwriteaccess directory="${temp}"/>

    <filemanagerwriteaccess directory="${servlettemp}"/>

    <filemanagerreadaccess directory="c:/bmu_jtc"/>

    <filemanagerreadaccess directory="c:/temp"/>

    ...

    ...

</system>

 

There are some predefined variables, please check the documentation in the template file (system.xml_template) for detailed information.

If restricting the access then make sure that the following directories are always added, because CaptainCasa requires access:

    <filemanagerreadaccess directory="${servletwebapp}"/>

    <filemanagerwriteaccess directory="${temp}"/>

    <filemanagerwriteaccess directory="${servlettemp}"/>

 

Embedding a CaptainCasa dialog as IFRAME into other pages

By using the HTML element “iframe” you can embed one page into another page. There is a certain risk involved, named “clickjacking”. Basically the embedding page can try to overlay the content of the embedded page without showing to the user and by this e.g. can capture field input.

As consequence an HTML page needs to control the scenarios, in which it wants to be embedded into other pages – or not. This is controlled by the http header parameter “X-Frame-Options”.

CaptainCasa by default (from 20210628 on) sets the parameter to value “sameorigin” - which means: all pages that are running on the same domain can embed.

You can explicitly control the value of the parameter by configuring the system.xml file. The valid values are described within the documentation inside the template file:

<system>

    ...

    ...

    <!--

      *************************************************************************

      Configuration of RISCStarter - the servlet that is responding on .risc

      request.

      ...

      ...

      embedableasiframe: default "sameorigin"; completely switch off by value

      "deny" or "false"; allow embedding by value "true".

      ...

      ...

      *************************************************************************

    -->

    <riscstarter

        ...

        embedableasiframe="sameorigin"

        ...

     />

    ...

    ...

</system>

Server-side Script Injection

...is part of application processing!

On server side the similar rules have to be applied than the ones that need to be applied for avoiding client-side JavaScript injection – of course with different scripting languages

Every place inside your application that is executing dynamically assembled script is dangerous! Reason: an attacker might try to define input data in a way that it implicitly contains scripting statements that are executed when the full script is assembled and run.

SQL injection

Simple to attack...

The most prominent example typically is “SQL injection”.

When assembling an SQL out of input data...

String sql = “SELECT * FROM PERSONS WHERE NAME='” + name + ”'”;

 

...then “nice” users might try to input the following input as name:

%' AND SALARY>1000000 AND TOWN='Berlin

 

The result which will now be assembled at runtime is:

SELECT * FROM PERSONS WHERE NAME='%' AND SALARY>1000000 AND TOWN='Berlin'

 

Simple to solve...

Luckily the solution is very simple: never assemble SQL strings directly. Always use so called “PreparedStatements”, so that you write:

String sql = “SELECT * FROM PERSONS WHERE NAME=?”;

PreparedStatement ps = connection.prepareStatement(sql);

ps.setString(1,name);

 

Prepared statements will never mix in data into the script – they explicitly separate one from the other.

Using persistence frameworks

There are a couple of persistence frameworks (Hibernate, etc.) that actually hide the SQL processing in front of the user. These frameworks internally are built on prepared statements typically – but better do a check!

...CaptainCasa also provides a super-simple and efficient persistence framework in its “CCEE-addons” package. Of course it internally is based on prepared statements.

Special issues

Image Management – Accessing external images

When the client side JavaScript processing renders an image (e.g. IMAGE component itself, or: BUTTON-IMAGE) and when the size of the image is not explicitly set, then the size of the image is calculated by a server-side function, which is accessed through the servlet “ImageSizeServlet”.

The default operations are as follows:

(Of course result information is buffered both on client and on server-side.)

By default image definitions are links to images that are part of the web application. This means the image URL is following the format “/aaa/bbb/ccc.jpg”, addressing the file “webcontent/aaa/bbb/ccc.jpg”.

But: you can also define images coming from external addresses. Example:

<t:button ... image=”http://captaincasa.org/wp-content/uploads/2020/06/stock2-768x505.png” .../>

 

In this case the server side reads the image from the specified address by http-request and retrieves the size from the image data. The image data itself is afterwards removed, only the width/height result are kept.

In order to prevent the server to load data from any server of the world wide web, there is an interface “IExtImageFilter”:

package org.eclnt.util.image;

 

/**

* Filter to check URLs to be loaded by image size processing of the server side

* image manager (class ServerImageManager). Here is is possible to find the size

* of some image from some external url. This url can be checked with this interface

* to prevent uncontrolled loading of images.

*/

public interface IExtImageFilter

{

    /**

     * @param url - url of the image that is analyzed

     * @return - true: image is ok and can be loaded, false: image must not be loaded!

     */

    public boolean checkURL(String url);

}

 

The default implementation that is used inside the ImageSizeServlet is:

package org.eclnt.util.image;

 

import org.eclnt.util.log.CLog;

 

/**

* Implementation of {@link IExtImageFilter} which blocks any type

* of loading external images. This is the default manager that is used

* and which avoids any external URL to be loaded.

*/

public class ExtImageFilterAllBlocked implements IExtImageFilter

{

    public boolean checkURL(String url)

    {

        CLog.L.log(CLog.LL_WAR,"The external image was NOT read: " + url);

        CLog.L.log(CLog.LL_WAR,"Reason: it is blocked by " + this.getClass().getName());

        return false;

    }

}

 

This default implementaion always returns “false” - which means: all image loading from the server-side to other servers is completely blocked.

You need to add some own implementation, in order to open up this mechanism. Your implementation needs to be registered in the “eclntjsfserver/config/system.xml” conifguration file:

<!--

  *************************************************************************

  Server image manager.

  *************************************************************************

-->

<serverimagemanager

       

    ...

    extimagefilterclassname="...implementation of class IExtImageFilter..."

    ...

/>