• Defending against the Attack of the Clone[d website]s!

    Front matter

    In a previous post, Casey talked about our Cloned Website Canarytoken and how it fares against modern phishing attacks.

    Today, we are releasing two new versions of the token which alert you when an attacker is using an Adversary-in-the-Middle (AitM) attack against one of your sites. An added bonus is that the new tokens can be deployed on properties you only have limited administrative access to (like your Azure tenant login portal or hosted blog).

    In this post we briefly recap AitM phishing, the limitations of the Javascript-based Cloned Website Token, and how we built our new CSS-based one. Finally we wrap up with showing you how our CSS can be installed into an Azure Entra ID login portal with just a couple of clicks – giving you high-quality alerts if your users are being targeted.

    The folks at Zolder.io (a Thinkst Partner) independently built a very snazzy and similar token, check out their blog post for more details.

    AitM phishing

    Early phishing sites were static clones of the HTML/CSS and Javascript of the victim’s site, that would store entered credentials, and in some cases redirect the victim user to the legitimate site after stealing their credentials. These static sites struggled to handle dynamic login flows and MFA prompts. 

    Now, with tools like EvilGinx and Modlishka, the adversary creates a reverse proxy server that sits in between the user and the victim site. This allows for dynamic modification of Javascript to reflect the phishing domain (which can be configured to prevent a non-obfuscated Cloned Website Token from firing), as well as seamlessly passing the user to the victim site after stealing the session. Since the adversary is acting as a proxy, the victim site is presented to the users dynamically, and the adversary can bypass many types of MFA, since the user is logging in and will accept the push, or enter the SMS/TOTP code.

    This figure from Microsoft shows the steps of a classic AitM phishing attack:

    Javascript Cloned Website Token

    As detailed in Casey’s blog, our classic Cloned Website CanaryToken has been useful to companies around the world. We simply generate a small snippet of (optionally obfuscated) Javascript code to be added to your site. When the client loads the page, the javascript checks if the site was served from the expected parent domain, otherwise it triggers an alert.

    Side-Note:

    It’s worth noting that when the site is loaded from the expected parent domain, there is no external request made to the Canarytokens servers. We only receive requests in the infrequent situation that there is a cloned site detected.

    This token works really well, especially if obfuscated against simple domain name replacements by the AitM server. However, it requires the ability to insert Javascript into a page, a requirement that many 3rd party service providers do not allow.

    CSS Cloned Website Token

    We spent some time trying to figure out if there was a clever CSS trick to similarly only alert the Canarytokens server when the domain was unexpected, but in order to reduce the risk of 3rd party CSS imports, the CSS interpreter in the browser is quite restricted. Our solution is to create a reference via a url() for an invisible background image that points to our server, where we check the Referer [sic] HTTP header to ensure it’s being loaded from the correct domain. This means a Token can be inserted into your webpage by simply adding a CSS rule.

    Version 0.1

    Some services allow us light customization (mainly for look and feel) but won’t allow us to upload custom JavaScript (preventing us from using our trusty cloned site token) so we went off in search of a CSS alternative. CSS is relatively restricted, but we can get an early start by creating a reference via a url() for an invisible background image that points to a server we control.

    On that server, we can check the Referer [sic] HTTP header to ensure the CSS is being loaded from the correct domain.

    This will work for many AitM phishing attacks (since the adversary doesn’t control the privacy policy on the browser for the Referer header) but some browsers omit or otherwise spoof that header. 

    Another downside is that our Canarytokens server is now “in-the-loop” for every page load, benign or not, adding to latency for the sites valid users, and potentially adding significant load to our servers, especially if deployed to, for example, a popular Azure tenant’s login portal.

    Lambdas, functions and edges

    In order to manage this, and to obscure the purpose of the CSS reference (as there are numerous Canary Token detectors that essentially grep for a canarytokens.com string), we wanted to use a popular cloud-based provider to filter out the legitimate requests, and to then only pass suspect requests on to our servers.

    The first idea was an AWS Lambda, or the Azure Function equivalent, but the startup times could degrade the user experience, and the costs would be unnecessarily high. AWS provides a spectrum of other serverless functions that balance cost, latency, and features: in light of this, we explored Lambda@Edge functions, which execute automatically at all regions (reducing latency), but have some limitations on the runtime environment.

    Cloudfront Functions

    Even further in the scalability/functionality tradeoff are CloudFront Functions

    These run extremely quickly (~1ms maximum execution time), but have (deliberately) very limited functionality. The goal was then to figure out how to make use of the limited functions to provide a cost-effective and performant experience. 

    Our solution

    We deployed a single function to all of the CloudFront points-of-presence that parse an incoming request-string for two pieces of encoded data: an expected Referer, and a Canarytoken ID associated with it. If the Referer header matches the expected one, the function terminates by returning a 1×1 transparent GIF, otherwise it issues a HTTP Redirect to the Canarytoken server with the parsed ID. The below figure shows the flow as a user logs in to an Azure tenant:

    And this diagram shows what occurs when an AitM phishing server is deployed in-between the user the the login page:

    This design wins. It offers very low latency, global deployment, a lightweight function, and since CloudFront is a CDN, linking to CDN assets is not suspicious to an adversary.

    Now we just have to make it easy to deploy!

    Using the CSS token around the web

    In order to deploy one of these tokens to a site with limited scope for edits (e.g. one where you can only add HTML but not Javascript), I’ll show you how I added an invisible <span> to my personal web site that alerts when it’s not loaded via the correct domain.

    First I navigate to the Canarytokens site and select the CSS cloned website token from the dropdown. I then put in my email address, and the domain I expect (my webpage is jacobtorrey.com). It’s also important to put a useful memo to remind myself in months when this fires where it was placed to help me respond. Click create and the token is generated:

    This CSS is designed for copy and paste (or automatic installation) into an Azure Entra ID tenant, but the url() can be used elsewhere. I create an empty <span> on my webpage that has the style="display: hidden; background: url('https://dakg4cmpuclai.cloudfront.net/h6jf84z88jbpfuc1at5n5/amFjb2J0b3JyZXku/img.gif'); and save it. When I view this page as expected, it looks no different, and I get no alert:

    But if I use EvilGinx to phish this site and navigate to it, it looks the same:

    Immediately I get an email alert:

    This has the client IP address and the referring domain, as well as the reminder I set myself. Sweet! I can see where this site was served from, if this was a real phishing site, I’d know its URL and could proceed with filing an abuse report, or blocking that domain from my network. Clicking more information provides the following information (censoring the IP and hostname):

    This technique will work on most blogging platforms (e.g., WordPress) and other hosted platforms that allow some HTML editing, but not Javascript.

    Sweating the small stuff

    Now that we have the new CSS-based Cloned Website Token, it was time to make the user experience for deployment even simpler. We expect that Azure portals will be a popular use case, and in our testing found that the steps needed when uploading a custom CSS were cumbersome. It’s important to note that the custom branding feature in the Entra UI requires an Entra ID P1 or P2 subscription. In order to make this as easy to deploy as possible, we explored how to build Azure applications, which can install custom branding CSS on behalf of a tenant once authorized.

    We built an Azure application that can request access to install the CSS file automatically (but only if there is not already one present that would conflict) when the user is logged in to their tenant with sufficient admin privileges. The Azure application will then revoke its own permissions once the CSS is installed, reducing risk. We have noted that sometimes it takes minutes to hours for the custom CSS to be propagated to Azure’s CDN, but it is installed. The following screenshots show this simplified process for protecting an Azure tenant:

    Starting the same way, we create a token, this time selecting the Azure Entra ID login. Again we want to give ourselves a helpful reminder about the token:

    After we click ‘Create’, we see the token has been generated:

    This time we’re presented with an option to either follow the automatic installation flow, or manually download and manually install the CSS into the Azure tenant. I click on the automatic option and a new tab opens prompting me to login, or choose an Azure account to log in with. This account must be an Administrator account on the tenant to grant the permissions 1needed:

    I choose the account for the tenant I want to protect with this token, and am sent to an authorization page asking if I want to authorize the application and the permissions needed.

    Accepting this prompt will redirect you back to the tokens page with a status:

    That’s it! In a few moments your Azure login page will now include this CSS, and if an attacker tries to use an AitM phishing proxy to target your users, you’ll be alerted the moment it happens, and the domain the attacker is using.

    Conclusions

    Phishing remains a highly effective method of compromising accounts, and the tooling has matured to make all but FIDO2/Passkeys MFA techniques vulnerable to AitM phishing and session stealing. While our extant Javascript token remains popular and provides valuable alerts on phishing site creation, we wanted to cover more of our users’ online services. Our new CSS and seamless Azure login portal cloned site token offers another way to quickly instrument 3rd party service providers you rely on to protect your organization. These tokens rely on client behavior to alert, so they are part of a holistic security strategy (which should include token-based MFA!) and not a single silver bullet. We’d love it if you took it for a spin and let us know how it goes!

    1. The installer requires both the Organization.ReadWrite.All, Application.ReadWrite.All permissions to create/update the Company Branding with the CSS, and remove itself from the tenant, respectively. The User.Read is a default permission needed to authenticate the application. All permissions are revoked at the end of the installation attempt. ↩︎
  • Video File Canarytokens: to be or not to be

    Recently friend-of-Thinkst (and CTO of NCSC) Ollie Whitehouse tweeted this interesting tidbit:

    We’re always looking for new types of Canarytokens, so it would be cool if we used this method to create video file Canarytokens.

    Quick background explainer

    We build Canaries that act as entire machines, require almost no configuration and boot as various Operating Systems. The logic is that it takes you less than a minute to set it up, and when an attacker lands on your network, they look for their loot, or move laterally and inevitably discover your Canary and interact with it (tipping their hand and revealing their presence).

    Empirically, across 7 continents, Canaries just work.

    We also build Canarytokens. These are smaller “tripwires” that can also be used to detect attackers, but work slightly differently.

    They could be:

    • A fake AWS API key, that you placed on your code-signing-server. An attacker who breaks into the code-sign-1 server and finds the key has to try it, since potentially it gives her access to a new network. And when they do, they tip their hand and you are notified.
    • A fake MS-Excel file, maybe called server-passwords.xls.  Place that in the Documents folder of a DevOps employee’s laptop. An attacker who finds it assumes it’s her lucky day, opens the file, tips their hand and notifies you of their presence.
    • A ton more exist (see the free Canarytokens website).

    The AWS-API key token is defensive-gold. Attackers actively search for them. An attacker who finds them has to try them and bypassing them isn’t trivial.

    A fake file Canarytoken (like an MS-Office file, or a PDF file) typically works by embedding some sort of remote reference into them. Many file formats make provision for URLs, and the document readers (e.g. MS Office, or Acrobat Reader) will see the URLs and attempt to fetch content. If we can get the document to reach out and touch a server we control, even if it’s just by making a DNS request, then we can reliably alert when the file is accessed. It’s surprising just how many file formats allow for URLs to be fetched; for example, when Windows launches a signed EXE binary it will look for a Certificate Revocation List (CRL) URL in the signature, and if one is present it’ll first attempt to download the CRL from the embedded URL.

    Of course we have a bunch of files / techniques ready to use so anyone can deploy these tokens with almost no effort:

    Taking a peek inside a QuickTime movie file

    The QuickTime movie (.mov file) file format is a container format that contains media data as well as metadata describing the media data. Since the format is a container format, the media data doesn’t need to be decoded to parse and modify the metadata stored in the file.  

    A .mov file contains many different atoms (also called sections). Each atom has a type and a size, while some atoms also contain additional fields and/or child atoms, leading to a tree structured file. This design allows an application to parse a QuickTime movie file while ignoring atom types (and by extension parts of the tree structure) that it doesn’t care about.

    All .mov files contain one ‘moov’ atom, which is the parent atom of all metadata atoms describing the movie. Most .mov files also contain a ‘mdat’ atom, which stores the media data (encoded audio and video data). Movie files can also contain only reference movies (with no ‘mdat’ atom), such as the examples found here.

    The ‘moov’ atom contains one or both of the following child atoms:

    • ‘mvhd’ – A movie header atom which contains data describing the entire movie.
    • ‘rmra’ – A reference movie atom which contains references to one or more movies (which can be on the local machine or on an external resource)

    In order to specify a reference movie using a URL, a tree of atoms needs to be added to the ‘moov’ atom: ‘moov’ > ‘rmra’ > ‘rmda’ > ‘rdrf’. The URL is stored in the ‘rdrf’ atom.

    Let’s make a video file token

    So. Ollie pointed out that he could create a video file that triggered both a DNS request and an HTTP request by using ‘rdrf’ atoms. This seems like a token worth creating.

    Imagine an attacker who broke in and saw (what she thought were) saved Zoom recordings, or interesting video files for use at media companies (think avengers_6_can_we_go_home_now.mp4), or recordings of board meetings.

    A hex editor and ffmpeg’s reference files (which already contain ‘rdrf’ atoms) came in handy for a quick test. We could get VLC to send a request to a modified URL, but these .mov files don’t contain any video data, so we knew we could do better.

    After writing a small script to add the ‘rdrf’ atoms pointing to an external URL to an existing .mov file, we had some early success with a token firing on VLC! This is exciting and blood-in-the-water; opening our video file with VLC yields the alert and tells us there’s potentially a new Canarytoken in the offing.

    The .mov file’s structure is shown below (visualised by MP4Analyser). Multiple ‘rdrf’ atoms are necessary because VLC doesn’t fall back to the video data stored in the .mov file if the ‘rdrf’ atom’s URL does not resolve. Adding one ‘rdrf’ that points to an external URL and one that points to the local file works and VLC plays both references as a playlist of sorts.

    One neat feature is that the code worked as-is on .mp4 files with VLC because of the similarities between the .mov and the .mp4 file format.

    Our initial success was short-lived, however, since we quickly learned that the same file did not work on QuickTime or Windows Media Player. Windows Media Player completely ignores the ‘rdrf’ atoms and simply plays the video data stored in the .mov file. QuickTime refuses to open the file as soon as a ‘rmda’ atom is added (even if it contains no ‘rdrf’ atoms), despite Quick Look being able to play the file’s video data.

    A philosophical detour

    This is kinda par for the course when trying to create file-type Canarytokens. As defenders, we are hoping to exploit attacker behaviour to get a heads-up when they are operating. In some sense, we are hoping to exploit the behaviour of their machines. What would happen if the attacker opened the file in a non-standard application? What if they chose to read our Word-Doc in vim? 

    In that sense, a Canarytoken is a lot like a tripwire, and the question is akin to: “what happens if an attacker steps over your tripwire?”. Nothing…

    But, well placed tripwires will often work anyway and attackers who are aware of their existence, will find themselves moving much slower across a field than attackers who aren’t. It’s also a demonstration of why we really like Canarytokens which involve auth keys and third party services, where the attacker has to contact an Internet resource to check if it’s valid.

    Can we get it working by tweaking the file?

    We hypothesised that some of the additional metadata atoms (like ‘rmcd’ which specifies components required to play the ‘rdrf’ source, or ‘rmvc’ which specifies the required software version to play the ‘rdrf’ source) are required for QuickTime to play the file. After trying various configurations of metadata atoms to no avail, we tried our original file on an older version of QuickTime (7). Voilà! The token fired as expected. We therefore concluded that reference movies no longer work the same way (or aren’t supported at all) in the latest version of QuickTime (10.5).

    A second look at the QTFF specification showed one other place where URLs can be used: ‘dref’ atoms. As a final test, we pointed the ‘dref’ url to an external URL, but this was ignored by both VLC and QuickTime.

    It wasn’t meant to be… yet

    Alas. Despite the coolness of getting a video player to hit an external URL when opening a video file, a video file that only fires when opened in VLC doesn’t fit our ideal use case, so we won’t be making an official Canarytoken out of it. (We do dozens and dozens of forays like this throughout the year, and only detections that we feel meet the bar of being easy to use and reliable make it as Canarytokens or Canary services).

    The file format seems interesting though, with lots of room for fiddling. We may revisit it in the future, and figure this post will make it easier for others to go spelunking too.

  • What “personality” should I give my Canary?

    What “personality” should I give my Canary?

    You can do complex things with Canaries but you don’t need to. 

    Even though Canaries will happily pose as SCADA equipment or Mainframes, a Windows personality, with a well-named fileshare, has caught attackers all over the world. 

    Can it be that easy? Won’t really good attackers be suspicious? 

    The answer is slightly counter-intuitive: 

    Attackers who land on your network have to situate themselves.
    They have to poke around. 

    But won’t they ignore a server that looks suspiciously unguarded? 

    Almost never. Everyone is aware of that over-provisioned server that’s been forgotten,
    or that passwords.txt file.

    Attackers don’t ignore things that look easy, they count on them. 

    Tomorrow you can do complex things, make use of our API, and design your own services.

    Today, just get your birds online. You won’t be sorry…

    Ps. A long time user & want to get fancier?

    Have a look at our Birding Guide: (We’ve chosen some of the more popular examples to get you accustomed to typical configurations and deployment strategies). 

    Or check out our Latest Webinar

  • Oh Crumbs! (Breadcrumbs in Beta)

    tl;dr: You can now create breadcrumbs to lure attackers to your Canaries with just a few clicks.

    Canaries and (their) Discoverability

    Our thesis with Canary has always been simple: Attackers who land in your infrastructure need to situate themselves and they do this by looking around. They run commands and touch systems that regular users never need to. By being selective about which services Canaries offer we can find the sweet-spot of services that are super-trivial to deploy, super likely to be touched by attackers, and super likely to be ignored by regular users. We work hard for this trifecta and empirically, it works.

    The good thing about well- designed Canaries is that attackers following their TTPs will interact with the Canaries when they find them. It’s why they are there…

    But sometimes, defenders want to tip the scales. They want to leave a RDP session file on the backup server desktop that points to a Canary. They want to create an entry in an SSH config file that points to a Canary. Canary will now generate these for you with just a click.

    Breadcrumbs are created based on the services your bird is running. So the crumbs for a Canary running SSH will be different to a Canary running RDP. But both should be dead simple to use.

    Take it for a spin.. We think you will like it.

  • A (beta) Canarytoken for Active Directory Credentials

    Attackers on your network love finding stray credentials. They are an easy way to elevate privileges and are often one of the first things attackers look for during post-exploitation.

    There’s no shortage of places where these credentials can be found and surprisingly, there’s very little downside to attackers trying them…

    …unless there’s a way to drop decoy credentials. This isn’t a new idea, but it usually requires heavy tooling and configuration.

    Our newest AD tokens allow you to create fake credentials that can be left in all the familiar places, but without a heavy software component. A single, light-weight script that runs on your Domain Controller lets you know when the fake credentials are used.

    Lets walk through typical usage:

    1. Head over to your console to create a new “Active Directory Login” token:
    1. You’ll need to add:
    • A Token reminder, which is a note to your future-self reminding you where you placed the fake credentials. It’s possible that this token will fire months from now, when you’ve forgotten where you deployed it. The token reminder could be something like: credentials left in unattend.xml files on the backup server.
    • A few fake usernames which when used will trigger the token (we’ll suggest some randomized plausible candidates for you automatically).
    1. You can download these credentials as an unattend.xml file and/or as a plain text file to leave lying around.
    1. Then you can download the token itself. This script will create a task on your server that catches the planted credential (attempted) usage. Run this script on a Domain Controller to set up the task.
    1. An attacker who finds these credentials somewhere on your network will try them, which adds entries to event logs. The task processes the event logs and when it sees a login attempt for one of the fake credentials, it will fire off an alert to your Console (and announce their presence).

    This is an unusual token for us, because it runs a script on your Domain Controller. We’ve kept the script simple and legible so that you can make sure it’s not doing anything nefarious (and so that the script logic can be easily extended). Our work on this token is inspired by IppSec, who showed an initial concept for an AD token that you can catch in his YouTube video here.

    If you’d like to take it for a spin, reach out to us here. We’d love to hear how it works out!

  • Cloned Website Token and Reverse Proxies

    Our Cloned Website Token has been available for a long time now, both on our public Canarytokens.org site as well as for our Canary customers. It’s helped users all over the world detect attacks early in the process. We wanted to take a moment and go over some of the details of this token: how it works, how to create and use one, and critically, how it fares against the new “Adversary-in-the-Middle” (AitM)-generation of phishing attacks..

    The cloned website token is super simple: You get an alert any time your webpage is hosted or proxied through an unexpected location.

    It’s free, it’s easy, and finding out your site has been cloned as soon as it happens gives defenders precious hours (or days) to get ahead of serious attacks.

    Here is how you create it: 

    1) Visit canarytokens.org

    2) Select cloned site token

    3) Add this JS to your site

    4) You can choose to obfuscate it if you want

    Now.. if an attacker clones or proxies your site… 

    The JS runs.. If it is not on the right domain

    You get an alert.

    So, in essence. If the URL for a site that a user has visited, is not the same as the expected URL, you get an alert. 

    Many of our customers also obfuscate the JavaScript, to avoid attackers that replace strings in a cloned site or proxied site. For example, if you just leave the plain text domain string example.com, attackers can simply match and replace that inside of your page. By adding obfuscation, you can make it more difficult to find and replace your token. Below is an example of a recent addition to our customer console, that allows teams to simply click to obfuscate the JavaScript.

    We’ve also recently added obfuscation to our canarytokens.org site as well! 

    That is the basics. Takes you just a few seconds to create and obfuscate the JS Snippet and insert it. Go ahead and create one and put it on a site today, don’t worry, I’ll wait! If you want to learn more, keep on reading. 

    History of the Cloned Website Token – How did we get here?

    This token has more than proved its worth from huge tech companies discovering their red teamers weeks before the official engagement has begun to large media houses actively fighting nation-state attackers.

    Recently though, attackers have been upping their games with a move to making use of reverse proxies instead.

    This allows duped users to interact with the original site, making the attacks more believable. Attackers can steal both usernames and passwords, as well as web based session tokens while providing a seamless experience to the users being phished.

    What is a reverse proxy phishing attack?

    The reverse proxy has been rediscovered with new enthusiasm and tools. In essence this is very similar to running a tool like Fiddler or Burp, where you can control and inspect and modify all the requests and responses. The attacker runs a reverse proxy and sits in the middle of the user and the legitimate server, hence Adversary-in-the-Middle. The attackers will send phishing emails or links, and hope you click on the site, and login–then they have captured your credentials. 

    There are a number of tools on the market that allow you to perform these attacks. Some examples are Modlishka, Muraena and EvilGinx (see references below) . These tools grant an attacker or researcher or defender complete control over the HTTP[S] interactions. 

    The researcher Kuba Gretzky and others have also done a number of talks and published extensive tools and documentation on this topic.

    A common pattern is to register a domain name that is similar to the target that you hope to phish.

    So suppose you have a nice website canaryexample.com. An attacker may register 3xample.com and then proxy victims to canaryexample.com through the fake site.

    “The phishing page has two different Transport Layer Security (TLS) sessions—one with the target and another with the actual website the target wants to access. These sessions mean that the phishing page practically functions as an AiTM (Adversary in The Middle) agent, intercepting the whole authentication process and extracting valuable data from the HTTP requests such as passwords and, more importantly, session cookies. Once the attacker obtains the session cookie, they can inject it into their browser to skip the authentication process, even if the target’s MFA is enabled.” – Microsoft Threat Intelligence

    What’s the difference with “basic” phishing attacks?

    With basic phishing attacks, attackers attempt to recreate, or clone as faithfully as possible, a lookalike page (from Outlook, LinkedIn, Google, etc). They will then attempt to lure the victims into entering their credentials, which are then logged and stolen by the hacker.

    A reverse proxy attack takes it one step further. Instead of showing a lookalike page, it simply relays traffic between the real website and the phished user. 

    After clicking on a malicious link, phished victims are sent to the real website, unaware that the malicious proxy is capturing the data being transmitted between the victim and the site. There are no TLS warnings, since the domain the user lands on initially is controlled and issued a valid certificate to the attacker.

    This is an excellent diagram showing inspection and manipulation of HTTP body in the pages that are served:

    source: https://conference.hitb.org/hitbsecconf2019ams/materials/D2T1%20-%20Muraena%20-%20The%20Unexpected%20Phish%20-%20Michele%20Orru%20&%20Giuseppe%20Trotta.pdf

    How does the Cloned Website Token perform in the face of this new/old technique?

    tl;dr: Even in the face of these emerging attacks, the cloned website token performs as expected!

    This token is based on a very simple check: Expected vs Actual location of the website.

    By distilling this token down to the essence of the check, it allows us to endure across a wide range of geriatric as well as emerging attacks. While the attacker’s techniques may change, this simple token still endures.

    Let’s imagine our login site is canaryexample.com, however, the URL I clicked is associated with 3xample.com.

    We can see the difference between the expected URL and the actual URL.
    This is picked up by our Canarytoken and alerts us even before a user has even attempted to login to the fake / proxied site.

    We think this is very exciting for teams defending their web apps. 

    You can do this for free, you can do it today. 

    It’s a durable detection that works well in the face of emerging attacks. 

    A few more final thoughts 

    In our customer consoles we have an “ignore option” which is not available on canarytokens.org. The ignore list simply helps teams that have expected proxies or alternative hosting environments, or CDN, etc.. Even if you are using the open-source canarytokens.org, it’s important to think through possible expected domains that might trigger that don’t require an all-hands-on-deck response.

    Proper Mitigation

    While this may help you detect that your site has been cloned or is under an active proxy attempt, it is only a part of a holistic response to phishing campaigns. It is recommended to use FIDO2 as an MFA scheme as those authentication sessions are tied to the expected domain, so both simple cloning and AitM attacks will fail to get a session.  Microsoft offers other guidance as well: 

    Closing thoughts

    By adding a simple few lines of JavaScript, we can detect if a site we want to protect is being cloned or proxied. This gives defenders a quick insight that they may not otherwise have. Give it a try, it’s super easy, let us know how it goes. We are thankful for the authors of the reverse proxy tools for publishing their work and tooling to better help defenders with detection. It is important to realize, that without obfuscation, there is a chance your Cloned Website Token won’t alert, if the attacker is replacing strings–we’ve added obfuscation to help defenders. 

    Thanks for reading. 

    References 

    1. https://blog.duszynski.eu/hijacking-browser-tls-traffic-through-client-domain-hooking/
    2. https://blog.duszynski.eu/phishing-ng-bypassing-2fa-with-modlishka/
    3. https://github.com/drk1wi/Modlishka
    4. https://github.com/muraenateam/muraena
    5. https://github.com/kgretzky/evilginx2
    6. How Much Is The Phish? Evolving Defences Against Evilginx Reverse Proxy Phishing by Kuba Gretzky
    7. Kuba Gretzky – Phishing Through Modern 2FA Defences With Evilginx
    8. https://github.com/CERT-Polska/anti-modlishka
    9. https://cert.pl/en/posts/2019/01/recommendations-on-mitigation-of-man-in-the-middle-phishing-attacks-evilginx2-modlishka/
    10. Phishing with Modlishka (bypass 2FA)
    11. https://www.microsoft.com/en-us/security/blog/2022/07/12/from-cookie-theft-to-bec-attackers-use-aitm-phishing-sites-as-entry-point-to-further-financial-fraud/
    12. https://github.com/aalex954/evilginx2-TTPs
    13. #HITB2019AMS D2T1 – Muraena: The Unexpected Phish – Michele Orru and Giuseppe Trotta
    14. Muraena – Unexpected Phish
    15. https://learn.microsoft.com/en-us/security/operations/token-theft-playbook
    16. https://www.proofpoint.com/us/blog/threat-insight/mfa-psa-oh-my
    17. https://catching-transparent-phish.github.io/catching_transparent_phish.pdf
  • CourtVision – Where’s my padel at?

    Labs is the research arm of Thinkst but research has always been a key part of our company culture. All Thinksters are encouraged to work with Labs on longer term projects. These become that Thinkster’s “day job” for a while. (These are intended both for individual growth, and to stretch ourselves into new areas: They don’t have to be related to Canary or security).

    I took a brief hiatus from the engineering team to explore a computer vision project: CourtVision.

    CourtVision set out to explore how to process a video stream of a racquet and ball game (padel–popular in the southern hemisphere and growing in popularity world-wide!) from a stationary (but unaligned) camera and extract information about the game. Padel, like other racquet sports, is played on a regulation court with lines demarking in and out of bounds (though there are times when a ball is in play even outside of the court); CourtVision aimed to extract information such as player positions and ball trajectories from a video feed. Secondly, visualising these outputs to provide insights into game tactics and strategies.

    While there are existing computer vision systems to track play in racquet games, namely the Hawk-Eye system, these require systems of multiple fixed, calibrated, and synchronised cameras. The CourtVision challenge was to offer similar outputs from a single viewpoint, that is not in a specific location in relation to the court

    The problem formulation

    The problem is thought of as unwinding the events that gave rise to the video.  To achieve this we draw on prior knowledge such as court layout and ball and player dynamics. At each moment during a game the light emanating from the scene is sampled (at 30 fps) and produces a sequence of images.

    The problem now is to associate certain pixels in the image with objects in the scene we would like to know more about and then make estimates about the objects positions that best explain the sensor readings – image sequence. 

    Starting from here a number of avenues were explored and below is a linearized path of how we went about solving this problem.  

    The path is simple (looking back):

    1.  Establish a mapping from world coordinates to image plane pixel locations.
    2.  Detect objects of interest (players and ball) in each frame.
    3.  Estimate the world coordinates of each object by leveraging the inverse mapping found in Part 1.

    Establishing a mapping between world coordinates and image plane is a well understood problem and implementations exist in commonly used computer vision libraries. The unknown in our case is doing it given a single image. Taking inspiration from [3], where they used the net on a tennis court to form an additional plane, we took orthogonal planes from the court structure and jointly found the camera pose and intrinsic matrices. This is explained in Part 1of the blog below.

    In Part 2 we expand on how we leveraged existing computer vision models to detect objects of interest in each frame. 

    Previous works that attempted 3D tracking from a single camera relied on either: knowing the size of the object being tracked [1] and that its projected size is invariant to the viewing angle i.e spherical objects; or the object of interest followed purely ballistic trajectories [2]. Here, we modeled the ball trajectory as a ballistic trajectory but retained a multimodal distribution over the ball’s states in a particle filter allowing the tracker to quickly adapt to new trajectories (modes) without explicitly modeling the interaction with walls, floor and racket. Part 3 illustrates this approach.

    We made the following assumptions: 

    1. Camera is stationary (but does not need to be in a specific location)
    2. Court dimensions are known.

    Players’ feet remain on the ground. Part 3 illustrates limitations in our tracker and by making this assumption we could improve player tracking stability.

    Figure 1: The experimental setup showing a broadcast camera view (resized) and a schematic of a padel court dimensions in [mm].

    Part 1: Camera calibration and pose estimation

    Extracting real-world measurements from a camera requires knowing both the extrinsics (position and pose) and the intrinsics (such as focal length and distortion coefficients) of the camera. Once these are known we can map any point in the world coordinate frame to a pixel location in the image. We can also project rays into the world coordinate system from a desired pixel location.

    Figure 2: An annotated frame showing three of the eight planes used to perform single image calibration. The additional planes not visualised here are the side, front and back walls and a horizontal plane at the height of the glass.

    The trade off made for not having to collect data first hand is that little is known about the setup. In this case the camera intrinsics and extrinsics were unknown. The common approach to determine camera intrinsics is to capture a calibration sequence which is often a checkerboard pattern. Since we didn’t have such a luxury we exploited the structure in the scene and defined a set of planes for which the image plane and world coordinate correspondences could be identified. By doing this we effectively introduced a set of 8 planes (similar to a checkerboard) and performed camera calibrations from this. The mean reprojection error was approximately 9 pixels on 1080 x 1920 images. 

    Part 2: Bootstrapping custom object detectors

    There are a plethora of off-the-shelf models that can do object detection however, none have single class “padel ball” detectors. Fine-tuning such a model is fairly common and to achieve this a few annotated frames were needed. LabelStudio is a very versatile data labeling tool that makes it easy to “put a model in the loop”. By doing this we bootstrapped our ball detector by repeatedly annotating more images and each time using the latest model to automatically label the additional images that were manually verified and corrected.

    Figure 3: Cycle of labelling data, training a object detection model, manually labelling more data assisted by the latest model’s predictions and retaining.

    Part 3: Bringing image detections to the real world

    Making detections on an image plane tells us nothing about the player and balls position in the real world. To estimate the position of the ball and players we define a state for each player and the ball and then update this state based on the detections. To govern this process in a more principled manner we used a Bayesian filter and in particular a particle filter. 

    A particle filter stores a distribution over the state of each object. This is stored as a vector and an associated weight indicating a probability mass. To illustrate this the top image in figure 4 shows the cloud of particles representing the state of the ball. During the filter’s update step we follow Bayes rule to update the weight of each particle based on how well they explain the observation (the image). As we can see the core of the particle cloud is around the ray emanating from the detected ball position in the image. All particles along that ray “explain” the observation equally well. The information held in that current state (prior) ensures the updated state does not naively squash all particles onto the ray. Bayesian filters like this are a great way to encode knowledge we have about the ball dynamics and current state and update this belief as we get more observations.

    Figure 4: Top: showing the internal state of the ball tracker. Each particle representing an amount of “probability mass” over the position of the ball. Bottom: The yellow square is the ball detector’s output. The yellow dot is the weighted mean estimate of the ball position projected into the image plane.

    But we don’t want a fuzzy cloud around where the tracker “thinks” the ball is? We want to know the best estimate of the ball’s position. Once again we consult our probability distribution over our ball states. We can grab any statistic we want. The particle with the largest weight – argmax or the weighted mean over all states. Below is the weighted mean position of the ball. 

    Figure 5: Top: Shows the weighted mean ball position. Bottom: The reprojected mean estimate of the ball in the image plane.

    This approach shows promising results but we did see the tracker fail after a few missed detection and resulted in mode collapse. That is the distribution over ball state (cloud of particles as in figure 6) either dispersed or reduced to a point. Particle filters come in a number of flavors and we only implemented the simplest resampling methods so it might be a bug in this or just a naive choice somewhere. Ah, research, so many avenues to explore! 

    To constrain the player tracking to a plane we called on assumption 3. from above and projected the ray to intersect with the ground plane. These results are shown below as a heatmap of player positions and velocity. Tracking under this constraint means a detected player (measurement) can be projected onto the ground plane (tracker state) with no information loss (3D to 2D) and our tracker remains performant.

    Results

    Figure 6: Top: heatmaps of position (left) and velocity (right) of the players. The team on the left side of the court is in the foreground in the bottom image.

    The ultimate goal of such a system is to provide insights into game play and strategies. To this end we show court occupation and player movement speeds. The position and velocity heatmaps of players during a rally. The bottom image has Team A in the foreground and Team B in the background. Here we can see where players were during the rally as well as how they moved. In this rally we can see Team A  (on the left) plays from deep while Team B (on the right) occupies the mid court far more. Translating this raw positional information into actionable insights remains as future work. 

    Going from a set of hypotheses to evaluating them is a fun technical challenge and my time in Thinkst Labs was great. I still hope to bring this to a court sometime soon and test the final assumption: seeing game play metrics can improve tactics. 

    Resources

    A collection of tools this project found useful as well as outputs from this work.

    References

    [1] 3D Ball Localization From A Single Calibrated Image

    [2] MonoTrack: Shuttle trajectory reconstruction from monocular badminton video

    [3] Generic 3-D Modeling for Content Analysis of Court-Net Sports

  • Default behaviour sticks (And so do examples)

    Introduction

    We spend huge amounts of time sweating the details of our products. We want to remove all the friction we can from using them and want to make sure we never leave our users confused. To get this right, we do a bunch of things: we use simple language, we make extensive use of context-sensitive help and where it’s needed, we nudge users with illustrative examples.

    Recently we bumped into something that made us rethink our use of examples.

    Background

    Paid Canary customers also receive a private Canarytokens server as part of their subscription. This is a private, managed version of the service publicly available at www.canarytokens.org. They get to mint an unlimited number of Canarytokens, get access to some tokens before they are released to the world and are able to trivially customise the service.

    Canarytokens typically (but not always) rely on a DNS zone that’s unique per-customer. When a customer signs up, we create a DNS zone for them and usually that’s sufficient for their needs.

    However, one of the advanced customisations for customers is the ability to create their own DNS zone with a name they pick. They’d typically do this to make the underlying hostname obviously tied to their company, so their custom DNS zone might look like assets.their-company.com. This requires users to pick a zone name, and as a UX guide we autogenerated a name for them. We happily used someprefix.their-company.com21, as an example:

    When we built the UI for this feature, the inclusion of the someprefix example was to make it easier for customer to configure DNS on their end, given that DNS can be tricky to get right. It wasn’t the intention that customer only use a zone called someprefix, we simply picked it because we needed something to use in our examples. If the example zone name becomes an implicit standard then the risk is that it lets attackers more confidently guess about Canarytokens based on discovered hostnames.

    Recently, one of our engineers was working in this area of code and wondered how many customers simply followed the example shown and picked someprefix.their-company.com as their custom domain of choice, as opposed to choosing another. His intuition was spot on. Among customers using this feature, ~40% used the example we provided:

    We use the custom domain to make Canarytokens less identifiable. If 40% of them use the same custom name, then the disguise is not as effective.

    Learning

    To be sure, this is not an individual customer problem. Looking at other configuration options present in our UI, the pattern is clear. When given an example, a significant number of users default to using that same example in their customisation. The behaviour is consistent across customers and configurations. This surprised us! 2

    It’s important to realise this isn’t a customer-side issue; they shouldn’t have to consider the impact of every configuration option we choose to put in front of them. They don’t have the full context and knowledge, and expecting them to be experts in the nitty gritty of Canarytoken discoverability makes no sense. Frankly it’s a reason enterprise software is often so terrible; tons of options you barely understand or know about, and are configured according to tutorials/examples rather than understanding. This is a lesson for us internally about how we guide customers through using Canarytokens, and more generally through Canary.

    Fortunately this particular case has a simple enough fix. Going forward, we will show multiple examples of prefixes. A user looking to add a custom domain will see a variety of example zones when they visit the page, and the examples will cycle each time they open the configuration page. We want to convey that they have options in choosing the name, and we show them a variety of sample options. Our hope is that this will prompt customers to pick their own names, and if they do rely on our examples then those are now spread over a large list of examples.

    Conclusion

    The outsized impact what seemed like a very minor placeholder choice made years ago helped us reevaluate how we select the examples we show customers. It’s a strong reminder about sweating every small detail in the UI; we were surprised at the oversized effect of our examples.

    Going forward this particular placeholder has been altered and is already live for customers. We will report back with a count with the new active examples in the future.

    1. some-prefix is used in this post to protect our poorly chosen actual-prefix 🙄 ↩︎
    2. It’s likely this result is known in UI design circles, but was new to us. Please send references to other work!
      ↩︎
  • Meet “ZipPy”, a fast AI LLM text detector

    Introduction

    Today we’re open-sourcing a research project from Labs, ZipPy, a very fast LLM text detection tool. Unless you’ve been living under a rock (without cellphone coverage), you’ve heard of how generative AI large language models (LLMs) are the “next big thing”. Hardly a day goes by without seeing a breathless article on how LLMs are either going to remake humanity, or bring upon its demise; this post is neither, while we think there are some neat applications for LLMs, we doubt it’s the end of work or humanity. LLMs do provide the ability to scale natural language tasks, for good or ill, it is when that force-multiplier is used for ill, or without attribution, that it becomes a concern already showing up, from disinformation campaigns, cheating in academic environments, or automating phishing; detecting LLM-generated text is an important tool in managing the downsides.

    There are a few LLM text classifiers available, the open-source Roberta-base-openai-detector model, GPTZero, and OpenAI’s detector. All of these have shortcomings: they are also large models trained on large datasets, and the latter two are commercial offerings with little information on how they operate or perform. ZipPy is a fully open-source detector that can be embedded into any number of places, enabling detection “on the edge”.

    TL:DR; ZipPy is a simple (< 200 LoC Python), open-source (MIT license), and fast (~50x faster than Roberta) LLM detection tool that can perform very well depending on the type of text. At its core, ZipPy uses LZMA compression ratios to measure the novelty/perplexity of input samples against a small (< 100KiB) corpus of AI-generated text—a corpus that can be easily tuned to a specific type of input classification (e.g., news stories, essays, poems, scientific writing, etc.).

    We should note that no detection system is 100% accurate, ZipPy included, and it should not be used to make high-consequence determinations without corroborating data.

    Background

    Generative AI and LLMs

    LLMs are statistical machine learning (ML) models with millions or billions of parameters, trained on many gigabytes or terabytes of training input. With the immense volume of input data, during the training phase the model aims to build a probability weighting for all tokens or words given the preceding context. For example, if you were to read the contents of the entire web, the sentence “The quick brown fox jumps over the lazy dog” would [relatively] frequently. Given the context “The quick brown”, the most probable next word is learned to be “fox”. LLMs have to be trained on large datasets in order to attain the “magical” level of text understanding, and this requirement leads to our detection strategy.

    Intuitively, every person has a unique vocabulary, style, and voice—we each learned to communicate from different people, read different books, had different educations. An LLM by comparison has the most probable/average style, being trained on close to the entire internet. This nuance is how LLM classifiers work—text written by a specific human will be more unique than the LLM’s model average human writer. The detectors listed above work by either explicitly or implicitly (through training on both human and LLM datasets) trying to determine how unique a text is. There are two common metrics, Perplexity and Burstiness.

    Perplexity is a measure of surprise encountered with reading a text. Imagine you had read the entire internet and knew the probability tables for each word given the preceding context. Given “The quick brown” as context, and the word “fox”, there would be a low perplexity as the chance of seeing “fox” come next is high. If the word was instead “slug”, that would have a large difference between expectations and reality, so the perplexity would increase. The challenge with calculating perplexity is that you have to have a model of all language in order to quantify the probability of the text. For this reason, the existing detectors use large models trained on either the same training data as is used to train the LLM generators, or datasets of both human and LLM generated texts.

    Burstiness is a calculation of sentence lengths and how they change throughout a text. Again, an LLM will generally migrate towards the mean, so lengths will be closer to the average, with human-written text having more variance in sentence length. This is easier to calculate, but more impacted by the type of text: some poems have little to no punctuation, whereas others have a number of highly uniform stanzas; news briefs are commonly punchier; and academic papers (and blogs about burstiness) can have extremely long sentences.

    Both of these metrics are impacted by the temperature parameter used by an LLM to determine how much randomness to include in generation. Higher temperatures will be more perplexity and bursty, but run the risk of being more non-sensical to a human reader. If a human author is writing a summary of a local slug race, captioning a picture: “The quick brown slug, Sluggy (left), took home the gold last Thursday” would make sense. LLMs don’t understand the world or what they are writing, so if the temperature were set high enough that it would output: “The quick brown slug”, the rest of the text would likely be nonsensical.

    Compression

    Compression is the act of taking data and making it smaller, with a matched decompression function that returns the compressed data to [close to] the original input. Lossless compression (e.g., .ZIP files) ensures that the data post compression and decompression is the same as the original input; lossy compression (e.g., .JPG or .MP3 files) may make minor adjustments for better compression ratios. Compression ratios are a measure of how much smaller the compressed data is than the original input. For the remainder of this blog post we’ll just be discussing lossless compression.

    Compression generally works by finding commonly repeated sequences and building a lookup table or dictionary. A file consisting of all one character would compress very highly, whereas truly random data would compress more poorly. Each compression algorithm may have different scheme for choosing which sequences to add to the table, and how to efficiently store that table, but generally they work on the same principles.

    Compression was used in the past as a simple anomaly detection system: by feeding network event logs to a compression algorithm and measuring the resultant compression ratio, the novelty (or anomaly) of the input could be determined. If the input changes drastically, the compression ratio will decrease, alerting to anomalies, whereas more of the same background event traffic will compress well having already been included in the dictionary.

    Implementation

    ZipPy is a research tool that uses compression to estimate the perplexity of an input. With this estimation, it is possible to classify a text’s source in a very efficient manner. Similar to the network event anomaly model, ZipPy looks for anomalies in the input when compared to a [relatively] large initial input of AI-generated text. If the compression ratio improves when the sample is compressed, the perplexity is low as there are existing dictionary entries for much of the sample, whereas a high-perplexity input would reduce the ratio.

    ZipPy starts with a body of text, all generated by LLMs (GPT, ChatGPT, Bard, and Bing) and compresses it with the LZMA compression algorithm (the same as in .ZIP files), calculating the ratio = compressed_size / original_size. The input sample is then appended to the LLM-generated corpus and compressed again with the new ratio computed the same way. If the corpus compresses worse than with the sample, then the sample is likely to be LLM-generated; if the compression ratio decreases, then the sample is more perplexity, and is more likely human-generated.

    At its core, that’s it! However, as part of our research, there are a number of questions we’ve been exploring:

    • How does the compression algorithm change the performance?
      • What about compression presets (which improve compression but are slower)
    • What is the optimal size and makeup of the initial body of AI-generated text?
      • Should the samples be split into smaller pieces?
      • Is there a minimum length of sample that can impact the overall ratio enough to get good data?
    • How should formatting be handled? An early test on a human sample failed because each line was indented with 8 spaces (which compressed well).

    We don’t have all the answers yet, but our initial findings are promising!

    Evaluation

    In order to test how well ZipPy performs, we needed datasets of both human and LLM text. In addition to using ChatGPT, Bard, and Bing to generate about ~100 new samples to test, we explored the following datasets:

    OpenAI’s GPT-3 dataset

    OpenAI’s GPT-2 dataset (webtext and xl-1542M)

    MASC 500k (excluding the email and twitter collections)

    GPT-2-generated academic abstracts

    News articles re-written by ChatGPT

    CHEAT (ChatGPT-generated academic abstracts)

    ZipPy performs best on datasets that are English (due to all of the AI-generated “training” text being English-language) and that are written as sensical prose. Two of the datasets we evaluated, GPT-2 and GPT-3 output were created without prompts to guide the output. ZipPy performs poorly on these, as the output is either poor (difficult to understand as a human) and/or extremely diverse (multiple languages, code, and odd formatting). A few examples from these datasets are provided below to provide a sense of the data that is difficult to classify for ZipPy:

    layout_container:Genotion 2 – HD select

    Focus: Batsu

    Most more much HD contains information about is one of the best addon…read more Posts: 7

    Check out more from Christina at: stock666.com Posted by:| September 03, 2018 06:36 AM design3D 2-3-3-3 … Posted by:| September 03, 2018 06:05 AM hiszog 2-3-3-3 … Posted by:| September 03, 2018 05:27 AM too amateur. At boot it says DLL missing. Posted by:| September 03, 2018 04:12 AM likes2eat 4-3-3-3 Early Review andenjoy! Posted by:| September 03, 2018 05:54 AM AutoVR 2-3-3-3 Built Dutch : O Posted by:| September 03, 2018 05:30 AM looks like it will get more popular : o Posted by:| September 03, 2018 02:10 AM Cross Fitness 3.0 Part 1 by CrossFit up

    OpenAI GPT-2 sample #1

    Convocainftvalerie 20

    13.9” L Y

    1107g

    With Screen Case

    Material: Acetate

    Auction Location:

    10360 W. San Ramon Fairgrounds, Sonoma, California, 94950, United States

    Taxes: TAXES MAY APPLY

    Buyer’s Premiums: From (Incl.) To (Excl.) Premium 0.00 Infinite 20%

    Shipping Details:

    There if be 3 Methods to Buy from the Big T: (1) eTailer, Ebay or other Auction Sites, or (2) Ebay (convention). This Year Auction Will be Conducted on Ebay.com

    OpenAI GPT-2 sample #2

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399…1280

    OpenAI GPT-3 sample #1

    Někdy mi začne zazvonit v telefonu život, protože to vůbec není telefon, ale sekundární vlna, kterou jsem přivolala k sobě.

    Dnes mi to začalo zazvonit už po desáté, mám ráda pravidelnost, abych se v ní vyznala, a začala se pohybovat rychleji.

    Ne, nemůžete se najít v mém životě, ale nemusíte také.

    Protože se mi začne zazvonit, pořád stejně krásně, v okamžiku, když to přijde.

    A je to pro vás taky tak nějak to pravé.

    -Nekončí se už zase?- zaslechla jsem vyslovené základní já, a snažila jsem se mu na to odpovědět.

    Nemáte moc důvodů mě zastrašovat, nebo mi přerušovat. Vy jste větší zvíře. Můžete si mě zavolat, když vám bude zase chybět něco vážnějšího. Nechcete to zas vyhodit, jako každého docela rozumného a slušného kluka, nebo jak jejich říkáte.

    Komentáře

    OpenAI GPT-3 sample #2

    With a subset of at most 500 samples per included dataset, we run just under 5000 documents through ZipPy (2m14s), OpenAI’s detector (29m22s), Roberta (1h36m17s), and GPTZero (1h1m39s). From this data, we construct a ROC curve for each. ROC curves show both the accuracy (area under the curve, or AUC) as well as the sensitivity at different decision thresholds. All the detectors provide a confidence score that a sample is either AI or human-generated, if the threshold for the decision boundary is adjusted, the detector may detect more true positives, but at the expense of more false positive detections.

    If the un-prompted datasets are excluded, the performance of the detectors gives the following ROC curve, with LZMA being the curve for ZipPy:

    ROC curve excluding un-prompted GPT-2 and GPT-3 output

    In simple terms, this curve shows that ZipPy correctly classifies the origin of an input 82% of the time, whereas Roberta has 80% accuracy, and both GPTZero and OpenAI sit at only 62% accurate. Adding the GPT-3 samples back in (without adding any new samples to the “training” file), the performance drops for ZipPy, and slightly improves for Roberta, which was trained on GPT datasets:

    ROC curve excluding only un-prompted GPT-2

    This shows that ZipPy’s compression-based approach can be accurate, but is much more sensitive to the type of input than Roberta. As ZipPy is more of an anomaly detector than a trained model, it cannot differentiate between novel types of input as well as the larger models. It does appear able to handle different types of data that have been added to the training file, the same data is used for news, essays, abstracts, forum posts, etc. but not completely differently formatted texts or those not in the same language as the training data. Additionally, due to the simple implementation, it is comparably easy to customize ZipPy for a specific set of inputs: simply replace the training file with LLM-generated inputs those that more closely the type of data to be detected.

    It is interesting to see how poor the performance is from both OpenAI’s and GPTZero’s detectors, they are the commercial, closed-source options. That OpenAI’s detector should perform so poorly on datasets that presumably they would have easy access to is curious, hopefully as they improve their models their performance will catch up with the open-source Roberta model.

    Conclusion

    In conclusion, we think that ZipPy can add utility to workflows handling data of unknown origin. Due to its size, speed, and tunability, it can be embedded into a host of places where a 1.5B parameter model (Roberta) couldn’t. In the GitHub repository is: a Python 3 implementation of ZipPy, a Nim implementation that compiles to both a binary and a web-based detector, all of the data tested on, and harnesses for testing ZipPy and the other detectors.

    As a cute example of how this could be used, we also include a browser extension that uses ZipPy in a web worker to set the opacity of web text to the confidence it is human-written. While there is too much diversity to the style of text in an average day’s browsing session, it demonstrates a proof-of-concept for filtering out the LLM-generated noise.

    We are still actively exploring this idea, and would love feedback or thoughts. If you’d like to collaborate with us, or have something you’d like to share, please reach out to research@thinkst.com.

  • Birds at (Tail)scale

    This week we are super excited to release the latest addition to our lineup of Thinkst Canary platforms: Tailscale.

    Background

    We’ve always made sure that deploying Canaries is absurdly quick and painless. It’s why you can add a hardware Canary to your network just by plugging it in and why most customers end up re-thinking their detection roadmaps:

    https://twitter.com/bigendiansmalls/status/970342360923033601

    We adore Tailscale: They have a first-rate team and their product is also widely loved for being startlingly simple to deploy. For this reason alone, we needed to consider a Tailscale Canary. But first, what is Tailscale?

    Tailscale

    Tailscale is a mesh VPN to run your own secure network. Think: I want all my endpoints to talk to each other on a secure network wherever they are in the world without worrying about eavesdropping. (They happen to do this with  amazingly little configuration, across enough platforms to make your head spin). Like Canary, “it just works”.

    (Really) Why a Tailscale Canary?

    As Tailscale grows (and we think it will) you will see logical networks being setup and used regardless of the configuration (or location) of the physical networks beneath them. The Tailscale admin gets to create policies that allow a developer-machine access to staging, or to prod through simple Tailscale routing rules.

    What will attacker lateral movement look like in a world like that?

    An attacker who compromises user-A effectively becomes user-A, and views the world from their perspective. (As always) They are able to pivot to machines on user-A’s local network, but they also have access to hosts on user-A’s Tailnet. This is where Canaries shine. Attackers probing for other hosts on the Tailnet deserve to bump into Canaries as much as attackers exploring your cloud environments do. If only we can make deployment quick and painless.

    Ed: they totally can.

    Deploying a Canary into your Tailnet is (unsurprisingly) shockingly easy. 

    Head over to your Console and select the [+] icon to add a Canary. Then head over to the “Tailscale (beta)” block and select “Add Tailscale Canary”.

    Enter an ephemeral Tailscale auth key and hit Launch. That’s it!

    A Canary boots and is added to your Console (and your Tailnet). 

    You can configure the Canary just like any of its cousins (and you can use your Tailscale config to make sure the Canary never sends traffic to other hosts on your Tailnet for added security).

    In the background we spin up an AWS environment per customer, drop a Canary into it and the bird joins your Tailnet. The AWS environment consists of a VPC and a private subnet in which the Canary lives. The Tailscale auth key is a single use tagged key such that the Canary joins with predefined ACLs that you control.

    What this gives you is a Canary in your inner circle. Here we configured the Canary called DataStore with a Windows file share and RDP. Nmap-ing shows it as Windows machine with the corresponding service ports open. 

    Mounting the file share places a Canary right in the path of any attacker.

    No matter where you work from, a Canary will be nearby to alert you to any undesired activity. For a total of 3 clicks and 4 minutes you will know when it matters. For more details head over to our knowledge base article.

Site Footer

Authored with 💚 by Thinkst