From 178ab9ec439e457daa6820d9f5f41e7342402dc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lex=20Hermida?= Date: Wed, 10 Oct 2018 10:47:57 +0200 Subject: [PATCH] Prevent local webhook requests --- taiga/webhooks/tasks.py | 16 ++++++++++++++++ taiga/webhooks/utils.py | 21 +++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 taiga/webhooks/utils.py diff --git a/taiga/webhooks/tasks.py b/taiga/webhooks/tasks.py index 343a87ac..62bdd8d8 100644 --- a/taiga/webhooks/tasks.py +++ b/taiga/webhooks/tasks.py @@ -30,6 +30,7 @@ from .serializers import (EpicSerializer, EpicRelatedUserStorySerializer, UserStorySerializer, IssueSerializer, TaskSerializer, WikiPageSerializer, MilestoneSerializer, HistoryEntrySerializer, UserSerializer) +from . import utils from .models import WebhookLog @@ -71,6 +72,21 @@ def _send_request(webhook_id, url, key, data): "X-Hub-Signature": "sha1={}".format(signature), "Content-Type": "application/json" } + + try: + utils.validate_destination_address(url) + except utils.IpaddresValueError as e: + # Error validating url + webhook_log = WebhookLog.objects.create(webhook_id=webhook_id, url=url, + status=0, + request_data=data, + request_headers=dict(), + response_data="error-in-request: {}".format( + str(e)), + response_headers={}, + duration=0) + return webhook_log + request = requests.Request('POST', url, data=serialized_data, headers=headers) prepared_request = request.prepare() diff --git a/taiga/webhooks/utils.py b/taiga/webhooks/utils.py new file mode 100644 index 00000000..0a87462b --- /dev/null +++ b/taiga/webhooks/utils.py @@ -0,0 +1,21 @@ +import ipaddress +import socket +from urllib.parse import urlparse + + +class IpaddresValueError(Exception): + pass + + +def validate_destination_address(url): + host = urlparse(url).hostname + port = urlparse(url).port + socket_args, _ = socket.getaddrinfo(host, port) + destination_address = socket_args[4][0] + + try: + ipa = ipaddress.ip_address(destination_address) + except ValueError: + raise IpaddresValueError(_("IP Address error")) + if ipa.is_private: + raise IpaddresValueError("Not allowed IP Address")