../ Design Issues: Emacs vs BurpSuite

It was in my second year of university that I discovered Emacs. It took me about four to five years to learn how to use it properly. Then another three years to truly understand its design principles and why it was built exactly this way and not in any other way. There's still a lot to learn about Emacs, and in the last few years I feel like something has deeply changed in the way I look at software. Now I'm better able to express why I prefer using Emacs and why sometimes I have troubles with the way other software is designed.

Few months ago I started a new job as a consultant. The company I work for does all sorts of things related to software security, going from WAPT (Web Application Penetration Test), to MAPT (Mobile Application Penetration Test), to SCR (Secure Code Review). During these early months, as I'm learning the job and all the new workflows that come with it, I'm also trying to integrate these workflows in Emacs as much as possible. Given that I was already very efficient in Emacs, I'm noticing a great increase in productivity whenever I'm able to integrate a new workflow within Emacs.

For some tasks however this is not possible, not at the moment anyway. For example, during every single WAPT activity a software we use is BurpSuite, which is a famous tool in the context of web security. It acts as a MiTM (Man in The Middle) between the browser and the web application under test, and it allows the tester to observe and modify the traffic sent within the communication channel to see how the server application responds to malicious payloads that the normal client application would not typically generate and vice versa (sometimes we modify server responses to trigger vulnerable behavior within the client).

In this blog post I want to discuss my observation with respect to certain limitations of BurpSuite. Specifically, the discussion will consider these two software, Emacs and BurpSuite, from a point of view of software design.

My argument is that while Emacs can be complex and confusing at first, it is actually built following a set of useful design principles which, when understood, actually help you to tackle the complexity of the software, to learn new things about it and in general to expand your knowledge on how to use it, extend it for tackling new use-cases and also debug it. A software like BurpSuite instead, while it can be immensely useful for certain activities, has no such design principles. The lack of certain design principles in BurpSuite lead to a frustrating experience when trying to understand it in order to modify it and expand its capabilities. It remains therefore a static software that does not adapt well to new situations.

Hoping it is an interesting read, I'll leave you to it!

#Real Stories Are Useful Starting Points

While it can be tempting to start a discussion using general and abstract terms, it will be much more useful for my argument to start from a really pratical example which should set the right expectations.

Within BurpSuite there is a functionality called Repeater, which allows the user to take an existing request, modify it, and send it again. You start from the Proxy, which contains all the messages that the browser sent to the application, you select the request you're interested in modifying and you can send it to the Repeater page.

Within the Repeater page there are different tabs. Each tab contains a single request. By clicking on one such tab you can modify the request and send it again. This is extremely useful when you want to craft malicious request and you want to check how the web application responds to a specific payload.

As you can see from the image, each tab has a specific label, and by default BurpSuite has an internal counter which is incremented by one for each new request sent to the Repeater page. Since in a given activity it usually happens that I create a lot of tabs, I wanted to find a way if I could change the way these tabs are labeled.

Initially I found no such way. Technically, you can click on each tab and rename it, but I wanted to have an automatic mechanism for doing it, and no such mechanism exist. What does this tells us about this specific software?

There is a significant distance between the user of the application and the internal variables which govern the application

Thankfully, I was already aware of the existence of Extensions. Extensions are ways in which you can expand BurpSuite capabilities by writing code in Java, Python or Ruby. Since I was already experimenting with writing some extension in java, I decided to understand if there was someway in which I could implement this behavior using the extension API.

After some work, I managed to get it working. In the future I will probably open source my extensions, for now it suffices the following code.

public void customSendToRepeater(HttpRequestResponse requestResponse) {
    HttpRequest req = requestResponse.request();
    String tabName = this.id + " - " + req.method(); + " - " + req.pathWithoutQuery();
    this.api.repeater().sendToRepeater(req, tabName);
    this.id += 1;
}

The above code is executed everytime I click on a custom new entry within the HTTP proxy tab contextual menu. I'm using the sendToRepeater() method in order to send the request to the repeater tab. The first parameter of the method is the actual request, which is an HttpRequest object, while the second parameter is the string which represents the tab label for that request within Repeater. I'm able to compute it by extracting various information of interest from the request. If you want more information on how the API works, check out the following resource:

With this extension I was able to modify the behavior of BurpSuite the way I wanted. I was happy! Now, by using the menu I can click on a specific entry, which was added by the extension, and the request will be sent to repeater as before, but now with the new label computation.

At this point I was satisfied, but of couse I wanted more. It is an interest of mine to find places where I can optimize the workflow to get the job done faster and with less effort. Clicking everytime on the menu seemed not practical to me. I live within the keyboard and I try to touch the mouse as less as possible. Given that the original "Send to Repeater" was bound to Control-R, I wanted to replace the keybind to use my custom functionality. Something not too hard to do, I suspected originally.

I tried to search if this was possible, but I could not find any officially supported ways of doing this. The API did not allow for this sort of thing to be done. I can add extra functionalities, but I cannot bind them to the various keybinds, at least not through the official API. All the references I found point to the Sharpener extension, which apparently implements this sort of behavior.

By understanding the code of this extension, and modifying it for my own needs, I should be able to hack something together. But that's the catch. There is a need to "hack something" in order to create a keybind to a custom functionality. The software does not make it "easy to do". Once again, there is a considerable distance between the user and the application.

Let's now talk about design. First, I will discuss the design of Emacs, and then that of BurpSuite.

#The Design of Emacs

In Emacs the situation I just described simply cannot happen. This is because in Emacs I have complete access over almost every single variable that controls the program.

Emacs is built using two main technologies: C and Emacs-Lisp. While the main engine is written in C, and therefore cannot be easily modified without re-building the entire system, everything that is executed in the Emacs-Lisp environment is easily accessible, modifiable and transparent.

I want to define a new function that is accessible from the M-x system? I just need to add an interactive within the new function, as I've already discussed in my previous blog post on RSS feed generation.

(defun yt2git/gen-rss ()
  (interactive)
  (yt2git/gen-rss-by-repo (yt2git/select-repository))
  )

I need to add a new keybind to a newly created custom function? I can use the global-set-key function.

(global-set-key (kbd "C-c f") #'yt2git/gen-rss)

In emacs I can get immediate access to every function, variable and keybinds with the describe functionalities.

  • With C-h f I can describe any function.
  • With C-h v I can describe any variable.
  • With C-h k I can describe any keybind.

In order to change the behavior of Emacs I simply need to understand the the variable that controls that particular behavior, and then change it accordingly. Since I have direct access over every elisp variable, it all comes down to just finding the right variable. Let me be clear: this process is not always simple, especially when one begins to learn Emacs, but it is always doable, and the more you know about Emacs the easier it gets.

The main benefit of Emacs is that everything is controlled using the same language (Emacs-Lisp). This greatly reduces the distance between the user and the application. Specifically, it gives to the final user the choice to reduce that distance. When you start out, the distance seems insane, almost unbearable, but then, by slowling learning these basic principles, by getting familar around both the keybinds and the functionalities of the editor, it all slowly starts to make sense, until finally one day everything clicks and you're able to see Emacs as a single computational environment that is completely at your disposal.

#The Design of BurpSuite

The design of BurpSuite is very different from the design of Emacs.

There is a clear, rigid and high abstraction barrier between the functionalities implemented in the application and the way the user is able to access them. It feels as if someone said: "ok, the proxy history must be used like this, and the repeater like that, and the introduer like that" and so on.

It is not just that the UI at times is bad. It is rather the fact that the software puts rigid expectation on the behavior of the user. It forces its way, and the user is forced to adapt to it with limited possibility for change. If a user wants to do something differently, because maybe they feel more comfortable or more productive with a different workflow, there is no simple way of changing the way the software presents itself.

While Emacs was designed from its inception in order to minimize as much as possible the number of arbitrary choices made (this number is always greater than zero), it feels like BurpSuite was developed without any worries over this matter.

Even the API they offer, while it is extremely useful for certain things, as soon as you want to do something that goes outside what it was meant to do, it becomes completely useless. What if, for example, the sendToRepeater() did not have the second extra parameter for specifying a custom label? How much effort would it have taken create the tab rename functionality? And why I cannot control the style of the newly created tab anyways? Or the size of the font?

I could keep listing all the features that I wish I could have added to the sendToRepeater() API, but clearly this is not the point. The software should not be designed with respect to my point of view, because different people will inevitably have different needs and therefore would design the API in a different way. I simply wanted to bring attention to the fact that an arbitrary choice has been made in the design of that API. Instead of letting the final user choose, someone has already choosen for them. This is clearly a different design than the one showcased in Emacs.

#Open and Flexible Technology Matters

As I was writing this blog post, I started to think: could it be that the fact that Emacs is open-source and BurpSuite is not source has something to do with this deep difference?

Probably yes, at least in part. It seems like closed software will always be limited in the sense that in its design choices will be made to hide its core implementation from the user, which inevitably creates distance. I'm not saying open-source is always better than closed-source, rather that closed-source will always be limited to the rigid expectations imposed by its nature. For Open-Source the problem is the opposite: the lack of rigid expectations can destroy its nature in the long run if it is not properly maintained.

I also suspect that another major difference is in the respective languages used by each tool. While Java does inherit some flexibility of Lisp, it is nowhere near as flexible as a language that directly belongs to the Lisp family such as Emacs-Lisp. Could it be the case that a program written in Java will always be limited in the interaction it has with the final user? In this matter, I'm starting to understand why and where exactly LISP is great: it is great anytime a complex API has to be offered to a knowledgable user that wants to interact with it programmatically. It is one of the most minimal-yet-usable kind of languages, and it seems to be an extremely good "frontend language".

#Sometimes Less is More

To finish off, I also want to make clear another point. In this discussion I analyzed the limitations of BurpSuite, specifically the fact that it was implemented with rigid expectations for the final user, as a negative aspect of the software. Is this always the case?

Not at all. In some situations imposing a rigid set of behaviors on the final user can be extremely useful. This is the case with cryptography for example and with cryptographic software. In this context, leaving too much freedom to the final user can be dangerous as it increases the complexity of the software and less knowledgeable users might not be able to handle all that freedom, leading to a decrease in security. In these situations It is a much wiser choice to offer a limited, well documented and robust API that only does a few things.

In the context where BurpSuite operates however I find its rigidity a limitation for experienced users that desire to work with specific and adaptable workflows.