Tuesday, May 7, 2024

Bypassing Certificate Pinning on Flutter-based Android Apps. A new guide.

One of the preliminary activities when analyzing mobile application, more usually than not, is to be able to sniff HTTP/S traffic via a MitM proxy
This is quite straightforward in the case of naive applications, but can be quite challenging when applications use certificate pinning techniques. In this post I'll try to explain the methodology I used to make this possible for a Flutter-based Android sample application in a reliable way.

Introduction

It was indeed the need to bypass a certificate validation on a Flutter framework during a mobile application penetration testing activity for a customer of ours, that led to this research. 

As a first approach, as usual, we tried some of the specific exploits/bypasses we found on the web. 
Alas, in this case, they failed.

Some of the main concepts that are going to be explained, actually, overlap in what those articles contain; what it differs is the technique used for identifying and hooking at runtime the routine used for certificate verification.

While minimizing effort was a key objective in bypassing certificate pinning controls, the chosen approach turned out to be overly generic.  Unlike pattern matching techniques, which can be tailored to specific scenarios, this method becomes unreliable across different platforms, architectures, and even builds.

While the article's findings may not address all the case studies, it proposes an effective methodology that can be readily applied, with minimal adjustments, to similar scenarios. 

Moreover, as a different approach, reFlutter would be a valid tool for such a similar job. Anyway, as it statically patches code to deactivate runtime checks, if the mobile application was signed and/or had file integrity checks, static approach would definitely be challenging.  

In the next paragraphs, we're going to cover the following topics:
  • Why Flutter is so different
  • Flutter based APK structure
  • Force traffic forwarding to my proxy
  • Diving into BoringSSL source code
  • Reverse-engineering on libflutter.so
  • Frida hooking script
Finally, in order to give some testbed, we created a basic Flutter application which fetches data from the URL https://dummy.restapi.example.ltd/api/v1/employees, using code that correctly implements certificate pinning.
The entire application code, the build and the Frida script are available on Github at the following link:



Why Flutter is so Different

This is, obviously, not the first time we have to deal with bypassing certificate pinning, so, why is Flutter so different from other scenarios?
  • Flutter is a Google's open source portable toolkit able to create natively compiled applications for mobile, web, and desktop from a single codebase. 
  • The final Flutter applications are written in Dart, whilst the framework engine is built mainly in C++. 
  • The compilation obviously differs on the target platform: for Android, the engine is compiled using the Android's NDK (for this blogpost we are going to focus only on the Android ARMv8 platform). 

In this development environment more blazoned SSL pinning bypass methodswould not work, as the real checks are implemented in "native code", thus results compiled in machine code and many details may change among different framework builds. 

In addition, for our activities of analysis of the HTTP request sent to remote servers we would like to forward the application's traffic throughout a forward HTTP proxy:
- the first idea that an unaware analyst could have is to set this in the Network settings of Android system, but this would not work at all. 

Flutter, at low level, uses dart:io library for managing socket, file and other I/O support in non browser-based applications. 
As dart:io documentation says, by default the HttpClient uses the proxy configuration available from the environment, i.e it will take into account enviroment variables http_proxy, https_proxy, no_proxy, HTTP_PROXY, HTTPS_PROXY, NO_PROXY which, on Android based OSs, are not affected by any settings change, since every application runs in a child process of Zygote inheriting its environment variables, that are loaded at system boot.

Flutter Based APK Structure

The resource/lib folder inside the APK contains the compiled Dart code (compiled to native binary code using the Dart VM's Ahead-of-Time compilation) for the Flutter application. 
The compiled code is stored in various folders organized according to the target platform, such as arm64-v8a for 64-bit ARM, armeabi-v7a  for 32-bit ARM etc. 
Specifically the two main shared objects are:
  • libapp.so: which contains the compiled native code that corresponds to the Dart code of your Flutter app. This native code is executed when the Flutter app is launched on a device.
  • libflutter.socontaining the native code of the Flutter engine, which powers the Flutter framework and enables the execution of Flutter apps on Android devices. This library includes the core functionalities of the Flutter framework

Forcing Traffic Forwarding to the Proxy

We know that the Flutter application will not honor the proxy settings at system level, thus we need a finer technique for fundamental part.
Once granted root privileges on our Android device (Google Pixel 4a), we have the possibility to set an iptables rule for the redirection of the desired HTTP traffic table throughout the a Burp Pro proxy instance running on my laptop:

  1. connect the android device via USB and run an adb shell as root.
    adb shell su
  2. setup the redirection:
    iptables -t nat -A OUTPUT -p tcp -d destination-host.domain --dport 443 \-j DNAT --to-destination 127.0.0.1:8080
  3. reverse map the port 8080 of the android device over the proxy running on my laptop on port 8080:
    adb reverse tcp:8080 tcp:8080
Note: proxydroid could also be adopted equivalently to the iptables rule: it is just a frontend for iptables.

Finally, it is also important to point out that we need to set up our Burp listening server as invisible, so that it won't be necessary to explicitly set a proxy on the device, and the proxy itself will act as a perfect man-in-the-middle and directly intercept the SSL/TLS handshaking.  

At this point the traffic is redirected to Burp as shown in a screenshot of the test application taken just after the triggering of the sample HTTP request and after the setting up of the proxy interception:

Sample application's error message after having forced traffic to Burp Pro proxy instance


The error is pretty verbose about the code which triggered the HandshakeException.
Someone at this point might say: "Well, production applications usually don't show such verbose errors!"
We're using our test bed, once we have the know-how to bypass such controls, we'll be able to replicate it to any Flutter-based application. 

Diving into BoringSSL Source Code

Flutter Engine relies on boringssl library for SSL/TLS implementation, which is the Google's fork of the well known openssl. 
As the error suggested, the certificate verification which trapped was performed in boringssl/ssl/handshake.cc at line 393, coherently with what displayed in the previous screenshot, there is the raising of the represented error concerning the failure of the certificate verification. 

Point of triggering in BoringSSL source code of the TLS certificate verification error


The interesting part of this function is the else block immediately above: assuming no custom_verify_callback has been set, the code is invoking ssl->ctx->x509_method->session_verify_cert_chain and is setting ret by evaluating the boolean result of the same. 

That method is a function pointer referring ssl_crypto_x509_session_verify_cert_chain, which is defined in borisngssl/ssl/ssl_x509.cc. To bypass the check was only needed to make this function return always true.  

Reverse-Engineering on libflutter.so

At this point, we unpack the application's apk and open in IDA the resources/lib/arm64-v8a/libflutter.so shared object; which is the Flutter core engine natively compiled for the platform Android ARM64
The ELF file was stripped and had just a single exported symbol: JNI_Onload (address 0x00382940). For this reason, identifying the portion of assembly which was related to ssl_crypto_x509_session_verify_cert_chain was not so trivial.

Here follows the integral source code of that function.

ssl_crypto_x509_session_verify_cert_chain implementation taken from BoringSSL repository

As it can be seen, the function at a certain point uses two string literals: "ssl_client" and "ssl_server". Those are both stored in the .rodata section of libflutter.so. So, the strategy used was to analyze the XREFS (cross-references) of those strings to find a function which locally addressed both. The single procedure which used both was that at address 0x005FDF64.

Decompiled ssl_crypto_x509_session_verify_cert_chain by IDA Pro 7.7 


Frida Hooking Script

After identifying the native subroutine that should have been hooked, it is possible to implement a simple Frida script to intercept calls to the function  ssl_crypto_x509_session_verify_cert_chain and force its return value to true (i.e., 0x01).
To find the absolute address which depends on the memory mapping of libflutter.so into application proces,s the reader will have to:
  • Calculate the relative logical offset between ssl_crypto_x509_session_verify_cert_chain and JNI_Onload: this is done by simply subtract the JNI_Onload logical address inside libflutter.so, which is readable into the shared object exports table, to the ssl_crypto_x509_session_verify_cert_chain logical address address, whose value was previously found with the technique shown in the previous section; in this sample analysis they are respectively 0x005FDF64 and 0x00382940, thus the resulting offset would be:
     0x005FDF64 - 0x00382940 = 0x0027b624.
  • Since JNI_OnLoad is an exported symbol, the dynamic linker updates the global offset table (GOT) upon its first invocation. This update provides the logical address of JNI_OnLoad relative to the shared object's memory layout within the process.  Therefore, we can easily access it using the enumerateExports() method in the Frida script.
  • Add the offset obtained to the JNI_Onload address for this process, to get the current ssl_crypto_x509_session_verify_cert_chain address (i.e. the address to which the function 



function hook_ssl_crypto_x509_session_verify_cert_chain(address){
Interceptor.attach(address, {
onEnter: function(args) { console.log("Disabling SSL certificate validation") },
onLeave: function(retval) { console.log("Retval: " + retval); retval.replace(0x1);}
});
}
function disable_certificate_validation(){
var m = Process.findModuleByName("libflutter.so");
console.log("libflutter.so loaded at ", m.base);
var jni_onload_addr = m.enumerateExports()[0].address;
console.log("jni_onload_address: ", jni_onload_addr);
// Adding the offset between
// ssl_crypto_x509_session_verify_cert_chain and JNI_Onload = 0x0027b624
let addr = ptr(jni_onload_addr).add(0x0027b624);
console.log("ssl_crypto_x509_session_verify_cert_chain_addr: ", addr);
let buf = Memory.readByteArray(addr, 12);
console.log(hexdump(buf, { offset: 0, length: 64, header: false, ansi: false}));
hook_ssl_crypto_x509_session_verify_cert_chain(addr);

}
setTimeout(disable_certificate_validation, 1000)




Conclusion

At this point we are ready to execute Frida server via adb and run the above script with this command:
frida -U -f com.application -l script.js
We managed to bypass the certificate verification and intercepted HTTPS traffic:


Frida script launching 



Here follows the result of the bypass, showing the Burp Pro intercepting the request and its related response.

 

Request triggered by the Flutter App intercepted by Burp Pro




Wednesday, April 17, 2024

Semgrep Rules for iOS Application Security (Swift)


Swift_security

Nowadays, millions of people rely on iOS mobile applications for almost everything. As a result iOS devices manage a significant amount of data including sensitive ones, such as: credentials, health data, payment data and so on. 

For these reasons ensuring the security of iOS applications is more critical than ever when developing iOS applications. Securely handling sensitive data and minimizing vulnerabilities are essential core concepts for developers when coding iOS applications, using Swift and Objective-C languages.

Swift is an open-source object-oriented language mostly used on Apple platforms, which  allows to write software for various environments and devices such as: phones, tablets, desktops, servers, etc.

To harden the attack surface of the iOS applications it is crucial to analyze and test the code both manually and using automatic tools throughout the SDLC. 

This can be achieved by combining: 

  • SCA (Software Composition Analysis) is the process that aims to identify the versions of the open source dependencies used by the application, and then verify if there are known vulnerabilities related to them.
  • DAST (Dynamic Analysis Security Testing) is the process of testing an application while it is running in order to detect security weaknesses and vulnerabilities present on it.
  • SAST (Static Analysis Security Testing) is a testing process focused in the static analysis of the source code to find security flaws and marking their precise location.

SAST, Swift and Semgrep

SAST involves the comprehensive examination of an application's source code to identify and rectify security vulnerabilities, coding errors, and potential threats. 

This process aims to uncover weaknesses that could be exploited by malicious threat actors to compromise the integrity, confidentiality, or availability of the application and its associated data.

In particular, focusing on SAST tools for iOS applications, currently it is difficult to find an efficient automated tool able to analyze adequately Swift code-bases (especially regarding open-source SAST tools). In fact, in some cases performing source code analysis of iOS applications could be complicated and cumbersome. 

In the information security landscape various SAST tools are available (open and closed source software), in these recent years undoubtedly Semgrep (semantic grep) is the one that is gaining increasing fame.

Semgrep OSS is a fast, open-source, static analysis tool for searching code, finding bugs, and enforcing code standards at editor, commit, and CI time. It supports many different languages and package managers, and it comes with a number of other tools to help make static analysis intuitive, accessible and integrated into CI/CD pipelines. 

Semgrep OSS permit to perform intra-file analysis, and together with it also is provided a collection of pre-written rules and testing code excerpts in its public-free Registry. Additionally, any "semgrepper" user could create his custom rules for any of the supported languages and test/enhance them using the public-free Semgrep Playground.

This SAST tool could be useful during secure source code review activities, in particular are appreciable its efficiency, speed, ease of use/configuration and rule's customization. 

For instance, supposing you want detect all the occurrences of a peculiar vulnerability that has been found during manual code analysis. If this vulnerability is not recognized by the public Semgrep rules, it would be very helpful writing a custom rule to identify the other occurrences of the same vulnerable code pattern, especially when analyzing large volumes of code.

No Country for Old Rules

Due the complete absence of Semgrep rules regarding iOS applications security for Swift code (Objective-C is not yet supported), in late 2022 I decided to create and publish my first Semgrep rule-set for Swift based mobile applications: 

akabe1-semgrep-rules

with the aim to fill this gap, and of course to improve my knowledge on how Semgrep works and to speed-up source code analysis activities during my work at IMQ MindedSecurity.

With pleasure I noticed that the project has aroused interest in the security community, maybe because it was the first one for Swift.. 

Even better! The rules are also currently used by some security products that integrate code scanners to CI/CD pipelines.

For each Semgrep rule, as other tools, points for improvement can be identified during their usage. In fact, a Semgrep rule-set could necessitate periodic tuning in terms of efficiency and code coverage, then new rules could be added and existent ones could be improved. Furthermore the rules should evolve as the Semgrep syntax/features change and the target code evolve. 

For these reasons, I spent some spare time this year to add new rules and make some improvements to the existing ones for the Swift security rule-set. 

The newly released rules not only increase the coverage of iOS mobile apps security issues and improve the speed, but they also further reduce the percentage of false negatives/positives.

For the sake of completeness, it should be pointed out that currently writing Semgrep rules for Swift is not so easy. In fact, there are some obstacles to overcome during development and testing phases:

  • the Semgrep support for Swift language is still experimental, this means that some specific pattern syntax necessary to write the Swift rules are not yet completely available and functioning
  • the fact that almost all iOS mobile apps have closed source code reduces the opportunities to test extensively the Swift rules (there are few open-source Swift repos)

These problems, as can be guessed, make the development of efficient and effective Swift security rules for Semgrep a quite slow and effort-intensive process. As a result, there's always room for further improvements to my Swift rule set.

Project Details

The "akabe1-semgrep-rules" project is a collection of Semgrep rules for Swift language - there's also some rule for Java - that are based on my experiences in the security field.

The Swift rule-set cover many of the checklist of the OWASP Mobile Security Testing Guide for iOS and has been developed by studying the Apple documentation, analyzing Swift source code, and sometimes writing purposely vulnerable Swift code by myself.

For developers and testers working with Swift-based iOS applications, these Semgrep rules could be a useful resource to include into SDLC processes, in order to detect in Swift code-bases:

  • Vulnerabilities
  • Coding bad-practices
  • Security misconfiguration issues 

The rules cover a wide range of topics for iOS apps security, including:

  • Biometric Authentication issues
  • Certificate Pinning issues
  • External XML Entities (XXE) issues
  • SQL Injection issues
  • Cryptographic issues
  • Log Injection issues
  • NoSQL Injection issues
  • WebView issues
  • Insecure Storage issues
  • Keychain Settings issues
  • Critical Device Feature issues
  • Hardcoded Sensitive Data issues


Below is reported a summary table:

Security Issue Rule Name Rule Description OWASP MASTG Category
1 Biometric Authentication improper_biometric_auth Find insecure biometric authentication mechanisms MASVS-AUTH
2 Certificate Pinning afnetworking_pinning Find security misconfigurations for certificate pinnijng via AFNetworking libraries MASVS-NETWORK
3 Certificate Pinning alamofire_pinning Find security misconfigurations for certificate pinnijng via Alamofire libraries MASVS-NETWORK
4 Certificate Pinning trustkit_pinning Find security misconfigurations for certificate pinnijng via Trustkit libraries MASVS-NETWORK
5 XXE xxe Detect if the resolution of XML external entities is enabled MASVS-CODE
6 SQL Injection sqli_query Detect SQL queries built insecurely MASVS-CODE
7 Hardcoded Secrets hardcoded_secret Detect secrets hardcoded into Swift source code MASVS-STORAGE
8 Log Injection log_inj Detect if logs are written using untrusted input MASVS-CODE
9 NoSQL Injection nosql_inj Detect NoSQL queries built insecurely MASVS-CODE
10 WebView Misconfiguration improper_wkwebview Detect security misconfigurations on WKWebview MASVS-PLATFORM
11 WebView Deprecation insecure_webview Find usages of insecure/deprecated webviews (UIWebview and SFSafariViewController) MASVS-PLATFORM
12 Insecure Storage insecure_storage Find usages of cleartext storage mechanisms MASVS-STORAGE
13 Insecure Storage none_file_protection_part1 Find occurrences of some specific insufficient data protection classes MASVS-STORAGE
14 Insecure Storage none_file_protection_part2 Find occurrences of some specific insufficient data protection classes MASVS-STORAGE
15 Insecure Storage weak_file_protection_part1 Find occurrences of some specific weak data protection classes MASVS-STORAGE
16 Insecure Storage weak_file_protection_part2 Find occurrences of some specific weak data protection classes MASVS-STORAGE
17 Keychain Settings exportable_keychain Find exportable configurations of iOS Keychain MASVS-STORAGE
18 Keychain Settings weak_keychain Find weak configurations of iOS Keychain MASVS-STORAGE
19 Critical Device Features critical_device_features Find the usages of critical device features (SMS/Mail sending, phone calls) MASVS-PLATFORM
20 Broken Cryptography broken_commoncrypto Find usages of insecure cryptography MASVS-CRYPTO
21 Broken Cryptography broken_crypto_idz Find usages of insecure cryptography MASVS-CRYPTO
22 Broken Cryptography broken_cryptoswift Find usages of insecure cryptography MASVS-CRYPTO
23 Broken Cryptography broken_rncrypt Find usages of insecure cryptography MASVS-CRYPTO
24 Broken Cryptography broken_swiftcrypto_sodium Find usages of insecure cryptography MASVS-CRYPTO


Conclusions

The secure source code analysis plays a pivotal role in bolstering the security of software development, including iOS mobile applications. 

By conducting thorough static code analysis, developers/testers can identify and remediate security vulnerabilities, promote compliance with industry standards and best practices, and enhance the overall resilience of their applications against emerging threats. 

Nevertheless the manual analysis performed by security professional people remains indispensable, the introduction of SAST automated instruments with tailored rule-sets facilitates and speeds-up the secure source code reviews. 

As the mobile landscape continues to evolve, integrating secure source code analysis into the development workflow remains essential for safeguarding user data, maintaining user trust, and mitigating the risk of security breaches and cyber attacks.


Wednesday, March 6, 2024

Testing the Security of Modbus Services


ICS and Building Management Systems (BMS) support several protocols such as Modbus, Bacnet, Fieldbus and so on. Those protocols were designed to provide read/write control over sensors and actuators from a central point. 

Driven by our past experience with BMS, we decided to release our own methodology and internal tool used for proactive attack surface analysis within systems supporting the Modbus protocol.

The Modbus Protocol

Modbus is a well defined protocol described on modbus.org. It was created in 1979 and has become one of the most used standards for communication between industrial electronic devices in a wide range of buses and network.

It can be used over a variety of communication media, including serial, TCP, UDP, etc..

The application part of the protocol is quite simple. In particular, the part we are interested into is its Protocol Data Unit, which is independent from the lower layer protocols, is defined as follows:

| FUNCTION CODE | DATA |

Where FUNCTION CODE is a 1 Byte size 0-127 (0x00-0x7F) value, and DATA is a sequence of bytes that changes according to the function code.

Here is a set of function codes already defined by the protocol specification:


By setting a specific function code together with its expected set of data field values, it will be possibile to read/write the status of coils, inputs and registers, or access information about other interesting aspects such as diagnostic data.

For example the following request, queries about the status of 2 coils starting from address 0x0033 in a remote device:

 \x01\x01\x00\x33\x00\x02  

Where:

| \x01 [SlaveId] | \x01 [Function Code] | \x00\x33 [Address] | \x00\x02 [Quantity] |


As it can be noticed, that is quite similar to an API based modern application, the name of the function and its arguments:

Protocol://URL/EndPoint?Parameters=Values..

Apart from the public function codes, several codes are left as custom implementation and are reserved but not defined in the standard.



In particular 65-72 (0x41-0x48), and 100-110 (0x64-0x6e), for a total of 19 function codes, are left to the vendor/manufacturer for custom implementations.

While some of the vendors make the specification of custom functions, publicly available, with all the expected arguments and formats, in their manuals, others do not release any information.
From a security tester point of view, first questions are:

  • How can we identify if a custom Function Code is implemented but no details are available?
  • How can we find the correct set of expected arguments?
  • How can we fuzz the arguments to find security issues?

Modbus Attack Surface

As defined by the standard, if the client request presents some error the slave response will trigger specific exception codes:

| 0x80 + [Request Function Code] | 0xHH [Exception Code] | ... |

Where exceptions code are the following:



This behavior can help when testing and identifying the exposed services.

In particular, the first three exceptions will help identifying the presence of a custom function code.

  • 0x01 Unimplemented Function: Function does not exist in the present status.
  • 0x02 Function Implemented but address is not correct: Function exists but address is wrong.
  • 0x03 Function Implemented but the arguments are not correct: Function exists but provided arguments are wrong.

As you may already guessed 0x02 and 0x03 responses do actually reveal the presence of a custom function!
On the other hand 0x01 does not mean that there's no custom implementation for that requested function but just that it's not available for the status of the device and it will require some more analysis effort.

The Methodology

Apart from public function codes, where it would be quite easy to check for read/write access to data, we want to identify if there's a set of implemented custom function codes on a black box system.

According to the response, we'll identify if a function code is implemented by analyzing the response for each required function code:

for code in function_codes:


resp = send(code)

if has_exception(resp):

  switch(exception(resp)):

      case 0x01: # UNIMPLEMENTED Function Error

                    #Function does not Exist (maybe)!  

          break;

      case 0x02: # Invalid Address Error

                    #Function Exists ! 

         break;

      case 0x03: # Invalid Data Error

                    #Function Exists ! 

         break;

      default: # other codes..

         break;


the previous pseudo code shows the approach we use to identify if a custom function is implemented and where we should fuzz.

The Tool

Here comes M-SAK (the Modbus Swiss Army Knife), a pretty useful command line and library which can help for scanning and identifying custom functions on a Modbus device.
MSAK is a tool written in Python to help discovering and testing exposed standard and custom services of Modbus Servers/Slaves over Serial or TCP/IP connections. 

It also offers a highly customizable payload generator that will help the tester to perform complex scans using a simple but powerful templating format.

MSAK can help in:
- finding undocumented functions 
- fuzzing the arguments in order to find security issues or weird behavior.

For example if we want to scan all function we can just use the Service Scan option, which will scan all functions codes [1-127] using the given payload and then will print a summary grouped by response:

 $ python3 msak.py -S -d '0001'
Requested Data \x01\x01\x00\x01\x91\xD8
..
Requested Data \x01\x02\x00\x01\x91\xD8
..
Requested Data \x01\x03\x00\x01\x91\xD8
...
Requested Data \x01\x64\x00\x01\x91\xD8
...
ILLEGAL DATA VALUE
1 (0x01) Read Coils [FUN_ID|ADDRESS|TOTAL NUMBER| >BHH]
2 (0x02) Read Discrete Inputs [FUN_ID|ADDRESS|TOTAL NUMBER| >BHH]
3 (0x03) Read Holding Registers [FUN_ID|ADDRESS|TOTAL NUMBER| >BHH]
4 (0x04) Read Input Registers [FUN_ID|ADDRESS|TOTAL NUMBER| >BHH]
15 (0x0F) Write Multiple Coils [FUN_ID|ADDRESS|TOTAL NUM|BYTE COUNT|BYTE VALS >BHHBN*B]
16 (0x10) Write Multiple registers [FUN_ID|ADDRESS|TOTAL NUM|BYTE COUNT|VALS >BHHBN*H]
20 (0x14) Read File Record
ACCEPTED_WITH_RESPONSE
5 (0x05) Write Single Coil [FUN_ID|ADDRESS|COIL VALUE| >BHH]
6 (0x06) Write Single Register [FUN_ID|ADDRESS|REG VALUE| >BHH]
17 (0x11) Report Server ID (Serial Line only)  [FUN_ID >B]
105 CUSTOM
ILLEGAL FUNCTION
7 (0x07) Read Exception Status (Serial Line only) [FUN_ID >B]
8 (0x08) Diagnostics (Serial Line only) [|FUN_ID|SUB_FUN|VALUES| >BHN*H]
9 CUSTOM
10 CUSTOM
11 (0x0B) Get Comm Event Counter (Serial Line only) [FUN_ID >B]
12 (0x0C) Get Comm Event Log (Serial Line only)[FUN_ID >B]
13 CUSTOM
....
ILLEGAL DATA ADDRESS
21 (0x15) Write File Record

The result shows that a custom function 0x69 (105) was found as the device responded with a 0x03 exception (Illegal data value). We can now try to find the correct set of arguments through fuzzing using the following command: 


$ python3 msak.py -C -d '0169{R[0,0xFF,">H"]}'

Which will send 0 to 65535 requests and collect the responses.
In fact:
- 0x01 is the slave ID
- 0x69 is the service function
- R[0,0xFF,">H"] asks to generate 0-65535 sequence of payloads in for a 2 Bytes, little endian format.
- the request will be via serial port and the CRC are automatically computed.

After the whole scan, MSAK will return an output similar to the following:

{
'NO_RESPONSE':
  [ ... 
   b'\x01\x69\x36\xfe',
  ...
  ], 
'ACCEPTED_WITH_RESPONSE': 
  [ b'\x01\x69\x36\xff', 
    b'\x01\x69\x37\x00',
...
  ]
}


We have found that the undocumented function responds to arguments values of \x36\xff and \x37\x00! 
Next step is to play with this new function and see if there's some way to abuse it...
What could go wrong if an undocumented function for firmware update is found, right?! :P 

For more information, the fuzzing engine support several template patterns documented on MSAK README file.

N.B.: The fuzzing template engine is available also as a separate python library called Simple Payload Generator.

Conclusions

Although Modbus is a quite old protocol, it's still used on Build Management Systems, Industrial Control Systems and SCADA Systems. 
Apart from dealing using well defined functionalities, to  read/write sensors and controls, which could lead to very interesting security issues, the standard leaves pretty much space to vendors for implementing their own services and that might be even more interesting from a security point of view!
That's where MSAK can give its best by automating the boring part and leave all the fun to the tester!

Feel free to send us your feedback and happy hacking!

Author: Stefano Di Paola 
Twitter: @WisecWisec 

Monday, October 23, 2023

Semgrep Rules for Android Application Security

Introduction

The number of Android applications has been growing rapidly in recent years. In 2022, there were over 3.55 million Android apps available in the Google Play Store, and this number is expected to continue to grow in the years to come. The expansion of the Android app market is being driven by a number of factors, including the increasing popularity of smartphones, the growing demand for mobile apps, and the ease of developing and publishing Android apps. At the same time, the number of Android app
downloads is also growing rapidly. In 2022, there were over 255 billion Android app downloads worldwide.

For this reason, introducing automatic security controls during Mobile Application Penetration Testing (MAPT) activity and the CI phase is necessary to ensure the security of Android apps by scanning for vulnerabilities before merging into the main repository.


Decompiling Android Packages

The compilation of Android applications is a multi-step process that involves different bytecodes, compilers, and execution engines. Generally speaking, a common compilation flow is divided into three phases:

  1. Precompilation: The Java source code(".java") is converted into Java bytecode(".class").
  2. Postcompilation: The Java bytecode is converted into Dalvik bytecode(".dex").
  3. Release: The ".dex" and resource files are packed, signed and compressed into the Android App Package (APK)

Finally, the Dalvik bytecode is executed by the Android runtime (ART) environment.

Generally, the target of a Mobile Application Penetration Testing (MAPT) activity is in the form of an APK file. The decompilation of the both aforementioned bytecodes is possible and can be performed through the use of tools such as Jadx.

jadx -d ./out-dir target.apk


OWASP MAS

The OWASP MAS project is a valuable resource for mobile security professionals, providing a comprehensive set of resources to enhance the security of mobile apps. The project includes several key components:
  • OWASP MASVS: This resource outlines requirements for software architects and developers who aim to create secure mobile applications. It establishes an industry standard that can be used as a benchmark in mobile app security assessments. Additionally, it clarifies the role of software protection mechanisms in mobile security and offers requirements to verify their effectiveness.
  • OWASP MASTG: This comprehensive manual covers the processes, techniques, and tools used during mobile application security analysis. It also includes an exhaustive set of test cases for verifying the requirements outlined in the OWASP Mobile Application Security Verification Standard (MASVS). This serves as a foundational basis for conducting thorough and consistent security tests.
  • OWASP MAS Checklist: This checklist aligns with the tests described in the MASTG and provides an output template for mobile security testing.
OWASP MAS
https://mas.owasp.org/


Semgrep

Semgrep is a Static Application Security Testing (SAST) tool that performs intra-file analysis, allowing you to define code patterns for detecting misconfigurations or security issues by analyzing one file at a time in isolation. Some advantages of using Semgrep include:

  • It does not require that the source code is uploaded to an external cloud.
  • It does not require that the target source code is buildable and have all dependencies. It can work only with a single source file.
  • It is exceptionally fast.
  • It allows you to write your custom patterns very easily.
Once Semgrep is integrated into your CI pipeline, it automatically scans your code for potential vulnerabilities every time you commit changes. This helps identify and address vulnerabilities early in the development process, improving your software's security.

Key Insights on Semgrep

First of all, install Semgrep with the following command:
python3 -m pip install semgrep
Semgrep accepts two fundamental input:
  • Rules collection: A collection is composed by ".yaml" files, alternatively referred to as "rules". A rule includes a series of patterns designed to identify or exclude specific elements within the target source code.
  • Target source code: This denotes the source code subject to analysis. It may also encompass partial code or code with certain dependencies omitted.
The four main elements you can find inside a Semgrep rule yaml file are:
...Match a sequence of zero or more items such as arguments, statements, parameters, fields, characters.
"..."Match any single hardcoded string.
$AMatch variables, functions, arguments, classes, object methods, imports, exceptions, and more.
<... e ...>Match an expression ("e") that could be deeply nested within another expression.

Moreover, Semgrep provides several experimental modes that could be really useful in more difficult situations:
  • taint: It enables the data-flow analysis feature allowing to specify sources and sinks.
  • join: It allows to use multiple rules on more than one file and to join the results.
  • extract: It allows work with source file that contains different programming languages.
Suppose to have a rules collection in the directory "myrules/" and a target source code "mytarget/". To launch a Semgrep scan is very simple:
semgrep -c ./myrules ./mytarget

Wednesday, June 21, 2023

A Cool New Project: Semgrep Rules for Android Apps Security

Android Logo with a key like shape to introduce security.

In today's digital landscape, mobile application security has become an paramount concern

With the increasing number of threats targeting Android applications and the stored personal data, developers and security professionals alike are seeking robust solutions to fortify their code against potential vulnerabilities. 

That's why speeding up the time and minimizing the effort in the identification of mobile security issues has become definitely important.

We are excited to introduce our new project, focused on creating Semgrep rules specifically designed to enhance the security of Android apps.

Semgrep Rules for Android Application Security

The project provides a new set of specific rules for OWASP Mobile Security Testing Guide (MSTG), that will help to find security issues using static code analysis (SAST).

The Project

The OWASP Mobile Security Testing Guide (MSTG) is an invaluable resource for assessing the security posture of mobile applications. It provides comprehensive guidelines and best practices to identify and address potential security weaknesses. However, manually conducting these tests can be time-consuming and prone to human error. 

This is where this project come into play. 

By creating a set of Semgrep rules based on the OWASP Mobile Security Testing Guide, we aim to automate and streamline the security testing process for Android applications. 

These rules act as a way to shift left in the SDLC of Mobile apps, enabling developers and security practitioners to efficiently identify and mitigate vulnerabilities in their code. 

With Semgrep's static analysis capabilities and the knowledge base of the MSTG, we can significantly enhance the effectiveness and efficiency of mobile apps security assessments. 

Our project bridges the gap between theory and practice, empowering developers to build robust and resilient Android applications while ensuring that security remains a top priority.

Status

Since the beginning of the project to the present stage, we have continuously strived to deliver a solution to empower developers and security practitioners and defend against evolving threats and safeguard user data. 

The actual status of our project shows where it's going to be improved and where the semgrep version limitation is a blocker to create a useful rule is shown here, and every improvement will be updated as soon as it will be implemented.




Check it out now!

How to contribute:

In future posts we'll give some insight and explain how everyone can contribute to the project, in the meantime, your feedback is absolutely welcome! 

We strongly believe in the power of collaboration and community involvement, hence we invite developers, security enthusiasts, and Android app experts to actively contribute to our project through our GitHub repository. 

By participating in the project, you can contribute new Semgrep rules, suggest improvements to existing rules, report bugs, or even share insights and ideas to enhance the overall effectiveness of our Android app security framework. 

Visit our GitHub repository to explore the project, engage with fellow contributors, and make a meaningful impact in the field of mobile app security. 

Credits