HawkTrace Logo
Research
March 13, 2026

ibWebAdmin Unauthenticated RCE

A technical advisory for ibWebAdmin authentication bypass via session initialization and panel manipulation leading to remote code execution through command injection.

Batuhan Er• Security Researcher
6 mins read

ibWebAdmin - Unauthenticated RCE

The vulnerability starts in the exec_command function. As is well known, PHP has multiple built-in functions for executing system commands. Today, we will focus on the one that uses the exec function.


exec_command Function

function exec_command($cmd, $parameters, $stderr=FALSE) {

    $is_windows = (stristr(php_uname(), 'wind') == TRUE) ? TRUE : FALSE;

    if (($is_windows  &&  !is_file(BINPATH.$cmd.'.exe'))  &&  !is_file(BINPATH.$cmd)) {

        return array(array(), sprintf($GLOBALS['ERRORS']['BAD_BINPATH'], BINPATH.$cmd));
    }

    $fcmd = $cmd . $parameters . (($stderr  &&  !$is_windows) ? ' 2>&1' : '');


    if (DEBUG_COMMANDS === TRUE) {
        $GLOBALS['externcmd'] .= ($GLOBALS['externcmd'] != '') ? '<br>'.BINPATH.$fcmd : BINPATH.$fcmd;
    }

    $err = '';
    $out = array();
    $olddir = getcwd();
    if (!chdir(BINPATH)) {
        $err = $GLOBALS['WARNINGS']['CAN_NOT_ACCESS_DIR'];
    }
    else {
        $path_prefix = ($is_windows) ? '' : './';

        exec($path_prefix.$fcmd, $out, $retval);

        if ($retval != 0  && $retval != 1) {
            $err = BINPATH.$cmd.' returned error code '.$retval;
        }
        chdir($olddir);
    }

    return array($out, $err);
}

The exec_command function takes three external parameters: 1. cmd 2. parameters 3. stderr. The general purpose of this function is to first identify the system whether the script is running on Linux or Windows then concatenate the incoming data with pre-configured values such as BINPATH, and after a few processing steps, pass the result to the exec function.


Trace exec_command

line 19 - admin.php
line 158 - admin.php
line 169 - admin.php
line 189 - admin.php

It is used in many places, but it is particularly heavily used in the admin.php file.


admin.php

The general purpose of the admin.php file is to take user-supplied data and place it into specific locations. The first check in admin.php is the have_panel_permissions function.

function have_panel_permissions($user, $pname) {

    $is_open = FALSE;
    foreach (panel_array_names() as $paname) {
        foreach ($GLOBALS[$paname] as $idx => $panel) {
            if (in_array($pname, $panel)  && $panel[2] == 'open') {
                $is_open = TRUE;
                break 2;
            }
        }
    }
    if (!$is_open) {
        return FALSE;
    }

    if (in_array($pname, $GLOBALS['HIDE_PANELS'])
    &&  ($user != 'SYSDBA'  || SYSDBA_GET_ALL == FALSE)) {

        return FALSE;
    }

    return TRUE;
}

function panel_array_names() {

    $panel_arrays = array('s_database_panels',
                          's_tables_panels',
                          's_accessories_panels',
                          's_sql_panels',
                          's_data_panels',
                          's_users_panels',
                          's_admin_panels');
    return $panel_arrays;
}

The have_panel_permissions function assigns the data defined in the panel_array_names function to a global variable and checks whether it is open or closed. Now we need to look at how we can supply these variables externally.


toggle_fold_panel

toggle_fold_panel generally includes two PHP files and takes three external parameters via the GET method: 1. p 2. d 3. a

toggle_fold_panel.php - line 38
$pvar = 's_'.strtolower($HTTP_GET_VARS['a']).'_panels';

Does this code look familiar? :) We will be able to generate the values that were previously hardcoded in panel_array_names. This will be accomplished through the globalize_session_vars function in the session.inc.php file.


session.inc.php

function globalize_session_vars() {
    global $HTTP_SESSION_VARS;

    $session_var_names =
        array('s_init',
              's_cookies',
              ...
              's_adm_shut_force',
              's_adm_shut_reconnect',
              's_adm_command',
              's_backup',
              's_restore',
              's_csv',
              's_POST',
              's_GET',
              's_database_panels',
              's_tables_panels',
              's_accessories_panels',
              's_sql_panels',
              's_data_panels',
              's_users_panels',
              's_admin_panels'
              );

    foreach ($session_var_names as $sname) {
        if (isset($GLOBALS[$sname])) {
            $HTTP_SESSION_VARS[$sname] = $GLOBALS[$sname];
        } else {
            unset($HTTP_SESSION_VARS[$sname]);
        }
    }
}

The globalize_session_vars function is located in the session.inc.php file and is responsible for assigning values to global variables.


Obtaining a Session

Now let's look at how we proceed toward RCE we already have many of the pieces. First, we need a session, so we will go to the database.php file. At first glance, it is immediately visible that a script_start.inc.php file is included.

script_start.inc.php

if (!isset($HTTP_SESSION_VARS['s_init'])
||  ($HTTP_SESSION_VARS['s_cookies'] === 'untested')) {
    if (!in_array('interbase', get_loaded_extensions())) {

        die($ERRORS['NO_IBASE_MODULE']);
    }

    $ver = phpversion();
    if ($ver[0] == 5  &&
        ini_get('register_long_arrays') == 0) {

        die('You have to change your php-configuration and set register_long_arrays=On to use ibWebAdmin with php5!');
    }
    initialize_session();
    fallback_session();
}

The script_start.inc.php file performs certain PHP-related checks and then verifies whether s_init exists. If it does not, it calls the initialize_session function.


initialize_session

function initialize_session() {
    global $HTTP_SESSION_VARS, $HTTP_COOKIE_VARS, $ptitle_strings, $adm_strings;

    $useragent = guess_useragent();

    $session_vars =
        array('s_init' => TRUE,                           // indicates that the session is already initialized
              's_cookies' => 'untested',
              's_stylesheet_etag' => '',
              's_connected' => FALSE,                     // TRUE if successfilly connected toa database
              's_binpath' => FALSE,                       // becomes TRUE if isql was found in BINPATH
              's_tab_menu' => check_gd_ttf_png(),         // becomes TRUE if TabMenu.class is possible
              's_useragent' => $useragent,                // see comments at function guess_useragent()
              's_referer' => '',                          // replacement for $_SERVER['HTTP_REFERER']
              's_use_jsrs' => FALSE,

              's_cust' => get_customize_defaults($useragent), // user specific customization values

              's_login' => array('database' => DEFAULT_PATH.DEFAULT_DB,    // set by the db_login panel
                                 'user'     => DEFAULT_USER,
                                 'host'     => DEFAULT_HOST,
                                 'password' => '',
                                 'role'     => DEFAULT_ROLE,
                                 'cache'    => DEFAULT_CACHE,
                                 'charset'  => DEFAULT_CHARSET,
                                 'dialect'  => DEFAULT_DIALECT,
                                 'server'   => DEFAULT_SERVER),

             ...

              's_systable' => array('table'   => '',      // show this table on the System Tables panel
                                    'order'   => '',      // order the system table by this column
                                    'dir'     => 'ASC',   // order direction for the system table, 'ASC' or 'DESC'
                                    'ffield'  => '',      // filter field
                                    'fvalue'  => '',      // filter value
                                    'sysdata' => TRUE,    // show system data in the system tables if TRUE
                                    'refresh' => 15),
              's_system_table' => '',

The important part here is the s_login function which sets DEFAULT_USER. DEFAULT_USER is defined as SYSDBA in the configuration.inc.php file.


Exploitation Chain

Now we combine all the findings to perform an authentication bypass, followed by the RCE stage. The first request goes to the database.php file to obtain a valid session. The second request goes to toggle_fold_panel.php to set adm_gfix to open. Here is what we need to do let's go back to session.inc.php:

At line 317, s_admin_panels is defined:

              // panels on the Admin page
              's_admin_panels' => array(array('info',      $ptitle_strings['info'],'open'), // [0]
                          array('adm_server',$ptitle_strings['adm_server'],'close'),		// [1]
                          array('adm_dbstat',$ptitle_strings['adm_dbstat'],'close'),		// [2]
                          array('adm_gfix',  $ptitle_strings['adm_gfix'],  'close'),		// [3]
                          array('adm_backup',$ptitle_strings['adm_backup'],'close'),
                          array('adm_restore',$ptitle_strings['adm_restore'],'close'))

In PHP, arrays are zero-indexed, so: toggle_fold_panel.php?a=admin&p=3&d=open

Where a = $pvar = 's_'(externally supplied GET value)'_panels';

Let's go back to admin.php. We set the adm_gfix_buffers and adm_buffers values externally. Finally, the exec_command function at line 158 of admin.php is triggered.


PoC

IbWebAdmin Unauth RCE


Conclusion

I found this chain during a red team engagement we were running at Red Team. What started as poking around ibWebAdmin's source ended up being a full auth bypass to RCE no credentials needed, straight to command execution on the box.

This is the kind of stuff we do at HawkTrace we dig into source code, trace the data flows manually, and find attack paths that scanners will never catch. If you're curious about what an actual attacker would find in your environment, hit us up.


Stay Protected

Security vulnerabilities are discovered constantly. HawkTrace helps organizations stay ahead of threats through comprehensive security assessments, APT simulations, and continuous threat hunting.

Need expert security consultation? Contact us or explore more research.