Home InterBase Firebird Community About us Search Help English Russian
Everything about Borland InterBase and Firebird
Get Firebird power with FIBPlus
 
Anonymous Login / Register
Site News
Third-party Product News
Programming
Miscellaneous
Encyclopedia
FAQ


Search the site


Subscribe the site news

Sections:
News
E-mail:


InterBase World is a Full Member of Firebird Foundation



Login


Hits 2621582
1712
Hosts 152019
527
Visitors 771121
717

7



Powered by Bitrix Site Manager - Content Management & Portal Solutions

Home / Article archives / Programming

Security - Enhanced isc4.gdb


01/17/2003  | Views: 7343

Source: Ivan Prenosil's InterBase site

Some tips to improve security of isc4.gdb database. Author: Ivan Prenosil. Original text
Whenever user logs into InterBase database, his/her password is verified against encrypted password stored in special database - isc4.gdb, that is common for all databases on that IB server. I said "special database", but in fact it is ordinary database like any other. It's (simplified) structure looks like
  CREATE TABLE USERS (
    USER_NAME  VARCHAR(128),
    PASSWD     VARCHAR(32) );

  GRANT SELECT ON USERS TO PUBLIC;

At first glance you can see several drawbacks of such structure, e.g. only SYSDBA can modify USERS table, so users can't modify their own passwords. But since you can connect to isc4.gdb like to any other database and modify its structure, here are some tips how to improve it. You can also look at full scripts to modify ordinary isc4.gdb to its enhanced version. Never forget to do (physical) copy of isc4.gdb before playing with that database.

How to allow users to modify their own passwords

The easiest and well known modification is to grant update on USERS table to PUBLIC, and add trigger that prevents users (except SYSDBA) from modifying somebody else's password. You can look at full script here . Note that if you want to use standard methods for modifying password (like IBConsole or GSEC utility), you need to grant update rights to several fields (not just PASSWD), specifically
  GRANT UPDATE(PASSWD, GROUP_NAME, UID, GID, FIRST_NAME, MIDDLE_NAME, LAST_NAME)
     ON USERS
     TO PUBLIC;
This modification (as well as original isc4.gdb) has still drawback that full list of users (and their encrypted passwords as well) is visible to PUBLIC.


How to hide list of users/passwords

When you rename USERS table and create USERS view instead of it, you will allow users to modify their passwords as well as hide full list of users from PUBLIC. Each user (except SYSDBA) will see only one (its own) record in isc4.gdb! New isc4.gdb will then look like this (simplified version):
  CREATE TABLE USERS2 (
    USER_NAME  VARCHAR(128),
    PASSWD     VARCHAR(32) );

  CREATE VIEW USERS AS
    SELECT *
      FROM USERS2
     WHERE USER = ''
        OR USER = 'SYSDBA'
        OR USER = USER_NAME;

  GRANT SELECT
     ON USERS
     TO PUBLIC;

  GRANT UPDATE(PASSWD, GROUP_NAME, UID, GID, FIRST_NAME, MIDDLE_NAME, LAST_NAME)
     ON USERS
     TO PUBLIC;

Real table USERS2 is visible only to SYSDBA. The condition
  USER = USER_NAME  
ensures that each user sees its own record. The condition
  USER = 'SYSDBA'  
ensures that SYSDBA can see all records. The condition
  USER = ''  
is important because USER variable contains empty string during password verification!
You can look at full script to modify standard isc4.gdb here .


How to log login-attempts

Replacing USERS table in security database by USERS view has one great advantage - it allows us to call stored procedure whenever user tries to login, i.e. whenever IB server executes command
  SELECT PASSWD
    FROM USERS
   WHERE USER_NAME=:usr;
In other words, we can have some kind of select-trigger, or login-trigger. Such procedure can then be used e.g. to refuse login during some part of day, or to log date/time when user tried to login. Note that it is not possible to distinguish whether login was successful, and that it logs only known usernames (i.e. names already stored in USERS table). But even this limited information can be useful, e.g. to see whether somebody logged at unusual time (night), or to reveal suspicious number of logins during short time. To implement this we need
  • External table, because transaction used by IB server to verify username/password is not committed, but rolled back.
      CREATE TABLE log_table
        EXTERNAL FILE 'C:Program FilesBorlandInterBaseisc4.log'
        ( tstamp TIMESTAMP,
          uname  CHAR(31) ); 
    If you want log table to be readable as text file, you can add two more fields: one CHAR(1) to separate tstamp and uname fields, one CHAR(2) to be filled with CR+LF codes by stored procedure, and use CHAR(20) instead of TIMESTAMP.
  • Stored procdure (select type, to be callable from view), that is able to return information whether user is allowed to see specific row. In the method I chose the procedure either returns a row (i.e. SUSPEND is called) to indicate success, or does not return any row (i.e. EXIT is called) to indicate that row is forbidden. Output parameter is just formal, it's value is ignored.
      CREATE PROCEDURE log_proc
        (un VARCHAR(31))
      RETURNS
        (x CHAR(1))
      AS
      BEGIN
        IF (USER='')
        THEN
          INSERT INTO log_table (TSTAMP, UNAME)
                 VALUES ( CURRENT_TIMESTAMP, :un);
    
        IF (USER='' OR USER='SYSDBA' OR USER=:un)
        THEN
          SUSPEND;
      END 
    Notice the test (USER=''); when IB server verifies password, USER variable is empty! It helps distinguish whether password is being verified by IB server, or whether user is directly connected to isc4.gdb.
  • Rename table USERS. It can be easily done by creating new table, copying existing records, and dropping original table.
  • Create view that will be used instead of original USERS table and that calls our select stored procedure.
      CREATE VIEW USERS (USER_NAME) AS
        SELECT *
          FROM users2
         WHERE EXISTS (SELECT * FROM log_proc(users2.user_name)); 
  • Grant appropriate rights, i.e.
      GRANT SELECT ON USERS TO PUBLIC;
    
      GRANT UPDATE(PASSWD, GROUP_NAME, UID, GID, FIRST_NAME, MIDDLE_NAME, LAST_NAME)
         ON USERS
         TO PUBLIC;
    
      GRANT INSERT   ON log_table           TO PROCEDURE log_proc;
      GRANT EXECUTE  ON PROCEDURE log_proc  TO PUBLIC;  
Full script is here .
Because log entires are appended to log_table, it is necessary from time to time to delete or rename external file!


How to slow down intruders

Once we are able to log who/when tried to login to database, we can use this information to further restrict access. It is possible to e.g. count number of login attempts for given username during last minute and refuse connection if this number is too high, thus effectively preventing using brute force to break into database by scanning all possible passwords. So when somebody tries to guess password by trying to login with different password combinations, it will temporarily block that username from login; for this reason time interval and allowed login count should be carefuly chosen to slow down intruder, but still do not restrict regular users too much (e.g. when somebody just make typo in password). Similar system (more sophisticated, of course) is used in OpenVMS OS. The relevant part of code in SP is as simple as this
  DECLARE VARIABLE cnt INTEGER;

  SELECT COUNT(*)
    FROM log_table
   WHERE uname=:un
     AND tstamp>CURRENT_TIMESTAMP-0.0007
    INTO :cnt;

  IF (cnt>=3) THEN EXIT;

where you can change constants 3 (allowed number of mistakes) and 0.0007 (approximately 1 minute). Full script is here. This procedure works (i.e. prevents access) for all users. One possible modification whould be to choose one user (different than SYSDBA, because it is the most endangered username) that is not restriced by that procedure, and that owns all databases (and thus has rights to shutdown the database).


Copyright © 2001 Ivan Prenosil

Back to the news section


 Last articles 
09/24/2007 IBSurgeon would like to inform you about a series of free Firebird technical seminars

09/23/2007 Firebird System Tables (Parts II+III)

09/20/2007 Firebird Maestro 7.9 released

09/19/2007 And the Winner is —

09/19/2007 Unable to access fireruby lib - with firebird 2.0.x and ror

news archive