Wednesday, May 31, 2023

The RastaLabs Experience

Introduction


It was 20 November, and I was just starting to wonder what I would do during the next month. I had already left my previous job, and the new one would only start in January. Playing with PS4 all month might sound fun for some people, but I knew I would get bored quickly.

Even though I have some limited red teaming experience, I always felt that I wanted to explore the excitement of getting Domain Admin – again. I got my first DA in ˜2010 using pass-the-hash, but that was a loooong time ago, and things change quickly.
While reading the backlogs of one of the many Slack rooms, I noticed that certain chat rooms were praising RastaLabs. Looking at the lab description, I felt "this is it, this is exactly what I need." How hard could it be, I have a whole month ahead of me, surely I will finish it before Christmas. Boy, was I wrong.



The one-time fee of starting the lab is 90 GBP which includes the first month, then every additional month costs 20 GBP. I felt like I was stealing money from Rastamouse and Hackthebox... How can it be so cheap? Sometimes cheap indicates low quality, but not in this case.



My experience


Regarding my previous experience, I already took OSCP, OSCE, SLAE (Securitytube Linux Assembly Expert), and PSP (Powershell for Pentesters), all of which helped me a lot during the lab. I also had some limited red teaming experience. I had more-than-average experience with AV evasion, and I already had experience with the new post-exploit frameworks like Covenant and Powershell Empire. As for writing exploits, I knew how a buffer overflow or a format string attack worked, but I lacked practice in bypassing ASLR and NX. I basically had zero experience with Mimikatz on Windows 10. I used Mimikatz back in 2012, but probably not since. I also had a lot of knowledge on how to do X and Y, on useful tools and hot techniques, but I lacked recent experience with them. Finally, I am usually the last when it comes to speed in hacking, but I have always balanced my lack of speed with perseverance.

RastaLabs starts in 3,2,1 ...


So I paid the initial entry fee, got the VPN connection pack, connected to the lab, and got my first flag after ... 4 days. And there were 17 of them in total. This was the first time I started to worry. I did everything to keep myself on the wrong track, stupid things like assuming incorrect lab network addresses, scanning too few machines, finding the incorrect breadcrumbs via OSINT, trying to exploit a patched web service (as most OSCPers would do), etc. I was also continually struggling with the tools I was using, as I never knew whether they were buggy, or I was misusing them, or this is just not the way to get the flag. I am sure someone with luck and experience could have done this stage in 2-3 hours, but hey, I was there to gain experience.

During the lab, whenever I got stuck with the same problem for more than 30-40 hours and my frustration was running high, I pinged Rastamouse on the official RastaLabs support channel on https://mm.netsecfocus.com/. I usually approached him like "Hi, I tried X, Y, and Z but no luck", then he replied "yeah, try Y harder". This kind of information was usually all I needed, and 2-3 hours later I was back on track again. His help was always enough, but never too much to spoil the fun. The availability and professionalism of Rastamouse was 10/10. Huge multi-billion dollar companies fail to provide good enough support, this one guy here was always there to help. Amazing. I highly recommend joining the Mattermost channel – it will help you a lot to see that you are not the only one stuck with problems. But please do not DM him or the channel if you have not already tried harder.

What's really lovely in the lab is that you can expect real-world scenarios with "RastaLabs employees" working on their computer, reading emails, browsing the web, etc. I believe it is not a spoiler here that at some point in time you have to deliver malware that evades the MS Defender AV on the machine. Yes, there is a real working Defender on the machines, and although it is a bit out of date, it might catch your default payload very quickly. As I previously mentioned, luckily I had recent experience with AV evasion, so this part was not new to me. I highly recommend setting up your own Win10 with the latest Defender updates and testing your payload on it first. If it works there, it will work in the lab. This part can be especially frustrating, because the only feedback you get from the lab is that nothing is happening, and there is no way to debug it. Test your solution locally first.

Powershell Empire turned out to be an excellent solution for me, the only functionality it lacked was Port Forwarding. But you can drop other tools to do this job efficiently.

A little help: even if you manage to deliver your payload and you have a working C&C, it does not mean your task with AV evasion is over. It is highly probable that Defender will block your post-exploit codes. To bypass this, read all the blog posts from Rastamouse about AMSI bypass. This is important.

Lateral movement


When you finally get your first shell back ...



A whole new world starts. From now on, you will spend significant time on password cracking, lateral movement, persistence, and figuring out how Windows AD works.
In the past, I played a lot of CTF, and from time to time I got the feeling "yeah, even though this challenge was fun, it was not realistic". This never happened during RastaLabs. All the challenges and solutions were 100% realistic, and as the "Ars poetica" of RastaLabs states:



...which is sooooo true. None of the tasks involve any exploit of any CVE. You need a different mindset for this lab. You need to think about misconfigurations, crackable passwords, privilege abuse, and similar issues. But I believe this lab is still harder to own than 90% of the organizations out there. The only help is that there are no blue-teamers killing our shells.

About the architecture of the lab: When connecting to the lab with VPN, you basically found yourself in a network you might label as "Internet", with your target network being behind a firewall, just as a proper corporate network should be.
There are a bunch of workstations – Win10 only, and some servers like fileserver, exchange, DC, SQL server, etc. The majority of servers are Windows Server 2016, and there is one Linux server. The two sites are adequately separated and firewalled.

As time passed, I was getting more and more flags, and I started to feel the power. Then the rollercoaster experience started. I was useless, I knew nothing. Getting the flag, I was god. One hour later, I was useless.



For example, I spent a significant amount of time trying to get GUI access to the workstations. In the end, I managed to get that, just to find out I did not achieve anything with it. For unknown reasons, none of the frameworks I tried had a working VNC, so I set up my own, and it was pain.

On December 18, I finally got Domain Admin privileges. So my estimation to "finish the lab" in one month was not that far off. Except that I was far from finishing it, as I still had to find five other flags I was missing. You might ask "you already have DA, how hard could it be to find the remaining five?". Spoiler alert, it was hard. Or to be more precise, not hard, just challenging, and time-consuming. This was also a time when connections on Mattermost RastaLabs channel helped me a lot. Hints like "flag X is on machine Y" helped me keep motivated, yet it did not spoil the fun. Without hints like this, I would not have written this post but would have been stuck with multiple flags.

About exploitation


And there was the infamous challenge, "ROP the night away." This was totally different from the other 16. I believe this image explains it all:


If you are not friends with GDB, well, you will have a hard time. If you don't have lots of hands-on experience with NX bypass - a.k.a ROP - like me, you will have a hard time with this challenge. The binary exploit challenges during OSCP and OSCE exams are nowhere near as complex as this one. If you have OSEE, you will be fine. For this challenge, I used GDB-Peda and Python pwntools – check them out in case you are not familiar with them. For me, solving this challenge took about 40 hours. Experienced CTF people could probably solve it in 4 hours or less.

Conclusion


I would not recommend taking this lab for total beginners *. I also do not recommend doing the lab if you only have limited time per day, which is especially true if you are working on your home computer. I probably would have saved hours or even days if I had set up a dedicated server in the cloud for this lab. The issue was that the lab workstations were rebooted every day, which meant that I always lost my shells. "Persistence FTW", you might say, but if your C&C is down when the workstation reboots, you are screwed. "Scheduled tasks FTW", you might say, but unless you have a strict schedule on when you start your computer, you will end up with a bunch of scheduled tasks just to get back the shell whenever you start your computer. Day after day I spent the first hour getting back to where I had been the day before. And I just figured out at the end of the lab why some of my scheduled tasks were not working ...

I would be really interested to see how much time I spent connected to the lab. Probably it was around 200–250 hours in total, which I believe is more than I spent on OSCP and OSCE combined. But it was totally worth it. I really feel the power now that I learned so many useful things.

But if you consider that the price of the one-month lab is 20 GBP, it is still a very cheap option to practice your skills. 
* It is totally OK to do the lab in 6 months, in case you start as a beginner. That is still just 190 GBP for the months of lab access, and you will gain a lot of experience during this time. You will probably have a hard time reaching the point when you have a working shell, but it is OK. You can find every information on Google, you just need time, patience and willingness to get there.

Anyway, it is still an option not to aim to "get all the flags". Even just by getting the first two flags, you will gain significant experience in "getting a foothold". But for me, not getting all the flags was never an option.



If you are still unconvinced, check these other blog posts:

Or see what others wrote about RastaLabs.


Footnote


In case you start the lab, please, pretty please, follow the rules, and do not spoil the fun for others. Do not leave your tools around, do not keep shared drives open, do not leave FLAGs around. Leave the machine as it was. If you have to upload a file, put it in a folder others won't easily find. This is a necessary mindset when it comes to real-world red teaming. Don't forget to drop a party parrot into the chat whenever you or someone else gets a new flag. And don't forget:
OSCP has no power here. Cry harder!

I will probably keep my subscription to the lab and try new things, new post-exploit frameworks. I would like to thank @_rastamouse for this great experience, @superkojiman for the ROP challenge. Hackthebox for hosting the lab with excellent uptime.
As for @gentilkiwi and @harmj0y, these two guys probably advanced red-teaming more than everyone else combined together. pwntools from @gallopsled was also really helpful. And I will be forever grateful to Bradley from finance for his continuous support whenever I lost my shells.
More articles

Baca lagi..

Removing Windows 8/8.1 Password With CHNTPW



[Update] If you want to recover Windows 8/8.1 passwords instead of removing them see this tutorial

So we are back. About a Year ago I wrote a post on how to remove Windows Password using CHNTPW but many readers complained that it was not working on Windows 8. I tried myself on many it worked but once I also got stuck. So I did a little work around. In this tutorial I'm going to show you how to remove Windows 8/8.1 passwords using CHNTPW. Well it's little bit tedious than the older one but believe me it's fun too.


Background:

Let's get started with a little bit background. Windows OSs have a User known as Administrator which is hidden by default. This user is there for security reasons (maybe it's the way around). Most of the users who use Windows are lame, sorry to say that but I'm not talking about you, they don't even know that such an invisible account exists so it is almost everytime without a password. But this Administrator user is a SU (Super User), that means you work wonders once you get access to this account. So our first task will be to make it visible and then we'll access it and using it's power privilages we'll remove password of other accounts (which is not really neccessary cuz you can access any user folder or file using Administrator Account).


Requirements:

1. Physical Access to the Victems computer.
2. A Live Bootable Kali/Backtrack Linux Pendrive or DVD.
    (You can downoad Kali Linux here)


Steps:

1. Plug in the Live Bootable Pendrive/DVD into to victim's computer and then boot from it.

2. After accessing kali linux (I'm using Kali Linux) from victim's computer open a terminal.

3. Now we have to mount the drive on which the victim's OS is loaded. In my case it is sda2. So in order to mount that drive I'll type the command:
mount /dev/sda2 /media/temp



this means that I'm mounting the drive in folder /media/temp if you haven't created a temp folder in /media then you must create one by typing these command:
cd /
mkdir /media/temp

4. After mounting the OS we need to access the SAM file and make visible Administrator account using chntpw. It's so simple lemme show you how.
first we'll navigate to /media/temp/Windows/System32/config:
cd /media/temp/Windows/System32/config

now we display the list of users on our victim's computer:
chntpw SAM -l



You'll see an Administrator User there which is disabled. Now we'll enable that:
chntpw SAM -u Administrator



now type 4 and hit return



press 'y' to save changes to SAM file.



OK voila! the hard part is done.

5. Now restart your Computer and take out your Pendrive/DVD from your computer and boot into windows 8 OS. You should be able to see Administrator User on Logon screen now. If not then look for a backward pointing Arrow besides the user Login Picture. Click on that Arrow and you should see an Administrator User. Click on the Administrator Account and wait for a while until windows 8 sets it up.

6. After a while you get Access to the computer and you can access anything. Enjoy :)

7. What you want to remove the password? I don't think it's a stealth mode idea, is it? OK I'll tell you how to do that but It's not a good hacker way of doing.
Open up the command prompt, simple way to do it is:

Press Ctrl + 'x' and then Press 'a' and if prompted click yes.
After that Enter following commands:

net user
(This command will display all users on computer)

net user "User Name" newPassword 
(This Command will change the Password of User Name user to newPassword).
OK you're done now logout and enter the new password. It will work for sure.

8. If you want to disable the Administrator Account again then type in command prompt:
net user Administrator /active:no

I tried it on Windows 8/8.1 all versions and it works. Guess what it works on all windows OSs.

Hope you enjoyed this tutorial. Don't forget to share it and yes always read the Disclaimer.

Related posts


  1. Hackrf Tools
  2. Tools Used For Hacking
  3. How To Make Hacking Tools
  4. Pentest Tools Android
  5. Hacking Tools Pc
  6. Hacking Tools Windows
  7. Hacking Tools Download
  8. Pentest Tools
  9. Hacker Tools For Windows
  10. How To Make Hacking Tools
  11. Hack Tools For Windows
  12. Hacker Techniques Tools And Incident Handling
  13. Pentest Tools Alternative
  14. Hacker Tools
  15. Pentest Tools Online
  16. Hacking Tools And Software
  17. Pentest Tools Linux
  18. Hacker Tools For Ios
  19. Kik Hack Tools
  20. Best Hacking Tools 2020
  21. Hacker Tools For Mac
  22. Hacking Tools Pc
  23. Pentest Tools Nmap
  24. Hack Tools Download
  25. Hacking Tools Name
  26. Kik Hack Tools
  27. Tools Used For Hacking
  28. Hacking Tools Windows 10
  29. Pentest Tools Framework
  30. Pentest Tools For Mac
  31. Nsa Hack Tools
  32. Hack Apps
  33. Pentest Reporting Tools
  34. Game Hacking
  35. Hack Tools For Games
  36. Hacking Tools For Beginners
  37. Pentest Tools Website
  38. Hack Tools 2019
  39. Pentest Tools Android
  40. What Are Hacking Tools
  41. Hacker Tools 2019
  42. Hacking Tools For Kali Linux
  43. How To Make Hacking Tools
  44. Hacker Tools For Pc
  45. Hacking Tools Mac
  46. Pentest Tools Kali Linux
  47. Pentest Tools Framework
  48. Hacks And Tools
  49. Hacker Hardware Tools
  50. Underground Hacker Sites
  51. Hak5 Tools
  52. Hacking Tools 2020
  53. Beginner Hacker Tools
  54. Hacking Tools Usb
  55. Pentest Tools Free
  56. Hacker Tools Github
  57. Pentest Reporting Tools
  58. Tools Used For Hacking
  59. Pentest Tools Free
  60. How To Make Hacking Tools
  61. Pentest Tools Nmap
  62. Hack Tools 2019
  63. Growth Hacker Tools
  64. Hacker Tools For Windows
  65. Top Pentest Tools
  66. Pentest Tools For Mac
  67. Android Hack Tools Github
  68. Hacker Tools For Ios
  69. How To Hack
  70. Pentest Automation Tools
  71. What Is Hacking Tools
  72. Android Hack Tools Github
  73. World No 1 Hacker Software
  74. Hacking Tools For Windows Free Download
  75. Hacker Tools Mac
  76. New Hack Tools
  77. Ethical Hacker Tools
  78. Pentest Tools Bluekeep
  79. Hacking Tools Github
  80. Kik Hack Tools
  81. Hacking Tools For Windows 7
  82. Hacker Tools List
  83. Pentest Tools Apk
  84. Hacking Tools Kit
  85. Physical Pentest Tools
  86. Hacking Tools Windows
  87. Hacker Tools Apk Download
  88. Hacking Tools Windows
  89. Hacker Tools Software
  90. Hacker Tools Hardware
  91. Hack And Tools
  92. Pentest Tools Port Scanner
  93. Growth Hacker Tools
  94. Wifi Hacker Tools For Windows
  95. Pentest Tools Website Vulnerability
  96. Hacker Security Tools
  97. Best Hacking Tools 2019
  98. Hack Website Online Tool
  99. Top Pentest Tools
  100. Hacker Tools List
  101. Hacker Tools Free Download
  102. Ethical Hacker Tools
  103. Hacker Hardware Tools
  104. Pentest Tools Port Scanner
  105. Pentest Tools Subdomain
  106. Hacking Tools 2019
  107. Hacking Tools For Windows Free Download
  108. Best Pentesting Tools 2018
  109. Hack Tools For Games
  110. Nsa Hack Tools Download
  111. What Is Hacking Tools
  112. Hack Tools For Games
  113. Hacker Hardware Tools
  114. Hacking Tools For Kali Linux
  115. New Hack Tools
  116. Hacking Tools Kit
  117. Hack Tool Apk
  118. Hacks And Tools
  119. Hacking Tools For Kali Linux
  120. Hack Tools For Pc
  121. Hacker Tools Mac
  122. Beginner Hacker Tools
  123. Pentest Tools Linux
  124. Hack Tools For Pc
  125. Hacker Tools Linux
  126. Install Pentest Tools Ubuntu
  127. Wifi Hacker Tools For Windows
  128. Pentest Tools Subdomain
  129. Hack Tools
  130. Hacking Tools And Software
  131. Hacker Tools Apk
  132. Hacker Tools Online
  133. Pentest Recon Tools
  134. Easy Hack Tools
  135. How To Hack
  136. Pentest Tools Tcp Port Scanner
  137. Hacking Tools For Pc
  138. Nsa Hack Tools Download
  139. Hack Tools For Mac
  140. Hack Tools For Pc
  141. Hack Tools Mac
  142. Hacker Tools 2019
  143. Hack Tools Online
  144. Pentest Tools Tcp Port Scanner
  145. Hacking Tools For Windows 7
  146. Hacker Tools Github
  147. Hacking Tools Hardware
  148. Pentest Tools Kali Linux
  149. Pentest Tools Android
  150. Hacking Tools 2019
  151. Hack Tools For Mac
  152. Pentest Tools For Mac
  153. Ethical Hacker Tools
  154. Hacking Tools Download
  155. Hacking Tools Windows
  156. Pentest Tools
  157. Pentest Tools Tcp Port Scanner
  158. Pentest Tools Framework
  159. Easy Hack Tools
Baca lagi..

Smart Contract Hacking Chapter 5 - Understanding And Attacking Authentication & Authorization On The Ethereum Blockchain

 

In this chapter we will take a look at bypassing UI restrictions using Indirect Object Reference (IDOR) vulnerabilities to bypass unprotected functionality. We will then take a look at various authorization schemes and how to implement them so you can easily spot authorization issues when attacking contracts. We will take a look at both simple authorization and role-based authorization.

Contact Info:  

Twitter: @ficti0n

Penetration Testing: http://cclabs.io


Understanding Smart Contract Authorization and Visibility

Smart contracts function in much the same way as an API that uses endpoints as interfaces to its functionality. You can code DApps for various platforms and access needed functionality within smart contracts for value transfers with functional logic. A common issue in the past was that smart contract functions had public visibility by default, meaning that they were accessible by anyone knew how to interact with them. If you didn't explicitly define the access level of the function it would automatically default to public, allowing anyone to call the function and perform actions using the contracts ABI. 

In newer versions of solidity, the compiler will complain and refuse to compile if you do not explicitly define the visibility of a function as one of the following:

Visibility:

ü  External – Is accessible to other contracts but cannot be accessed internally to the contract.

ü  Public - Is accessible to other contracts and can be accessed internally.

ü  Internal – Can only be accessed within the current contract or contracts deriving from it

ü  Private – These are only visible by the contract that defined them.

 

 

A quick example of a pubic vs a private method is as follows:

Action Steps:

ü  Open up remix in your browser

ü  Create a new solidity file named visibility.sol

ü  Type the following code into the new document and compile/deploy the contract.

ü  Play with the resulting functionality taking note of the visibility definitions above.

 

Simple Visibility Example:

 

1.    pragma solidity ^0.6.6;
2.   
3.    contract visibility {
4.   
5.      function add(uint _a, uint _b) private pure returns (uint){
6.           return _a + _b; 
7.      }
8.      
9.      function get_add_result(uint a, uint b) public pure returns (uint){
10.        return add(a, b);
11.  }   
12.}

 

The visibility.sol contract has two functions at lines 5 and 9. The add function at line 9 is set to private which means that you cannot call it directly from an external call with the contracts ABI, nor with another contract using an external interface to this contract. However, it is called via another function within the same contract at line 10. This is because a function can call private functions within its own contract. Visibility limits certain functions you can call directly. 

If we take a look at a screenshot of the deployed contract you will see that you only have a button to call the public function get_add_result and not the private add function. Note when submitting of 3 + 4 the get_add_result function is easily able to access the private functionality even if you cannot directly and 7 is returned.

 


Visibility is the first part of the equation and determines where the function is accessible from. There is also the matter of actual authorization to access functionality within the smart contract regardless of its visibility.  This is not something that is built in by default and usually managed by the reviewing the address of the caller and making a decision.  The address of the caller is generally going to be the msg.sender unless coded in alternative ways. We will use those other ways in upcoming chapters to bypass authorization in unique ways but for now we will focus on msg.sender.


Video WalkThrough of Visibility Code



 

Implementing Authorization:

Our functions are properly using private and public variables where appropriate, call it a day we are good to go right?  Nope not even close, this just means we have a proper flow to our program and we have limited the visibility of functions that have no need to have direct interaction with a user.  This does not stop a malicious hacker from directly accessing all of our public functions. Many of these public functions are bound to have sensitive functionality tied to financial transactions or interact with private functions that have the functionality you are trying to manipulate.

In a smart contract we need a way to actually tell who has access to a public function in order to setup authorized transactions, for example a bank transfer. Otherwise you would create an account and everyone would be able to access its funds and transfer the funds out to themselves. An attacker can call any public function within the contract, even those meant for administrators only.

Some examples of administrative functionality you would not want exposed would be a self-destruct function to render a contract useless or adding a new administrative account that does have authorization to sensitive functions.

To illustrate this point let's take a look at the following contract that has a few sensitive functions but no protection against unauthorized users. Before you read what the code below does, try the following steps and take a guess at what it's doing yourself and where it should have protections.

Action Steps:

ü  Open your browser and go to remix.ethereum.org

ü  Create a new file named noAuth.sol and type in the following code

ü  Deploy this contract and play with its deposit and withdraw functionality

ü  Do you see any potential issues in authorization?

ü  Do you see any potential issues with the business logic, etc?

 

Example Walkthrough of No Authorization

1.    pragma solidity ^0.6.6;
2.   
3.    contract noAuth {
4.      mapping (address =>uint) balances;
5.   
6.      function deposit() public payable{
7.            balances[msg.sender] = balances[msg.sender]+msg.value;       
8.      }
9.      
10.   function withdraw(uint amount) public payable {
11.         msg.sender.transfer(amount);
12.   }
13.    
14.    function kill() public {
15.        selfdestruct(msg.sender);
16.    }
17.}

 

The noAuth contract above is setup like a mini bank account, where you have the ability to deposit your funds and withdraw your funds. The funds are mapped to your msg.sender address on line 4.  However, there are a few flaws with the way this contract is setup, both in authorization as well as business logic. 

Let's go through the code and look about how it is setup.  First, we have a deposit function on line 6 which accepts a value transfer via the "payable" keyword and applies the value to your current balance associated with your address.  This function seems ok.

Next, we have a withdraw function which receives an amount and transfers that amount to the address which calls the function. But.

ü  The withdraw function never actually checks if you have a balance associated with your address

ü  It also doesn't validate if you have enough in your balance to send the amount you're asking for.

 

That poses a few interesting questions:

  1. Where is this function withdrawing funds from if you don't have a balance associated with your address?
  2. Can you simply liquidate the funds from the account as a whole?

 

Is this a potential business logic / authorization issue?

Finally, we have a kill function on line 14, which simply calls the built-in solidity self-destruct function and transfers all of the contract's funds to the caller of the function. This function will terminate the contracts functionality permanently and liquidate the contracts funds into the account address which ran the kill function. Much like the other two functions the kill function has no authorization, poses a risk to everyone's funds, and leaves the whole contract vulnerable to termination.

Let's play around with this functionality and determine if this is true within the Remix UI.

Action Steps:

ü  Deposit 10 Ether via the deposit function with the value field using account one.

ü  Switch accounts to account two which has no funds and try to withdraw funds. Did it work?

ü  Now call the kill function from account two. What happened?

ü  Try to withdraw funds again with either account. What happened? 

 

Vulnerable Authorization Code WalkThrough: 




Thinking about Smart Contracts as unpublished API's for DApps

There are multiple critical issues with the above smart contract:

ü  It's not validating the logic that users need to have funds associated with their account to make withdrawals. 

ü  It's not stopping a user from killing the contract and liquidating all of the funds of other accounts.

But I have UI mitigation's!!

What if a developer mitigates the issues via a Web or Mobile DApp simply by not providing a way for a user to execute the Kill functionality unless that user is the administrator in the DApp.  Also, what if the UI manages your funds on the DApp's business logic. For example, restricting you from withdrawing funds if the address using the DApp does not have an appropriate balance.  So, we are safe right?

No, not really, much like an API we can call these directly without ever accessing the UI.  By directly calling the public functions of the smart contract, we do not have UI or middleware restrictions. In the web app world this would be equivalent to Indirect object reference (IDOR).  You often see this with video games or web applications where the application from the front end looks good with solid restrictions. But then you start doing some enumeration you realize that all of the functionality comes from an API.

If you start poking around that API enumerating endpoints and fuzzing keywords you often will start finding API endpoints with interesting names that do things intended only for developers and administrators. This can lead to sensitive information disclosure or the ability to change and modify sensitive data. This is a very typical occurrence in web applications and Smart Contracts are no different.

Case of the Video Game Heist

For example, I was performing a penetration test against a large video game development shop whose primary fear was the ability to bypass the in-app purchases functionality.

I first started playing the video game and getting a feel for the game play and sequence of events. For example, the gameplay, how money transfers worked and how in-app purchases were processed. Everything seemed pretty good from the perspective of the mobile and web application UI parameters.  I noted all of the calls were to external APIs and decided to take a look at those.

I setup both a local TCP sniffer on the mobile application, a TCP proxy and captured all of the web requests using a web proxy while playing the game.  When reviewing the output, I noticed some interesting calls which exposed a list of every API endpoint in the application.

I started looking at the returned API endpoints and noted many functions which were not available to me from within the mobile application. Most notably for the client was functions named something similar to Get_Gold, and Get_All_Items. These endpoint names seemed interesting to me so I coded up a python loop which called the API for Get_Gold 100 times. At this point my Gold within the game increased 100-fold. Next, I called the Get_All_items endpoint and received every single item in the game for free.

At this point I didn't even need the gold which I just stole as I owned every single item in the game.   Apparently, these were created by developers and never removed from the API endpoints. Instead they were just restricted by not having the functionality available on the UI of the game.

Yes, sometimes it is just that easy!!!  But how do we do this with a smart contract?

 

Enumerating functions in a contract

So how does this story relate to your Smart Contracts?  Well we have a few options available to us when trying to enumerate public functionality so we can make direct calls.  The most useful resources for enumerating these issues is both the sour
ce code and the Application Binary Interface (ABI).

First, we can take a look at the source code, if you are performing the penetration test the client should provide the source code. If the client does not provide the source code, most Ethereum projects tend to be open source, so you should find a GitHub with the source code. A third option for retrieving the source code would be pulling it from etherscan.io at the address where the contract is deployed. This should be located under the contract tab.  For example, try the following steps to illustrate this point:


Go to etherscan.io and type chainlink into the search field at the top right and click the result shown below that pops up while your typing: 




Next under the profile summary click the contract address: 


You will then see a contract tab on the page that loads. Click that:

 


4.       This will provide the source code for the application if it's available and it will provide the ABI:

ol


Secondly you will want the ABI for the contract in order to interact with it. The ABI is a JSON file which describes the functionality of the smart contract and how to interact with its functions.  You can also generally obtain this exactly as you did above from the contract tab of etherscan.io shown below.

 


Another option if you were provided a contract from the client is to deploy a contract to Remix and grab the ABI that is created. You can grab this in Remix under the compiler section under compiler details. Just click the ABI text and it will copy it to your clipboard.

 


An ABI file for our noAuth contract will look something like the following Snippet.

___________________________________________________________________________________

                [{

                                "inputs": [],

                                "name": "deposit",

                                "outputs": [],

                                "stateMutability": "payable",

                                "type": "function"

                },

                {

                                "inputs": [],

                                "name": "kill",

                                "outputs": [],

                                "stateMutability": "nonpayable",

                                "type": "function"

                },

                {

                                "inputs": [

                                                {

                                                   "internalType": "uint256",

                                                   "name": "amount",

                                                   "type": "uint256"

                                                }

                                ],

                                "name": "withdraw",

                                "outputs": [],

                                "stateMutability": "payable",

                                "type": "function"

                }]

___________________________________________________________________________________

 

Notice that the ABI above is simply just a JSON file that describes the functions in the contract for example the last function in the ABI shows the withdraw function with the following elements:

ü  It takes an amount with the type uint256

ü  It says it has no outputs

ü  It is payable meaning it can send and receive transactions

ü  It also notes that it is a function

 

So, the question is, how we can call these public functions directly if they were not programmed into the UI? The answer is we can use Web3 and programmatically interact with the contract via its ABI to bypass any front-end restrictions. 

Let's directly interact with the noAuth contract and then let's implement authorization and requirement checks. This way you understand how to access public functions but also ways to properly prevent authorization issues with standard security libraries. This also helps with knowing what to look for when reviewing contract source code. 


Directly Calling Public Functions with Web3.js

Steps for setting up the lab:

(Follow the video in the below reference section if you want a walkthrough of the setup)

1.       Open up your browser, and in Remix and create the noAuth.sol file

2.       Start Ganache-Cli on in your terminal

3.       Set the provider in Remix Deploy section to Web3 Provider

4.       Deploy the noAuth.sol contract, which will now deploy to your local ganache blockchain

5.       Copy the address for noAuth.sol. You will need it.

6.       Copy the address of the second account

7.       Deposit 10 Ether via the Deposit function and the Value field (don't forget to change the value type to Ether from Wei)

 

Since not all of the public functions are accessible or may contain restrictions from our UI, we will attack the contract from the command line by directly calling the functions via Web3 using the contracts ABI. 

We will need the ABI for this and we can get the ABI by going to the compilation section in Remix and clicking the ABI link shown below. 

 


 

Note that as Web3 updates and ABI contract formats update you will need to update your web3 commands, I have had this happen to me frequently as this is a newer technology and the formats are always updating so, if this gives you issues feel free to steal the ABI from above to work with the Web3 commands below.

Now open up a terminal and install web3 followed by opening a node terminal:

$ npm install web3

$ node

Once node is running you will see a blank line with a > meaning you are in the node interactive console.  We will now setup a direct connection and attack both the withdraw and kill functions to liquidate the contracts funds and terminate its functionality.  The first thing we will need to do is setup our web3 import using the localhost target where our ganache-cli is running our blockchain transactions.  Note with the commands below the output will usually say "undefined", you can ignore this output.

 

> const Web3 = require('web3')

> const URL = "http://localhost:8545"

> const web3 = new Web3(URL)

 

These lines of input simply create an instance of web3 and set its target network URL. If this were a bug bounty or pentest on another network you would supply that target URL for the target network, we can do this with Infura URL's to the test nets and mainnet on ethereum. We cover how to do this in other labs, but for this lab we are using our local targets.

 

Next lets setup our accounts so that we are using the 2nd account we selected in our remix account dropdown which was imported from ganache-cli. Note accounts start with 0 so the second account is actually labeled as account 1. And also note we deployed our contract with account 0.

 

> accounts = web3.eth.getAccounts();

> var account;

> accounts.then((v) => {(this.account = v[1])})

 

We setup our account in web3 simply by grabbing all of the accounts and then setting the value of account (singular) to 1 with the commands above. Syntax in node / JavaScript is a bit cryptic at times so the commands may look a bit odd but you can easily look them up in the web3 documentation. 

 

Now we need to setup our target contract address from the proxy contract. We also need to paste in the full ABI and then connect the address and the ABI with a contract variable to reference in our calls to the contract. We can do that with the input below.

 

> const address = "ADD CONTRACT ADDRESS HERE"

> const abi = ADD ABI HERE

> const contract = new web3.eth.Contract(abi, address)


Now we are ready to make a call to the contract with the contract connection variable we just created. We will first withdraw funds to our second account which never deposited any funds. We do this using the command below that calls the withdraw function using our account variable. We also specify sending a default gas value since we need to send gas with transactions that make changes on the blockchain.

Before using the command below, first note your account balance in remix on your second account. This should be 100 ether at this point as it was not used in any transactions and it also holds no balance to withdraw in the contract.  Then send the following command which requests 1 ether in Wei. Wei is denominated as the following 1 Ether = 1,000,000,000,000,000,000 Wei (10^18)


> contract.methods.withdraw("1000000000000000000").send({gas: 3000000,from: account})

 

After a few moments you should see your balance increase in the second account on Remix.  Now let's kill the contract so no one else can use it which will additionally send the remaining ether in the contract to our address per the msg.sender value in the source code call to self-destruct.


> contract.methods.kill().send({gas: 3000000,from: account})

 

Video WalkThrough Attacking Authorization with Web3.js: 





Example Fix with Simple Authorization

So obviously it's easy to understand we have functions we don't want directly called. To prevent this we need to implement some kind of protection scheme. Whether that is a require statements for accounts or more elaborate role-based designs.  There are various ways we can implement authorization. We will cover a few common things you will see while auditing solidity smart contract code.  While this is not a book about how to securely code your applications, in this case it is appropriate to understand what you might see while analyzing a contract you are trying to exploit.

The first example we will review is a simple authorization scheme using a contract owner and require statements.

Important Reminder:

Make sure to type out each of these contracts and test what they are doing for yourself before reading the descriptions below the code. The muscle memory of typing all of this code and trying to understand what you typed out will help you in spotting issues when you are auditing code. Also learning how to code will help you write exploits against contracts quickly and understand when it is or is not working and how to fix it.

 

1.    pragma solidity ^0.6.6;
2.   
3.    contract simpleAuth {
4.      address owner;
5.      mapping (address =>uint) balances;
6.      
7.      constructor() public {
8.           owner = msg.sender;
9.      }
10. 
11.   function deposit() public payable{
12.  balances[msg.sender] = balances[msg.sender]+msg.value;       
13.                 }
14.    
15.   function withdraw(uint amount) public payable {
16.         require (balances[msg.sender] >= amount);
17.        msg.sender.transfer(amount);
18.   }
19.    
20.   function kill() public {
21.        require(msg.sender == owner);
22.        selfdestruct(msg.sender);
23.   }
24. }

 

You will notice two changes to this contract from the original. The first change is on line 7 where a constructor sets the owner of the contract to the address of the user who deployed the contract.  This constructor is only run one time when the contract is deployed. Meaning the owner cannot change.  You will notice the initialization of the owner variable was also added on line 4.

 

The second change is the usage of require statements on lines 16 and 21. The require statement on line 16 is not associated to the owner but does add a check to make sure the user requesting a withdrawal has an amount in their balances mapping which is higher than the balance they are requesting to withdraw. This fixes the issue with users withdrawing funds they do not actually have.

 

The next require statement on line 21 makes sure to check that the user calling the Self-Destruct functionality is the owner of the contract. This prevents anyone from just killing the contract and stealing the funds from the account.

 

Exit Scam Warning

Something still smells bad regarding this contract!! The kill function is highly suspect as it removes all of the funds in the contract and could be indicative of an "exit scheme". Whereby a malicious developer creates a contract that handles funds, for example in a game, or an online exchange. But the malicious contract is created for the sole purpose of exiting with all of the user's funds when the balance reaches a desired balance.

These types of issues are something you should always take note of when you see them, and flag them during your assessment. The client might not like that you flagged their intended functionality but that is not your problem. They should know better than to have sketchy functionality and it should be called out.  Even if they did not intend to use the function maliciously, it opens the door for someone else to do so.

 

Example Fix-2 Using Modifiers for Simple Authentication

Another popular authorization pattern is using an onlyOwner modifier. This is often coupled with Openzeppelin security libraries, which we will take a look at in our role-based example. However, in the example below we use a modifier in a simple way to illustrate what you may see in a contract. 

 

1.    pragma solidity ^0.6.6;
2.   
3.    contract simpleAuth2 {
4.      address owner;
5.      mapping (address =>uint) balances;
6.      
7.      constructor() public {
8.           owner = msg.sender;
9.      }
10.   modifier onlyOwner() {
11.        require(msg.sender == owner);
12.         _;
13.   }
14. 
15.   function deposit() public payable{
16.  balances[msg.sender] = balances[msg.sender]+msg.value;       
17.                 }
18.    
19.    function withdraw(uint amount) public payable {
20.         require (balances[msg.sender] >= amount);
21.         msg.sender.transfer(amount);
22.   }
23.   
24.    function kill() public  onlyOwner{
25.         selfdestruct(msg.sender);
26.   }
27.}

 

 

This contract is also very similar to the simpleAuth contract above with a few small modifications to make it more extendable when there are a ton of functions that need authorization restrictions. These changes will also make the authorization simpler and more readable within your code.  Changes in this contract are on lines 10 and 24.

On line 10 we define a modifier named onlyOwner which we can apply to any function. This modifier code will run prior to the original functions execution. In this example the modifier simply checks that the user calling the function is the owner of the contract. You will also note the use of _; which simply signals contract to continue running the function after this modifier code is finished.

You can apply this onlyOwner modifier to any function you wish to have authorization restrictions by simply adding onlyOwner in the function definition. You will see this on line 24. If modifiers requirement is not met the function will not be run. If the requirement is met it transfers control back to the function to continue execution.


WalkThrough of Fixing Authorization Issues With Modifiers: 

 


Example Using Openzeppelin for Role Based Access Control:

The best way to cover your security needs as always is with well-audited, open source security libraries. One option we have for a bit more complex authorization is the Openzeppelin libraries located at:

https://github.com/OpenZeppelin/openzeppelin-contracts

For the previous examples you could have replicated the simple authorization with the ownable contract by OpenZeppelin by importing its functionality in the same way you would import library functionality in any other language.

Since we already looked at a simple example without OpenZeppelin, lets instead take a look at role-based authorization using OpenZeppelin. Role based authorization a bit more involved, but not complicated.  Let's take a look at a simple example.

Before you read the descriptions type out the role-based code below in remix and try to figure out what's happening on your own by deploying this contract and playing with its functionality and see if you can understand how it works.

 

Action Steps to deploy:

ü  Open up remix in your browser

ü  Type out the following code and the import will import all of the OpenZeppelin files in a directory within remix automatically

ü  With your first account, make sure to compile this with the newest version of Solidity that OpenZepplin files are using at the time of writing this was 0.6.2. I used version 0.6.6 without any issues. If versions change in the future you will get an error. Review the error and update the compiler version and pragma version in the code appropriately. But always use the latest version of OpenZepplin files.

ü  Take a look at the created users and make assumptions as to what each user has access to

ü  Play with each function under both the admin and the user context with the first account and another account of your choice.

 

1.    pragma solidity ^0.6.6;
2.    import "https://github.com/OpenZeppelin/openzeppelin-
3.    contracts/blob/master/contracts/access/AccessControl.sol";
4.   
5.    contract roleBased is AccessControl {
6.      bytes32 public constant admin = keccak256("admin");
7.      bytes32 public constant user = keccak256("user");
8.      mapping (address =>uint) balances;
9.      
10.  constructor() public {
11.         _setupRole(admin, msg.sender);
12.  }
13.   
14.  function deposit() public payable{
15.        if (!(hasRole(admin, msg.sender))){
16.            _setupRole(user, msg.sender);
17.        }
18.  balances[msg.sender] = balances[msg.sender]+msg.value;
19.         
20.  }
21.  function withdraw(uint amount) public payable {
22.        require(hasRole(user, msg.sender), "Not a user of this bank");
23.         require (balances[msg.sender] >= amount);
24.        
25.         msg.sender.transfer(amount);
26.  }
27.    
28.  function kill() public {
29.        require(hasRole(admin, msg.sender), "Not an administrator");
30.        selfdestruct(msg.sender);
31.  }
32.}

 

Once you have the roleBased contract deployed you will notice a few changes from the simpleAuth version. First, we are importing the OpenZeppelin libraries which imports all of the prerequisite needs for the role-based access control into Remix.

Secondly, on lines 6-7 we are creating both a user and admin role identifiers. If you take a look at the documentation link from the references at the end of this section it states that the role identifier must be created as a bytes32 hash. We create these as a bytes32 type and hash them with keccak256 which is essentially the equivalent of a sha3 hash function. This type of hashing is standard on Ethereum's consensus engine for producing blocks. Keccak256 is often seen as the hashing function within Solidity smart contracts.

The constructor was updated to execute the _setupRole function from OpenZeppelin. This sets the admin user as the user who initially deployed the contract. In this case we used our first account, so our first account is our admin user. 

The user account is then setup within the deposit function on line 16 for every user who deposits funds and is not already an administrator, as we don't want to overwrite the admin role with the user role. This would be a business logic error that eliminated all admin accounts, which would be bad.  When you deposit funds as the second account your address will be associated with a regular user role.

As an example of how authorization is handled with role identifiers take a look at lines 22 and 29.  On line 22 if you have not already deposited funds you will not have a user role so you cannot withdraw funds. You will be given an error when checking the hasRole requirement.

Try this out with a user who has not deposited funds yet. 

Finally, within the kill function on line 29 you will see a check for an admin role identifier. If the account address calling kill does not have this associated role identifier, an error is displayed and the transaction will not process.

Try the kill function with your second user and take a look at your output window. It should turn red and show that error.  Now if you switch back to your admin user on the first account you can successfully kill the contract.

Note that you can also enumerate, grant and revoke user roles. Check out the references section below for more information if you are interested in that functionality.

 

Authorization Summary:

I hope this chapter was enlightening on how authorization is handled on the blockchain and the dangers of not having authorization on sensitive functions. In the lab package for the certification and on the final CTF exam, there will be many occurrences of authorization which you can further test your business logic and authorization bypass attacking skills.

 

Authorization References

https://docs.openzeppelin.com/contracts/3.x/access-control

https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/access

Related posts
Baca lagi..