storj-archived / core

Deprecated. Implementation of the Storj v2 protocol for Node.js.
https://storj.io
Other
396 stars 88 forks source link

Easy brute force data_hash, unsecure RETRIEVE, CONSIGN, MIRROR #758

Closed littleskunk closed 6 years ago

littleskunk commented 6 years ago

Package Versions

Replace the values below using the output from npm list storj. Use npm list -g storj if installed globally.

root@storj:~# npm list -g storj-lib
/usr/local/lib
└─┬ storjshare-daemon@5.3.0
  └── storj-lib@8.5.0

Replace the values below using the output from node --version.

v8.9.4

Expected Behavior

Please describe the program's expected behavior. Include an example of your usage code in the back ticks below if applicable.

A login on a website has to return the same error message for not existing users and wrong passwords. Different error messages will give an hacker additonal informations. That is a security risk.

Same problem for the storj network. Each farmer has to send the same error message for not existing data_hash / contract and not authorized nodeID. If the farmer is sending different error messages a hacker can create a nodeID - data_hash / contract list. Additional informations are a security risk.

Actual Behavior

Please describe the program's actual behavior. Please include any stack traces or log output in the back ticks below.

RETRIEVE, CONSIGN, MIRROR are sending different error messages. All 3 can be used by an hacker to create a nodeID - data_hash / contract list.

RETRIEVE example:

error: { code: -32603, message: 'Key not found in database [0000000000000000000000000000000000000000]' }
error: { code: -32603, message: 'Retrieval is not authorized' }

Steps to Reproduce

Please include the steps the reproduce the issue, numbered below. Include as much detail as possible.

'use strict';

const request = require('request');
const storj = require('storj-lib');
const keypair = storj.KeyPair('54e8b615160e91c129b4a2054a8dda83257236ded266131adb50a378438662a0');

const nonce = '1511220328771';
const nodeID = keypair.getNodeID();

const id = nonce;
const data = {
        method: 'RETRIEVE',
        params: {
                data_hash: '0000000000000000000000000000000000000000',
                contact: {
                        address: 'litteskunk retrieve test',
                        port: 1337,
                        nodeID: nodeID,
                        protocol: '1.2.0',
                        userAgent: 'littleskunk',
                        spaceAvailable: true,
                        lastSeen: nonce
                },
                nonce: nonce,
                signature: keypair.sign(id + nonce),
        },
        id: id,
};
request.post({
        url: 'http://localhost:4000',
        json: data,
        timeout: 30000
}, (err, res, data) => {
        if (err) {
                console.log('Error request:', err);
        } else if (res.statusCode !== 200) {
                console.log('Status code %s message %s', res.statusCode, res.statusMessage);
        } else {
                console.log(data);
        }
});
braydonf commented 6 years ago

Guessing a 160-bit hash would take a very long time. Related comment discussing something similar: https://github.com/Storj/service-storage-models/pull/136#discussion_r155152691

littleskunk commented 6 years ago

If I already have a shard hash I only need to send one unauthorized RETRIEVE request to each farmer and they will send me usefull informations.

Please take a look at the pull request. It will minimize the risk.