Immutability, Scope, and Data Protection
A change cannot occur if you don’t allow it
One of my post that may later become a book on Secure Code. Also one of my posts on Application Security.
Free Content on Jobs in Cybersecurity | Sign up for the Email List
![](https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*SmjSyhtxW_AqmzbaYtCAYQ.png)
The last chapter on concurrency explained how multiple threads in the same application can operate change the values for a single resource. Sometimes different threads make a mistake while performing calculations. But sometimes, a malicious individual can get a handle on a variable and intentionally change it to the wrong value. You need to prevent these errors in either case.
You will find different constructs within your programming language to help you protect your variables. You should use them appropriately to minimize the chance of an inadvertent or malicious change by some other thread. You should also protect against unwanted changes by other functions that use or have access to your variables.
Atomic variables and classes
Some types of variables and classes exist to help you protect your data. An atomic variable prevents two threads from improperly updating data at the same time. Sometimes you can use an atomic resource instead of locks. That may improve the performance of your application.
In our bank balance example in the last blog post, the application first had to get the variable and then update it. Another thread could take an action on the variable in between. With an atomic variable that would not be possible. The get and set (or update) operations are completed together.
Not all variables can be atomic. Sometimes only certain functions work on atomic variables. You’ll need to read the documentation of your chosen programming language for the details.
Commonly counters are atomic. When you use the ++ operator in your programming language it is often two operations under the hood: one to get the variable and one to set it.
a = 1
a++ (Get a and add 1)
print a
(Prints out 2)
While one thread performs those operations another could call an operation on the variable in between. If you make the variable atomic then the other thread will get an error during that operation when it tries to access the variable. The atomic variable gives you a thread-safe value without having to implement a more complicated locking scheme.
Here’s are some resources for a deeper dive into atomic variables.
Some languages, such as C# try to make certain data types atomic for you. A brief overview of the topic is murky as to which types and whether they are guaranteed to be atomic. As always, don’t just trust the first answer on StackOverflow or some blog post. Review the documentation and test applications carefully if you count on that functionality for accurate results.
As always, the functionality in your programming language that tries to implement code that helps you with concurrent programming. Here’s a CVE in Rust related to atomic operations that leads to a race condition — the very thing it should be preventing.
An issue was discovered in the atomic-option crate through 2020–10–31 for Rust. Because AtomicOption<T> implements Sync unconditionally, a data race can occur.
Immutable Objects and Infrastructure as Code
I first learned about immutable objects while studying Java in my software engineering master’s program. An immutable object can’t change after instantiating it. That means once you create your class and initialize the variables, some other thread or function cannot come along and change them.
You can create an immutable object by declaring a variable inside a class and never exposing the variable or a method that allows an external piece of code to change the value. If you want to learn more about immutable classes in Java, Effective Java 2nd Ed is an excellent resource. It’s a bit dated but I presume most of the concepts still hold true, as most principles do.
I went on to apply this concept to my cloud infrastructure code. I didn’t think of it on that terms and no one was using the phrase immutable infrastructure at the time. I was working at Capital One and had to deploy a bastion host in all cloud environments. If you are not sure what a bastion host is and why you might want to use one, I wrote about it in Cybersecurity for Executives in the Age of Cloud.
A bastion host is sometimes exposed to the Internet and usually the gateway to something an organization wants to protect. Often, a bastion host exists between the administrative billing systems and the systems that run critical infrastructure such as electrical, water, and oil pipeline Supervisory Control and Data Acquisition (SCADA) systems. Often companies will use a bastion host between developer laptops and cloud production systems. A bastion host is a valuable target for attackers. If they get access to the bastion host, then they can try to attack all the other systems the bastion host can access.
I was concerned that developers who never had any security training would not understand this. They might try to install software on the bastion host that might allow an attacker to compromise it. Of course, we also had it behind a VPN. But sometimes attackers get into private networks and move laterally. You might also have an insider trying to “fix” a problem that wasn’t allowing them to reach out from their desktop directly to a host in the cloud environment with a proxy. Those are some topics I cover in more detail in the Cybersecurity for Executives in the Age of Cloud.
I thought, “What if I can make the bastion host immutable so it can’t change once it is deployed?” Neither software developers, nor attackers who gain access via stolen credentials or through the use of system vulnerabilities would be able to install anything.
What if you wanted to make a change to the host configuration? You might need to do that at some point. I completely automated the bastion host deployment. I wrote code stored in a GitHub repo accessible only to the people responsible for managing the bastion host. If you wanted to change the bastion host, you changed the code in GitHub, terminated the old host, and instantiated a new one — just like an immutable class.
Another company recruited me away from Capital One to help them move to the cloud. I considered using Chef to manage all of our system configurations. It was expensive because you had to pay for each node. I loved Chef and knew people who worked there down the street from us. But I started to think, what if we could just skip that expense and require all changes to come from source control?
But was that crazy? Would it work? Could I convince my DevOps team to try it? I did some research and found this article on immutable servers. Someone else was thinking the same way. It was on the Martin Fowler website and that was good enough for me. Martin Fowler is a well-known software engineer for those who have been in the industry for a while.
I still had to convince my DevOps team. Luckily that was easy. I had hired an amazingly smart DevOps guy from the AWS meetup I had started back around 2012. He was into trying it. As it turned out once they implemented it, they loved it!
I went on to speak about this concept of immutable infrastructure at our Seattle AWS Meetup. I had never heard anyone use that term before. I saw someone at a vendor who had been at that meetup tweeted out something about the term after watching my presentation.
We often had people from AWS at our meetups. In fact, I think I helped indirectly helped write the demo for AWS Config at one of our hands-on meetups. The only person that showed up was the AWS Config Product Manager at the time (a super nice guy!) and we worked on something similar to what was presented in the AWS Config demonstration when it was announced at re:Invent. I’m not sure if anyone from AWS saw that presentation on immutable infrastructure or not as we generally had 50 up to sometimes 100 attendees. I didn’t know who everyone was.
The next year after my presentation on the topic at the meetup, numerous talks at AWS re:Invent appeared in the session catalog with “immutable infrastructure” in the title. Coincidence? I don’t know. Perhaps the universe is a giant mind-meld where everyone comes to the same conclusion at the same time. At any rate, now everyone talks about the security benefits of immutable infrastructure.
Some people have used the term incorrectly in presentations I watched. They talked about patching immutable infrastructure. Those servers are not immutable — they change. Immutable infrastructure doesn’t equate to automated deployments. It means once deployed it cannot change. To change something you terminate the immutable host and create a new immutable host.
Constants
A constant is an immutable value. As the name suggests, the value of a constant variable never changes. If you create a variable and assign a value that should never change, make it a constant variable.
In Java you declare a constant variable like this:
final int var5 = 100;
In C#:
const int X = 0;
In JavaScript:
const PI = 3.141592653589793;
In Python…sorry you can’t. But you could create an immutable object.
Scope in its many forms
You can protect variables by using the concept of scope. Scope defines what code within and external to your application can access and change variables, or call methods in your code.
For example, you may have a variable that any code in your application including third-party libraries can change (a global variable.) You might instead want to ensure that a particular variable can only be changed by a function.
Take a look at the code below:
a = 10
b = 1
function add_one:
a = a + b
return a
main:
b = 2
add_one() #now add_one adds 2 because b has changed
Any code in this program can change a or b. What if you wanted to make sure no one else changes b outside of your function? Move b into your function. Nothing outside of the function can reference b.
a = 10
function add_one:
b = 1
a = a + b
return a
main:
b = 2 <<<< ERROR b can only be accessed in function add_one
add_one()
The same holds true for classes. If you only want the code in a single class to be able to change the value of a variable, declare it inside your class. Do not return a reference to your variable.
When you create methods for classes in Java and some other languages, you can define what other code and classes can call the methods. In Java, you write a keyword at the beginning of the method. The possible scopes are as follows:
public: The default. No keyword. Anyone can call your method
private: Only the class that contains the function can call it
protected: Only methods in the same package can call the method.
A package in Java is a collection of classes defined in a program that work together and are often allowed to call each other’s methods. Other programming languages have similar concepts with different names such as namespaces. The concept of namespaces exists in infrastructure too, such as Kubernetes namespaces, but we won’t get into that too much here.
I wrote about the importance of separation of duties and zero trust in my last book. Those same concepts apply to your code. Limit access to data within your application to only the other code that requires it. This helps you prevent bugs and security problems. Use the constructs your programming language provides to offer need-to-know access to data within the program. Limit changes to the classes under your control unless you explicitly want to allow external code to access your methods and data. Do so with care.
Consider the case where you have global variables and public methods handling sensitive data in your application. You include a third-party component. That component may be complex and hard to review. It has functionally that reads and sets values incorrectly, such as moving money to the wrong bank account.
Avoid letting untrusted components access things they shouldn’t. This is a common problem in web applications. Developers include third-party components from external webpages that cross boundaries and make changes that should not be allowed. Any time you include third-party code or components in your application understand what code and data it can access or modify within your own application code.
In web applications, CORS is a means for keeping code from different domains separate. Too often developers get frustrated with CORS and completely turn it off, leading to serious security problems. I wrote about how CORS misconfigurations can allow an attacker to steal all your cookies.
Attackers can do more than that if you disable CORS. Do not assume just because you don’t use cookies that you are safe. I might expand on that in the book, but make sure you understand how CORS works and what it does before you disable it or allow the entire world to have access to your web application to run scripts and request data.
You can also limit what third-party code can do with a proper content security policy (CSP). Often when these are not in place, I find reflected, DOM, and blind XSS attacks where my code can send information to my own attack server. Generally, your web application should not allow code injected into your website to send data to any domain on the Internet.
Set the permissions in your code carefully and before you “fix” a problem with a security “workaround” make sure you understand the potential consequences. Understand all the constructs in your programming language of choice that help you restrict access from third-party code.
Next Steps
- Consider where an atomic variable or class might be appropriate in your multi-threaded applications.
- Try to make objects that do not need to change immutable within your application.
- Use immutable infrastructure as code to prevent misconfigurations and security problems in cloud environments.
- If a value in your code doesn’t need to change, use a constant if you can.
- Only provide access to methods and data in your application by code that requires it.
- Understand the programming concepts in your environment that disallow third-party malicious code from introducing security problems.
Follow for updates.
Teri Radichel | © 2nd Sight Lab 2022
About Teri Radichel:
~~~~~~~~~~~~~~~~~~~~
⭐️ Author: Cybersecurity Books
⭐️ Presentations: Presentations by Teri Radichel
⭐️ Recognition: SANS Award, AWS Security Hero, IANS Faculty
⭐️ Certifications: SANS ~ GSE 240
⭐️ Education: BA Business, Master of Software Engineering, Master of Infosec
⭐️ Company: Penetration Tests, Assessments, Phone Consulting ~ 2nd Sight Lab
Need Help With Cybersecurity, Cloud, or Application Security?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
🔒 Request a penetration test or security assessment
🔒 Schedule a consulting call
🔒 Cybersecurity Speaker for Presentation
Follow for more stories like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
❤️ Sign Up my Medium Email List
❤️ Twitter: @teriradichel
❤️ LinkedIn: https://www.linkedin.com/in/teriradichel
❤️ Mastodon: @teriradichel@infosec.exchange
❤️ Facebook: 2nd Sight Lab
❤️ YouTube: @2ndsightlab
![](https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*H9Ew1KCl-29nZiPR.jpeg)