storj-archived/core

Easy brute force data_hash, unsecure RETRIEVE, CONSIGN, MIRROR

Closed this issue · 2 comments

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);
        }
});

Guessing a 160-bit hash would take a very long time. Related comment discussing something similar: storj-archived/service-storage-models#136 (comment)

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.