= Proposal title = || '''Date''' || 2013/02/24 || || '''Contact(s)''' || Jose García, Heikki Doeleman || || '''Last edited''' || || || '''Status''' || in progress || || '''Assigned to release''' || To be determined || || '''Resources''' || https://github.com/josegar74/core-geonetwork/tree/csrf || || '''Ticket #''' || || == Overview == Improve the security in !GeoNetwork, adding support to CSRF tokens to prevent Cross-Site Request Forgery. Also fixes have been done in user request parameters accepted in main page to prevent XSS attacks. === Proposal Type === * '''Type''': Core Change * '''App''': !GeoNetwork * '''Module''': Jeeves, Services === Links === * '''Documents''': * '''Email discussions''': * '''Other wiki discussions''': === Voting History === * Vote proposed by X on Y, result was +/-n (m non-voting members). ---- == Motivations == Improve the security in !GeoNetwork to prevent CSRF (Cross-site request forgery) attacks. This type of attacks force an end user to execute unwanted actions on a web application in which he/she is currently authenticated. See additional information in https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) Additionally, improvements in main page have been done to prevent XSS attacks in user requests parameters. == Proposal == An effective way to prevent CSRF attacks it is to generate a random string (CSRF token) that is included in application forms. When the form is submitted, the CSRF token is send along the other form data, the server validates it before. approving the request for processing. This way, prevents a malicious website from post a request even if have access to a valid session in a browser. To implement this mechanism in !GeoNetwork: '''1)''' A new base service class for services that require CSRF (Cross Site Request Forgery) tokens: {{{BaseSecureService}}} This class validates the CSRF token before processing the service: * If it's not valid and exception {{{ServiceNotAllowedEx}}} is thrown. * If it's valid, the service processing continues. {{{ package jeeves.services; public abstract class BaseSecureService implements Service { public final Element exec(Element params, ServiceContext context) throws Exception { if (!CSRFUtil.isValidToken(params, context)) { throw new ServiceNotAllowedEx("Service not allowed. CSRF Token is not valid"); } return doExec(params, context); } /** Services that require CSRF tokens must implement doExec instead of exec **/ protected abstract Element doExec(Element params, ServiceContext context) throws Exception; } }}} Services that require CSRF tokens must extend this class and implement the logic in {{{doExec}}} method instead of {{{exec}}} method. {{{ package org.fao.geonet.services.user; public class Update extends BaseSecureService { public Element doExec(Element params, ServiceContext context) throws Exception { // Service logic } } }}} Code: https://github.com/josegar74/core-geonetwork/blob/csrf/jeeves/src/main/java/jeeves/services/BaseSecureService.java Example service requiring CSRF token: https://github.com/josegar74/core-geonetwork/blob/csrf/web/src/main/java/org/fao/geonet/services/user/Update.java '''2)''' A new service to create/retrieve a CSRF token: {{{secure.token}}}. This service is used to provide the secure token in services that create forms (see next point) and can be used from scripts that use actual !GeoNetwork services that have been changed to require CSRF tokens. For example, a script that call {{{metadata.category}}} to update the categories of metadata, will require to call first {{{secure.token}}} to get the token and use it in {{{metadata.category}}} calls. CSRF tokens are created using {{{SecureRandom}}} java class. Code: https://github.com/josegar74/core-geonetwork/blob/csrf/jeeves/src/main/java/jeeves/services/GetSecureToken.java, https://github.com/josegar74/core-geonetwork/blob/csrf/jeeves/src/main/java/jeeves/utils/CSRFUtil.java '''3)''' Services that create forms to submit data to services that require CSRF tokens validation require to add this token in the form to submit. This requires 2 changes: - Update service definition to provide the CSRF token: {{{ }}} - Add the token value as a hidden field in the form: {{{
}}} Also as part of this work security improvements in main page user request parameters have been done to prevent XSS attacks: https://github.com/josegar74/core-geonetwork/commit/50f722f12c36e403ffa80724004e937db0ef2821 Useful resources: * https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) * http://ricardozuasti.com/2012/preventing-csrf-in-java-web-apps === Backwards Compatibility Issues === User scripts using !GeoNetwork services to update data will require to be updated to use {{{secure.token}}} to retrieve the CSRF token and use it in the services. See Proposal description (point 2) for more details. These changes don't affect interfaces like CSW. UI WIdgets requires to be changed to use the CSRF token. === New libraries added === == Risks == == Participants == * Jose García * Heikki Doeleman