1. 程式人生 > >hydra掃描不出oracle中sys使用者的弱密碼

hydra掃描不出oracle中sys使用者的弱密碼

sys使用者需要以sysdba身份登入

我們知道,oracle資料庫的使用者是分許可權的,其中sys使用者許可權最高,在登入時需要以sysdba的身份才可以成功登陸,否則會報錯:ORA-28009: connection as SYS should be as SYSDBA or SYSOPER.(如圖)
在這裡插入圖片描述

hydra登入oracle的程式碼

hydra登入oracle的程式碼在原始檔hydra-oracle.c中的start_oracle函式中,使用的是OCI介面,登入時呼叫的介面是OCILogon,如圖。
在這裡插入圖片描述

OCILogon介面原型

查詢OCI官方文件,得知OCILogon介面原型如下:

sword OCILogon ( 
OCIEnv          *envhp,    //環境控制代碼
OCIError        *errhp,   //錯誤控制代碼
OCISvcCtx       **svchp,  //服務上下文控制代碼
CONST text      *username,   //使用者名稱
ub4             uname_len,  //使用者名稱長度
CONST text      *password,   //密碼
ub4             passwd_len,   //密碼長度
CONST text      *dbname,   //資料庫名
ub4             dbname_len   //資料庫名長度
); sword OCILogoff ( OCISvcCtx *svchp, //服務上下文控制代碼 OCIError *errhp //錯誤控制代碼 );

可以看出,OCILogon介面中並不存在指定使用者角色的引數,所以當呼叫此函式以sys使用者登入時,就會報許可權不足的錯誤。

使用其他介面替代OCILogon

既然問題出在OCILogon沒有指定使用者身份的引數,那麼我們找個有指定身份引數的介面去代替。查詢OCI官方文件可知,OCISessionBegin符合要求(如圖)。這個介面是為某使用者開始一個會話,既然能開始會話,當然也就表明該使用者登入成功了。
在這裡插入圖片描述

hydra-oracle.c原始碼修正

經過上述討論,決定改用OCISessionBegin介面來代替OCILogon介面。在呼叫時對sysdba類使用者做判斷(這裡預設只處理sys使用者),如圖:
在這裡插入圖片描述

修正後的hydra-oracle.c在:

關於OCILogon和OCISessionBegin的介面測試程式碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oci.h>

/*user name and password*/
#if 1
static text* username=(text *)"sys";
static text* password=(text *)"oracle11g";
#else
static text* username=(text *)"system";
static text* password=(text *)"oracle11g";
#endif

static text* oracle=(text *)"//172.16.7.30:1521/ORCL";


/*handle define*/
static OCIEnv           *p_env;                                        //OCI environment handle
static OCIError         *p_err;                                        //OCI error handle
static OCISvcCtx        *p_svc;                                        //OCI service context handel
static OCIServer        *p_ser;                                        //OCI server handle
static OCISession       *p_usr;                                        //OCI user session handle
static OCIStmt          *p_sql;                                        //OCI statement handle
static OCIDefine        *p_dfn = (OCIDefine *)NULL;                    //OCI define handle
static OCIBind          *p_bnd = (OCIBind *)NULL;                      //OCI bind handle

text o_errormsg[512];
sb4 o_errorcode;

/*create OCI environment*/
int create_env()
{
  int swResult;            //Return value
  if(swResult = OCIEnvCreate(&p_env,OCI_DEFAULT,NULL,NULL,NULL,NULL,0,NULL)) {
    printf("environment create error!\n\n");
    return -1;
  } else {
    printf("environment create success!\n\n");
    return 0;
  }
}

/*init handle*/
int init_handle()
{
  int swResult;
  if(swResult = OCIHandleAlloc(p_env,(dvoid *)&p_ser,OCI_HTYPE_SERVER,0,NULL)) {  //伺服器控制代碼
    printf("init server handle error!\n\n");
    return -1;
  } else {
    printf("init server handle success!\n\n");
  }

  if(swResult = OCIHandleAlloc(p_env,(dvoid *)&p_err,OCI_HTYPE_ERROR,0,NULL)) {  //錯誤控制代碼
    printf("init error handle error!\n\n");
    return -1;
  } else {
    printf("init error handle success!\n\n");
  }
  if(swResult = OCIHandleAlloc(p_env,(dvoid *)&p_usr,OCI_HTYPE_SESSION,0,NULL)) {  //事務控制代碼
    printf("init session handle error!\n\n");
    return -1;
  } else {
    printf("init session handle success!\n\n");
  }
  if(swResult = OCIHandleAlloc(p_env,(dvoid *)&p_svc,OCI_HTYPE_SVCCTX,0,NULL)) {  //上下文控制代碼
    printf("init service context handle error!\n\n");
    return -1;
  } else {
    printf("init service context handle success!\n\n");
  }
  if(swResult = OCIHandleAlloc(p_env,(dvoid *)&p_sql,OCI_HTYPE_STMT,0,NULL)) {      //SQL語句控制代碼
    printf("init statement handle error!\n\n");
    return -1;
  } else {
    printf("init statement handle success!\n\n");
  }
  return 0;
}

/*connect server*/
int conn_server()
{
  int swResult;
  if(swResult = OCILogon(p_env,p_err,&p_svc,(text *)username,strlen(username),(text *)password,strlen(password),(text *)oracle,strlen(oracle))) {
    printf("connect error!\n\n");

    OCIErrorGet(p_err, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR);
    printf("error: %s\n", o_errormsg);

    return -1;
  } else
    printf("connect success!\n\n");
  return 0;
}

int begin_session()
{
  int swResult;
  
  swResult = OCIServerAttach(p_ser, p_err, (text *)oracle, strlen(oracle), OCI_DEFAULT);
  if (swResult != OCI_SUCCESS )
  {
    printf("attach server failed!\n");
    OCIErrorGet(p_err, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR);
    printf("error: %s\n", o_errormsg);    
    return -1;  	
  }
  	
	swResult = OCIAttrSet((dvoid *)p_svc, (ub4)OCI_HTYPE_SVCCTX, (dvoid *)p_ser, (ub4)0, (ub4)OCI_ATTR_SERVER, (OCIError *)p_err);
  if (swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO) {
    printf("set service attr failed!\n");
    return -1;
  }
  	  
  swResult = OCIAttrSet((dvoid*)p_usr, (ub4)OCI_HTYPE_SESSION, (dvoid*)username, (ub4)strlen(username), OCI_ATTR_USERNAME, p_err);
  if (swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO) {
    printf("set username attr failed!\n");
    return -1;
  }
  
  swResult = OCIAttrSet((dvoid*)p_usr, (ub4)OCI_HTYPE_SESSION, (dvoid*)password, (ub4)strlen(password), OCI_ATTR_PASSWORD, p_err);
  if (swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO) {
    printf("set password attr failed!\n");
    return -1;
  }
  
  swResult = OCISessionBegin(p_svc, p_err, p_usr, OCI_CRED_RDBMS, OCI_SYSDBA);
  if (swResult != OCI_SUCCESS) {
    printf("begin_session failed!\n");
    OCIErrorGet(p_err, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR);
    printf("error: %s\n", o_errormsg);
    return -1;
  } else {
    printf("begin session success!\n\n");
  }
  
  return 0;
}


/*SQL statements*/
int oci_exec()
{
  int swResult;
  //準備SQL語句
  if(swResult = OCIStmtPrepare(p_sql,p_err,SQL,strlen(SQL),OCI_NTV_SYNTAX,OCI_DEFAULT)) {
    printf("prepare SQL statements error!\n\n");
  } else {
    printf("prepare SQL statements success!\n\n");
  }

  //設定繫結變數
  int getId ;
  char getName[10];

  OCIBind     *p_bndp1 = NULL;
  OCIBind     *p_bndp2 = NULL;

  printf("輸入ID,NAME:\n");
  scanf("%d %s",&getId,getName);

  if(swResult = OCIBindByPos(p_sql,&p_bndp1,p_err,1,(dvoid *)&getId,(sb4)sizeof(getId),SQLT_INT,NULL,NULL,NULL,0,NULL,OCI_DEFAULT)) {
    printf("Bind p1 error!\n\n");
    return -1;
  } else {
    printf("bind success!\n\n");
  }

  if(swResult = OCIBindByPos(p_sql,&p_bndp2,p_err,2,&getName,(sb4)sizeof(getName),SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) {
    printf("Bind p2 error!\n\n");
    return -1;
  } else {
    printf("bind success!\n\n");
  }


  //執行SQL statements
  if(swResult = OCIStmtExecute(p_svc,p_sql,p_err,1,0,NULL,NULL,OCI_DEFAULT)) {
    printf("execute SQL statement error!\n\n");
    return -1;
  } else {
    printf("execute SQL statement success!\n\n");
  }
  return 0;
}


/*quit server*/
void quit_server()
{
  OCILogoff(p_svc,p_err);
  printf("Quit success!\n");
}

/*free handle*/
void free_handle()
{
  OCIHandleFree(p_ser,OCI_HTYPE_SERVER);            //釋放伺服器控制代碼
  OCIHandleFree(p_err,OCI_HTYPE_ERROR);            //釋放錯誤控制代碼
  OCIHandleFree(p_usr,OCI_HTYPE_SESSION);        //釋放事務控制代碼
  OCIHandleFree(p_svc,OCI_HTYPE_SVCCTX);            //釋放上下文控制代碼
  OCIHandleFree(p_sql,OCI_HTYPE_STMT);            //釋放SQL語句控制代碼
}

int main()
{
  if(create_env() == -1)                //建立環境
    return -1;
  if(init_handle() == -1)                //初始化控制代碼
    return -1;
#if 0
  if(conn_server() == -1)                //連線資料庫
    return -1;
#else
  if (begin_session() == -1)
    return -1;
#endif

#if 0
  if(oci_exec() == -1)
    return -1;
#endif
  quit_server();                            //退出資料庫
  free_handle();                            //釋放控制代碼
  return 0;
}

總結

本文使用的hydra版本是V8.5,對掃不出oracle中sysdba類使用者密碼的問題進行了分析,最後給出瞭解決方法。