Thursday, July 29, 2021

Republishing Post from  for my reference 

/ / / Auditing Users and Roles in PostgreSQL


Auditing Users and Roles in PostgreSQL

One of the services we offer are security reviews (or audits, if you want), covering a range of areas related to security. It may be a bit surprising, but a topic that often yields the most serious issues is roles and privileges. Perhaps the reason why roles and privileges are a frequent source of issues is that it seems to be quite simple and similar to things the engineers are familiar with (e.g. Unix system of users and groups), but it turns out there are a few key differences with major consequences.

The other parts are either very straightforward and understandable even for sysadmins without much PostgreSQL experience (e.g. authentication config in pg_hba.conf), or the engineers recognize the complexity and take their time to familiarize with the details (a good example of this is Row Level Security).

That is not to say there are no interesting topics e.g. how to use RLS with application-level users but I’ll leave that for another blog post, as this one is about roles and privileges.

So let’s look at roles and privileges a bit a closer …

Owner is a small superuser

When it comes to roles, the initial checks are mostly expected. The role should not be a superuser (as superusers simply bypass various checks), and in general should not have any excessive privileges (e.g. CREATEDB, CREATEROLE and so on).

But it also should not own the database objects (tables, functions, …), since owners can simply grant themselves arbitrary privileges on the objects they own, which turns them into small superusers.

Consider the following example, where we attempt to protect the table from the owner by revoking all the privileges from that role:

db=# CREATE USER u;
CREATE ROLE

db=# SELECT rolsuper FROM pg_roles WHERE rolname = 'u';
 rolsuper
----------
 f
(1 row)

db=# \c 'user=u dbname=db'
You are now connected to database "db" as user "u".

So we have created a user who is not a superuser, and we have connected using that account (that’s the slightly cryptic psql command). Let’s create a table (so the user is an owner) and restrict our own access to it

db=> CREATE TABLE t (id INT);
CREATE TABLE

db=> REVOKE ALL ON t FROM u;
REVOKE

db=> SELECT * FROM t;
ERROR:  permission denied for relation t

So that works, right? Well, the problem is a user with access to SQL (e.g. an “attacker” that discovered a SQL injection vulnerability) can do this:

db=> GRANT ALL ON t TO u;
GRANT

db=> select * from t;
 id
----
(0 rows)

The owner can simply grant all privileges back to himself, defeating the whole privilege system. A single SQL injection vulnerability and it’s a game over. Another issue with owners is that they are not subject to RLS by default, although that can be fixed with a simple ALTER TABLE ... FORCE ROW LEVEL SECURITY.

In any case, this should be a clear hint that the application should use a dedicated role (or multiple roles), not owning any of the objects.

BTW users are often surprised when I mention that we can grant privileges to individual columns e.g. allow SELECT on a subset of columns, UPDATE on a different subset of columns, and so on.

When combined with SECURITY DEFINER functions, this is a great way to restrict access to columns the application should not access directly, but allow special operations. For example it shouldn’t be possible to select all passwords (even if hashed) or e-mails, but it should be possible to verify a password or an e-mail. SECURITY DEFINER functions are great for that, but sadly it’s one of the powerful yet severely underused features 🙁

Role inheritance

Let’s assume you have a role that owns the objects, and a separate role used by the application. In fact, if you have sufficiently complex application, chances are you’ve split it into multiple parts, perhaps segregated into schemas, and each module uses a separate set of roles (owner + application, possibly more).

This gives you the ability to create application roles covering only part of the application e.g. the administration panel needs access to all modules, while a public web interface only needs read-only access to a small subset of modules.

CREATE ROLE module_users;    -- full access to user info
CREATE ROLE module_users_ro; -- limited access user info (register/verify)
CREATE ROLE module_posts;    -- full access to blog posts
CREATE ROLE module_posts_ro; -- read-only access to blog posts
... roles for additional modules ...

CREATE USER admin_user   -- full access
    IN ROLE module_users, module_posts;

CREATE USER web_user     -- limited access
    IN ROLE module_users_ro, module_posts_ro;

In other words, roles may be seen as groups and used for making the privileges easier to manage. There are two aspects that make this different from unix-like groups it’s possible to use multi-level hierarchy of roles (while Unix groups are flat), and inheritance (will get to that in a minute).

The above scheme works just fine, but only if you keep the connections for the two users (admin_user and web_user) separate. With a small number of users (modules, applications) that’s manageable, as you can maintain separate connection pools, but as the number of connection pools grows it ceases to serve the purpose. But can we use a single connection pool and keep the benefit of separate users?

Well, yes. We can create another user role for the connection pool and grant it all the existing users (admin_user and web_user).

CREATE USER pool_user IN ROLE admin_user, web_user

This seems a bit strange, because the new user becomes member of admin_user and web_user roles (users are just roles with LOGIN privilege), effectively inheriting all the privileges. Wasn’t the whole point using roles with limited privileges?

Let me introduce you the SET ROLE command, which can be used to switch the session to arbitrary role the user is member of. So as the pool_user user is member of both admin_user and web_user roles, the connection pool or application may use this:

SET ROLE admin_user

to switch it to “full” privileges for the admin interface, or

SET ROLE web_user

when the connection is intended for the website.

These commands are akin to dropping privileges in Unix. The init scripts are executed as root, but you really don’t want to run all the services as root, so the init script does something like sudo -u or chpst to switch to unprivileged user.

But wait, we can actually do the opposite. We can start with “no privileges” by default, all we need to do is create the role like this:

CREATE USER pool_user NOINHERIT IN ROLE admin_user, web_user

The user is still member of the two roles (and so can switch to them using SET ROLE), but inherits no privileges from them. This has the benefit that if the pool or application fails to do the SET ROLE, it will fail due to lack of privileges on the database objects (instead of silently proceeding with full privileges). So instead of starting with full privileges and eventually dropping most of them, with NOINHERIT we start with no privileges and then acquire a limited subset of them.

But why am I wasting time by explaining all this SET ROLE and INHERIT or NOIHERIT stuff? Well, it has implications on testing.

Note: You have to trust the pool/application to actually execute the SET ROLE command with the right target role, and the user must not be able to execute custom SQL on the connection (because then it’s just a matter of RESET ROLE to gain the full privileges, or SET ROLE to switch to another role). If that’s not the case, the shared connection pool is not a path forward for you.

Testing roles

Pretty much no one tests privileges. Or to be more accurate everyone tests the positive case implicitly, because if you don’t get the necessary privileges the application breaks down. But only very few people verify that there are no unnecessary/unexpected privileges.

The most straightforward way to test absence of privileges (user has no access) might be to walk through all existing objects (tables, columns) and try all compatible privileges. But that’s obviously a lot of combinations and a lot of additional schema-specific work (data types, constraints, …).

Luckily, PostgreSQL provides a collection of useful functions for exactly this purpose (showing just table-related ones, there are additional functions for other object types):

  • has_any_column_privilege(...)
  • has_column_privilege(...)
  • has_table_privilege(...)

So for example it’s trivial to check which roles have INSERT privilege on a given table:

SELECT rolname FROM pg_roles WHERE has_table_privilege(rolname, 'table', 'INSERT')

or listing tables accessible by a given role:

SELECT oid, relname FROM pg_class WHERE has_table_privilege('user', oid, 'INSERT')

And similarly for other privileges and object types. The testing seems fairly trivial – simply run a bunch of queries for the application users, check that the result matches expectation and we’re done.

Note: It’s also possible to use the information_schema, e.g. table_privileges which essentially just runs a query with has_table_privilege and formats the output nicely.

Except there’s a small catch – the inheritance. It works just fine as long as the role inherits privileges through membership, but as soon as there’s a NOINHERIT somewhere, those privileges will not be considered when checking the access (both in the functions and information_schema). Which makes sense, because the current user does not currently have the privileges, but can gain them easily using SET ROLE.

But of course, PostgreSQL also includes pg_has_role() function, so we can merge the privileges from all the roles, for example like this:

SELECT DISTINCT relname
  FROM pg_roles CROSS JOIN pg_class
 WHERE pg_has_role('user', rolname, 'MEMBER')
   AND has_table_privilege(rolname, pg_class.oid, 'SELECT')

Making this properly testable requires more work (to handle additional object types and applicable privileges), but you get the idea.

Summary

Let me briefly summarize this blog post:

  • separate the owner and application user – Don’t use a single role for both things.
  • consider using SET ROLE role – Either drop (INHERIT) or acquire (NOINHERIT).
  • test the expected privileges – Ideally run this as part of regular unit tests if possible.
  • keep it simple – It’s definitely better to have a simple hierarchy of roles you understand.

Thursday, June 3, 2021

PostgreSQL Features

 

List of PostgreSQL Features for quick review before interview

Source:https://www.postgresql.org/about/

Below is an inexhaustive list of various features found in PostgreSQL, with more being added in every major release:

  • Data Types
    • Primitives: Integer, Numeric, String, Boolean
    • Structured: Date/Time, Array, Range, UUID
    • Document: JSON/JSONB, XML, Key-value (Hstore)
    • Geometry: Point, Line, Circle, Polygon
    • Customizations: Composite, Custom Types
  • Data Integrity
    • UNIQUE, NOT NULL
    • Primary Keys
    • Foreign Keys
    • Exclusion Constraints
    • Explicit Locks, Advisory Locks
  • Concurrency, Performance
    • Indexing: B-tree, Multicolumn, Expressions, Partial
    • Advanced Indexing: GiST, SP-Gist, KNN Gist, GIN, BRIN, Covering indexes, Bloom filters
    • Sophisticated query planner / optimizer, index-only scans, multicolumn statistics
    • Transactions, Nested Transactions (via savepoints)
    • Multi-Version concurrency Control (MVCC)
    • Parallelization of read queries and building B-tree indexes
    • Table partitioning
    • All transaction isolation levels defined in the SQL standard, including Serializable
    • Just-in-time (JIT) compilation of expressions
  • Reliability, Disaster Recovery
    • Write-ahead Logging (WAL)
    • Replication: Asynchronous, Synchronous, Logical
    • Point-in-time-recovery (PITR), active standbys
    • Tablespaces
  • Security
    • Authentication: GSSAPI, SSPI, LDAP, SCRAM-SHA-256, Certificate, and more
    • Robust access-control system
    • Column and row-level security
    • Multi-factor authentication with certificates and an additional method
  • Extensibility
    • Stored functions and procedures
    • Procedural Languages: PL/PGSQL, Perl, Python (and many more)
    • SQL/JSON path expressions
    • Foreign data wrappers: connect to other databases or streams with a standard SQL interface
    • Customizable storage interface for tables
    • Many extensions that provide additional functionality, including PostGIS
  • Internationalization, Text Search
    • Support for international character sets, e.g. through ICU collations
    • Case-insensitive and accent-insensitive collations
    • Full-text search

There are many more features that you can discover in the PostgreSQL documentation. Additionally, PostgreSQL is highly extensible: many features, such as indexes, have defined APIs so that you can build out with PostgreSQL to solve your challenges.

Tuesday, June 1, 2021

Topics to Prepare for an Interview: (C, Linux and Networking Interview Questions)

 

This article captures the list of topics to be covered/prepared for an Interview in Networking domain with C as a programming language and Linux as a work environment. This will help the candidate/employee who is experienced, having no idea of how to prepare (begin with) for an interview. All the topics covered here are collected from different experienced employees who gave interview for different companies on Networking domain.

Following are the list of topics which needs to be covered in order to prepare for an interview in Networking domain,

1.    Storage classes in C (Important)

>> Most of the questions will be on static and extern variables

2.    Memory layout of a process in Linux

>> Correlation of memory layout with storage classes

3.    Inter Process Communication (IPC)

>> Message queue, Shared memory, Pipes, FIFO, Semaphore, IOCTL, Sockets -Learn each concept in detail with their use cases

4.    Multi-threading

>> POSIX threads and mutex, critical section problem

5.    Process synchronization Techniques

>> Semaphores and Mutex and their use cases

6.    Socket programming

>> Different types of sockets such as TCP, UDP, RAW, NETLINK, UNIX Domain socket and their use cases (When to use)

7.    C data structures

>> Linked list (Singly linked list and Doubly linked list), Stack, Queue - (add a node (add a node to the front of the list or at the end of the list), delete a node (delete first node or delete a node from the end of the list), reverse a linked list, push-pop operations on stack, detect a loop in linked list, intersection in linked list etc.

8.    Knowledge about your core domain you worked on (Important)

>> Prepare well on your domain (Ex. Firmware, Wi-Fi, L2/L3 etc.) and you should be in a position to explain all the works that you have done on your domain.

9.    Pointers and de-referencing

>> Recall basics of pointers (Good to have deep knowledge on pointers and its use cases)

10. Implementation of our own functions for memcpy, strrev, memmove, sizeof, strlen etc.

>> Understand how each function is actually implemented.

11. Concepts of networking protocols such as DHCP, ARP, ICMP, TCP/IP, NAT, Routing, switching, VLAN etc.

>> Good to know the use cases and scenarios

12. Operations on bits (Important)

>> Toggle a bit, clear a bit, set a bit, count number of bits set in a given number, reverse bits of a number etc.

13. Operating System concepts

>> Process states, scheduling, dispatching, paging, page fault, virtual memory concept etc.

14. Linux internals

>> Interrupt, ISR, system boot up sequence, software interrupts, system calls etc.

15. Dynamic memory allocation concepts

>> malloc, calloc, realloc (return value of these functions and how these memory allocations implemented)

16. Good understanding of C programming language.

>> Brush up on C programming concepts such as function pointer, call back function, pointer arithmetic, MACRO, inline functions, structures padding and packing etc. 



Hope this article will help you to start your preparation for the interview. I will add more topics in future. Keep visiting this space for more update.


Monday, May 31, 2021

 

Different Format Specifiers available in C


Format specifiers define the type of data to be printed on standard output. You need to use format specifiers whether you're printing formatted output with printf() or accepting input with scanf().

Below are some of the format specifiers that are available in ANSI C

SPECIFIER

USED FOR

%c

a single character

%s

a string

%hi

short (signed)

%hu

short (unsigned)

%Lf

long double

%n

prints nothing

%d

a decimal integer (assumes base 10)

%i

a decimal integer (detects the base automatically)

%o

an octal (base 8) integer

%x

a hexadecimal (base 16) integer

%p

an address (or pointer)

%f

a floating point number for floats

%u

int unsigned decimal

%e

a floating point number in scientific notation

%E

a floating point number in scientific notation

%%

the % symbol










Friday, May 28, 2021

Shift command in Linux with examples

 Shift command in Linux with examples

                                                                                                    Source:  https://www.geeksforgeeks.org 

Shift is a built-in command in bash which after getting executed, shifts/move the command line arguments to one position left. The first argument is lost after using shift command. This command takes only one integer as an argument. This command is useful when you want to get rid of the command line arguments which are not needed after parsing them.

Syntax:

shift n

Here, n is the number of positions by which you want to shift command-line arguments to the left if you do not specify, the default value of n is assumed to be 1 i.e shift works the same as shift 1.

Example: Let’s create a shell script file named as sampleshift.sh as follows. The total number of command-line arguments is represented by $#. Use the following command to create the desired shell script file

vi sampleshift.sh

Now paste the following code:

#!/bin/bash

# total number of command-line arguments
echo "Total arguments passed are: $#"

# $* is used to show the command line arguments
echo "The arguments are: $*"

echo "The First Argument is: $1"
shift 2

echo "The First Argument After Shift 2 is: $1"
shift

echo "The First Argument After Shift is: $1"

Now to save the file press ESC and then type “:x” without quotes and hit Enter. Now to execute the file, use the following command on Linux terminal

sh sampleshift.sh

But here we have to pass command-line arguments so we can use the following command

sh sampleshift.sh G1 G2 G3 G4

Here, we are passing 4 command-line arguments named G1, G2, G3, and G4. Below is the screenshot of the output of using shift command:

Shift-Command-in-Linux-with-Examples



Functions in Shell Scripts


#!/bin/sh
# A simple script with a function...

add_a_user()
{
  USER=$1
  PASSWORD=$2
  shift; shift;
  # Having shifted twice, the rest is now comments ...
  COMMENTS=$@
  echo "Adding user $USER ..."
  echo useradd -c "$COMMENTS" $USER
  echo passwd $USER $PASSWORD
  echo "Added user $USER ($COMMENTS) with pass $PASSWORD"
}

###
# Main body of script starts here
###
echo "Start of script..."
add_a_user bob letmein Bob Holness the presenter
add_a_user fred badpassword Fred Durst the singer
add_a_user bilko worsepassword Sgt. Bilko the role model
echo "End of script..."


Below is the output after execution of above script (test1.sh)








Sunday, May 9, 2021

Saturday, April 17, 2021

Hacker Rank SQL Practice

Solutions to problem : The PADS

There are different ways to solve this 

First : Using SUBSTR and || 

select Name || '(' || UPPER(SUBSTR(Occupation, 1, 1)) || ')' from OCCUPATIONS order by Name;

select 'There are a total of ' || count(Occupation) || ' ' ||LOWER(Occupation) ||'s.' from OCCUPATIONS group by Occupation ORDER BY count(Occupation), Occupation;


Second: Using CASE and CONCAT

select Name|| (CASE Occupation 
WHEN 'Professor' THEN CONCAT(CONCAT('(', 'P'), ')')
WHEN 'Actor'     THEN CONCAT(CONCAT('(', 'A'), ')')
WHEN 'Doctor'    THEN CONCAT(CONCAT('(', 'D'), ')')
WHEN 'Singer'    THEN CONCAT(CONCAT('(', 'S'), ')')
END) Occupation from OCCUPATIONS order by Name ;


select 'There are a total of', count(Occupation), CONCAT(LOWER(Occupation),'s.') from OCCUPATIONS group by Occupation order by count(Occupation), Occupation ;


Friday, April 16, 2021

Dual Table in Oracle


Source : https://www.oracletutorial.com/oracle-basics/