Package eu.righettod

Class SecurityUtils

java.lang.Object
eu.righettod.SecurityUtils

public class SecurityUtils extends Object
Provides different utilities methods to apply processing from a security perspective.
These code snippet:
  • Can be used, as "foundation", to customize the validation to the app context.
  • Were implemented in a way to facilitate adding or removal of validations depending on usage context.
  • Were centralized on one class to be able to enhance them across time as well as missing case/bug identification.
  • Method Summary

    Modifier and Type
    Method
    Description
    static String
    applyURLDecoding(String encodedData, int decodingRoundThreshold)
    Perform sequential URL decoding operations against a URL encoded data until the data is not URL encoded anymore or if the specified threshold is reached.
    static void
    clearPDFMetadata(org.apache.pdfbox.pdmodel.PDDocument document)
    Remove as much as possible metadata from the provided PDF document object.
    static byte[]
    Compute a SHA256 hash from an input composed of a collection of strings.

    This method take care to build the source string in a way to prevent this source string to be prone to abuse targeting the different parts composing it.

    static Map<String,Object>
    ensureSerializedObjectIntegrity(ProcessingMode processingMode, String input, byte[] secret)
    Provide a way to add an integrity marker (HMAC) to a serialized object serialized using the java native system (binary).
    The goal is to provide a temporary workaround to try to prevent deserialization attacks and give time to move to a text-based serialization approach.
    static List<URL>
    Extract all URL links from a PDF file provided.
    This can be used to apply validation on a PDF against contained links.
    static String
    identifyMimeType(byte[] content)
    Identify the mime type of the content specified (array of bytes).
    Note that it cannot be fully trusted (see the tweet '1595824709186519041' referenced), so, additional validations are required.
    static boolean
    Apply a collection of validations on a string expected to be an email address: Is a valid email address, from a parser perspective, following RFCs on email addresses. Is not using "Encoded-word" format. Is not using comment format. Is not using "Punycode" format. Is not using UUCP style addresses. Is not using address literals. Is not using source routes. Is not using the "percent hack".
    This is based on the research work from Gareth Heyes added in references (Portswigger).

    Note: The notion of valid, here, is to take from a secure usage of the data perspective.
    static boolean
    isExcelCSVSafe(String csvFilePath)
    Apply a collection of validations on a EXCEL CSV file provided (file was expected to be opened in Microsoft EXCEL): Real CSV file. Do not contains any payload related to a CSV injections. Ensure that, if Apache Commons CSV does not find any record then, the file will be considered as NOT safe (prevent potential bypasses).

    Note: Record delimiter used is the , (comma) character.
    static boolean
    isImageSafe(String imageFilePath, List<String> imageAllowedMimeTypes)
    Apply a collection of validations on a image file provided: Real image file. Its mime type is into the list of allowed mime types. Its metadata fields do not contains any characters related to a malicious payloads.
    Important note: This implementation is prone to bypass using the "raw insertion" method documented in the blog post from the Synacktiv team.
    static boolean
    isJSONSafe(String json, int maxItemsByArraysCount, int maxDeepnessAllowed)
    Apply a collection of validations on a JSON string provided: Real JSON structure. Contain less than a specified number of deepness for nested objects or arrays. Contain less than a specified number of items in any arrays.
    Note: I decided to use a parsing approach using only string processing to prevent any StackOverFlow or OutOfMemory error that can be abused.

    I used the following assumption: The character { identify the beginning of an object. The character } identify the end of an object. The character [ identify the beginning of an array. The character ] identify the end of an array. The character " identify the delimiter of a string. The character sequence \" identify the escaping of an double quote.
    static boolean
    Apply a collection of validations on a string expected to be an system file/folder path: Does not contains path traversal payload. The canonical path is equals to the absolute path.
    static boolean
    isPDFSafe(String pdfFilePath)
    Apply a collection of validations on a PDF file provided: Real PDF file. No attachments. No Javascript code. No links using action of type URI/Launch/RemoteGoTo/ImportData.
    static boolean
    The PSD2 STET specification require to use HTTP Signature.
    static boolean
    Apply a collection of validations on a string expected to be an public IP address: Is a valid IP v4 or v6 address. Is public from an Internet perspective.
    Note: I often see missing such validation in the value read from HTTP request headers like "X-Forwarded-For" or "Forwarded".
    static boolean
    isRelativeURL(String targetUrl)
    Validate that the URL provided is really a relative URL.
    static boolean
    Apply a collection of validation to verify if a provided PIN code is considered weak (easy to guess) or none.
    This method consider that format of the PIN code is [0-9]{6,}
    Rule to consider a PIN code as weak: Length is inferior to 6 positions. Contain only the same number or only a sequence of zero. Contain sequence of following incremental or decremental numbers.
    static boolean
    Apply a collection of validations on a Word 97-2003 (binary format) document file provided: Real Microsoft Word 97-2003 document file. No VBA Macro.
    No embedded objects.
    static boolean
    Identify if an XML contains any XML comments or have any XSL processing instructions.
    Stream reader based parsing is used to support large XML tree.
    static boolean
    isXMLOnlyUseAllowedXSDorDTD(String xmlFilePath, List<String> allowedSystemIdentifiers)
    Ensure that an XML file only uses DTD/XSD references (called System Identifier) present in the allowed list provided.

    The code is based on the validation implemented into the OpenJDK 21, by the class java.util.prefs.XmlSupport, in the method loadPrefsDoc().

    The method also ensure that no Public Identifier is used to prevent potential bypasses of the validations.
    static boolean
    isXMLSafe(String xmlFilePath)
    Ensure that an XML file does not contain any External Entity, DTD or XInclude instructions.
    static boolean
    isZIPSafe(String zipFilePath, int maxLevelDeepness, boolean rejectArchiveFile)
    Apply a collection of validations on a ZIP file provided: Real ZIP file. Contain less than a specified level of deepness. Do not contain Zip-Slip entry path.
    static byte[]
    sanitizeFile(String inputFilePath, InputFileType inputFileType)
    Rewrite the input file to remove any embedded files that is not embedded using a methods supported by the official format of the file.
    Example: a file can be embedded by adding it to the end of the source file, see the reference provided for details.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • isWeakPINCode

      public static boolean isWeakPINCode(String pinCode)
      Apply a collection of validation to verify if a provided PIN code is considered weak (easy to guess) or none.
      This method consider that format of the PIN code is [0-9]{6,}
      Rule to consider a PIN code as weak:
      • Length is inferior to 6 positions.
      • Contain only the same number or only a sequence of zero.
      • Contain sequence of following incremental or decremental numbers.
      Parameters:
      pinCode - PIN code to verify.
      Returns:
      True only if the PIN is considered as weak.
    • isWord972003DocumentSafe

      public static boolean isWord972003DocumentSafe(String wordFilePath)
      Apply a collection of validations on a Word 97-2003 (binary format) document file provided:
      • Real Microsoft Word 97-2003 document file.
      • No VBA Macro.
      • No embedded objects.
      Parameters:
      wordFilePath - Filename of the Word document file to check.
      Returns:
      True only if the file pass all validations.
      See Also:
      • "https://poi.apache.org/components/"
      • "https://poi.apache.org/components/document/"
      • "https://poi.apache.org/components/poifs/how-to.html"
      • "https://poi.apache.org/components/poifs/embeded.html"
      • "https://poi.apache.org/"
      • "https://mvnrepository.com/artifact/org.apache.poi/poi"
    • isXMLSafe

      public static boolean isXMLSafe(String xmlFilePath)
      Ensure that an XML file does not contain any External Entity, DTD or XInclude instructions.
      Parameters:
      xmlFilePath - Filename of the XML file to check.
      Returns:
      True only if the file pass all validations.
      See Also:
      • "https://portswigger.net/web-security/xxe"
      • "https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java"
      • "https://docs.oracle.com/en/java/javase/13/security/java-api-xml-processing-jaxp-security-guide.html#GUID-82F8C206-F2DF-4204-9544-F96155B1D258"
      • "https://www.w3.org/TR/xinclude-11/"
      • "https://en.wikipedia.org/wiki/XInclude"
    • extractAllPDFLinks

      public static List<URL> extractAllPDFLinks(String pdfFilePath) throws Exception
      Extract all URL links from a PDF file provided.
      This can be used to apply validation on a PDF against contained links.
      Parameters:
      pdfFilePath - pdfFilePath Filename of the PDF file to process.
      Returns:
      A List of URL objects that is empty if no links is found.
      Throws:
      Exception - If any error occurs during the processing of the PDF file.
      See Also:
      • "https://www.gushiciku.cn/pl/21KQ"
      • "https://pdfbox.apache.org/"
      • "https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox"
    • isPDFSafe

      public static boolean isPDFSafe(String pdfFilePath)
      Apply a collection of validations on a PDF file provided:
      • Real PDF file.
      • No attachments.
      • No Javascript code.
      • No links using action of type URI/Launch/RemoteGoTo/ImportData.
      Parameters:
      pdfFilePath - Filename of the PDF file to check.
      Returns:
      True only if the file pass all validations.
      See Also:
      • "https://stackoverflow.com/a/36161267"
      • "https://www.gushiciku.cn/pl/21KQ"
      • "https://github.com/jonaslejon/malicious-pdf"
      • "https://pdfbox.apache.org/"
      • "https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox"
    • clearPDFMetadata

      public static void clearPDFMetadata(org.apache.pdfbox.pdmodel.PDDocument document)
      Remove as much as possible metadata from the provided PDF document object.
      Parameters:
      document - PDFBox PDF document object on which metadata must be removed.
      See Also:
      • "https://gist.github.com/righettod/d7e07443c43d393a39de741a0d920069"
      • "https://pdfbox.apache.org/"
      • "https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox"
    • isRelativeURL

      public static boolean isRelativeURL(String targetUrl)
      Validate that the URL provided is really a relative URL.
      Parameters:
      targetUrl - URL to validate.
      Returns:
      True only if the file pass all validations.
      See Also:
      • "https://portswigger.net/web-security/ssrf"
      • "https://stackoverflow.com/q/6785442"
    • isZIPSafe

      public static boolean isZIPSafe(String zipFilePath, int maxLevelDeepness, boolean rejectArchiveFile)
      Apply a collection of validations on a ZIP file provided:
      • Real ZIP file.
      • Contain less than a specified level of deepness.
      • Do not contain Zip-Slip entry path.
      Parameters:
      zipFilePath - Filename of the ZIP file to check.
      maxLevelDeepness - Threshold of deepness above which a ZIP archive will be rejected.
      rejectArchiveFile - Flag to specify if presence of any archive entry will cause the rejection of the ZIP file.
      Returns:
      True only if the file pass all validations.
      See Also:
      • "https://rules.sonarsource.com/java/type/Security%20Hotspot/RSPEC-5042"
      • "https://security.snyk.io/research/zip-slip-vulnerability"
      • "https://en.wikipedia.org/wiki/Zip_bomb"
      • "https://github.com/ptoomey3/evilarc"
      • "https://github.com/abdulfatir/ZipBomb"
      • "https://www.baeldung.com/cs/zip-bomb"
      • "https://thesecurityvault.com/attacks-with-zip-files-and-mitigations/"
      • "https://wiki.sei.cmu.edu/confluence/display/java/IDS04-J.+Safely+extract+files+from+ZipInputStream"
    • identifyMimeType

      public static String identifyMimeType(byte[] content)
      Identify the mime type of the content specified (array of bytes).
      Note that it cannot be fully trusted (see the tweet '1595824709186519041' referenced), so, additional validations are required.
      Parameters:
      content - The content as an array of bytes.
      Returns:
      The mime type in lower case or null if it cannot be identified.
      See Also:
      • "https://twitter.com/righettod/status/1595824709186519041"
      • "https://tika.apache.org/"
      • "https://mvnrepository.com/artifact/org.apache.tika/tika-core"
      • "https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types"
      • "https://www.iana.org/assignments/media-types/media-types.xhtml"
    • isPublicIPAddress

      public static boolean isPublicIPAddress(String ip)
      Apply a collection of validations on a string expected to be an public IP address:
      • Is a valid IP v4 or v6 address.
      • Is public from an Internet perspective.

      Note: I often see missing such validation in the value read from HTTP request headers like "X-Forwarded-For" or "Forwarded".

      Note for IPv6: I used documentation found so it is really experimental!
      Parameters:
      ip - String expected to be a valid IP address.
      Returns:
      True only if the string pass all validations.
      See Also:
      • "https://commons.apache.org/proper/commons-validator/"
      • "https://commons.apache.org/proper/commons-validator/apidocs/org/apache/commons/validator/routines/InetAddressValidator.html"
      • "https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html"
      • "https://cheatsheetseries.owasp.org/assets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet_Orange_Tsai_Talk.pdf"
      • "https://cheatsheetseries.owasp.org/assets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet_SSRF_Bible.pdf"
      • "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For"
      • "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded"
      • "https://ipcisco.com/lesson/ipv6-address/"
      • "https://www.juniper.net/documentation/us/en/software/junos/interfaces-security-devices/topics/topic-map/security-interface-ipv4-ipv6-protocol.html"
      • "https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/InetAddress.html#getByName(java.lang.String)"
      • "https://www.arin.net/reference/research/statistics/address_filters/"
      • "https://en.wikipedia.org/wiki/Multicast_address"
      • "https://stackoverflow.com/a/5619409"
      • "https://www.ripe.net/media/documents/ipv6-address-types.pdf"
      • "https://www.iana.org/assignments/ipv6-unicast-address-assignments/ipv6-unicast-address-assignments.xhtml"
      • "https://developer.android.com/reference/java/net/Inet6Address"
      • "https://en.wikipedia.org/wiki/Unique_local_address"
    • computeHashNoProneToAbuseOnParts

      public static byte[] computeHashNoProneToAbuseOnParts(List<String> parts) throws Exception
      Compute a SHA256 hash from an input composed of a collection of strings.

      This method take care to build the source string in a way to prevent this source string to be prone to abuse targeting the different parts composing it.

      Example of possible abuse without precautions applied during the hash calculation logic:
      Hash of SHA256("Hello", "My", "World!!!") will be equals to the hash of SHA256("Hell", "oMyW", "orld!!!").

      This method ensure that both hash above will be different.

      Note: The character | is used, as separator, of every parts so a part is not allowed to contains this character.
      Parameters:
      parts - Ordered list of strings to use to build the input string for which the hash must be computed on. No null value is accepted on object composing the collection.
      Returns:
      The hash, as an array of bytes, to allow caller to convert it to the final representation wanted (HEX, Base64, etc.). If the collection passed is null or empty then the method return null.
      Throws:
      Exception - If any exception occurs
      See Also:
      • "https://github.com/righettod/code-snippets-security-utils/issues/16"
      • "https://pentesterlab.com/badges/codereview"
      • "https://blog.trailofbits.com/2024/08/21/yolo-is-not-a-valid-hash-construction/"
      • "https://www.nist.gov/publications/sha-3-derived-functions-cshake-kmac-tuplehash-and-parallelhash"
    • isXMLOnlyUseAllowedXSDorDTD

      public static boolean isXMLOnlyUseAllowedXSDorDTD(String xmlFilePath, List<String> allowedSystemIdentifiers)
      Ensure that an XML file only uses DTD/XSD references (called System Identifier) present in the allowed list provided.

      The code is based on the validation implemented into the OpenJDK 21, by the class java.util.prefs.XmlSupport, in the method loadPrefsDoc().

      The method also ensure that no Public Identifier is used to prevent potential bypasses of the validations.
      Parameters:
      xmlFilePath - Filename of the XML file to check.
      allowedSystemIdentifiers - List of URL allowed for System Identifier specified for any XSD/DTD references.
      Returns:
      True only if the file pass all validations.
      See Also:
      • "https://www.w3schools.com/xml/prop_documenttype_systemid.asp"
      • "https://www.ibm.com/docs/en/integration-bus/9.0.0?topic=doctypedecl-xml-systemid"
      • "https://www.liquid-technologies.com/Reference/Glossary/XML_DocType.html"
      • "https://www.xml.com/pub/98/08/xmlqna0.html"
      • "https://github.com/openjdk/jdk/blob/jdk-21%2B35/src/java.prefs/share/classes/java/util/prefs/XmlSupport.java#L397"
      • "https://en.wikipedia.org/wiki/Formal_Public_Identifier"
    • isExcelCSVSafe

      public static boolean isExcelCSVSafe(String csvFilePath)
      Apply a collection of validations on a EXCEL CSV file provided (file was expected to be opened in Microsoft EXCEL):
      • Real CSV file.
      • Do not contains any payload related to a CSV injections.
      Ensure that, if Apache Commons CSV does not find any record then, the file will be considered as NOT safe (prevent potential bypasses).

      Note: Record delimiter used is the , (comma) character. See the Apache Commons CSV reference provided for EXCEL.
      Parameters:
      csvFilePath - Filename of the CSV file to check.
      Returns:
      True only if the file pass all validations.
      See Also:
      • "https://commons.apache.org/proper/commons-csv/"
      • "https://commons.apache.org/proper/commons-csv/apidocs/org/apache/commons/csv/CSVFormat.html#EXCEL"
      • "https://www.we45.com/post/your-excel-sheets-are-not-safe-heres-how-to-beat-csv-injection"
      • "https://www.whiteoaksecurity.com/blog/2020-4-23-csv-injection-whats-the-risk/"
      • "https://book.hacktricks.xyz/pentesting-web/formula-csv-doc-latex-ghostscript-injection"
      • "https://owasp.org/www-community/attacks/CSV_Injection"
      • "https://payatu.com/blog/csv-injection-basic-to-exploit/"
      • "https://cwe.mitre.org/data/definitions/1236.html"
    • ensureSerializedObjectIntegrity

      public static Map<String,Object> ensureSerializedObjectIntegrity(ProcessingMode processingMode, String input, byte[] secret) throws Exception
      Provide a way to add an integrity marker (HMAC) to a serialized object serialized using the java native system (binary).
      The goal is to provide a temporary workaround to try to prevent deserialization attacks and give time to move to a text-based serialization approach.
      Parameters:
      processingMode - Define the mode of processing i.e. protect or validate. (ProcessingMode)
      input - When the processing mode is "protect" than the expected input (string) is a java serialized object encoded in Base64 otherwise (processing mode is "validate") expected input is the output of this method when the "protect" mode was used.
      secret - Secret to use to compute the SHA256 HMAC.
      Returns:
      A map with the following keys:
      • PROCESSING_MODE: Processing mode used to compute the result.
      • STATUS: A boolean indicating if the processing was successful or not.
      • RESULT: Always contains a string representing the protected serialized object in the format [SERIALIZED_OBJECT_BASE64_ENCODED]:[SERIALIZED_OBJECT_HMAC_BASE64_ENCODED].
      Throws:
      Exception - If any exception occurs.
      See Also:
      • "https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html"
      • "https://owasp.org/www-project-top-ten/2017/A8_2017-Insecure_Deserialization"
      • "https://portswigger.net/web-security/deserialization"
      • "https://www.baeldung.com/java-serialization-approaches"
      • "https://www.baeldung.com/java-serialization"
      • "https://cryptobook.nakov.com/mac-and-key-derivation/hmac-and-key-derivation"
      • "https://en.wikipedia.org/wiki/HMAC"
      • "https://smattme.com/posts/how-to-generate-hmac-signature-in-java/"
    • isJSONSafe

      public static boolean isJSONSafe(String json, int maxItemsByArraysCount, int maxDeepnessAllowed)
      Apply a collection of validations on a JSON string provided:
      • Real JSON structure.
      • Contain less than a specified number of deepness for nested objects or arrays.
      • Contain less than a specified number of items in any arrays.

      Note: I decided to use a parsing approach using only string processing to prevent any StackOverFlow or OutOfMemory error that can be abused.

      I used the following assumption:
      • The character { identify the beginning of an object.
      • The character } identify the end of an object.
      • The character [ identify the beginning of an array.
      • The character ] identify the end of an array.
      • The character " identify the delimiter of a string.
      • The character sequence \" identify the escaping of an double quote.
      Parameters:
      json - String containing the JSON data to validate.
      maxItemsByArraysCount - Maximum number of items allowed in an array.
      maxDeepnessAllowed - Maximum number nested objects or arrays allowed.
      Returns:
      True only if the string pass all validations.
      See Also:
      • "https://javaee.github.io/jsonp/"
      • "https://community.f5.com/discussions/technicalforum/disable-buffer-overflow-in-json-parameters/124306"
      • "https://github.com/InductiveComputerScience/pbJson/issues/2"
    • isImageSafe

      public static boolean isImageSafe(String imageFilePath, List<String> imageAllowedMimeTypes)
      Apply a collection of validations on a image file provided:
      • Real image file.
      • Its mime type is into the list of allowed mime types.
      • Its metadata fields do not contains any characters related to a malicious payloads.

      Important note: This implementation is prone to bypass using the "raw insertion" method documented in the blog post from the Synacktiv team. To handle such case, it is recommended to resize the image to remove any non image-related content, see here for an example.
      Parameters:
      imageFilePath - Filename of the image file to check.
      imageAllowedMimeTypes - List of image mime types allowed.
      Returns:
      True only if the file pass all validations.
      See Also:
      • "https://commons.apache.org/proper/commons-imaging/"
      • "https://commons.apache.org/proper/commons-imaging/formatsupport.html"
      • "https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types"
      • "https://www.iana.org/assignments/media-types/media-types.xhtml#image"
      • "https://www.synacktiv.com/en/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there"
      • "https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html"
      • "https://github.com/righettod/document-upload-protection/blob/master/src/main/java/eu/righettod/poc/sanitizer/ImageDocumentSanitizerImpl.java"
      • "https://exiftool.org/examples.html"
      • "https://en.wikipedia.org/wiki/List_of_file_signatures"
      • "https://hexed.it/"
      • "https://github.com/sighook/pixload"
    • sanitizeFile

      public static byte[] sanitizeFile(String inputFilePath, InputFileType inputFileType) throws Exception
      Rewrite the input file to remove any embedded files that is not embedded using a methods supported by the official format of the file.
      Example: a file can be embedded by adding it to the end of the source file, see the reference provided for details.
      Parameters:
      inputFilePath - Filename of the file to clean up.
      inputFileType - Type of the file provided.
      Returns:
      A array of bytes with the cleaned file.
      Throws:
      IllegalArgumentException - If an invalid parameter is passed
      Exception - If any technical error during the cleaning processing
      See Also:
      • "https://www.synacktiv.com/en/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there"
      • "https://github.com/righettod/toolbox-pentest-web/tree/master/misc"
      • "https://github.com/righettod/toolbox-pentest-web?tab=readme-ov-file#misc"
      • "https://stackoverflow.com/a/13605411"
    • isEmailAddress

      public static boolean isEmailAddress(String addr)
      Apply a collection of validations on a string expected to be an email address:
      • Is a valid email address, from a parser perspective, following RFCs on email addresses.
      • Is not using "Encoded-word" format.
      • Is not using comment format.
      • Is not using "Punycode" format.
      • Is not using UUCP style addresses.
      • Is not using address literals.
      • Is not using source routes.
      • Is not using the "percent hack".

      This is based on the research work from Gareth Heyes added in references (Portswigger).

      Note: The notion of valid, here, is to take from a secure usage of the data perspective.
      Parameters:
      addr - String expected to be a valid email address.
      Returns:
      True only if the string pass all validations.
      See Also:
      • "https://commons.apache.org/proper/commons-validator/"
      • "https://commons.apache.org/proper/commons-validator/apidocs/org/apache/commons/validator/routines/EmailValidator.html"
      • "https://datatracker.ietf.org/doc/html/rfc2047#section-2"
      • "https://portswigger.net/research/splitting-the-email-atom"
      • "https://www.jochentopf.com/email/address.html"
      • "https://en.wikipedia.org/wiki/Email_address"
    • isPSD2StetSafeCertificateURL

      public static boolean isPSD2StetSafeCertificateURL(String certificateUrl)
      The PSD2 STET specification require to use HTTP Signature.
      Section 3.5.1.2 of the document Documentation Framework version 1.6.3.
      The problem is that, by design, the HTTP Signature specification is prone to blind SSRF.
      URL example taken from the STET specification: https://path.to/myQsealCertificate_714f8154ec259ac40b8a9786c9908488b2582b68b17e865fede4636d726b709f.
      The objective of this code is to try to decrease the "exploitability/interest" of this SSRF for an attacker.
      Parameters:
      certificateUrl - Url pointing to a Qualified Certificate (QSealC) encoded in PEM format and respecting the ETSI/TS119495 technical Specification .
      Returns:
      TRUE only if the url point to a Qualified Certificate in PEM format.
      See Also:
      • "https://www.stet.eu/en/psd2/"
      • "https://www.stet.eu/assets/files/PSD2/1-6-3/api-dsp2-stet-v1.6.3.1-part-1-framework.pdf"
      • "https://datatracker.ietf.org/doc/draft-cavage-http-signatures/"
      • "https://datatracker.ietf.org/doc/rfc9421/"
      • "https://openjdk.org/groups/net/httpclient/intro.html"
      • "https://docs.oracle.com/en/java/javase/21/docs/api/java.net.http/java/net/http/package-summary.html"
      • "https://portswigger.net/web-security/ssrf"
      • "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control"
    • applyURLDecoding

      public static String applyURLDecoding(String encodedData, int decodingRoundThreshold) throws SecurityException
      Perform sequential URL decoding operations against a URL encoded data until the data is not URL encoded anymore or if the specified threshold is reached.
      Parameters:
      encodedData - URL encoded data.
      decodingRoundThreshold - Threshold above which decoding will fail.
      Returns:
      The decoded data.
      Throws:
      SecurityException - If the threshold is reached.
      See Also:
      • "https://en.wikipedia.org/wiki/Percent-encoding"
      • "https://owasp.org/www-community/Double_Encoding"
      • "https://portswigger.net/web-security/essential-skills/obfuscating-attacks-using-encodings"
      • "https://capec.mitre.org/data/definitions/120.html"
    • isPathSafe

      public static boolean isPathSafe(String path)
      Apply a collection of validations on a string expected to be an system file/folder path:
      • Does not contains path traversal payload.
      • The canonical path is equals to the absolute path.

      Parameters:
      path - String expected to be a valid system file/folder path.
      Returns:
      True only if the string pass all validations.
      See Also:
      • "https://portswigger.net/web-security/file-path-traversal"
      • "https://learn.snyk.io/lesson/directory-traversal/"
      • "https://capec.mitre.org/data/definitions/126.html"
      • "https://owasp.org/www-community/attacks/Path_Traversal"
    • isXMLHaveCommentsOrXSLProcessingInstructions

      public static boolean isXMLHaveCommentsOrXSLProcessingInstructions(String xmlFilePath)
      Identify if an XML contains any XML comments or have any XSL processing instructions.
      Stream reader based parsing is used to support large XML tree.
      Parameters:
      xmlFilePath - Filename of the XML file to check.
      Returns:
      True only if XML comments or XSL processing instructions are identified.
      See Also:
      • "https://www.tutorialspoint.com/xml/xml_processing.htm"
      • "https://docs.oracle.com/en/java/javase/21/docs/api/java.xml/javax/xml/stream/XMLInputFactory.html"
      • "https://portswigger.net/kb/issues/00400700_xml-entity-expansion"
      • "https://www.w3.org/Style/styling-XML.en.html"