Skip to content

Application Security Posts

Book Review: Art of Impossible by Steven Kotler

Book Link:

Flow Triggers

  • Intrinsic Drivers (Curiosity, Passions and Purpose [Massively Transformative Purposes])
  • Autonomy (Freedom to do)
  • Mastery (Challenge-Skills improvement)


  • List down 25 items that you are curious about. For example, you will spend your free time on researching a topic or problem, read a book on a subject, attending a lecture, watching a youtube video and keeping track of the topic in news or social media like Twitter.
  • Make sure that the listed items are specific enough so that your brain can look for patterns. If the topic is too broad (e.g. Application Security), then it will be hard to discover what exactly you want to explore.
  • Hunt for the curiosities intersections. Discover the overlapping areas between the different items that you have listed.
  • Curiosity by itself is not enough to trigger any motivation. You need to stack one curiosity on top on another. The more you stack, the more powerful the list of stacked curiosities will be to motivate you to research and learn more.
  • Whenever you recognize a new pattern between what you are curious about, your brain reward you with Dopamine.
    • Helps you to focus on the task
    • Detect more patterns by improving signal-to-noise ratio
    • Makes us feel good about doing an activity.
    • Enhance our memory on a specific subject.
  • Spend time on these intersections. Allocate 20 to 30 minutes daily on listening to podcasts, watching videos, reading articles, books, lectures, doing practical projects related to any aspects of the intersections.
    • For example, if you are interested in how solving Leetcode problems can help to improve your programming skills. You might try to read a few pages on a Data Structure and Algorithm (DSA) topics. Then try to solve 1 related question to the topic that you are reading. Or you might read a specific book on the programming language such as Fluent Python and see how you can write better code.
  • Engage in these curiosities everyday. This will allow your brain to adapt and process the new information in the new subject slowly. This method is similar to “incubation” stage where your brain is joining the old information with the new information to form more patterns. Let our brain naturally make these connections without forcing our brain to make any discoveries.
  • Pay attention to these two things while you are engaging in your curiosities:
    • History of the subject. If you note down the historical details of the subject, your brain will create a narrative that help you to snitch the details into a coherent story that you can remember easily without effortful memorization.
    • Technical Language. There are precise definitions for jargons in the field that you need to understand in order to make better connections between what you are exploring. To communicate and understand the subject better, you need to note down the jargons definitions. The experts in the field use the jargons to explain something precisely.
  • Go Public. Before going public, make sure you spend time playing around the intersections of your curiosities. At least have some unique perspectives and ideas before going to public (online forum, book clubs, meetups etc.)


  • Write down your massively transformative purpose (MTPs). The purpose (reason why the work is done) that is large and audacious, and bring significant change to an industry, community or to the planet.
  • Look for areas where your core passions intersect with the MTPs. You want to look for the overlap between passion and purpose.

Personal Notes:

Although the book presented like an algorithmic process for triggering flow that help to accomplish the daily tasks, the process is not so linear. You might not know what are your MTP (massively transformative purposes) while reading the book. This discovery of your MTP might take time and explorations of your curiosity.

How do you even have 25 list of items that you are curious about? It can be things that you learn from books, online courses, youtube videos, internet forums, social media or from friends etc. Everytime you consume the information, take note of what you are curious about and the questions that you want to ask further on a specific area.

Reading Git Blob objects in Java

In order to read the Git Blob objects, we need to understand that git uses zlib to compress the stored objects. We can use the Java zip utils to decompress the Git blob.

Code Snippets

Below are some methods of decompressing the Blob file. If you did some research online, you will find many examples showing Method 1.

But I recommend using Method 2 as it is does not assume the size of the decompressed file. This method is also used in Apache Commons library.

Make sure the binary file is not corrupted or you might encounter

Method 1

The byte array size of result can be arbitrarily set with a specific size. But you will have problems if the decompressed file size is uncertain.

String file = "<PATH to Git blob>";
byte[] fileBytes = Files.readAllBytes(Paths.get(file));
Inflater decompresser = new Inflater();
decompresser.setInput(fileBytes, 0, fileBytes.length);

byte[] result = new byte[1024]; // Size need to be set

int resultLength = 0;
resultLength = decompresser.inflate(result);


Method 2: Checks if end of compressed data is reached

This method reads the content of the file and output to ByteArrayOutputStream object.

String file = "<PATH to Git blob>";
byte[] fileBytes = Files.readAllBytes(Paths.get(file));

Inflater inflater = new Inflater();

ByteArrayOutputStream outputStream = new ByteArrayOutputStream(fileBytes.length);
byte[] buffer = new byte[1024];

while (!inflater.finished()) {
  int count = inflater.inflate(buffer);
  outputStream.write(buffer, 0, count);


byte[] result = outputStream.toByteArray();


Notes on Finding Evasive Bugs (by James Kettle)

Highly recommend security researchers to watch this. The talk focuses more toward improving your methodology and mindset:

  1. Don’t look for defences; Start with the attacks first.
  2. Look for unfashionable flaws.
  3. Your understanding of a vulnerability concept may be corrupted. Don’t reply on internet searches to learn. Learn from the original sources.
  4. Recognise the fear from the new or unknown (Technique sounds cool but…)
  5. Recognise that you might think that something is an implausible idea. Don’t just try something and then give out if it does not work. Instead do this: Explain why the idea will not work unless condition X exists. Try the obvious to make sure that it is obviously secured.
  6. Invisible Chainlinks give you advantages. They can be related to a particular context, application specific knowledge, inconvenient. For example, param miner works well if you have the application specific knowledge.


  • Use automation to scan for clues about the application.
  • Scan to learn
    • Test Hypothesis
    • Ask question and iterate
  • When enumerating, focus on specific things rather than broad information to reduce noise.
    • Make asking questions cheap.
    • Develop your own framework.

Using snap in Kali Linux to install tools

Snap is a nice tool manager to install tools such as IDEs quickly without hassle.

Installing snap in Kali

Run these command to install snap.

$ sudo apt update
$ sudo apt install snapd
$ systemctl enable --now snapd apparmor

If you encountered below error, this is because snapd.service is not started yet.

snap install hello-world
error: cannot communicate with server: Post "http://localhost/v2/snaps/hello-world": dial unix /run/snapd.socket: connect: no such file or directory

Run the following command and you should be able to see the version

$ systemctl enable --now snapd apparmor
$ snap version                                                                                                                                                                        127 ⨯
snap    2.55.5
snapd   2.55.5
series  16
kali    2021.1
kernel  5.10.0-kali3-amd64

Installing and Running Pycharm

According to, we can install pycharm in Kali Linux using snap.

$ sudo snap install pycharm-community --classic

To run Pycharm, simply use snap run:

snap run pycharm-community



Walkthrough – Solidity Smart Lottery project

The source of the project is from:

The purpose of this walkthrough is to explain each part of the Smart Contract code with more context so that we can gain better understanding.


Think about the different processes for a lottery.

  1. Participants have to enter the lottery. We need to track down who are the participants for this lottery.
  2. We need to know how much to charge the participants for entering the lottery.
  3. Owner will need to start the lottery.
  4. Owner will end the lottery and we need a random way to calculate the winner of the lottery. And we need a robust way of generating the random winner that minimise the probability of participants cheating.
  5. We need to track the state of the lottery: whether it is opened, closed or the winner is being calculated.

Tracking Participants

We need to create an address array to track down the participants. Before we add the new player to the participant list, they have to pay an entry fee. This entry fee is calculated based on current Ether price.

address payable[] public players;

function enter() public payable {
    require(msg.value > getEntranceFee());

We can use ChainLink price feed to get the latest Ether data. To do so, we need to specify the dependencies and remappings in brownie-config.yaml file.

import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";

AggregatorV3Interface internal ethUsdPriceFeed;

function getEntranceFee() public view returns (uint256) {
    (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
    uint256 adjustedPrice = uint256(price) * 10**10;
    uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
    return costToEnter;

Walkthrough – Solidity Local Development setup (with Python)


  • Install python3 and the following python packages:
pip install web3 py-solc-x
  • VS code IDE and extensions: Solidity (Juan Blanco), Python (Microsoft)

We are going to walkthrough a tutorial created by Patrick Collins (

  • Install nodejs
  • Install ganache using yarn or npm (to simulate a local blockchain VM)

Setting and Deploying the Smart Contract

Create a new project folder and copy the sample solidity code to a new file SimpleStorage.sol:

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.9.0;

contract SimpleStorage {
    uint256 favoriteNumber;

    // This is a comment!
    struct People {
        uint256 favoriteNumber;
        string name;

    People[] public people;
    mapping(string => uint256) public nameToFavoriteNumber;

    function store(uint256 _favoriteNumber) public {
        favoriteNumber = _favoriteNumber;

    function retrieve() public view returns (uint256) {
        return favoriteNumber;

    function addPerson(string memory _name, uint256 _favoriteNumber) public {
        people.push(People(_favoriteNumber, _name));
        nameToFavoriteNumber[_name] = _favoriteNumber;

Create a file. We are going to walkthrough step-by-step to understand each part of the code.

1. Import these required modules.

from solcx import compile_standard
from solcx import install_solc
import json
import os
from web3 import Web3

2. We use solcx to compile the smart contract code. This is a python wrapper for the Solidity compiler.

First we open and read the content of the smart contract code.

Then install the solidity compiler version. It will download the compiler from the project’s Github download link.

Configure the compile standards:

  • language
  • sources
  • settings
  • solidity compiler version

We can dump the compiled code to see the structure of the code.

with open("./SimpleStorage.sol", "r") as file:
    simple_storage_file =

print("Installing solc...")

# Configure compile standards
compiled_sol = compile_standard(
        "language": "Solidity",
        "sources": {"SimpleStorage.sol": {"content": simple_storage_file}},
        "settings": {
            "outputSelection": {
                "*": {
                    "*": ["abi", "metadata", "evm.bytecode", "evm.bytecode.sourceMap"]

# Dump the compiled code to see the structure of the code
with open("compiled_code.json", "w") as file:
    json.dump(compiled_sol, file)

3. Get the bytecode and abi from the compiled code. How do we know the structure of the JSON? Refer to the compiled_code.json file

bytecode = compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["evm"]["bytecode"]["object"]

abi = compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["abi"]

4. Now start ganache server and we can see the generated dummy accounts and private keys. Note down where the server is listening.

$ ganache
ganache v7.0.2 (@ganache/cli: 0.1.3, @ganache/core: 0.1.3)
Starting RPC server

Available Accounts
(0) 0xB136383615B477B1B816f4227A509ea8F0C0c9DD (1000 ETH)
(1) 0xB6c6BDb34A834BAcc8e07c9765E2f85D1619beDc (1000 ETH)
(2) 0xb2e141ed4EF4F30BC7a1848FFbd623b19B08608C (1000 ETH)
(3) 0x32c0DB620E7355feE0254813932a4E7a454D74f8 (1000 ETH)
(4) 0xB19D507aEE3BdA3c9da9b360E491B88FFd857f14 (1000 ETH)
(5) 0x7B0929a005B39Cce2C9795558371F3865Cff1Bf9 (1000 ETH)
(6) 0x13665EC9cEE2915402BD7Ce69c05F70E9CBCF2ef (1000 ETH)
(7) 0x2C2c3C4585c9425969C03055554dD0C15f5a57b8 (1000 ETH)
(8) 0xdAD8Ae2871Cb242C001A68EB5Bc6941BFDB0d2A7 (1000 ETH)
(9) 0x85214561dCD632581a0b60BeE5989607005BE663 (1000 ETH)

Private Keys
(0) 0xa4c6bac88b45ba1e21eafbd736c92ca60b67bbfb956ccd3da37fa6f83ebe38c1
(1) 0xfa197f239d6df371b0242b8fe96b0d1883a392ff5ab4502cefae0e972f07f081
(2) 0x6c96d2d7b0fb9b56cad49887e3f198de2faa93d321240201d0572732f83bbcc8
(3) 0xd9eb1ec171c1aee37b0603b85d58b615d678f3f9c85c4e5fe31c322113d009d3
(4) 0xd6c212925da4e19a4708b43d1728efef1cf5c839fd44ee411107837b30d8e38c
(5) 0x048c50d14357791a5cbf1ecbf1febda6bf215f946bac50fac410524cde6cb397
(6) 0xb9eeb83abac9b23a5bc801e584c646f92ecb37cd4b7770100f84ea2ccdf3a304
(7) 0xad157fbf68f3e7fb3047ca653c073b4389f5020ce8d397c7c8f3533c491a15ba
(8) 0x01caede47d8ad5d0e5c125b9d4ceba7abd201a26be10730fc926f673f275fd42
(9) 0x07da7e22ff6a56ce2c07bf724913e507621181f369d481fd94ebb12d577d4650

HD Wallet
Mnemonic:      team shoot anchor limit inform imitate melody decrease wing sadness orange mammal
Base HD Path:  m/44'/60'/0'/0/{account_index}

Default Gas Price

BlockGas Limit

Call Gas Limit

Chain Id

RPC Listening on

5. Setup connection to the ganache server

w3 = Web3(Web3.HTTPProvider(""))
chain_id = 1337
my_addr = "0xB136383615B477B1B816f4227A509ea8F0C0c9DD"
private_key = os.getenv("PRIVATE_KEY")


If we want to connect to Testnet environment, we can use an ETH gateway such as Infura or Alchemy.

6a. Create the contract with the provider using the abi and bytecode.

SimpleStorage = w3.eth.contract(abi=abi, bytecode=bytecode)

6b. Get latest transaction count and use it as the nonce

nonce = w3.eth.getTransactionCount(my_addr)

6c. Submit the transaction that deploys contract using the chainId, gasPrice, from (which addr) and nonce

transaction = SimpleStorage.constructor().buildTransaction(
        "chainId": chain_id,
        "gasPrice": w3.eth.gas_price,
        "from": my_addr,
        "nonce": nonce

6d. Sign the transaction with private key

signed_txn = w3.eth.account.sign_transaction(transaction, private_key=private_key)

7. Deploy the contract

tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)contract_addr = tx_receipt.contractAddressprint(f"Contract is deployed to {contract_addr}")

Using the Smart Contract

Since the Smart Contract is deployed, we can provide the contract address and abi to create the smart contract (“simple_storage”).

simple_storage = w3.eth.contract(address=contract_addr, abi=abi)

We can make a function call without changing any state in the smart contract. In this example, we are trying to retrieve the stored value in the smart contract.

print(f"Initial Stored Value = {simple_storage.functions.retrieve().call()}")

Now, we call the store function in the smart contract to update favoriteNumber variable.

greeting_transaction =
        "chainId": chain_id,
        "gasPrice": w3.eth.gas_price,
        "from": my_addr,
        "nonce": nonce + 1

We will sign this transaction with the private key, send the transaction to the Ganache server and then wait for the transaction receipt.

Notice if you execute the transaction in local blockchain VM, the transaction speed will be very fast. But in actual Testnet or Mainnet, the transaction is likely to be slower.

signed_greeting_txn = w3.eth.account.sign_transaction(greeting_transaction, private_key=private_key)

tx_greeting_hash = w3.eth.send_raw_transaction(signed_greeting_txn.rawTransaction)

tx_receipt = w3.eth.wait_for_transaction_receipt(tx_greeting_hash)

Let’s print the stored value and we can see it is changed to 15


How to Dockerize your project?

Creating a Dockerfile

Usual steps of creating a Dockerfile of your application:

  1. Specify Base Image
  2. Specify any environment variables
  3. Specify commands to run on the top of OS layer such as:
    • downloading or updating dependencies
    • add groups or users to run process instead of root
  4. Copy the application files into the image.
  5. Specify which port(s) for container to listen
  6. Specify the command to start the application
Dockerfile InstructionsArguments
FROMBase Image or other Container Image
RUN1. Passing commands (runs in shell)
2. Passing exec form: [“executable”, “p1”, “p2”]
Execute command in a new layer.

– Updating dependencies
COPYCOPY is preferred to ADD as we know clearly that COPY will just copy files from local directory. ADD is useful if you wanna copy the content in a tar file.
ENTRYPOINTDefine the command that will always be executed when the container starts.

By default, Docker is using  /bin/sh -c as the entrypoint.
CMDDefine the arguments that will be appended to the ENTRYPOINT
WORKDIRDefine where your commands should run. Saves the trouble of running to many cd .....
EXPOSEDefine the ports that a container listens.
ENVSetting environment variables that can be used in other instructions such as RUN
FROM node:12-alpine
RUN apk add --no-cache python2 g++ make
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]


Running a container

Make sure the port publish setting (-p) is positioned before the image tag so that it can override the image default settings.
docker run -p 9091:9091 -t spring-boot-docker


Purpose of DevSecOps and its future

“…make sure that the constraint is not allowed to waste any time. Ever. It should never be waiting on other resource for anything, and it should always be working on the highest priority commitment the IT Operations organization has made to the rest of the enterprise. Always.”

The Phoenix project

The NUMBER ONE constraint in Security department is people.

It is unlikely we can hire enough people to match the number of developers and operations engineers.

The way to free up our constraint (people) is to try to automate as many tasks as possible so that the people can do the things that are unique and contextual.

Another way is to take a preventative approach by educating developers and ops engineers on best security practices that they need to follow (this means secure by defaults configurations, having documentation and guides). The famous Netflix’s paved roads….

any improvement not made at the constraint is just an illusion, yes?

The Phoenix project

The Programmer’s Brain – Improving your skills in reading and writing code

Performing source code review is one of the important skills that you should pickup as an Application Security engineer. Being polygot in programming is helpful because you might be reviewing source code that are written in different languages. Right now, I seldom see anyone mentioning a systematic approach to read source code if you are a novice with the codebase or languages.

Reading source code is a underrated skill in today’s programming education. Often when we want to learn programming, we are given advice to build projects and write more code to learn programming. However, another aspects of learning programming is to read the code of other programmers.

This is why I think “The Programmer’s Brain” is one of the insightful programming books to read because it discusses about different aspects of being a programmer:
– How to get better at reading code?
– How to get better at thinking about code?
– How to get better at writing code?

Get better at reading code!

Cognitive Processes in relations to programming

We can model our cognitive processes with the below diagram:

Hermans, F. (2021). Programmer’s brain: What every programmer needs to know about cognition. Manning.

At a high level, when we start reading the code, information relating to the code enters to our Short-term memory. Think of the time when you remember some information for a short period of time to memorize a phone number or a quick task to complete. This is the use of short-term memory.

Then when we are thinking and interpreting the code, we are using the information from our Short-term memory to our Working memory. The information is processed in our Working memory to generate new understanding / meaning.

Our Working memory retrieves and connect information from our Long-term memory to process the information. Think of our Working memory like a melting pot. For example, we can recall certain syntax pattern from our Long-term memory. Like when we are reading the Javascript code, we know console.log(...) will print out information based on our Long-term memory.


In short, when we are reading a code, different cognitive processes are engaged to comprehend the code and perform certain actions later such as changing the code or adding new code etc.

Why we get confused when reading code?

1) Lack of knowledge

Sometimes you get confused when reading a source code if you are unfamiliar with the language syntax or concepts. Or you might be unfamiliar with the specific industry / domain knowledge that the code is written for. In this context, we say that you lack knowledge to understand the code.

For example, below is a snippet of a Racket code. If you do not understand LISP-like code or concept of Lambda, then you will not know how to evaluate ((double inc) 5)

(define (inc n) (+ n 1))
(define (double f)
  (lambda (x) (f (f x))))

((double inc) 5)

To understand what is going on:
– You need to know the syntax of a function in LISP
– You understand that you can pass function into another function
– In this case, the function inc is passed to the function double. In this function double, the inc function will be applied twice.
– Hence ((double inc) 5) will evaluate to 7.

Example code here

To understand in terms of cognitive processes, we are unable to retrieve any information from our Long-term memory that can be used by the working memory to evaluate the code.

2) Lack of information

Unfamiliar with how a particular method works or purpose of a class etc because the information cannot be retrieved directly from the code itself.

For example, we can see a python function that seems to filter a group of members by name. But we do not know how exactly the name is gonna be filtered. Hence we might guess or search for additional information from the code base.

We are temporarily confused because we cannot understand the function immediately from the code itself.

def filter_members(all_members):
  return filter_by_name(all_members)

3) Lack of processing power

Too many items to hold in your working memory.

Code is written in too complex manner.

Why reading unfamiliar code is hard?

Types of cognitive loads




Difference between Experts and Novice?


Learning language syntax quickly

While coding a program, we might forget about how a particular concept works or their syntax. Often, we will just quickly google to retrieve for an answer (either from the documentation or stackoverflow).

The author argues it is better to know some of these syntax by heart rather than googling for answers all the time. First of all, it is distracting to google for the answers as you might be tempted to do something else (once you are in your browser especially with the multi-tabs). Second, you need to be able to recall the language syntax from your long-term memory in order to clunk the code (that you are reading) effectively.

Our long-term memories will decay in a pattern similar to a forgetting curve. If we don’t recall the things that we learned in a specific period of time, we will forget things. But if we try to recall the memories at a specific time, the decay will be slowed down.

We know this very well when we tried to cram for an exam, then we might forget everything a few things after the exam is over. Because of the failure of having future reminders, we will struggle a retrieve a concept or syntax from our long-term memory.

Want to Remember Everything You'll Ever Learn? Surrender to This Algorithm  | WIRED

What can you do to recall the syntax effectively?

It is not efficient to recall every concepts every single day. Instead, we can use a spaced repetition system (SRS) software to automate the reminders for us based on how well we think we can recall a particular concept.

Note: I have tried spaced repetition system and struggles to integrate to my everyday workflow. It’s not because SRS methodology does not work. Rather it takes a commitment to adopt SRS well and make it a habit go through your deck everyday. I will keep trying and see what are the ways we can integrate SRS better into our lives.

Adopt a spaced repetition system (SRS) and add new knowledge that you have to your deck. This can be a situation where you are learning a new programming language, a new concept or framework. You will need to use judgments to know what concepts or syntax need to be included as you can’t add everything you learned into the deck.

Adding a new card on Javascript’s array prototype filter method

Also when you find yourself googling for an answer, then add a new card to your deck. This shows that you have not understand the concepts or syntax by heart. For example, most programmers would know how to write a for-loop in their language. If they do not know, it means that they have not learned the language deeply yet.

Further reading on SRS

Memorizing a programming language using spaced repetition software by Derek Sivers

Augmenting Long-term Memory

Spaced Repetition for Efficient Learning by Gwern

Effective learning: Twenty rules of formulating knowledge

Another way to recall the syntax better is to actively think about the concepts that you are studying. It is easier for us to recall something if they are related to something that we know. When we relate a new concept / syntax to our existing knowledge, then we have a better chance of recalling the new concept / syntax in the future. Some questions to think about can be:

  • Think and write down the concepts that you think is related to this new concept or syntax.
    • In what ways are they similar and different?
  • Think of variants of code that can achieve the same goals as this new concept or syntax.
  • How important is this concept or syntax to the language, framework or codebase etc.?

Reducing cognitive loads when reading complex code

  • Refactoring code temporarily
  • Replacing unfamiliar language constructs
  • Adding the concepts that you are confused to SRS.
  • Working memory aids
    • Create Dependency graph
    • Using a state table

Think about code better!

Reaching deeper understanding of the codebase

Get better at solving programming problems

Avoiding bugs (misconceptions in thinking)

Write better code!

Naming things better

  • Name moulds
  • Feitelson’s three-step model

Avoiding code smells and cognitive loads

  • 22 code smells from Martin Fowler’s Refactoring
  • Arnaoudova’s six linguistic antipatterns

Get better at solving complex programming problem

  • Automatization
  • Learn from code and its explanation
  • Germane Load

Practices that you can do

A) Reading different code base and attempt to understand what each code is doing.

1. Choose a code base to read

Choose a codebase where you have at least some knowledge of the programming language. You should have a high level understanding of what the code does.

2. Select a code snippet and study it for two minutes.

Choose a method, function or coherent code that is about half a page or maximum 50 lines of code.

3. Reproduce the code in paper or in an IDE (new file).

4. Reflect on what you have produced.

Which lines do you find easy and which lines are difficult?

Does the lines of code that are unfamiliar to you because of the programming concepts or domain knowledge?

B) Reading and using more programming concepts