Example #1
0
    def render_GET(self, request):
        try:
            token  = request.args.get('token', None)[0]
            fmt    = request.args.get('fmt', None)[0]

            canarydrop = Canarydrop(**get_canarydrop(canarytoken=token))
            if not canarydrop:
                raise NoCanarytokenPresent()

            if fmt == 'zip':
                request.setHeader("Content-Type", "application/zip")
                request.setHeader("Content-Disposition",
                                  'attachment; filename={token}.zip'\
                                  .format(token=token))
                return make_canary_zip(hostname=
                            canarydrop.get_hostname(with_random=False))
            elif fmt == 'msword':
                request.setHeader("Content-Type",
                                  "application/vnd.openxmlformats-officedocument"+\
                                                      ".wordprocessingml.document")
                request.setHeader("Content-Disposition",
                                  'attachment; filename={token}.docx'\
                                  .format(token=token))
                return make_canary_msword(url=canarydrop.get_url())
            elif fmt == 'pdf':
                request.setHeader("Content-Type", "application/pdf")
                request.setHeader("Content-Disposition",
                                  'attachment; filename={token}.pdf'\
                                  .format(token=token))
                return make_canary_pdf(hostname=canarydrop.get_hostname(nxdomain=True, with_random=False))
        except Exception as e:
            log.err('Unexpected error in download: {err}'.format(err=e))


        return NoResource().render(request)
Example #2
0
    def render_POST(self, request):
        request.responseHeaders.addRawHeader(b"content-type", b"application/json")
        response = { 'Error': None,
                     'Url': "",
                     'Token': "",
                     'Email': "",
                     'Hostname': "",
                     'Auth': ''}
        try:
            try:
                email = request.args.get('email', None)[0]
                webhook = request.args.get('webhook', None)[0]
                if not email and not webhook:
                    response['Error'] = 1
                    raise Exception('No email/webhook supplied')
            except IndexError:
                response['Error'] = 1
                raise Exception('No email supplied')
            try:
                memo  = ''.join(request.args.get('memo', None))
                if not memo:
                    response['Error'] = 2
                    raise Exception('No memo supplied')
            except TypeError:
                response['Error'] = 2
                raise Exception('No memo supplied')

            if webhook and not is_webhook_valid(webhook):
                response['Error'] = 3
                raise Exception('Invalid webhook supplied')

            alert_email_enabled = False if not email else True
            alert_webhook_enabled = False if not webhook else True
            canarytoken = Canarytoken()

            try:
                browser_scanner = request.args['subtype'][0] == 'browserscanner'
            except:
                browser_scanner = False

            canarydrop = Canarydrop(generate=True,
                                  alert_email_enabled=alert_email_enabled,
                                  alert_email_recipient=email,
                                  alert_webhook_enabled=alert_webhook_enabled,
                                  alert_webhook_url=webhook,
                                  canarytoken=canarytoken.value(),
                                  memo=memo,
                                  browser_scanner_enabled=browser_scanner)

            if settings.TWILIO_ENABLED:
                try:
                    if not request.args['mobile'][0]:
                        raise KeyError

                    canarydrop['alert_sms_recipient'] = request.args['mobile'][0]
                    canarydrop['alert_sms_enabled'] = True
                except KeyError:
                    canarydrop['alert_sms_recipient'] = ''
                    canarydrop['alert_sms_enabled'] = False

            save_canarydrop(canarydrop)

            response['Token'] = canarytoken.value()
            response['Url'] = canarydrop.get_url()
            response['Hostname'] = canarydrop.get_hostname()
            response['Auth'] = canarydrop['auth']
            response['Email'] = email

            try:
                clonedsite = request.args['clonedsite'][0]
                if not clonedsite:
                    raise KeyError

                cloned_token = {'clonedsite': clonedsite,
                               'canarytoken': canarytoken.value()}
                canarydrop.clonedsite_token = save_clonedsite_token(cloned_token)
                save_canarydrop(canarydrop)
                response['clonedsite_js'] =  CLONED_SITE_JS\
                                    .replace('CLONED_SITE_DOMAIN', clonedsite)\
                                    .replace('CANARYTOKEN_SITE', canarydrop.get_random_site())\
                                    .replace('CANARYTOKEN', response['Token'])
                response['clonedsite'] =  clonedsite
            except (IndexError, KeyError):
                pass

            try:
                imgur_id = request.args['imgur'][0]
                if not imgur_id:
                    raise KeyError

                imgur_token = {'id': imgur_id,
                               'canarytoken': canarytoken.value()}
                canarydrop.imgur_token = save_imgur_token(imgur_token)
                save_canarydrop(canarydrop)
                response['imgur_count'] = imgur_token['count']
                response['imgur_id'] =  imgur_id
            except (IndexError, KeyError):
                pass

            try:
                linkedin_user = request.args['linkedin_user'][0]
                linkedin_password = request.args['linkedin_password'][0]
                if not linkedin_user and not linkedin_password:
                    raise KeyError

                create_linkedin_account(username=linkedin_user,
                                        password=linkedin_password,
                                        canarydrop=canarydrop)

                response['linkedin_account'] = linkedin_user
                response['linkedin_account_views'] = \
                          get_linkedin_account(username=linkedin_user)['count']
            except (IndexError, KeyError):
                pass

            try:

                bitcoin_address = request.args['bitcoin_address'][0]
                if not bitcoin_address:
                    raise KeyError

                create_bitcoin_account(address=bitcoin_address)

                btc = get_bitcoin_account(address=bitcoin_address)

                response['bitcoin_address'] = bitcoin_address
                response['bitcoin_balance'] = btc['balance']
            except (IndexError, KeyError):
                pass

            try:
                qrcode = pyqrcode.create(canarydrop.get_url()).png_as_base64_str(scale=5)
                response['qrcode_png'] = "data:image/png;base64,{qrcode}".format(qrcode=qrcode)
            except:
                pass

        except Exception as e:
            if response['Error'] is None:
                response['Error'] = 255
                log.err('Unexpected error: {err}'.format(err=e))

        return simplejson.dumps(response)
    def render_POST(self, request):
        request.responseHeaders.addRawHeader(b"content-type",
                                             b"application/json")
        response = {
            'Error': None,
            'Url': "",
            'Url_components': None,
            'Token': "",
            'Email': "",
            'Hostname': "",
            'Auth': ''
        }

        try:
            try:
                token_type = request.args.get('type', None)[0]
                if token_type not in [
                        'web', 'dns', 'web_image', 'ms_word', 'adobe_pdf',
                        'windows_dir', 'clonedsite', 'qr_code', 'svn', 'smtp',
                        'sql_server', 'aws_keys', 'signed_exe',
                        'fast_redirect', 'slow_redirect'
                ]:
                    raise Exception()
            except:
                raise Exception('Unknown type')

            try:
                email = request.args.get('email', None)[0]
                webhook = request.args.get('webhook', None)[0]
                if not email and not webhook:
                    response['Error'] = 1
                    raise Exception('No email/webhook supplied')
            except IndexError:
                response['Error'] = 1
                raise Exception('No email supplied')
            try:
                memo = ''.join(request.args.get('memo', None))
                if not memo:
                    response['Error'] = 2
                    raise Exception('No memo supplied')
            except TypeError:
                response['Error'] = 2
                raise Exception('No memo supplied')

            if webhook and not is_webhook_valid(webhook):
                response['Error'] = 3
                raise Exception(
                    'Invalid webhook supplied. Confirm you can POST to this URL.'
                )

            alert_email_enabled = False if not email else True
            alert_webhook_enabled = False if not webhook else True
            canarytoken = Canarytoken()

            if token_type == "web":
                #always enable the browser scanner by default
                browser_scanner = True
            else:
                browser_scanner = False

            canarydrop = Canarydrop(
                type=token_type,
                generate=True,
                alert_email_enabled=alert_email_enabled,
                alert_email_recipient=email,
                alert_webhook_enabled=alert_webhook_enabled,
                alert_webhook_url=webhook,
                canarytoken=canarytoken.value(),
                memo=memo,
                browser_scanner_enabled=browser_scanner)

            if settings.TWILIO_ENABLED:
                try:
                    if not request.args['mobile'][0]:
                        raise KeyError

                    canarydrop['alert_sms_recipient'] = request.args['mobile'][
                        0]
                    canarydrop['alert_sms_enabled'] = True
                except KeyError:
                    canarydrop['alert_sms_recipient'] = ''
                    canarydrop['alert_sms_enabled'] = False

            save_canarydrop(canarydrop)

            response['Token'] = canarytoken.value()
            response['Url'] = canarydrop.get_url()
            response['Hostname'] = canarydrop.get_hostname()
            response['Auth'] = canarydrop['auth']
            response['Email'] = email
            response['Url_components'] = list(canarydrop.get_url_components())
            save_canarydrop(canarydrop)

            try:
                clonedsite = request.args['clonedsite'][0]
                if not clonedsite:
                    raise KeyError

                cloned_token = {
                    'clonedsite': clonedsite,
                    'canarytoken': canarytoken.value()
                }
                canarydrop.clonedsite_token = save_clonedsite_token(
                    cloned_token)
                canarydrop['clonedsite'] = clonedsite
                save_canarydrop(canarydrop)
                response[
                    'clonedsite_js'] = canarydrop.get_cloned_site_javascript()
                response['clonedsite'] = clonedsite
            except (IndexError, KeyError):
                pass

            try:
                if not request.args.get('type', None)[0] == 'qr_code':
                    raise Exception()
                response['qrcode_png'] = canarydrop.get_qrcode_data_uri_png()
            except:
                pass

            try:
                if not request.args.get('type', None)[0] == 'aws_keys':
                    raise Exception()
                keys = get_aws_keys(token=canarytoken.value(),
                                    server=get_all_canary_domains()[0])
                if not keys:
                    raise Exception()
                response['aws_access_key_id'] = keys[0]
                response['aws_secret_access_key'] = keys[1]
                canarydrop['aws_access_key_id'] = keys[0]
                canarydrop['aws_secret_access_key'] = keys[1]
                save_canarydrop(canarydrop)
            except:
                pass

            try:
                if not request.args.get('type', None)[0] == 'web_image':
                    raise Exception()

                if not settings.WEB_IMAGE_UPLOAD_PATH:
                    raise Exception(
                        "Image upload not supported, set CANARY_WEB_IMAGE_UPLOAD_PATH in frontend.env."
                    )

                fields = cgi.FieldStorage(
                    fp=request.content,
                    headers=request.getAllHeaders(),
                    environ={
                        'REQUEST_METHOD': 'POST',
                        'CONTENT_TYPE':
                        request.getAllHeaders()['content-type'],
                    })

                filename = fields['web_image'].filename
                filebody = fields['web_image'].value

                if len(filebody) > settings.MAX_UPLOAD_SIZE:
                    raise Exception('File too large')

                if not filename.lower().endswith(('.png', '.gif', '.jpg')):
                    raise Exception('Uploaded image must be a PNG, GIF or JPG')
                ext = filename.lower()[-4:]

                #create a random local filename
                r = hashlib.md5(os.urandom(32)).hexdigest()
                filepath = os.path.join(settings.WEB_IMAGE_UPLOAD_PATH, r[:2],
                                        r[2:]) + ext
                if not os.path.exists(os.path.dirname(filepath)):
                    try:
                        os.makedirs(os.path.dirname(filepath))
                    except OSError as exc:  # Guard against race condition
                        if exc.errno != errno.EEXIST:
                            raise

                with open(filepath, "w") as f:
                    f.write(filebody)

                canarydrop['web_image_enabled'] = True
                canarydrop['web_image_path'] = filepath
                save_canarydrop(canarydrop)
            except:
                pass

            try:
                if request.args.get('type', None)[0] != 'signed_exe':
                    raise Exception()

                fields = cgi.FieldStorage(
                    fp=request.content,
                    headers=request.getAllHeaders(),
                    environ={
                        'REQUEST_METHOD': 'POST',
                        'CONTENT_TYPE':
                        request.getAllHeaders()['content-type'],
                    })  #hacky way to parse out file contents and filenames

                filename = fields['signed_exe'].filename
                filebody = fields['signed_exe'].value
                if len(filebody) > settings.MAX_UPLOAD_SIZE:
                    raise Exception('File too large')

                if not filename.lower().endswith(('exe', 'dll')):
                    raise Exception(
                        'Uploaded authenticode file must be an exe or dll')

                signed_contents = make_canary_authenticode_binary(
                    hostname=canarydrop.get_hostname(with_random=False,
                                                     as_url=True),
                    filebody=filebody)
                response['file_name'] = filename
                response[
                    'file_contents'] = "data:octet/stream;base64," + base64.b64encode(
                        signed_contents)
            except:
                pass

            try:
                if request.args.get('type', None)[0] != 'fast_redirect':
                    raise Exception()

                if not request.args['redirect_url'][0]:
                    raise Exception()

                canarydrop['redirect_url'] = request.args['redirect_url'][0]
                save_canarydrop(canarydrop)
            except:
                pass

            try:
                if request.args.get('type', None)[0] != 'slow_redirect':
                    raise Exception()

                if not request.args['redirect_url'][0]:
                    raise Exception()

                canarydrop['redirect_url'] = request.args['redirect_url'][0]
                save_canarydrop(canarydrop)
            except:
                pass

        except Exception as e:
            if response['Error'] is None:
                response['Error'] = 255
                log.err('Unexpected error: {err}'.format(err=e))

        return simplejson.dumps(response)
Example #4
0
    def render_GET(self, request):
        try:
            token = request.args.get('token', None)[0]
            fmt = request.args.get('fmt', None)[0]
            auth = request.args.get('auth', None)[0]
            canarydrop = Canarydrop(**get_canarydrop(canarytoken=token))
            if not canarydrop:
                raise NoCanarytokenPresent()
            if not canarydrop['auth'] or canarydrop['auth'] != auth:
                raise NoCanarytokenPresent()

            if fmt == 'zip':
                request.setHeader("Content-Type", "application/zip")
                request.setHeader("Content-Disposition",
                                  'attachment; filename={token}.zip'\
                                  .format(token=token))
                return make_canary_zip(hostname=canarydrop.get_hostname(
                    with_random=False))
            elif fmt == 'msword':
                request.setHeader("Content-Type",
                                  "application/vnd.openxmlformats-officedocument"+\
                                                      ".wordprocessingml.document")
                request.setHeader("Content-Disposition",
                                  'attachment; filename={token}.docx'\
                                  .format(token=token))
                return make_canary_msword(url=canarydrop.get_url())
            elif fmt == 'pdf':
                request.setHeader("Content-Type", "application/pdf")
                request.setHeader("Content-Disposition",
                                  'attachment; filename={token}.pdf'\
                                  .format(token=token))
                return make_canary_pdf(hostname=canarydrop.get_hostname(
                    nxdomain=True, with_random=False))
            elif fmt == 'awskeys':
                request.setHeader("Content-Type", "text/plain")
                request.setHeader("Content-Disposition",
                                  'attachment; filename=credentials')
                text="[default]\naws_access_key={id}\naws_secret_access_key={k}\nregion={r}\noutput={o}"\
                        .format(id=canarydrop['aws_access_key_id'], k=canarydrop['aws_secret_access_key'], r=canarydrop['region'], o=canarydrop['output'])
                return text
            elif fmt == 'incidentlist_json':
                request.setHeader("Content-Type", "text/plain")
                request.setHeader("Content-Disposition",
                                  'attachment; filename={token}_history.json'\
                                  .format(token=token))
                return simplejson.dumps(canarydrop['triggered_list'], indent=4)
            elif fmt == 'incidentlist_csv':
                request.setHeader("Content-Type", "text/plain")
                request.setHeader("Content-Disposition",
                                  'attachment; filename={token}_history.csv'\
                                  .format(token=token))
                csvOutput = StringIO()
                incident_list = canarydrop['triggered_list']

                writer = csv.writer(csvOutput)

                details = []
                for key in incident_list:
                    for element in incident_list[key].keys():
                        details.append(element)

                headers = ["Timestamp"] + details
                writer.writerow(headers)
                items = []
                for item in details:
                    for key in incident_list:
                        items.append(incident_list[key][item])

                for key in incident_list:
                    data = [
                        datetime.datetime.fromtimestamp(
                            float(key)).strftime('%Y-%m-%d %H:%M:%S.%s')
                    ] + items
                    writer.writerow(data)

                return csvOutput.getvalue()

        except Exception as e:
            log.err('Unexpected error in download: {err}'.format(err=e))

        return NoResource().render(request)
Example #5
0
    def render_POST(self, request):
        request.responseHeaders.addRawHeader(b"content-type", b"application/json")
        response = { 'Error': None,
                     'Url': "",
                     'Token': "",
                     'Email': "",
                     'Hostname': ""}

        try:
            try:
                email = request.args.get('email', None)[0]
            except IndexError:
                response['Error'] = 1
                raise Exception('No email supplied')
            try:
                memo  = ''.join(request.args.get('memo', None))
            except TypeError:
                response['Error'] = 2
                raise Exception('No memo supplied')

            canarytoken = Canarytoken()
            canarydrop = Canarydrop(generate=True,
                                  alert_email_enabled=True,
                                  alert_email_recipient=email,
                                  canarytoken=canarytoken.value(),
                                  memo=memo)

            if settings.TWILIO_ENABLED:
                try:
                    if not request.args['mobile'][0]:
                        raise KeyError

                    canarydrop['alert_sms_recipient'] = request.args['mobile'][0]
                    canarydrop['alert_sms_enabled'] = True
                except KeyError:
                    canarydrop['alert_sms_recipient'] = ''
                    canarydrop['alert_sms_enabled'] = False

            save_canarydrop(canarydrop)

            response['Token'] = canarytoken.value()
            response['Url'] = canarydrop.get_url()
            response['Hostname'] = canarydrop.get_hostname()
            response['Email'] = email

            try:
                clonedsite = request.args['clonedsite'][0]
                if not clonedsite:
                    raise KeyError

                cloned_token = {'clonedsite': clonedsite,
                               'canarytoken': canarytoken.value()}
                canarydrop.clonedsite_token = save_clonedsite_token(cloned_token)
                save_canarydrop(canarydrop)
                response['clonedsite_js'] =  CLONED_SITE_JS\
                                    .replace('CLONED_SITE_DOMAIN', clonedsite)\
                                    .replace('CANARYTOKEN_SITE', canarydrop.get_random_site())\
                                    .replace('CANARYTOKEN', response['Token'])
                response['clonedsite'] =  clonedsite
            except (IndexError, KeyError):
                pass

            try:
                imgur_id = request.args['imgur'][0]
                if not imgur_id:
                    raise KeyError

                imgur_token = {'id': imgur_id,
                               'canarytoken': canarytoken.value()}
                canarydrop.imgur_token = save_imgur_token(imgur_token)
                save_canarydrop(canarydrop)
                response['imgur_count'] = imgur_token['count']
                response['imgur_id'] =  imgur_id
            except (IndexError, KeyError):
                pass

            try:
                linkedin_user = request.args['linkedin_user'][0]
                linkedin_password = request.args['linkedin_password'][0]
                if not linkedin_user and not linkedin_password:
                    raise KeyError

                create_linkedin_account(username=linkedin_user,
                                        password=linkedin_password,
                                        canarydrop=canarydrop)

                response['linkedin_account'] = linkedin_user
                response['linkedin_account_views'] = \
                          get_linkedin_account(username=linkedin_user)['count']
            except (IndexError, KeyError):
                pass

            try:

                bitcoin_address = request.args['bitcoin_address'][0]
                if not bitcoin_address:
                    raise KeyError

                create_bitcoin_account(address=bitcoin_address)

                btc = get_bitcoin_account(address=bitcoin_address)

                response['bitcoin_address'] = bitcoin_address
                response['bitcoin_balance'] = btc['balance']
            except (IndexError, KeyError):
                pass

        except Exception as e:
            if response['Error'] is None:
                response['Error'] = 255
                log.err('Unexpected error: {err}'.format(err=e))

        return simplejson.dumps(response)
    def render_POST(self, request):
        request.responseHeaders.addRawHeader(b"content-type",
                                             b"application/json")
        response = {
            'Error': None,
            'Url': "",
            'Token': "",
            'Email': "",
            'Hostname': ""
        }

        try:
            try:
                email = request.args.get('email', None)[0]
            except IndexError:
                response['Error'] = 1
                raise Exception('No email supplied')
            try:
                memo = ''.join(request.args.get('memo', None))
            except TypeError:
                response['Error'] = 2
                raise Exception('No memo supplied')

            canarytoken = Canarytoken()
            canarydrop = Canarydrop(generate=True,
                                    alert_email_enabled=True,
                                    alert_email_recipient=email,
                                    canarytoken=canarytoken.value(),
                                    memo=memo)

            if settings.TWILIO_ENABLED:
                try:
                    if not request.args['mobile'][0]:
                        raise KeyError

                    canarydrop['alert_sms_recipient'] = request.args['mobile'][
                        0]
                    canarydrop['alert_sms_enabled'] = True
                except KeyError:
                    canarydrop['alert_sms_recipient'] = ''
                    canarydrop['alert_sms_enabled'] = False

            save_canarydrop(canarydrop)

            response['Token'] = canarytoken.value()
            response['Url'] = canarydrop.get_url()
            response['Hostname'] = canarydrop.get_hostname()
            response['Email'] = email

            try:
                imgur_id = request.args['imgur'][0]
                if not imgur_id:
                    raise KeyError

                imgur_token = {
                    'id': imgur_id,
                    'canarytoken': canarytoken.value()
                }
                canarydrop.imgur_token = save_imgur_token(imgur_token)
                save_canarydrop(canarydrop)
                response['imgur_count'] = imgur_token['count']
                response['imgur_id'] = imgur_id
            except (IndexError, KeyError):
                pass

            try:
                linkedin_user = request.args['linkedin_user'][0]
                linkedin_password = request.args['linkedin_password'][0]
                if not linkedin_user and not linkedin_password:
                    raise KeyError

                create_linkedin_account(username=linkedin_user,
                                        password=linkedin_password,
                                        canarydrop=canarydrop)

                response['linkedin_account'] = linkedin_user
                response['linkedin_account_views'] = \
                          get_linkedin_account(username=linkedin_user)['count']
            except (IndexError, KeyError):
                pass

            try:

                bitcoin_address = request.args['bitcoin_address'][0]
                if not bitcoin_address:
                    raise KeyError

                create_bitcoin_account(address=bitcoin_address)

                btc = get_bitcoin_account(address=bitcoin_address)

                response['bitcoin_address'] = bitcoin_address
                response['bitcoin_balance'] = btc['balance']
            except (IndexError, KeyError):
                pass

        except Exception as e:
            if response['Error'] is None:
                response['Error'] = 255
                log.err('Unexpected error: {err}'.format(err=e))

        return simplejson.dumps(response)