MQTT over Websocket request / x-amzn-ErrorType: ForbiddenException - websocket

I am using ESP8266-Websocket, aws-sdk-arduino(cleaned branch) and pubsubclient to try to comunicate with aws iot mqtt service using websockets.
My question is about the first connection request. I am using this browser app as reference https://github.com/awslabs/aws-iot-examples and the sign code from aws-sdk-arduino (that works fine calling the aws iot restful api)
My request was this (after connect to the endpoint at 443 port):
GET wss://ENDPOINT.iot.us-west-2.amazonaws.com/mqtt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AWSKEY%2F20160318%2Fus-west-2%2Fiotdevicegateway%2Faws4_request&X-Amz-Date=20160318T183246Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=a1f0d7b58983f9dff7e3bf6cab062db3243ebafc990803a018c6a23433891404 HTTP/1.1
host: ENDPOINT.iot.us-west-2.amazonaws.com
Connection: Upgrade
Upgrade: websocket
Origin: file://
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: D2alJOyUkBlR+8yhv2UBLg==
Sec-WebSocket-Protocol: mqtt
but I keep getting
HTTP/1.1 403 Forbidden
content-type: application/json
content-length: 241
date: Fri, 18 Mar 2016 18:34:57 GMT
x-amzn-RequestId: f2edfe83-1bbc-4481-97e0-39ccfc4d1c2f
connection: Keep-Alive
x-amzn-ErrorType: ForbiddenException:
am i missing some request header parameter? is there anyway to get a better feedback from x-amzn-ErrorType: ForbiddenException? am i messing up in the sign process? (even though it works for rest call)

Yeah, I've finally got response status 101 switching protocols \o/
when you are building the request, it must be:
GET /mqtt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AWSKEY%2F20160318%2Fus-west-2%2Fiotdevicegateway%2Faws4_request&X-Amz-Date=20160318T183246Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=a1f0d7b58983f9dff7e3bf6cab062db3243ebafc990803a018c6a23433891404 HTTP/1.1
instead of
GET wss://ENDPOINT.iot.us-west-2.amazonaws.com/mqtt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AWSKEY%2F20160318%2Fus-west-2%2Fiotdevicegateway%2Faws4_request&X-Amz-Date=20160318T183246Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=a1f0d7b58983f9dff7e3bf6cab062db3243ebafc990803a018c6a23433891404 HTTP/1.1
the js example that I was following was using the full path. When I got the request built by chrome (throught developer tools) the path was full as well. Just after use firebug I got the real request that browser was sending to the server (with short path).
now I can continue to try the solution (mqtt over websockets at esp8266) :-) if it works, I will share the code ;-)

Related

Prevent Open URL Redirect from gorilla/mux

I am working on a RESTful web application using Go + gorilla/mux v1.4 framework. Some basic security testing after a release revealed an Open URL Redirection vulnerability in the app that allows user to submit a specially crafted request with an external URL that causes server to response with a 301 redirect.
I tested this using Burp Suite and found that any request that redirects to an external URL in the app seems to be responding with a 301 Moved Permanently. I've been looking at all possible ways to intercept these requests before the 301 is sent but this behavior seems to be baked into the net/http server implementation.
Here is the raw request sent to the server (myapp.mycompany.com:8000):
GET http://evilwebsite.com HTTP/1.1
Accept: */*
Cache-Control: no-cache
Host: myapp.mycompany.com:8000
Content-Length: 0
And the response any time is:
HTTP/1.1 301 Moved Permanently
Location: http://evilwebsite.com/
Date: Fri, 13 Mar 2020 08:55:24 GMT
Content-Length: 0
Despite putting in checks for the request.URL to prevent this type of redirect in the http.handler, I haven't had any luck getting the request to reach the handler. It appears that the base http webserver is performing the redirect without allowing it to reach my custom handler code as defined in the PathPrefix("/").Handler code.
My goal is to ensure the application returns a 404-Not Found or 400-Bad Request for such requests. Has anybody else faced this scenario with gorilla/mux. I tried the same with a Jetty web app and found it returned a perfectly valid 404. I've been at this for a couple of days now and could really use some ideas.
This is not the claimed Open URL redirect security issue. This request is invalid in that the path contains an absolute URL with a different domain than the Host header. No sane client (i.e. browser) can be lured into issuing such an invalid request in the first place and thus there is no actual attack vector.
Sure, a custom client could be created to submit such a request. But a custom client could also be made to interpret the servers response in a non-standard way or visit a malicious URL directly without even contacting your server. This means in this case the client itself would be the problem and not the servers response.

Does it make any sense for a `HTTP/1.1` response to return HTTP status code `421 Misdirected Request`?

I am currently debugging a surprising "Bad Request" response from an API.
Request:
POST /path HTTP/1.1
...
Response:
HTTP/1.1 421 Misdirected Request
Date: Fri, 30 Nov 2018 21:59:12 GMT
...
Via: https/1.1 subdomain.example.org (ApacheTrafficServer/7.1.4)
...
Per my research, HTTP status code 421 was only added with the http/2 specification. As you can see, my client is sending a HTTP1.1 request.
Does it make any sense to use it in the response to a HTTPS/1.1 request? What could it mean there?
Update: Further research indicates that this 421 response is triggered by an invalid CSRF token and Cookie value in the header, retrying the request with a verifiable valid combination returns the expected result with 200 OK. Unfortunately this doesn't really explain anything.
421 was added for HTTP/2 which allowed connection reuse. If a client reused a connection incorrectly (like Firefox used to) then the server should respond with this.
However that doesn’t mean it’s an HTTP/2 only status code. For example if a load balancer takes HTTP/2 requests in and passes them to back end servers over HTTP/1.1, then one of those backend servers can reject a request over HTTP/1.1 if it believes it was incorrectly sent that request. As you can see your request was sent via an Apache Traffic Server, so I suspect that is what happened here.

Arduino WebSocketClient Sec-WebSocket-Key Error

I built a WebSocket server using WebSocket-Node and the client is an Arduino with an Ethernet shield using the library WebsocketClient from krohling.
The first issue I had was that even the example from the WebsocketClient library didn't return a response from the echo.websocket.org server.
Since the Arduino's Serial monitor didn't give me errors, I added a Serial.print on the handshake section of the library's code to debug the error and I got the following:
HTTP/1.1 400 Bad Request
Server: Kaazing Gateway
Date: Tue, 07 May 2013 05:11:21 GMT
Access-Control-Allow-Origin: ArduinoWebSocketClient
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Headers: x-websocket-extensions
Access-Control-Allow-Headers: x-websocket-version
Access-Control-Allow-Headers: x-websocket-protocol
Content-Type: text/html
Content-Length: 63
Connection: Keep-Alive
Then, I tested it with the WebSocket-Node server I created and got the following on the Serial monitor:
HTTP/1.1 400 Bad Request
Connection: close
X-WebSocket-Reject-Reason: Client must provide a value for Sec-WebSocket-Key.
Am I doing something wrong or does the WebsocketClient library need to be updated?
I haven't been lucky to find a better/newer Arduino Websocket client library. Does anyone know about one I could use?
Thanks a lot!

How to add basic auth header in autobahn client tool

I want to add basic auth header in the autobahn client tool. How can I achieve that?
Current request
GET / HTTP/1.1
User-Agent: AutobahnPython/0.5.2
Host: 10.35.34.172:9000
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Key: 1U4OeBs60qkmk1V/8voLOw==
Sec-WebSocket-Version: 8
Request I need:
GET / HTTP/1.1
User-Agent: AutobahnPython/0.5.2
Host: 10.35.34.172:9000
Authorization: Basic TXlMb2NhdGlvbkFwcDpNeUxvY2F0aW9uQXBwMTIz
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Key: 1U4OeBs60qkmk1V/8voLOw==
Sec-WebSocket-Version: 8
Note: I don't want autobahn server to authenticate the client.
My scenario is autobahn client --> my server --> autobahn server.
My server will take care of extracting the authorization header and then invoke the autobahn server.
I have implemented options to send custom HTTP headers for both AutobahnPython client and server. You need to use the latest AutobahnPython on GitHub (master branch).
A client can send headers by providing a headers keyword argument during construction of the WebSocketClientFactory or set headers via setSessionParameters.
A server can send headers similar to client, and additionally specify headers when returning from onConnect.
Here is a complete example.
Disclaimer: I am original author of Autobahn and work for Tavendo.

Method/program for sending a given HTTP request (with headers)

I am debugging my website. When it has an error, the full text form of the HTTP request that caused the error is logged. I want to be able to replay these HTTP requests to help debugging the error.
For instance, I have this in my log now:
POST /ipn/handler.ashx?inst=272&msgType=result HTTP/1.0
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Host: mysite.com
Content-Length: 28
User-Agent: AGENT/1.0 (UserAgent)
region=website&compName=ACTL
I want a way to make this exact request again on my local test machine (with changed Host attribute). What is the best way to do this?
You could use telnet to talk to your web server and type the exact requests.
You could also use libcurl (& curl) to make a program which is an HTTP client.
And many scripting languages (Python, Ruby, Perl, Ocaml, ...) also have HTTP client libraries (sometimes above Curl).

Resources