From e9f61b6a94bf54651b72daf6fcfaa016e1203650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Tue, 17 Jul 2018 12:03:03 +0200 Subject: [PATCH 1/6] fixed single quote on passwords --- server/src/uds/transports/RDP/RDPTransport.py | 4 ++-- server/src/uds/transports/RDP/TRDPTransport.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/uds/transports/RDP/RDPTransport.py b/server/src/uds/transports/RDP/RDPTransport.py index 282c8992c..372e826ab 100644 --- a/server/src/uds/transports/RDP/RDPTransport.py +++ b/server/src/uds/transports/RDP/RDPTransport.py @@ -44,7 +44,7 @@ logger = logging.getLogger(__name__) READY_CACHE_TIMEOUT = 30 -__updated__ = '2018-05-18' +__updated__ = '2018-07-17' class RDPTransport(BaseRDPTransport): @@ -125,7 +125,7 @@ class RDPTransport(BaseRDPTransport): 'ip': ip, 'port': 3389, 'username': username, - 'password': password, + 'password': password.replace('\'', '\\\''), 'hasCredentials': username != '' and password != '', 'domain': domain, 'width': width, diff --git a/server/src/uds/transports/RDP/TRDPTransport.py b/server/src/uds/transports/RDP/TRDPTransport.py index 163a0b0cb..5a43803fd 100644 --- a/server/src/uds/transports/RDP/TRDPTransport.py +++ b/server/src/uds/transports/RDP/TRDPTransport.py @@ -48,7 +48,7 @@ import logging import random import string -__updated__ = '2018-05-18' +__updated__ = '2018-07-17' logger = logging.getLogger(__name__) @@ -157,7 +157,7 @@ class TRDPTransport(BaseRDPTransport): 'tunPort': sshPort, 'tunWait': self.tunnelWait.num(), 'username': username, - 'password': password, + 'password': password.replace('\'', '\\\''), 'hasCredentials': username != '' and password != '', 'domain': domain, 'width': width, From fbbdc529fe2825199274b8987d2492242834d903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Tue, 17 Jul 2018 21:16:17 +0200 Subject: [PATCH 2/6] Fixes & DEBUG log fix --- client/full/src/uds/log.py | 2 +- server/src/uds/transports/RDP/RDPTransport.py | 2 +- server/src/uds/transports/RDP/TRDPTransport.py | 2 +- server/src/uds/transports/RDP/scripts/windows/direct.py | 2 +- server/src/uds/transports/RDP/scripts/windows/tunnel.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/full/src/uds/log.py b/client/full/src/uds/log.py index 417172423..8d015e5bd 100644 --- a/client/full/src/uds/log.py +++ b/client/full/src/uds/log.py @@ -46,7 +46,7 @@ logging.basicConfig( filename=logFile, filemode='a', format='%(levelname)s %(asctime)s %(message)s', - level=logging.DEBUG + level=logging.INFO ) logger = logging.getLogger('udsclient') diff --git a/server/src/uds/transports/RDP/RDPTransport.py b/server/src/uds/transports/RDP/RDPTransport.py index 372e826ab..5de7e6cde 100644 --- a/server/src/uds/transports/RDP/RDPTransport.py +++ b/server/src/uds/transports/RDP/RDPTransport.py @@ -125,7 +125,7 @@ class RDPTransport(BaseRDPTransport): 'ip': ip, 'port': 3389, 'username': username, - 'password': password.replace('\'', '\\\''), + 'password': password, 'hasCredentials': username != '' and password != '', 'domain': domain, 'width': width, diff --git a/server/src/uds/transports/RDP/TRDPTransport.py b/server/src/uds/transports/RDP/TRDPTransport.py index 5a43803fd..c88715976 100644 --- a/server/src/uds/transports/RDP/TRDPTransport.py +++ b/server/src/uds/transports/RDP/TRDPTransport.py @@ -157,7 +157,7 @@ class TRDPTransport(BaseRDPTransport): 'tunPort': sshPort, 'tunWait': self.tunnelWait.num(), 'username': username, - 'password': password.replace('\'', '\\\''), + 'password': password, 'hasCredentials': username != '' and password != '', 'domain': domain, 'width': width, diff --git a/server/src/uds/transports/RDP/scripts/windows/direct.py b/server/src/uds/transports/RDP/scripts/windows/direct.py index e273498e2..9fc38cba2 100644 --- a/server/src/uds/transports/RDP/scripts/windows/direct.py +++ b/server/src/uds/transports/RDP/scripts/windows/direct.py @@ -13,7 +13,7 @@ from uds import tools # @UnresolvedImport import six try: - thePass = six.binary_type('{m.password}'.encode('UTF-16LE')) + thePass = six.binary_type("""{m.password}""".encode('UTF-16LE')) password = win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01).encode('hex') except Exception: logger.info('Cannot encrypt for user, trying for machine') diff --git a/server/src/uds/transports/RDP/scripts/windows/tunnel.py b/server/src/uds/transports/RDP/scripts/windows/tunnel.py index 5743a368b..0806d6338 100644 --- a/server/src/uds/transports/RDP/scripts/windows/tunnel.py +++ b/server/src/uds/transports/RDP/scripts/windows/tunnel.py @@ -22,7 +22,7 @@ if forwardThread.status == 2: tools.addTaskToWait(forwardThread) try: - thePass = six.binary_type('{m.password}'.encode('UTF-16LE')) + thePass = six.binary_type("""{m.password}""".encode('UTF-16LE')) password = win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01).encode('hex') except Exception: logger.info('Cannot encrypt for user, trying for machine') From 4777b7e8f9854907c41ef7b94b6a6e4eac42c7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Wed, 18 Jul 2018 22:44:23 +0200 Subject: [PATCH 3/6] Fixes for passwords --- server/src/uds/dispatchers/guacamole/views.py | 2 ++ server/src/uds/transports/HTML5RDP/HTML5RDP.py | 3 ++- server/src/uds/transports/RDP/scripts/linux/direct.py | 4 ++-- server/src/uds/transports/RDP/scripts/linux/tunnel.py | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/server/src/uds/dispatchers/guacamole/views.py b/server/src/uds/dispatchers/guacamole/views.py index 0f153627f..71843c0e5 100644 --- a/server/src/uds/dispatchers/guacamole/views.py +++ b/server/src/uds/dispatchers/guacamole/views.py @@ -36,6 +36,7 @@ from django.http import HttpResponse from uds.models import TicketStore from uds.core.util import net from uds.core.auths import auth +from uds.core.managers import cryptoManager import logging @@ -57,6 +58,7 @@ def guacamole(request, tunnelId): try: val = TicketStore.get(tunnelId, invalidate=False) + val['password'] = cryptoManager().decrypt(val['password']) response = dict2resp(val) except Exception: diff --git a/server/src/uds/transports/HTML5RDP/HTML5RDP.py b/server/src/uds/transports/HTML5RDP/HTML5RDP.py index bda3c8d49..da990ad6d 100644 --- a/server/src/uds/transports/HTML5RDP/HTML5RDP.py +++ b/server/src/uds/transports/HTML5RDP/HTML5RDP.py @@ -44,6 +44,7 @@ from uds.core.transports.BaseTransport import TUNNELED_GROUP from uds.core.transports import protocols from uds.core.util import connection from uds.core.util import OsDetector +from uds.core.managers import cryptoManager from uds.models import TicketStore import logging @@ -194,7 +195,7 @@ class HTML5RDPTransport(Transport): 'protocol': 'rdp', 'hostname': ip, 'username': username, - 'password': password, + 'password': cryptoManager().encrypt(password), 'ignore-cert': 'true', 'security': self.security.value, 'drive-path': '/share/{}'.format(user.uuid), diff --git a/server/src/uds/transports/RDP/scripts/linux/direct.py b/server/src/uds/transports/RDP/scripts/linux/direct.py index 8443d3cda..af7224055 100644 --- a/server/src/uds/transports/RDP/scripts/linux/direct.py +++ b/server/src/uds/transports/RDP/scripts/linux/direct.py @@ -27,8 +27,8 @@ def execRdesktop(rdesktop): import subprocess # @Reimport params = [rdesktop] + {m.r.as_rdesktop_params} + ['{m.r.address}'] # @UndefinedVariable p = subprocess.Popen(params, stdin=subprocess.PIPE) - if '{m.password}' != '': - p.stdin.write('{m.password}') + if """{m.password}""" != '': + p.stdin.write("""{m.password}""") p.stdin.close() tools.addTaskToWait(p) diff --git a/server/src/uds/transports/RDP/scripts/linux/tunnel.py b/server/src/uds/transports/RDP/scripts/linux/tunnel.py index c5ef75701..74a662925 100644 --- a/server/src/uds/transports/RDP/scripts/linux/tunnel.py +++ b/server/src/uds/transports/RDP/scripts/linux/tunnel.py @@ -29,7 +29,7 @@ def execRdesktop(rdesktop, port): params = [rdesktop] + {m.r.as_rdesktop_params} + ['127.0.0.1:{{}}'.format(port)] # @UndefinedVariable p = subprocess.Popen(params, stdin=subprocess.PIPE) if {m.hasCredentials}: # @UndefinedVariable - p.stdin.write('{m.password}') + p.stdin.write("""{m.password}""") p.stdin.close() tools.addTaskToWait(p) From f177b98c78b151e8f3c7b996ffd82f839d7268e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Wed, 18 Jul 2018 23:11:55 +0200 Subject: [PATCH 4/6] Fixed tickets auth --- server/src/uds/REST/methods/tickets.py | 3 ++- server/src/uds/web/views/auth.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/server/src/uds/REST/methods/tickets.py b/server/src/uds/REST/methods/tickets.py index e88641416..8ed063c19 100644 --- a/server/src/uds/REST/methods/tickets.py +++ b/server/src/uds/REST/methods/tickets.py @@ -38,6 +38,7 @@ from uds.models import Authenticator from uds.models import DeployedService from uds.models import Transport from uds.models import TicketStore +from uds.core.managers import cryptoManager from uds.core.util.model import processUuid from uds.core.util import tools @@ -207,7 +208,7 @@ class Tickets(Handler): data = { 'username': username, - 'password': password, + 'password': cryptoManager().encrypt(password), 'realname': realname, 'groups': groups, 'auth': auth.uuid, diff --git a/server/src/uds/web/views/auth.py b/server/src/uds/web/views/auth.py index 205f0d649..56e355ba0 100644 --- a/server/src/uds/web/views/auth.py +++ b/server/src/uds/web/views/auth.py @@ -41,6 +41,7 @@ from django.template import RequestContext from uds.core.auths.auth import webLogin, webLogout, authenticateViaCallback, authLogLogin, getUDSCookie from uds.models import Authenticator, DeployedService from uds.core.managers import userServiceManager +from uds.core.managers import cryptoManager from uds.core.util import html from uds.core.util import OsDetector from uds.core.util.State import State @@ -57,7 +58,7 @@ import logging logger = logging.getLogger(__name__) -__updated__ = '2018-06-27' +__updated__ = '2018-07-18' @csrf_exempt @@ -156,7 +157,7 @@ def ticketAuth(request, ticketId): auth = data['auth'] realname = data['realname'] servicePool = data['servicePool'] - password = data['password'] + password = cryptoManager().decrypt(data['password']) transport = data['transport'] except Exception: logger.error('Ticket stored is not valid') From 34046c8a7eb0be620b3c1434897414369f2a127d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Thu, 19 Jul 2018 11:22:04 +0200 Subject: [PATCH 5/6] removed unsecure logging on exception on code --- client/full/src/UDSClient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/full/src/UDSClient.py b/client/full/src/UDSClient.py index 8f40ac209..a35e5012c 100755 --- a/client/full/src/UDSClient.py +++ b/client/full/src/UDSClient.py @@ -219,7 +219,7 @@ class UDSClient(QtGui.QMainWindow): QtCore.QTimer.singleShot(10000, self.getTransportData) except Exception as e: - logger.exception('Got exception executing script:') + #logger.exception('Got exception executing script:') self.showError(e) def endScript(self): From 4b75be2f02f9176505e4d5fb61b3d053296b2f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Thu, 19 Jul 2018 21:14:08 +0200 Subject: [PATCH 6/6] fully fixed password issue on HTML5 --- server/src/uds/core/workers/SystemCleaners.py | 2 +- server/src/uds/dispatchers/guacamole/views.py | 4 +++- server/src/uds/models/TicketStore.py | 9 +++++---- server/src/uds/transports/HTML5RDP/HTML5RDP.py | 8 ++++++-- server/src/uds/transports/RDP/RDPTransport.py | 4 ++-- server/src/uds/transports/RDP/TRDPTransport.py | 4 ++-- 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/server/src/uds/core/workers/SystemCleaners.py b/server/src/uds/core/workers/SystemCleaners.py index 466f6176d..41b65f44c 100644 --- a/server/src/uds/core/workers/SystemCleaners.py +++ b/server/src/uds/core/workers/SystemCleaners.py @@ -59,7 +59,7 @@ class CacheCleaner(Job): class TicketStoreCleaner(Job): - frecuency = 3600 * 12 # every twelve hours + frecuency = 60 # every minute (60 seconds) friendly_name = 'Ticket Storage Cleaner' def __init__(self, environment): diff --git a/server/src/uds/dispatchers/guacamole/views.py b/server/src/uds/dispatchers/guacamole/views.py index 71843c0e5..dea67e9ee 100644 --- a/server/src/uds/dispatchers/guacamole/views.py +++ b/server/src/uds/dispatchers/guacamole/views.py @@ -56,9 +56,11 @@ def dict2resp(dct): def guacamole(request, tunnelId): logger.debug('Received credentials request for tunnel id {0}'.format(tunnelId)) + tunnelId, scrambler = tunnelId.split('.') + try: val = TicketStore.get(tunnelId, invalidate=False) - val['password'] = cryptoManager().decrypt(val['password']) + val['password'] = cryptoManager().xor(val['password'], scrambler) response = dict2resp(val) except Exception: diff --git a/server/src/uds/models/TicketStore.py b/server/src/uds/models/TicketStore.py index 431fac09d..cf4a3bc6f 100644 --- a/server/src/uds/models/TicketStore.py +++ b/server/src/uds/models/TicketStore.py @@ -44,7 +44,7 @@ import logging logger = logging.getLogger(__name__) -__updated__ = '2016-01-14' +__updated__ = '2018-07-19' class TicketStore(UUIDModel): @@ -148,10 +148,11 @@ class TicketStore(UUIDModel): @staticmethod def cleanup(): + from datetime import timedelta now = getSqlDatetime() - cleanSince = now - datetime.timedelta(seconds=TicketStore.MAX_VALIDITY) - number = TicketStore.objects.filter(stamp__lt=cleanSince).delete() - logger.debug('Cleaned {} tickets'.format(number)) + for v in TicketStore.objects.all(): + if now > v.stamp + timedelta(seconds=v.validity): + v.delete() def __unicode__(self): if self.validator is not None: diff --git a/server/src/uds/transports/HTML5RDP/HTML5RDP.py b/server/src/uds/transports/HTML5RDP/HTML5RDP.py index da990ad6d..2ea1a2a8b 100644 --- a/server/src/uds/transports/HTML5RDP/HTML5RDP.py +++ b/server/src/uds/transports/HTML5RDP/HTML5RDP.py @@ -190,12 +190,15 @@ class HTML5RDPTransport(Transport): if domain != '': username = domain + '\\' + username + scrambler = cryptoManager().randomString(32) + passwordCrypted = cryptoManager().xor(password, scrambler) + # Build params dict params = { 'protocol': 'rdp', 'hostname': ip, 'username': username, - 'password': cryptoManager().encrypt(password), + 'password': passwordCrypted, 'ignore-cert': 'true', 'security': self.security.value, 'drive-path': '/share/{}'.format(user.uuid), @@ -227,4 +230,5 @@ class HTML5RDPTransport(Transport): ticket = TicketStore.create(params, validity=self.ticketValidity.num()) - return HttpResponseRedirect("{}/transport/?{}&{}".format(self.guacamoleServer.value, ticket, request.build_absolute_uri(reverse('Index')))) + return HttpResponseRedirect("{}/transport/?{}.{}&{}".format(self.guacamoleServer.value, ticket, scrambler, request.build_absolute_uri(reverse('Index')))) + diff --git a/server/src/uds/transports/RDP/RDPTransport.py b/server/src/uds/transports/RDP/RDPTransport.py index 5de7e6cde..8b60a1ad8 100644 --- a/server/src/uds/transports/RDP/RDPTransport.py +++ b/server/src/uds/transports/RDP/RDPTransport.py @@ -44,7 +44,7 @@ logger = logging.getLogger(__name__) READY_CACHE_TIMEOUT = 30 -__updated__ = '2018-07-17' +__updated__ = '2018-07-19' class RDPTransport(BaseRDPTransport): @@ -125,7 +125,7 @@ class RDPTransport(BaseRDPTransport): 'ip': ip, 'port': 3389, 'username': username, - 'password': password, + 'password': password.replace('"""', '\"\"\"'), 'hasCredentials': username != '' and password != '', 'domain': domain, 'width': width, diff --git a/server/src/uds/transports/RDP/TRDPTransport.py b/server/src/uds/transports/RDP/TRDPTransport.py index c88715976..578000901 100644 --- a/server/src/uds/transports/RDP/TRDPTransport.py +++ b/server/src/uds/transports/RDP/TRDPTransport.py @@ -48,7 +48,7 @@ import logging import random import string -__updated__ = '2018-07-17' +__updated__ = '2018-07-19' logger = logging.getLogger(__name__) @@ -157,7 +157,7 @@ class TRDPTransport(BaseRDPTransport): 'tunPort': sshPort, 'tunWait': self.tunnelWait.num(), 'username': username, - 'password': password, + 'password': password.replace('"""', '\"\"\"'), 'hasCredentials': username != '' and password != '', 'domain': domain, 'width': width,