NodeJS/PostgreSQL. I can authenticate using arbitrary/any password - node.js

I have the following problem. I created a PostgreSQL user app with this statement:
CREATE USER app WITH ENCRYPTED PASSWORD 'qwerty';
Then I gave it some privileges in my database bazy.
Then I access a database by authenticating as this user and using pg module like this:
const { Pool } = require('pg');
(async function() {
let pool = new Pool({
user: "app",
host: 'localhost',
database: "bazy",
password: "BS",
port: 5432
});
let client = await pool.connect();
let { rows } = await client.query("SELECT 'I love you';");
console.log(rows);
})();
The problem is that this works and gives this output:
[ { '?column?': 'I love you' } ]
But this should not work, for the password of the user is qwerty, not BS. And the thing is that any password works here.
What have I done wrong?
[EDIT]
The answer of #mike.k is 100% helpful.
The not commented (almost) part of pg_hba.conf file, which we can find following these instructions, looks like this:
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all 127.0.0.1/32 trust
# IPv6 local connections:
host all all ::1/128 trust
# Allow replication connections from localhost, by a user with the
# replication privilege.
local replication all trust
host replication all 127.0.0.1/32 trust
host replication all ::1/128 trust
We can see here that we do not require password in any type of connections listed here, for method trust means that in order to connect to those users we are not required any password (it is ignored obviously), in order to change that we can use method password or md5 or scram-sha-256 instead, as is said in pg_hba.conf file:
# Note that "password" sends passwords in clear text; "md5" or
# "scram-sha-256" are preferred since they send encrypted passwords.
To be honest, I don't know where exactly I should change it, though. ¯\_(ツ)_/¯. So I changed all of them (of the methods to password) and it worked :) It requires passwords now.

Check your pg_hba.conf content, it might be configured to not require a password for localhost connections.
Try using the local IP address and you might see that it behaves differently. Or try connecting from another system on the same network.

Related

No Username specified in startup packet

I am opening up a project from a year and a half ago and my local PostgreSQL database is not working. I am using a react front end, with a Node.js back end. The Node module I am using to connect with the local database is pg.pool. The error I get when I submit the data through pg.pool is:
Error with query for user error: no PostgreSQL user name specified in startup packet
I was reading on the internet and apparently the client has to submit a username to the backend for the Database to open up. The internet suggested opening the pg_hba.conf file and checking that the users are correct, but I checked the file and the users for the PostgreSQL is set to all, so I don't think that is the problem. Here is that file:
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all scram-sha-256
# IPv4 local connections:
host all all 127.0.0.1/32 scram-sha-256
# IPv6 local connections:
host all all ::1/128 scram-sha-256
# Allow replication connections from localhost, by a user with the
# replication privilege.
local replication all scram-sha-256
host replication all 127.0.0.1/32 scram-sha-256
host replication all ::1/128 scram-sha-256
Here is my pool.js file that connects the node server to the postgresql instance running locally, it uses a if else statement incase I want to connect locally or in case I want to connect to heroku:
const pg = require('pg');
const url = require('url');
let config = {};
if (process.env.DATABASE_URL) {
// Heroku gives a url, not a connection object
// https://github.com/brianc/node-pg-pool
const params = url.parse(process.env.DATABASE_URL);
const auth = params.auth.split(':');
config = {
user: auth[0],
password: auth[1],
host: params.hostname,
port: params.port,
database: params.pathname.split('/')[1],
ssl: { rejectUnauthorized: false },
max: 10, // max number of clients in the pool
idleTimeoutMillis: 30000, // how long a client is allowed to remain idle before being closed
};
} else {
config = {
host: 'localhost', // Server hosting the postgres database
port: 5432, // env var: PGPORT
database: "workout_app_prime", // CHANGE THIS LINE! env var: PGDATABASE, this is likely the one thing you need to change to get up and running
max: 10, // max number of clients in the pool
idleTimeoutMillis: 30000, // how long a client is allowed to remain idle before being closed
};
}
// this creates the pool that will be shared by all other modules
const pool = new pg.Pool(config);
// the pool with emit an error on behalf of any idle clients
// it contains if a backend error or network partition happens
pool.on('error', (err) => {
console.log('Unexpected error on idle client', err);
process.exit(-1);
});
module.exports = pool;
Other relevant facts: yesterday morning working on a different project my computer crashed, PostgreSQL wasn't working when I tried to reopen that project because the project didn't terminate correctly, So I deleted the .pid file and restarted the computer then it started working.
When I made this database a year and a half ago I was running postgreSQL 12, now I am on 13.
I am running on Mac OS 10.15, idk if that is relevant.
Anybody have any ideas? Thanks!

Is it ok to be setting rejectUnauthorized to false in production PostgreSQL connections?

We recently moved to Heroku and upon attempting to connect our apps to the DB, it kept rejecting our queries with the message "Self signed certificate". Passing in rejectUnauthorized solved for this but now I'm wondering, should we be doing this in production? If not, what is the appropriate way for us to be connecting to our Heroku PG Databases?
const pgp = require('pg-promise')(/*initOptions*/);
const {ConnectionString} = require('connection-string');
const cnObj = new ConnectionString(process.env.DATABASE_URL);
const cn = {
host: cnObj.hostname,
port: cnObj.port,
database: cnObj.path?.[0],
user: cnObj.user,
password: cnObj.password,
ssl: {
rejectUnauthorized: false,
},
};
const db = pgp(cn);
The risk you are running is that somebody gets between you and the Heroku server and impersonates the latter. They can then present their own certificate to you and negotiate a connection with you. The man in the middle can also pass the challenge from the server down to you and use your response to log into the database server in your stead.
All that assumes that the attacker has control over one of the network nodes between you and the Heroku server.
So I would say that while there is a residual risk, I wouldn't lose too much sleep over it, unless you are working with really sensitive data, in which case paranoia is a virtue.

How to connect to a postgreSQL database stored on a server and request this database? Node.js

I am working to develop a server with Node.js to request a postgreSQL database. My problem is, that I can't connect (with my local computer, using wifi connection, not ethernet) to this server, and also to the postgreSQL.
I have an username and a password to connect to the server, and also an another username and password to connect the database.
How can to connect both of those, and get the information I want from the postgreSQL database? Can I connect to this server with command bash like ssh but in node.js?
I did something like this:
var ssh = new SSH({
host: 'hostname',
user: 'user',
pass: 'password'
});
or something like this:
var connectionString = 'postgres://user:password#database:port';
I have another problem, my teacher give me a password containing a #, and I think this will make some problems when I have to put my password:
postgres://user:pass**#**word#database:port
How to bypass this password problem?
you need to pass ip address of machine where database resides in place of hostname.

Postgres md5 authentication from Node

I'm trying to connect to postgres via node using the md5 authentication method.
My pg_hba_conf file looks like this:
"local" is for Unix domain socket connections only
local all all md5
IPv4 local connections:
host all all 127.0.0.1/32 md5
IPv6 local connections:
host all all ::1/128 md5
I can connect to the database via psql without any problems, but my question is how do you create the connection string within node to connect to postgres when via md5? If I change the pg_hba.conf to use 'password' as the authentication method, then I can connect to the database with the following:
let connectionString = postgres://user:password#localhost:5432/database';
I had thought that I could md5hash my password within the connectionString e.g:
let password = crypto.createHash('md5').update(my_password).digest('hex');
let connectionString = 'postgres://user:' + password + '#localhost:5432/database';
But this didn't work :-(
Can someone point me in the right direction as to how you access postgres via Node using md5 authentication?
Cheers
Use:
let connectionString = 'postgres://user:' + my_password + '#localhost:5432/database';
Documentation says:
var client = new Client('postgres://brian:mypassword#localhost:5432/dev');
It doesn't mention md5 at all. It's database driver job to encode and send properly encoded password.

Do I need to enable authentication for MongoDB?

I've just set up MongoDB, got a hold of mongoose as well and while I was following some tutorial of connecting to the database I have noticed that there's no user/password being required by default which lead me to the following question:
Is that a security issue when moving to production? What security measures do I need to take? Would anyone be able to access MongoDB remotely? How to suppress that if so.
Indeed, You have stumbled upon a valid question.
You check out this source:
http://mongodb.github.io/node-mongodb-native/contents.html
And have a code which does something of this sort:
var Db = require('mongodb').Db,
MongoClient = require('mongodb').MongoClient,
BSON = require('mongodb').pure().BSON,
assert = require('assert');
var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
{auto_reconnect: false, poolSize: 4}), {w:0, native_parser: false});
// Establish connection to db
db.open(function(err, db) {
assert.equal(null, err);
// Add a user to the database
db.addUser('user', 'name', function(err, result) {
assert.equal(null, err);
// Authenticate
db.authenticate('user', 'name', function(err, result) {
assert.equal(true, result);
db.close();
});
});
});
Just adding a few more sources you might want to have a look at:
https://docs.mongodb.org/v3.0/administration/security-checklist/
https://docs.mongodb.org/manual/administration/security/
Hope this is a good starting point in your quest for productionizing MongoDB!
Yes it is problematic if access is possible from the internet (i.e., is not firewalled, has a weak/no password, or not bound to localhost only). Attackers might be easily able to access your DB and read all data. This is not just a theoretical threat, see http://www.cso.com.au/article/566040/students-find-40k-unprotected-mongodb-databases-8-million-telco-customer-records-exposed/ for a recent "indicent".
The mongodb developers provide a security checklist and also provide a security tutorial.
So, at least set a password and at best bind it to localhost only (also problematic if other users also have access to that machine) in order to prevent brute force attacks.
Security should be a multi-layered approach.
First of all, in production, I would recommend putting MongoDB on a separate physical machine.
I would restrict access to this machine via the firewall, such that only MongoDB traffic on port 27017 can access the MongoDB machine from the webservers.
I would only allow ssh access to the MongoDB machine or the webservers from specific IP addresses which need access to them.
I would use only key-based authentication for SSH to both the Webservers and MongoDB machine.
I would completely block the MongoDB machine from accessing the internet, aside from NTP for time synchronization.
Although I feel the above steps are more important, I would enable MongoDB authentication.
This is a weak layer of security, though, since only the webservers should be able to access port 27017 on the MongoDB machine, and anyone who compromised the webserver would be able to extract the MongoDB password from the source code on the server.
If you have multiple MongoDB databases, you can use different authentication credentials for each database, to add a level of isolation between applications.
In short, no, you don't need authentication, but it can add an extra layer of security. The other layers are far more important.

Resources