web: fix various vulnerabilities

- Send all cookies as HttpOnly (don't let Javascript see them)
- If page sending cookie is HTTPS, make the cookie secure
- Often we have something like:
        $name = get_str('name');
        if (!lookup($name)) {
            error_page("can't find $name");
        }
    Can't do this; it can be exploited for XSS attacks.
    Just say 'Can't find file' or whatever
- Don't show database error messages
This commit is contained in:
David Anderson 2024-12-19 17:55:43 -08:00
parent 57e0bdf3a7
commit c2defb6df6
12 changed files with 43 additions and 21 deletions

View File

@ -48,7 +48,9 @@ function consent_to_a_policy(
function check_user_consent($user, $consent_name) {
list($checkct, $ctid) = check_consent_type($consent_name);
if ($checkct) {
$consent_result = BoincLatestConsent::lookup("userid={$user->id} AND consent_type_id=$ctid AND consent_flag=1");
$consent_result = BoincLatestConsent::lookup(
"userid=$user->id AND consent_type_id=$ctid AND consent_flag=1"
);
if ($consent_result) {
return TRUE;
}
@ -64,7 +66,8 @@ function check_user_consent($user, $consent_name) {
// If the boolean is FALSE, the integer returned is -1.
//
function check_consent_type($name, $checkenabled=TRUE) {
$ct = BoincConsentType::lookup("shortname = '{$name}'");
$name = BoincDb::escape_string($name);
$ct = BoincConsentType::lookup("shortname = '$name'");
if ($ct and ( !$checkenabled or ($ct->enabled)) ) {
return array(TRUE, $ct->id);
}

View File

@ -32,13 +32,13 @@ function check_venue($x) {
if ($x == "home") return;
if ($x == "work") return;
if ($x == "school") return;
error_page(tra("bad venue: %1", $x));
error_page("bad venue");
}
function check_subset($x) {
if ($x == "global") return;
if ($x == "project") return;
error_page(tra("bad subset: %1", $x));
error_page("bad subset");
}
abstract class PREF {
@ -281,7 +281,7 @@ class PREF_CONSENT extends PREF {
$user, $consent_type_id, $flag, 0, 'Webform', time()
);
if (!$rc) {
error_page(tra("Database error:").BoincDb::error());
error_page("Database error");
}
}
}
@ -300,7 +300,7 @@ class PREF_CONSENT extends PREF {
$user, $consent_type_id, $this->default, 0, 'Webform'
);
if (!$rc) {
error_page(tra("Database error:").BoincDb::error());
error_page("Database error");
}
}

View File

@ -211,7 +211,7 @@ function validate_post_make_user() {
$team = BoincTeam::lookup_id($teamid);
$clone_user = BoincUser::lookup_id($team->userid);
if (!$clone_user) {
error_page("User $userid not found");
error_page("User $team->userid not found");
}
$project_prefs = $clone_user->project_prefs;
} else {

View File

@ -166,7 +166,11 @@ function send_cookie($name, $value, $permanent, $ops=false) {
$path .= "_ops/";
}
$expire = $permanent?time()+3600*24*365:0;
setcookie($name, $value, $expire, $path);
setcookie($name, $value, $expire, $path,
'',
is_https(), // if this page is secure, make cookie secure
true // httponly; no JS access
);
}
function clear_cookie($name, $ops=false) {
@ -887,10 +891,7 @@ function strip_bbcode($string){
}
function current_url() {
$url = "http";
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") {
$url .= "s";
}
$url = is_https()?'https':'http';
$url .= "://";
$url .= $_SERVER['SERVER_NAME'];
$url .= ":".$_SERVER['SERVER_PORT'];
@ -1107,7 +1108,7 @@ function do_download($path) {
function redirect_to_secure_url() {
if (defined('SECURE_URL_BASE')
&& strstr(SECURE_URL_BASE, "https://")
&& empty($_SERVER['HTTPS'])
&& !is_https()
) {
Header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
exit;

View File

@ -200,6 +200,7 @@ function dtime() {
// is $x a valid file (or dir) name?
//
function is_valid_filename($x) {
if (htmlspecialchars($x) != $x) return false;
if (strstr($x, '/')) return false;
return true;
}

View File

@ -16,6 +16,8 @@
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// Handler for RPC to change the venue of a host
require_once("../inc/boinc_db.inc");
require_once("../inc/xml.inc");

View File

@ -432,7 +432,7 @@ case 'view_file':
case null:
app_list(); break;
default:
error_page("unknown action $action");
error_page("unknown action");
}
?>

View File

@ -208,6 +208,6 @@ case "batches_form":
case "batches_action":
batches_action($app); break;
default:
error_page("unknown action $action");
error_page("unknown action");
}
?>

View File

@ -208,7 +208,7 @@ case 'edit_form':
case 'edit_action':
handle_edit_action(); break;
default:
error_page("unknown action: $action");
error_page("unknown action");
}
?>

View File

@ -88,7 +88,7 @@ function list_files($user) {
$dir = sandbox_dir($user);
if (!is_dir($dir)) error_page("Can't open sandbox directory");
page_head("File sandbox");
$notice = get_str('notice', true);
$notice = htmlspecialchars(get_str('notice', true));
if ($notice) {
echo "<p>$notice<hr>";
}
@ -197,6 +197,9 @@ function upload_file($user) {
function add_file($user) {
$dir = sandbox_dir($user);
$name = post_str('name');
if (!is_valid_filename($name)) {
error_page('bad filename');
}
if (!$name) error_page('No name given');
if (file_exists("$dir/$name")) {
error_page("file $name exists");
@ -215,6 +218,9 @@ function add_file($user) {
function get_file($user) {
$dir = sandbox_dir($user);
$url = post_str('url');
if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) {
error_page('Not a valid URL');
}
$fname = basename($url);
$path = "$dir/$fname";
if (file_exists($path)) {
@ -229,6 +235,9 @@ function get_file($user) {
//
function delete_file($user) {
$name = get_str('name');
if (!is_valid_filename($name)) {
error_page('bad filename');
}
$dir = sandbox_dir($user);
unlink("$dir/$name");
unlink("$dir/.md5/$name");
@ -238,16 +247,22 @@ function delete_file($user) {
function download_file($user) {
$name = get_str('name');
if (!is_valid_filename($name)) {
error_page('bad filename');
}
$dir = sandbox_dir($user);
do_download("$dir/$name");
}
function view_file($user) {
$name = get_str('name');
if (!is_valid_filename($name)) {
error_page('bad filename');
}
$dir = sandbox_dir($user);
$path = "$dir/$name";
if (!is_file($path)) {
error_path("no such file $name");
error_page("no such file");
}
echo "<pre>\n";
readfile($path);
@ -269,7 +284,7 @@ case 'delete_file': delete_file($user); break;
case 'download_file': download_file($user); break;
case 'view_file': view_file($user); break;
case 'add_form': add_form($user); break;
default: error_page("no such action: $action");
default: error_page("no such action: ".htmlspecialchars($action));
}
?>

View File

@ -205,7 +205,7 @@ if ($cmd == 'manage') {
require_founder_login($user, $team);
remove($team);
} else if ($cmd != "") {
error_page("unknown command $cmd");
error_page("unknown command ".htmlspecialchars($cmd));
} else {
show_forum($team);
}

View File

@ -145,7 +145,7 @@ case "decline":
}
break;
default:
error_page(tra("undefined action %1", $action));
error_page("undefined action ".htmlspecialchars($action));
}
echo "<a href='team_display.php?teamid=$team->id'>".tra("Return to team page")."</a>";