WebSphere Commerce has a number of security features built-in, but even with everything that's available there's always the opportunity for an account to be compromised. In particular, what if a site administrator password was discovered by an attacker? It would allow them to login and run commands that could have quite a significant impact to the site, even from outside a firewall. Minimizing the impact of a compromised administrator account may be an area to investigate further, so we'll take a closer look at that.
There's a number of ways minimizing the impact of a compromised administrator account could be implemented, the one I'll present here is to prevent any account that is not a registered shopper from being able to logon through external channels - this includes the storefront, through REST and component services. Should an admin account then be compromised, it would help reduce the risk of an external user from being to run commands which could cause harm.
Implementing the Logon Restrictions
See the sample code here. Please note that the sample code was developed only as a proof-of-concept for testing of the idea – it is strongly recommended that it be carefully reviewed and changed to best fit your requirements and is provided “as-is”. For example, as mentioned this prevents any non-registered shopper from logging in externally - which could impact CSR type users. The description below is a high-level overview of the workings of the provided sample code.
The key part to this will be the creation of a new filter which can be used to determine whether the incoming request is coming from an "external" source - in this example it will be determined to be external based on the incoming port number. The sample code uses port 80 or 443, however the external source could also be defined based on hostname, custom request header, etc.
If the request is determined to be external, a parameter tied to the specific request (a ThreadLocal in the sample code) is set so that later commands know if its an external request. The filter also defines a couple helper methods:
isSimpleRegisteredUser is used to check if the user has an administrator role.
isAllowed is used to check if the request should be allowed - returning false if the user has an admin role AND the request is from an external source.
Protecting Storefront and REST access
To implement the change to the storefront and REST services, the filter created earlier must be added to that module's web.xml and mapped to its standard servlet. The sample code provided includes extended LogonCmdImpl and LogonSeviceCmdImpl classes which would then be registered in the CMDREG table, replacing the default classes. When a user tries to logon through either the storefront or REST, the customized classes are executed, which rely on the filter to determine whether the logon should be allowed. If not, an error message is returned (the extended LogonCmdImpl takes advantage of adding a custom error message to the storeErrorMessages.properties file) and the logon is unsuccessful.
Protecting Component Services
By default, component services are not available externally so there generally is not a need to protect these; however if needed individual services can be externalized (see Externalizing WebSphere Commerce services in the Infocenter). If you have done so, you may wish to protect these as well. To protect basic authentication (when the logon credentials are part of the header), you'll want to again add the new logon filter to that component services' web.xml in the WAR file. The sample code then includes an extended BusinessContextServiceLogonCmdImpl to perform similar checking as was described earlier to determine if the logon should be successful. Specific to the Member services AuthenticatePassword command where the authentication information is sent in the body of the message, this requires extending the LogonServiceCmdImpl mentioned earlier and adding the new logon filter to the services web.xml.
One scenario that is not covered in the above or in the sample code is login with Single-Sign On (LDAP integration). This should be achievable using methods similar to the above, one such possibility is through extending the LDAPIntegrationCmd class and overriding postSingleSignOnProcessing. This method performs no logic by default and is provided only as an extension point.
With the implementation completed, administrators are now blocked from accessing various login methods externally, thereby enhancing site security and improving your resistance to an attack from outside!
Thanks to Andres Voldman (firstname.lastname@example.org) and Wesley Philip (email@example.com) for the help in authoring this post and with the provided sample code.