Giter Site home page Giter Site logo

hanover-computing / got-ssrf Goto Github PK

View Code? Open in Web Editor NEW
46.0 2.0 3.0 878 KB

Protect untrusted requests from SSRF

License: GNU Lesser General Public License v3.0

Shell 1.81% TypeScript 98.19%
npm-package javascript got http https client http-client https-client https-proxy ssrf

got-ssrf's Introduction

GitHub Public Organization Profile README

This repo, and in particular the .profile/README.md file, is the public-facing face of this organization on GitHub, and outlines this organization's vision and goals.

got-ssrf's People

Contributors

dependabot[bot] avatar janejeon avatar markus-rost avatar renovate-bot avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

got-ssrf's Issues

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/ci.yml
  • actions/checkout v4
  • actions/setup-node v3
  • actions/checkout v4
  • actions/setup-node v3
  • codecov/codecov-action v4
.github/workflows/codeql-analysis.yml
  • actions/checkout v4
  • github/codeql-action v2
  • github/codeql-action v2
  • github/codeql-action v2
.github/workflows/ossar-analysis.yml
  • actions/checkout v4
  • github/ossar-action v1
  • github/codeql-action v2
npm
package.json
  • debug ^4.3.2
  • ipaddr.js ^2.0.1
  • @janejeon/eslint-config-typescript ^0.1.0
  • @janejeon/prettier-config ^2.0.0
  • @janejeon/tsconfig ^0.3.1
  • @types/debug ^4.1.8
  • @types/node ^20.5.1
  • @vitest/coverage-istanbul ^1.0.0
  • @vitest/ui ^1.0.0
  • cacheable-lookup ^7.0.0
  • lint-staged ^15.0.0
  • nock ^13.1.3
  • npm-run-all2 ^6.0.0
  • skip-ci ^1.0.4
  • typescript ^5.1.6
  • vitest ^1.0.0
  • got ^14
  • node >=16
nvm
.nvmrc
  • node 20

  • Check this box to trigger a request for Renovate to run again on this repository

Add Github Actions CI

And figure out CircleCI config for libraries (without package-lock) while I'm at it

HTTP redirection attack bypass DNS check

Hello,

This library is fantastic. Thanks for that. I found an attack that is not being covered.

I setup a DNS record on my domain pointing to itself:

CleanShot 2021-09-24 at 16 30 26@2x

Nothing evil there. However, I added a redirection rule to redirect that URL into something evil:

CleanShot 2021-09-24 at 16 31 04@2x

So the library is preventing malicious attacks by checking for the hostname.

https://github.com/JaneJeon/got-ssrf/blob/master/index.js#L35

There the hostname is going to be 'local.urlint.co' being resolved into a unicast IP address.

However, if you interact with the resource, that URL is going to redirect you into the evil URL

$ curl -I -s -X GET https://local.urlint.co/dns
HTTP/2 301
date: Fri, 24 Sep 2021 14:28:30 GMT
cache-control: max-age=3600
expires: Fri, 24 Sep 2021 15:28:30 GMT
location: http://192.168.0.1

That's because we checked the DNS over the hostname but not over the hostname over the location.

Plus, most HTTP clients follow redirects by default (that's the case of got and that in fact a good expected behavior).

I wrote some code as suggestions to prevent the attack:

const { headers } = await got.head(url, { followRedirect: false })
const redirectHostname = new URL(headers.location).hostname

const { address } = await cacheableLookup.lookupAsync(url.hostname)

if (
  ip.parse(address).range() !== 'unicast' ||
  ip.parse(redirectHostname).range() !== 'unicast'
) {
  throw new Error("You're evil")
}

However, I don't like it at all, since the got.head extra network request needs to be performed. Maybe that could be handle at the DNS level?

SSRF doesn't work with IPv6 URLs

Hello,

I noted the SSRF protection is not working effectively against IPv6 URLs

For example, http://[::ffff:7f00:1]:1338/ is a valid URL; let's use got-ssrf for hitting it:

import { gotSsrf } from 'got-ssrf'
const result = await gotSsrf('http://[::ffff:7f00:1]:1338/')
console.log(result.body)

In case you want to run a local server, here is the code:

const { listen } = require('async-listen')
const { createServer } = require('http')

const html = `
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>OH NO YOU'RE COMPROMISED</h1>
</body>
</html>`

const server = () =>
  createServer((req, res) => {
    res.setHeader('Content-Length', Buffer.byteLength(html))
    res.setHeader('Content-Type', 'text/html; charset=UTF-8')
    res.end(html)
  })

Promise.resolve().then(async () => {
  const serverIPv4url = await listen(server(), {
    host: '192.168.4.50',
    port: '1337'
  })

  const serverIPv6url = await listen(server(), {
    host: '::ffff:127.0.0.1',
    port: '1338'
  })

  console.log('> Listening at IPv4:', serverIPv4url.toString())
  console.log('> Listening at IPv6:', serverIPv6url.toString())
})

The SSRF protection is not working for a little implementation detail at this point:

https://github.com/hanover-computing/got-ssrf/blob/master/index.js#L33

The options.url.hostname there is [::ffff:7f00:1]. That is the URL hostname representation of the hostname according to whatwg URL spec:

https://url.spec.whatwg.org/#host-serializing

However, brackets there should be removed in order to pass the value against DNS lookup.

If the code is replaced by something like:

const hostname = options.url.hostname.replace('[', '').replace(']', '')
const { address } = await lookup(hostname)

Then hit the server throw the same error as IPv4 version:

RequestError: The IP of the domain is reserved!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.