Learn how to introduce threat modeling in your team and take care of security before it's too late.
Thanks to this guide you will:
- reduce the number of security bugs in your code,
- use the audit time effectively,
- understand the concept of threat modeling and its importance,
- learn why you should carry them out,
but most of all, you'll be ready to conduct your first threat modeling session!
As a developer, the security of the project is in your hands. Be security-centric through the process, and become a security champ.
During conversations with clients, we always try to get to know their problems in depth, and we listen carefully to what they think they result from.
These are very valuable comments, thanks to which we are able not only to diagnose the problem much better but also start working on a solution.
A common problem is thinking too late about security.
Smart contract audit before the release
Many projects come into contact with security only before the release. They focus so heavily on product building that they leave the discovering vulnerabilities, identifying threats, and implementing additional protections for the end. Audit, patch, and that’s it. Some of them, having a better understanding of responsibility, will also be tempted to participate in the bug bounty program.
Is that all we can do for users to keep them secure?
No, all of this is just an absolute minimum. If you are reading this article, you feel that something more can be done… and - you are absolutely right.
Why is threat modeling important?
What if I tell you that you are not only able to significantly increase the security of your project by some small changes in your process, but also reduce the costs associated with time-consuming corrections after audits?
Sounds good? Then start doing threat modeling sessions with your team. It's really not worth leaving it to the last minute and having a ton of work to do when deadlines are tight.
A much smarter approach is to build a project based on good security assumptions. By working closely with many great teams, we know it's possible. Sometimes they just need guidance and advice in threat modeling process on HOW and WHEN to do it.
How to perform threat modeling within a team
1. Explain what threat modeling is
Threat modeling is nothing else, but brainstorming. An exercise to spot potential threats at a very early stage. Take on the role of this evil hacker for a moment and think as a threat agent. In addition to the valuable contribution, it is simply great fun.
2. Tell them why you want to introduce threat modeling and what it is for
Thanks to the introduction of the threat modeling process, we will realistically increase the security of our project and chances for finding operationally critical threats. Moreover, we will reduce the costs associated with introducing post-audit fixes, which sometimes might even require redesigning the protocol. Our users will be sure that their security is our priority.
3. Introduce the rules
It is crucial that each participant feels comfortable during the whole threat modeling process. If you want to use your colleagues' knowledge, don't let their ideas be criticized. All topics discussed should stay in the group. Shortcomings and omissions should be addressed, BUT not stigmatized. People must not be afraid to admit they were wrong or missed something. They all must feel at ease. Otherwise, they may hide relevant information to protect themselves from the consequences.
4. Select the session object
Anything can be the subject of the session. Every slight change in the code, new feature, update process, next integration, or even a whole project architecture. That’s up to you.
5. Gather people who have knowledge about the session object
To find numerous threats, it is worth exploring various perspectives and gathering experience. During the session, not only developers’ and security teams are valuable. Architects and business people have relevant knowledge and are able to determine what might have a negative impact on the project’s success and may significantly contribute to performing successful threat analysis. Keep the balance, do not invite the whole team for all sessions. Some of them can be done even by one developer.
6. Start by drawing the architectural diagram
You can use a blackboard, sheet of paper, or application. It does not matter. It is important that you have a place to accurately reproduce your idea. Furthermore, it is not worth getting into details, usually the most important are:
- components - smart contracts,
- business core functionalities - the most important functions of a smart contract that are used in the main business and data flows,
- roles - all users participating in the system with various rights (governance, owner, user, team member, etc.).
Keep it simple.
7. Determine the potential attacker
When the diagram is ready, start thinking together about possible attack vectors and threats. Where can they come from? From which side can the component be attacked?
- What roles are there in the system?
- Who potentially might not want you to succeed?
- Which role do most people have access to?
The shorthand term might be to consider everyone as threat agents. Yes, even team members and DAO. They also can be compromised and impose security risks, and we don't estimate the probability of it yet.
8. Think about what the attacker will want to achieve
Well, as you already know who might want to attack your project. Now the question is what for? Steal your users' funds? Make your project unavailable? Read some secret data? Or just harm your reputation in any way possible? Think about attack simulation and answer questions such as:
- What from our project has value in the market?
- What's the worst that could happen to our project?
- In what case are we losing money?
Thanks to this, you will know exactly what should be important to you. Determine the key assets that you need to protect.
9. Identify how attackers can do that
You know who can attack your project, and you know what they want to achieve - it's time to play the hacker and think about how you would try to achieve the goals set in the previous point.
- Which functions handle token transfer?
- Do we check who is calling the functions?
- What if the component we integrate with starts sending incorrect data?
- Are we sure about the arithmetic operation result?
- What if the user has a significant amount of tokens?
- Can I call functions in a different order than expected?
- What if the private key of one of the team members is compromised?
- ...
Make this brainstorm on every component and every function and add it to attack trees. Do not check whether these possible threats are real and reflected in the code. Write everything on the diagram. In the worst case, you'll expand your database of known security threats.
10. Write down discovered threats
After you have gone through all the components, write down the discovered threats. You can use a table to have a place where you can easily decide what to do with them later in your threat model.
ID | Threat | Priority | Action |
---|---|---|---|
1 | Increase user balance without a deposit | ||
2 | Withdraw more than the user's balance contains | ||
3 | Withdraw another user's funds | ||
4 | Compromise of a team member's private key | ||
5 | Invalid data format by oracle updates | ||
N | ... |
11. Prioritize
There can be many threats and handling all of them might be time-consuming. It is worth considering which of them is the most important. This table will help you with that - the higher the overall risk severity, the higher your priority should be.
Overall risk severity | ||||
Impact on risk | HIGH | CRITICAL | HIGH | MEDIUM |
MEDIUM | MEDIUM | MEDIUM | LOW | |
LOW | LOW | LOW | INFO | |
LOW | MEDIUM | HIGH | ||
Exploitation conditions |
12. Decide what to do with security threats
Each threat must be handled. You can choose from the following options:
- Accept the risk - not all the vulnerabilities need to be fixed, and not all the threats will eventually turn out to be significant. If something is very unlikely or irrelevant from your point of view - after the risk assesment, you can accept it.
- Delegate - Some of the risks arising from the necessary use of third-party resources. A great example of this is using AWS to host your platform. In many cases, you may find AWS responsible for the availability of your platform.
- Communicate - Some of the detected threats, the risk of which we can accept if disclosed, may harm the company's image. In these cases, you can accept the risk, but you should also send a message stating that it is a deliberate decision so that users have no doubts. This could be a documentation entry, a tweet, or a terms and conditions entry.
- Verify - If you are not sure if this threat exists, check it. Use your team or a professional auditing firm for this. If it’s confirmed, you will have to decide again how to handle it.
- Fix - When you are certain that there is a vulnerability with a real risk of security incident, there is nothing else to do but remove it. In some cases, this may require rapid intervention if threat modeling was organized late. However, if you did it at the beginning of the process as recommended - you can do it without a rush.
- Prevent - If the threat is real and you are at the initial stage of the project. Address potential vulnerabilities by providing developers with detailed threat information, such as checklists or tests. Instill a proactive, security-conscious mindset throughout the development process.
ID | Threat | Priority | Action |
---|---|---|---|
1 | Increase user balance without a deposit | HIGH | Prevent |
2 | Withdraw more than the user's balance contains | HIGH | Prevent |
3 | Withdraw another user's funds | HIGH | Prevent |
4 | Compromise of a team member's private key | MEDIUM | Verify |
5 | Invalid data format by oracle updates | LOW | Accept the risk |
N | ... |
No matter how you choose to handle each attack scenario, be aware of the threats and act consciously.
13. Write tests
If you choose to Verify, Fix or Prevent, it is worth trying to convert this scenario to a unit test. At the moment, the name of the scenario is enough. You don’t have to implement all the tests. Each time someone runs them, they will remember the existing threats that you want to avoid. Moreover, in some cases, you will be able to automatically confirm that the vulnerability does not exist.
Foundry template:
1contract TestThreats is Test {
2 // Should not be possible to increase user balance without a deposit
3 function testIncreasingBalance() public {
4…
5 }
6 // Should not be possible to withdraw more than the user's balance contains
7 function testWithdrawingMore() public {
8…
9 }
10 // Should not be possible to withdraw another user's funds
11 function testWithdrawingAnotherUserFunds() public {
12…
13 }
14}
Hardhat example:
1describe("Preventing threats", () => {
2 it("Should not be possible to increase user balance without a deposit", async function () {
3 …
4 });
5 it("Should not be possible to withdraw more than the user's balance contains", async function () {
6 …
7 });
8 it("Should not be possible to withdraw another user's funds", async function () {
9 …
10 });
11});
14. Take further action
Delegate responsibilities who should do what, and share the work. It's also a good idea to save your materials and build your own threat databases
When to perform threat modeling within a team?
The simple answer to that question is building threat models is needed every time you want to make some changes, or you are designing something new.
You don’t need a code for that. You don't need a whole team for it, you don't always have to do it with anyone at all. BUT you always have to ask yourself whether a particular change may have any impact on security. And if the answer is yes - you need to carry out at least a short threat modeling session by yourself.
Then, you will introduce this change by being aware of potential threats. That’s simple, but a huge change. We promise that if you do this, there will be much fewer vulnerabilities in your project code.
First session
The first threat modeling session is very important. If we do it for the entire architecture of the project, it is not only time-consuming but can also be a challenge. This requires knowledge of many attack vectors, keeping the appropriate level of abstraction, and threat modeling tools and practices.
Let's do this together. We will be happy to help you by conducting the first session to start the threat modeling process with your team. After such a session, you will not only know exactly how it should look but also get great materials to not start from scratch.
If you are interested in such a session, contact us, and we will take care of the rest.
About the author
Co-author of SCSVS and White Hat. Professionally dealing with security since 2017 and since 2019 contributing to the crypto space. Big DeFi fan and smart contract security researcher.