Social: SignatureException behind Apache proxy

Created on 23 Dec 2018  Â·  6Comments  Â·  Source: nextcloud/social

Describe the bug
Everytime an external service tries to communicate with Social the messages cannot be processed and result in a SignatureException as stated by a log entry like seen below.

My setup
Nextcloud running in a docker container <-- http --> Apache with proxy setup 443 to 80 and an official subdomain <-- https --> Internet

First approach of a solution
So I debugged a little and found, that the signature comparison done in SignatureService->generateEstimatedSignature() evaluated the header variable 'Host', which was filled with the name and port of my docker container.

Thinking, that this might be wrong, I took a peek at the available request headers at this point of execution. Apache put the "real", external hostname into X-Forwarded-Host, so I tried building the estimated Signature with this variable instead. This worked, although I can't say that I fully understand the implications of my hack. Here is what my method looks like now (added the second if-block in the loop):

    private function generateEstimatedSignature(string $headers, IRequest $request): string {
        $keys = explode(' ', $headers);
        $target = '';
        try {
            $target = strtolower($request->getMethod()) . " " . $request->getRequestUri();
        } catch (Exception $e) {
        }
        $estimated = "(request-target): " . $target;
        foreach ($keys as $key) {
            if ($key === '(request-target)') {
                continue;
            }
            if ($key === 'host' && isset($request->getHeader("X-Forwarded-Host")))
            {
                $estimated .= "\n" . $key . ': ' . $request->getHeader("X-Forwarded-Host");
                continue;
            }
            $estimated .= "\n" . $key . ': ' . $request->getHeader($key);
        }
        return $estimated;
    }

I can't even say, if this is maybe just a configuration problem of my setup, or if it is really a bug. Or my solution might lead to some horrible security issues. Or it works only on my special setup. All I know is that it worked after that change. What do you think?

To Reproduce
Steps to reproduce the behavior:

  1. Send a direct Mastodon message to my nextcloud account.
  2. Results in SignatureException like below.

Expected behavior
The message is being processed, received and displayed.


Server details
Social app version: 0.1.1

Operating system: Gentoo Linux

Web server: Apache 2.4

Database: MySQL

PHP version: 7.2.13

Nextcloud version: 15.0.0.10


Logs

Nextcloud log (data/nextcloud.log)

{"reqId":"WqV8OJgUD7drQlXXqBDk","level":2,"time":"2018-12-23T08:30:59+00:00","remoteAddr":"78.46.16.22","user":"--","app":"no app in context","method":"POST","url":"/index.php/apps/social/@riemy/inbox","message":"500 - {\"status\":-1,\"exception\":\"OCA\\\\Social\\\\Exceptions\\\\SignatureException\",\"message\":\"signature cannot be checked\"}","userAgent":"http.rb/3.3.0 (Mastodon/2.6.5; +https://ruhr.social/)","version":"15.0.0.10","id":"5c1f47c37ea4b"}

1. to develop bug

Most helpful comment

All 6 comments

This edit makes sense as Apache Proxy changes the Host header and backup the old value in $request->getHeader("X-Forwarded-Host").

We could implement it, but should we check also that the value of the X-Forwarded-Host is the host of our nextcloud ?
Wouldn't it be possible/simple to fix the host-header on the origin or duplicate the host-header on origin and proxy in your Apache setup ?

@juliushaertl @nickvergessen @rullzer

279

So I started with using the getInsecureServerHost, but I ended up forcing the value of the Host to the address used in the social App.

We assume that cloud.example.com in @[email protected] is the unique Host that is used to sign the Header of incoming request.

I can confirm this error (without doing further debugging to confirm the cause 100% matches OPs cause) with a nginx proxy in front of Nextcloud running in Docker container. Every interaction (direct message, follow, …) from an external Mastodon instance causes SignatureException: signature cannot be checked.

Sadly the interaction does not go through and it is broken.


Log entry

{
  "reqId": "kf7BXH2gYU8cedluiqnw",
  "level": 2,
  "time": "2018-12-29T13:37:50+00:00",
  "remoteAddr": "88.99.89.29",
  "user": "--",
  "app": "no app in context",
  "method": "POST",
  "url": "/apps/social/@knut/inbox",
  "message": "500 - {\"status\":-1,\"exception\":\"OCA\\\\Social\\\\Exceptions\\\\SignatureException\",\"message\":\"signature cannot be checked\"}",
  "userAgent": "http.rb/3.3.0 (Mastodon/2.6.5; +https://chaos.social/)",
  "version": "15.0.0.10",
  "id": "5c2778aec3946"
}

Fixed by #279

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ArtificialOwl picture ArtificialOwl  Â·  7Comments

jancborchardt picture jancborchardt  Â·  7Comments

maiki picture maiki  Â·  5Comments

jancborchardt picture jancborchardt  Â·  6Comments

poVoq picture poVoq  Â·  5Comments