Skip links

Vulnerability Detection in ink! Programming Language

CoinFabrik received a grant from the web3 foundation to study and build a proof of concept tool for detecting security vulnerabilities in ink! smart contracts. It’s been an interesting ride: we discovered what are the possible bugs in ink!, designed some methods to detect them and build a sound proof-of-concept toolset that clearly shows that an ink! vulnerability-detection tool is buildable, that this can be done iteratively, and how it would help ink! developers.

Parity’s ink! is a language for developing smart contracts on Substrate-based blockchains. In the case of Substrate parachains, like Kusama and Polkadot, smart contracts can be deployed when the parachain contains the Contracts pallet, and in that case the smart contracts are deployed to the execution environment in WebAssembly. Parity’s ink is an  embedded domain-specific language for Rust that can be compiled to this WebAssembly accepted by Substarate’s execution environment.

Starting Point

Software engineering, and in particular static/dynamic analysis have made great progress in vulnerability detection. The starting process appears to be simple: get a good deal of programs including vulnerabilities, get a good deal of programs with no vulnerabilities, all annotated with precise information about the vulnerabilities, build a tool that has good precision and recall and you have a start!

The last few years have seen the rise of many interesting blockchains tied to different programming languages. Rust has been chosen by Polkadot, Kusama, Elrond, Solana, NEAR Protocol, Hyperledger Sawtooth.

While Rust as a programming language has been here for a while, evidently more than Solidity and its other peers, it may not be considered mature as a web3 programming language. This is the situation, basically, of the complete family of programming languages used in blockchains.

Take for example the rise of web2 and the ubiquitous web applications we now use like navigation apps to drive anywhere, complex office applications, email, news feeds, social media apps and many other applications sourced on webservers. But even though the first reports of cross-site scripting vulnerabilities are over 20 years old (see, e.g., [1], [2]) the problem isn’t over and webapps continue to be insecure. Come on, even memory safety vulnerabilities have persisted in system security 50 years after the Kargr-Schell seminal report ([3]).

The situation is very different and very interesting in web3.  Smart contracts, having a small code base and being built on the shoulders of decades of innovations in programming and security, have an easier game. On the other hand, whereas there’s thousands of system and web vulnerabilities published every year (see, e.g., MITRE’s CVE database). There are a few interesting sources of web3 vulnerabilities or attacks (eg., rekt); these share valuable yet not extensive information. So one of the problems we found when developing a tool to find vulnerabilities in ink! code is that there’s no source from where we can get many vulnerable smart contracts paired with information about the vulnerabilities they include.

Our Approach

We decided to build an annotated database of vulnerable and remediated ink! smart contracts ourselves. We selected two sources for this:

  1. Public security Audit Reports on ink! Smart contracts
  2. Extrapolating vulnerabilities from other languages/blockchains.

We spent some time looking for security audits in ink! smart contracts browsing the websites of the top Security Auditing Companies, we used search engines and asked around in the community, but the result was unanimous: nothing to report. When enlarging the search for  Polkadot, Kusama and other Substrate-based networks we did find a few useful insights. We hit a roadblock. But, as Hunter S. Thompson liked to say: when the going gets tough, the weird get pro. We thus moved to pick a few popular projects and do a very, very abbreviated audit process (these audits take weeks, and we did not have that time available). We picked two projects, and confirmed vulnerabilities in one of these (see this)–at last something! 

With this traveled distance we were confident in building small smart contracts extrapolating from the web3 vulnerabilities that are found in other networks. We first developed smart contracts including instances of these vulnerabilities, their tests, then fixed the vulnerabilities and wrote more tests. 

Detectors Detect

We then had our annotated database of vulnerable ink! smart contracts. And with nearly half of the problem solved, we set out to build tools that would detect these vulnerabilities. There is a whole assortment of code analysis tools that we can use to analyze Rust or ink! in particular. We required from our tools that: 

  1. They help in the detection of security vulnerabilities,
  2. They are available and ready to install and use (e.g., there were some very powerful tools that do not fully support Rust and required months of work as a start) 
  3. They are open source

We first set ourselves to study Clippy and Dylint, two linters that verified all our requirements and with which we were well acquainted with. We selected dylint since adding lints (detection mechanisms) to it is straightforward, whereas in the case of Clippy every addition requires recompilation.

We were able to build detectors for all of the examples in our annotated database so that all bugs are detected, and no alarm is triggered on the fixed smart contracts.

Something essential to us was precision and recall: you do not want a detection tool to trigger alerts for non-vulnerabilities and you do not want to miss vulnerabilities. 

However, the dylint detectors rely on syntactic rules that may fail in other cases. We hence looked for more powerful analysis tools and picked two: semgrep, a tool which can grep code with a semantic understanding and has just added support for Rust, and cargo-fuzz, a dynamic analysis tool (a fuzzer actually) for Rust code.

With these tools we were able to confirm that detectors for ink! Smart contracts can be built and we build a few of these.

Are we there, yet?

Yes and no. Our detectors detect. We have learned how to use a few software analysis tools and built an annotated database of ink! vulnerabilities. We are done.

Yet, this does not guarantee 100% precision and 100% recall in every ink! smart contract. Before saying that we would need -at least- to grab a random sample of ink! smart contracts, use the tool against them and independently have these audited for security vulnerabilities. The differences found between those two processes are an estimate on the real precision and recall, and the quality of our tool. 

Growing our proof-of-concept toolset into a robust tool is another pending matter. We did some work in documenting the tool and the method anyone can use to add their detectors to the tool, and would like that to happen. More generally, there is no better test for a tool than having people use it and listening to their feedback. Moreover, we also want to enlarge our annotated database with more instances of the vulnerabilities we have already covered and whatever vulnerability class we missed.

There is some work ahead. Luckily, it is iterable: we can work in small intervals, releasing an improved prototype and growing the database on each step. The road ahead is open, with many interesting opportunities and some clear follow up paths. We hope to be able to share more in the future.

References

[1] CERT(R) Coordination Center. Cert advisory ca-2000-02 malicious html tags embedded in client web requests., February 2000. URL

[2] Jason Rafail, “2001 Tech Tip: Cross-Site Scripting Vulnerabilities”. Jan. 2001. URL

[3] Paul A. Karger, Roger R. Schell, “Multics Security Evaluation: Vulnerability Analysis”. USAF Technical Report, June 1974. URL