From c4633dffe99d4cc41e25fe165b6b8b5013ea34bd Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Fri, 28 Aug 2020 07:34:55 +0200 Subject: fix wrong SAML2 SubjectNameGeneration in case of mandate-attribute processing in proxy-mode --- .../auth/builder/MOAIDSubjectNameIdGenerator.java | 128 +++++++++++++-------- 1 file changed, 79 insertions(+), 49 deletions(-) (limited to 'id/server/idserverlib/src/main/java') diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/MOAIDSubjectNameIdGenerator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/MOAIDSubjectNameIdGenerator.java index 3dfba9cca..6864d4ec3 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/MOAIDSubjectNameIdGenerator.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/MOAIDSubjectNameIdGenerator.java @@ -1,6 +1,5 @@ package at.gv.egovernment.moa.id.auth.builder; -import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.w3c.dom.Element; @@ -18,9 +17,11 @@ import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; import at.gv.egiz.eaaf.modules.pvp2.idp.api.builder.ISubjectNameIdGenerator; import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException; import at.gv.egovernment.moa.id.data.IMOAAuthData; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.MandateAttributesNotHandleAbleException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMandateDataAvailableException; import at.gv.egovernment.moa.id.util.MandateBuilder; import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.sig.tsl.utils.MiscUtil; import at.gv.egovernment.moa.util.Constants; @Service("MOASAML2SubjectNameIDGenerator") @@ -31,8 +32,8 @@ public class MOAIDSubjectNameIdGenerator implements ISubjectNameIdGenerator { //build nameID and nameID Format from moasessio if (authData instanceof IMOAAuthData && ((IMOAAuthData)authData).isUseMandate()) { - String bpktype = null; - String bpk = null; + String identifier = null; + String identifierType = null; Element mandate = ((IMOAAuthData)authData).getMandate(); if(mandate != null) { @@ -56,59 +57,88 @@ public class MOAIDSubjectNameIdGenerator implements ISubjectNameIdGenerator { Logger.error("Failed to generate IdentificationType"); throw new NoMandateDataAvailableException(); } - - bpktype = id.getType(); - bpk = id.getValue().getValue(); - + + identifier = id.getValue().getValue(); + identifierType = id.getType(); + } else { Logger.debug("Read mandator bPK|baseID from PVP attributes ... "); - bpk = authData.getGenericData(PVPConstants.MANDATE_NAT_PER_SOURCE_PIN_NAME, String.class); - bpktype = authData.getGenericData(PVPConstants.MANDATE_NAT_PER_SOURCE_PIN_TYPE_NAME, String.class); - - if (StringUtils.isEmpty(bpk)) { - //no sourcePin is included --> search for bPK - bpk = authData.getGenericData(PVPConstants.MANDATE_NAT_PER_BPK_NAME, String.class); - - try { - if (bpk.contains(":")) - bpk = bpk.split(":")[1]; - - } catch (Exception e) { - Logger.warn("Can not split bPK from mandator attribute!", e); - - } - - //set bPK-Type from configuration, because it MUST be equal to service-provider type - bpktype = spConfig.getAreaSpecificTargetIdentifier(); - - } else { - //sourcePin is include --> check sourcePinType - if (StringUtils.isEmpty(bpktype)) - bpktype = Constants.URN_PREFIX_BASEID; - - } - } - - if (StringUtils.isEmpty(bpk) || StringUtils.isEmpty(bpktype)) { - throw new NoMandateDataAvailableException(); + String natSourcePin = authData.getGenericData(PVPConstants.MANDATE_NAT_PER_SOURCE_PIN_NAME, String.class); + String natSourcePinType = authData.getGenericData(PVPConstants.MANDATE_NAT_PER_SOURCE_PIN_TYPE_NAME, String.class); + String natBpk = authData.getGenericData(PVPConstants.MANDATE_NAT_PER_BPK_NAME, String.class); - } - - if (bpktype.equals(Constants.URN_PREFIX_BASEID)) { - try { - return new BPKBuilder().generateAreaSpecificPersonIdentifier(bpk, spConfig.getAreaSpecificTargetIdentifier()); + String jurSourcePin = authData.getGenericData(PVPConstants.MANDATE_LEG_PER_SOURCE_PIN_NAME, String.class); + String jurSourcePinType = authData.getGenericData(PVPConstants.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, String.class); + + if ( (MiscUtil.isNotEmpty(jurSourcePin) || MiscUtil.isNotEmpty(jurSourcePinType)) + && (MiscUtil.isNotEmpty(natSourcePin) || MiscUtil.isNotEmpty(natBpk))) { + Logger.warn("Found mandate attributes for legal- AND natural-person. " + + "Both not allowed during on authentication. Process stops now!"); + throw new MandateAttributesNotHandleAbleException(); + + } + + if (MiscUtil.isNotEmpty(jurSourcePin) && MiscUtil.isNotEmpty(jurSourcePinType)) { + Logger.debug("Find jur. person sourcepin. Build SubjectNameId from this ... "); + return Pair.newInstance(jurSourcePin, jurSourcePinType); + + + } else if (MiscUtil.isNotEmpty(natSourcePin)) { + Logger.debug("Find nat. person sourcepin. Build SubjectNameId from this ... "); + identifier = natSourcePin; + + if (MiscUtil.isNotEmpty(natSourcePinType)) { + identifierType = natSourcePinType; + + } else { + identifierType = Constants.URN_PREFIX_BASEID; + + } + + } else if (MiscUtil.isNotEmpty(natBpk)) { + Logger.debug("Find nat. person bPK. Build SubjectNameId from this ... "); + try { + if (natBpk.contains(":")) { + natBpk = natBpk.split(":")[1]; + + } + + } catch (Exception e) { + Logger.warn("Can not split bPK from mandator attribute!", e); + Logger.info("Use nat. person bPK as it is"); + + } + + return Pair.newInstance(natBpk, + spConfig.getAreaSpecificTargetIdentifier()); + + } else { + throw new NoMandateDataAvailableException(); + + } + } + + if (identifierType.equals(Constants.URN_PREFIX_BASEID)) { + try { + return BPKBuilder.generateAreaSpecificPersonIdentifier( + identifier, spConfig.getAreaSpecificTargetIdentifier()); - } catch (EAAFBuilderException e) { - Logger.warn("Can NOT generate SubjectNameId." , e); - throw new ResponderErrorException("pvp2.01", null); + } catch (EAAFBuilderException e) { + Logger.warn("Can NOT generate SubjectNameId." , e); + throw new ResponderErrorException("pvp2.01", null); - } + } - } else - return Pair.newInstance(bpk, bpktype); - - } else + } else { + return Pair.newInstance(identifier, identifierType); + + } + + //no mandate available. Use bPK from authenticated entity + } else { return Pair.newInstance(authData.getBPK(), authData.getBPKType()); + + } } -- cgit v1.2.3 From e10256fe93208ef786d2e38a68a98e2548d501ee Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Mon, 31 Aug 2020 10:22:11 +0200 Subject: fix SSRF bug in SAML1 parameter validator --- .../StartAuthentificationParameterParser.java | 12 +- .../auth/AuthConfigurationProviderFactory.java | 15 +++ .../PropertyBasedAuthConfigurationProvider.java | 2 + .../moa/id/util/ParamValidatorUtils.java | 139 +++++++++++---------- 4 files changed, 99 insertions(+), 69 deletions(-) (limited to 'id/server/idserverlib/src/main/java') diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java index ead80b117..03fd225e0 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java @@ -42,6 +42,7 @@ import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; import at.gv.egovernment.moa.id.commons.api.data.IAuthenticationSession; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; import at.gv.egovernment.moa.id.config.TargetToSectorNameMapper; +import at.gv.egovernment.moa.id.config.auth.PropertyBasedAuthConfigurationProvider; import at.gv.egovernment.moa.id.util.ParamValidatorUtils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; @@ -182,14 +183,14 @@ public class StartAuthentificationParameterParser extends MOAIDAuthConstants{ List defaulTemplateURLList = authConfig.getSLRequestTemplates(); - if ( templateURLList != null && templateURLList.size() > 0 + if ( templateURLList != null && !templateURLList.isEmpty() && MiscUtil.isNotEmpty(templateURLList.get(0)) ) { templateURL = FileUtils.makeAbsoluteURL( oaParam.getTemplateURL().get(0), authConfig.getRootConfigFileDir()); Logger.info("No SL-Template in request, load SL-Template from OA configuration (URL: " + templateURL + ")"); - } else if ( (defaulTemplateURLList.size() > 0) && MiscUtil.isNotEmpty(defaulTemplateURLList.get(0))) { + } else if ( !defaulTemplateURLList.isEmpty() && MiscUtil.isNotEmpty(defaulTemplateURLList.get(0))) { templateURL = FileUtils.makeAbsoluteURL( defaulTemplateURLList.get(0), authConfig.getRootConfigFileDir()); @@ -203,8 +204,13 @@ public class StartAuthentificationParameterParser extends MOAIDAuthConstants{ } - if (!ParamValidatorUtils.isValidTemplate(req, templateURL, oaParam.getTemplateURL())) + if (!ParamValidatorUtils.isValidTemplate(req, templateURL, oaParam.getTemplateURL(), + authConfig.getBasicConfigurationBoolean( + PropertyBasedAuthConfigurationProvider.PROP_STRICT_SAML1_PARAM_VALIDATION, + false))) { throw new WrongParametersException("StartAuthentication", PARAM_TEMPLATE, "auth.12"); + + } protocolReq.setRawDataToTransaction( MOAIDAuthConstants.AUTHPROCESS_DATA_SECURITYLAYERTEMPLATE, diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProviderFactory.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProviderFactory.java index 94bcae672..cf3e0efd7 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProviderFactory.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProviderFactory.java @@ -57,4 +57,19 @@ public class AuthConfigurationProviderFactory { return instance; } + + /** + * Set AuthConfig programmatically + * + * @param authConfig + */ + public static void setAuthConfig(AuthConfiguration authConfig) { + if (instance != null) { + throw new RuntimeException("AuthConfig can ONLY set once!"); + + } + + instance = authConfig; + + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java index f299e0e94..1ffdaa524 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java @@ -52,6 +52,8 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide public static final String PROP_MOAID_MODE = "general.moaidmode.active"; + public static final String PROP_STRICT_SAML1_PARAM_VALIDATION = + "configuration.validate.saml1.parameter.strict"; private static final boolean TRUST_MANAGER_REVOCATION_CHECKING_DEFAULT = true; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java index a44d8c1b6..065615666 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java @@ -220,11 +220,11 @@ public class ParamValidatorUtils extends MOAIDAuthConstants{ } // check if template is a valid URL - try { + try { + URL bkuUrl = new URL(bkuURI); // check if bku url starts with http or https - if (bkuURI.startsWith("http") || bkuURI.startsWith("https")) { - new URL(bkuURI); - + if (bkuUrl.getProtocol().equals("http") || bkuUrl.getProtocol().equals("https")) { + // check if bkuURI is a local BKU if (bkuURI.compareToIgnoreCase("https://localhost:3496/https-security-layer-request") == 0 || bkuURI.compareToIgnoreCase("http://localhost:3495/http-security-layer-request") == 0 || @@ -232,8 +232,8 @@ public class ParamValidatorUtils extends MOAIDAuthConstants{ bkuURI.compareToIgnoreCase("https://127.0.0.1:3496/https-security-layer-request") == 0) { Logger.debug("Parameter bkuURI erfolgreich ueberprueft"); return true; - } - else { + + } else { Logger.debug("Parameter bkuURI ist keine lokale BKU. Ueberpruefe Liste der vertrauenswuerdigen BKUs."); boolean b = allowedBKUs.contains(bkuURI); if (b) { @@ -246,17 +246,17 @@ public class ParamValidatorUtils extends MOAIDAuthConstants{ return false; } } - } - else if (MOAIDAuthConstants.REQ_BKU_TYPES.contains(bkuURI)) { + + } else if (MOAIDAuthConstants.REQ_BKU_TYPES.contains(bkuURI)) { Logger.debug("Parameter bkuURI from configuration is used."); return true; } else { Logger.error("Fehler Ueberpruefung Parameter bkuURI. bkuURI beginnt nicht mit http or https"); return false; + } - } catch (MalformedURLException e) { Logger.error("Fehler Ueberpruefung Parameter bkuURI", e); return false; @@ -268,9 +268,12 @@ public class ParamValidatorUtils extends MOAIDAuthConstants{ * Checks if the given template is valid * @param req * @param template + * @param oaSlTemplates + * @param useStrictValidation Enables strict validation with URLs from configuration, otherwise always allow templates from same host. * @return */ - public static boolean isValidTemplate(HttpServletRequest req, String template, List oaSlTemplates) { + public static boolean isValidTemplate(HttpServletRequest req, String template, + List oaSlTemplates, boolean useStrictValidation) { Logger.debug("Ueberpruefe Parameter Template bzw. bkuSelectionTemplateURL"); @@ -282,65 +285,38 @@ public class ParamValidatorUtils extends MOAIDAuthConstants{ // check if template is a valid URL try { - - // check if template url starts with http or https - if (template.startsWith("http") || template.startsWith("https")) { - - // check if template url is from same server - String name = req.getServerName(); - String httpName = "http://" + name; - String httpsName = "https://" + name; - - if (template.startsWith(httpName) || template.startsWith(httpsName)) { - new URL(template); - Logger.debug("Parameter Template bzw. bkuSelectionTemplateURL erfolgreich ueberprueft"); - return true; - } - else { - //check against configured trustet template urls - AuthConfiguration authConf = AuthConfigurationProviderFactory.getInstance(); - List trustedTemplateURLs = authConf.getSLRequestTemplates(); - - //get OA specific template URLs - if (oaSlTemplates != null && oaSlTemplates.size() > 0) { - for (String el : oaSlTemplates) - if (MiscUtil.isNotEmpty(el)) - trustedTemplateURLs.add(el); - } - - boolean b = trustedTemplateURLs.contains(template); - if (b) { - Logger.debug("Parameter Template erfolgreich ueberprueft"); - return true; - } - else { - Logger.error("Fehler Ueberpruefung Parameter Template bzw. bkuSelectionTemplateURL. Parameter liegt nicht am gleichen Server wie die MOA-Instanz (" + req.getServerName() + ") bzw. ist nicht auf Liste der vertrauenswuerdigen Template URLs (Konfigurationselement: MOA-IDConfiguration/TrustedTemplateURLs)"); - return false; - } - - } - - } else if (template.startsWith("file")){ - new URL(template); - Logger.debug("Parameter Template bzw. bkuSelectionTemplateURL erfolgreich ueberprueft"); - Logger.debug("Load SL-Layer Template from local filesystem " + template); - return true; - - } else { - Logger.error("Fehler Ueberpruefung Parameter Template bzw. bkuSelectionTemplateURL. Paramter beginnt nicht mit http oder https."); - return false; - } + if (useStrictValidation) { + Logger.trace("Use strict validation of Template bzw. bkuSelectionTemplateURL"); + return validateTemplateUrlToWhiteList(template, oaSlTemplates); + + } else { + Logger.trace("Use lazy validation of Template bzw. bkuSelectionTemplateURL"); + URL templateUrl = new URL(template); + String serverName = req.getServerName(); + + // check if template url starts with http or https + if (((templateUrl.getProtocol().startsWith("http") + || templateUrl.getProtocol().startsWith("https"))) + && templateUrl.getHost().equals(serverName)) { + Logger.debug("Parameter Template bzw. bkuSelectionTemplateURL erfolgreich ueberprueft" + + " Lazy check is activ and template is on same host as MOA-ID"); + return true; + + + } else { + return validateTemplateUrlToWhiteList(template, oaSlTemplates); + + } + } - } catch (MalformedURLException e) { + } catch (MalformedURLException | ConfigurationException e) { Logger.error("Fehler Ueberpruefung Parameter Template bzw. bkuSelectionTemplateURL.", e); return false; - } catch (ConfigurationException e) { - Logger.error("Fehler Ueberpruefung Parameter Template bzw. bkuSelectionTemplateURL.", e); - return false; - } + + } } - /** + /** * Checks if the given sessionID is valid * @param target HTTP parameter from request * @return @@ -540,13 +516,44 @@ public class ParamValidatorUtils extends MOAIDAuthConstants{ } catch (WrongParametersException e) { return false; + } - if (StringUtils.isEmpty(bkuURL) && StringUtils.isEmpty(useeIDAS)) + if (StringUtils.isEmpty(bkuURL) && StringUtils.isEmpty(useeIDAS)) { return false; - else + + } else { return true; + + } } + + private static boolean validateTemplateUrlToWhiteList(String template, List oaSlTemplates) + throws ConfigurationException { + //check against configured trustet template urls + AuthConfiguration authConf = AuthConfigurationProviderFactory.getInstance(); + List trustedTemplateURLs = authConf.getSLRequestTemplates(); + + //get OA specific template URLs + if (oaSlTemplates != null && oaSlTemplates.size() > 0) { + for (String el : oaSlTemplates) + if (MiscUtil.isNotEmpty(el)) + trustedTemplateURLs.add(el); + } + + boolean b = trustedTemplateURLs.contains(template); + if (b) { + Logger.debug("Parameter Template erfolgreich ueberprueft"); + return true; + + } else { + Logger.error("Fehler Ueberpruefung Parameter Template bzw. bkuSelectionTemplateURL. " + + "Parameter ist nicht auf Liste der vertrauenswuerdigen Template URLs " + + "(Konfigurationselement: MOA-IDConfiguration/TrustedTemplateURLs)"); + return false; + + } + } } -- cgit v1.2.3 From 3ead2fee52a1e43e12610fda8175cb1a74e8b1f0 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Mon, 31 Aug 2020 13:51:14 +0200 Subject: update validation in case of file:/ paths because trusted templates can be relative to config directory --- .../moa/id/util/ParamValidatorUtils.java | 28 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'id/server/idserverlib/src/main/java') diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java index 065615666..0e468bb6b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java @@ -49,6 +49,7 @@ package at.gv.egovernment.moa.id.util; import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; import java.util.Collections; import java.util.HashMap; @@ -63,6 +64,7 @@ import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.SAXException; import at.gv.egiz.eaaf.core.impl.utils.DOMUtils; +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; @@ -309,7 +311,7 @@ public class ParamValidatorUtils extends MOAIDAuthConstants{ } } - } catch (MalformedURLException | ConfigurationException e) { + } catch (MalformedURLException | ConfigurationException | URISyntaxException e) { Logger.error("Fehler Ueberpruefung Parameter Template bzw. bkuSelectionTemplateURL.", e); return false; @@ -529,24 +531,42 @@ public class ParamValidatorUtils extends MOAIDAuthConstants{ } private static boolean validateTemplateUrlToWhiteList(String template, List oaSlTemplates) - throws ConfigurationException { + throws ConfigurationException, MalformedURLException, URISyntaxException { //check against configured trustet template urls AuthConfiguration authConf = AuthConfigurationProviderFactory.getInstance(); List trustedTemplateURLs = authConf.getSLRequestTemplates(); //get OA specific template URLs - if (oaSlTemplates != null && oaSlTemplates.size() > 0) { + if (oaSlTemplates != null && !oaSlTemplates.isEmpty()) { for (String el : oaSlTemplates) if (MiscUtil.isNotEmpty(el)) trustedTemplateURLs.add(el); } - boolean b = trustedTemplateURLs.contains(template); + boolean b = false; + if (template.startsWith("file:")) { + for (String el : trustedTemplateURLs) { + URL templateUrl = new URL(template); + URL trustedUrl = new URL(FileUtils.makeAbsoluteURL(el, authConf.getConfigurationRootDirectory())); + b = trustedUrl.equals(templateUrl); + if (b) { + break; + } + } + + } else { + b = trustedTemplateURLs.contains(template); + + } + + if (b) { Logger.debug("Parameter Template erfolgreich ueberprueft"); return true; } else { + Logger.info("Template:" + template + " DOES NOT match to allowed templates: [" + + org.apache.commons.lang3.StringUtils.join(trustedTemplateURLs, ",") + "]"); Logger.error("Fehler Ueberpruefung Parameter Template bzw. bkuSelectionTemplateURL. " + "Parameter ist nicht auf Liste der vertrauenswuerdigen Template URLs " + "(Konfigurationselement: MOA-IDConfiguration/TrustedTemplateURLs)"); -- cgit v1.2.3