Checking user privileges before executing functions - php

This is more of a concept question. I would like to get an advice from very experienced members on how to better arrange my code. Often when handling user's requests we need to check their privileges in order to determine their rights to execute some function or method. The question is whether it is better to verify access rights prior to executing a function like so:
//handling some POST data from AJAX
//lets assume we have some function check_some_rights() which takes user id as argument and returns 1 if user has some right or 0 if he/she doesnt
if (check_some_rights($user)){ //the privileges are verified
some_function_that_does_some_stuff()
} else {//nope, this user got no right to do this
echo "Like hell you do!";//denying access to this user
}
Or is it better to check access rights as soon as execution of function is initiated like so:
//alternative solution with embedded privilege check
function some_function_that_does_some_stuff($user){
if (check_some_rights($user)){//the privileges are verified
//go on with the procedure
// ...
} else {
echo "Like hell you do!";//denying access to this user
}
}
I personally believe that the second approach would be better, because we wouldn't have to worry remembering to check privileges each time, but opinions of people with more experience are needed and would be highly appreciated. Thank you.

Related

PHP Save new item to Switch Statement

I am currently working on a Banlist for my game, and it is currently functional, but I want to know if there is a way to use post ex: http://example.com/banlist?newentry=SAVETHIS
and save into a new case in the switch statement.
Basically, I want to store the "SAVETHIS" after the newentry into a brand new case.
Here's an image to help you understand what I mean.
You need some type of storage instead of writing a code that writes itself.
if(isset($_GET['newentry'])){
if(file_put_contents('./banlist.txt', $_GET['newentry'] . PHP_EOL, FILE_APPEND) === false){
die('no perms, cant create file in '.getcwd());
} else {
die('user banned');
}
} elseif(isset($_GET['id'])){
if(in_array($_GET['id'], explode(PHP_EOL, file_get_contents('./banlist.txt')))){
die('user is banned');
}
}
See this as an EXAMPLE code, preferred is to use a database and put this code behind a login wall of some sorts as it has NO SECURITY checks.
In its current state, if I know the location of this script I can simply create a loop and ban every user in range of 0 to MAX_INT. Also it does not check if the user is already banned, so I can fill up your hard drive by looping a simple script to infinity. Noor does it check for potential XXS attacks.

Agiletoolkit Maximum number of failed login attempts

The agiletoolkit Auth/basic class allow to try to login without any limitation.
And i'm searching a way to limit the number of failed login attempt, i've tried to override some methods of this class but it use ajax reloading so php code is not executed correctly.
Any suggestion is welcome.
Many Thanks,
Inspired by StackOverflow I have implemented the following protection:
for each user we store soft / hard lock. Hard lock would refuse to verify password even if it's correct.
soft lock is a period of time after which we will reset "unsuccessful attempt" counter.
every time you type incorrect password both soft and hard lock increase making you wait longer (but not forever)
gradual increase puts a reasonable limit so if your attacker tries to hack your account for a hour - he will only get several attempts in, yet your account will be OK to log-in after few hours.
I have implemented this in one of my projects, although it's not a controller, but a built-in code. Please look through comments and I hope this will help you and others:
In User model add:
$this->addField('pwd_locked_until');
$this->addField('pwd_failure_count');
$this->addField('pwd_soft_unlock');
You'll also need two methods:
/* Must be called when user unsuccessfully tried to log-in */
function passwordIncorrect(){
$su=strtotime($this['pwd_soft_unlock']);
if($su && $su>time()){
// aw, they repeatedly typed password in, lets teach them power of two!
$this['pwd_failure_count']=$this['pwd_failure_count']+1;
if($this['pwd_failure_count']>3){
$this['pwd_locked_until']=date('Y-m-d H:i:s',time()
+pow(2,min($this['pwd_failure_count'],20)));
$this['pwd_soft_unlock']=date('Y-m-d H:i:s',time()
+max(2*pow(2,min($this['pwd_failure_count'],20)),60*5));
}
}else{
$this['pwd_failure_count']=1;
$this['pwd_soft_unlock']=date('Y-m-d H:i:s',time() +60*5);
}
$this->save();
}
and
/* Must be called when user logs in successfully */
function loginSuccessful(){
$this['last_seen']=date('Y-m-d H:i:s');
$this['pwd_soft_unlock']=null;
$this->save();
}
Finally - you can use this as a login form:
class Form_Login extends Form {
function init(){
parent::init();
$form=$this;
$form->setModel('User',array('email','password'));
$form->addSubmit('Login');
if($form->isSubmitted()){
$auth=$this->api->auth;
$l=$form->get('email');
$p=$form->get('password');
// check to see if user with such email exist
$u=$this->add('Model_User');
$u->tryLoadBy('email',$form->get('email'));
// user may have also typed his username
if(!$u->loaded()){
$u->tryLoadBy('user_name',$form->get('email'));
}
// incorrect email - but say that password is wrong
if(!$u->loaded())$form->getElement('password')
->displayFieldError('Incorrect Login');
// if login is locked, don't verify password at all
$su=strtotime($u['pwd_locked_until']);
if($su>time()){
$form->getElement('password')
->displayFieldError('Account is locked for '.
$this->add('Controller_Fancy')
->fancy_datetime($u['pwd_locked_until']));
}
// check account
if($auth->verifyCredentials($u['email'],$p)){
// resets incorrect login statistics
$u->loginSuccessful();
$auth->login($l);
// redirect user
$form->js()->univ()->location($this->api->url('/'))->execute();
}else{
// incorrect password, register failed attempt
$u->passwordIncorrect();
$form->getElement('password')->displayFieldError('Incorrect Login');
}
}
}
}
This should be converted into add-on by someone.
I think you may store numbers of usage of Model_User (usually used in Auth) in session or cookies using afterLoad hook and then check it where you need to.
Oops. FAILED login. So you model is NOT loaded.
You need just to count clicks on a button of a login form and store it somewhere (cookies, database). So create your own login form and add some condition when a form is submitted like:
$m = $this->add('Model_User');
$f = $this->add("Form");
$f->setModel($m, array('email', 'password'));
$f->addSubmit("Log In");
if ($f->isSubmitted()){
//Limmiting
if($_COOKIE[$this->api->name."_count_failed_login"] >= 5/*Here's you limit number*/){
/*redirect or something else*/
}
if (/*here should be you condition*/){
$_COOKIE[$this->api->name."_count_failed_login"] = 0;
$this->api->auth->login($f->get("email"));
$f->js()->univ()->redirect("index")->execute();
}else{
/* when login is failed*/
if($_COOKIE[$this->api->name."_count_failed_login"]){
$_COOKIE[$this->api->name."_count_failed_login"]++;
}else{
$_COOKIE[$this->api->name."_count_failed_login"] = 1;
}
$this->js()->univ()->alert('Wrong username or password')->execute();
}
}
I didn't check it. Maybe some adjastements are needed.
Just an idea.
Hope that helps.

PHP User Authentication with Sessions

So my question is very basic.
When checking if a user is still logged in on any page, I'll use
if (isset($_SESSION['user']) && $_SESSION['user'] == true) { CODE }
But, shouldn't I use a hashed value instead of a boolean value for the $_SESSION['user']?
All the guides I find are using boolean values, but from my point of view that is a security leak, isn't it? People are talking about Session-Hjacking and Session-Fixation all the time, and that would be very easy if I just used boolean values for the user-session, woulnd't it? Or am I just mixing things up here?
Thank you
I read two questions here. The first question, 'What is the best practice to determine if a user is logged in?" and the second question 'Is there a concern of Session-Hjacking and Session-Fixation?'
First question:
Most web apps/cms I have worked with have a user object. There is nothing particular special about this object from a code perspective, its just an object representing the user. The currently logged in user has their user object stored in the session. $_SESSION['user']
In Drupal (and other platforms) the a function is used to return the currently logged in user, or False if the user is not logged in.
Example:
function user(){
if( isset($_SESSION['user') and
is_object($_SESSION['user'] and
get_class($_SESSION['user']=='myUserClass')) ){
return $_SESSION['user'];
}else{
return False;
}
}
So in your example we see if ( user() ) { CODE } works because all object evaluate as True in an if clause.
Second Question: Session-Hjacking and Session-Fixation are not really concerns here. The client (a web browser) does not have access to the server's $_SESSION array. So in short, yes you are mixing things up here.

Stop if invalid user input

I want to check/filter user input. If, for example, the user chosen value does not match what we have on the db, I want the script/query to stop--obviously for security reasons.
Which is correct?
if (!floatval($esc_size || $esc_sizeid) )
{
echo "Invalid Size </br>";
$thread_id = mysqli_thread_id($con);
/* Kill connection */
mysqli_kill($link, $thread_id);
mysqli_close($link);
}
or just simply
exit;
or is there a better, more secure way?
Thanks,
Jen
exit() will stop the script completely. PHP runs server-side and you are in complete control of what code is executed. For that reason, security is not an issue here.
From a user interface perspective, it is much better to put any updates to the db etc. in an if statement that only runs if the user input was valid and if it was not, display a friendly message to the user about what he/she did wrong.

vBulletin as login for entire website (edit: a certain amount of progress has been made)

I've come up against a bit of a brick wall in the vBul forums on how to do this, so I thought I'd ask the forum that's never let me down.
Does anyone know of a simple way, on an EXTERNAL page to the forum, to take in whether the user is logged in, and possibly extract their user ID while it's at it? I've seen a few plug ins with that intension but all seem to have fallen out of support, and vBul 4.1 seems to have "broken" them as a result.
Any and all help appreciated. Once I have those too things I can write scripts myself that work with the database. I just need those two variables :)
I've made SOME progress anyway. On the alternate pages the following code seems to link into vBuls user manager:
<? ini_set('display_errors', 1);
error_reporting(E_ALL); ?>
<? chdir("/home/sites/<sitename>/public_html/forum/");
require("./global.php"); ?>
<? echo "Your vBul user id is: ".$vbulletin->userinfo['userid']." and your username is ".$vbulletin->userinfo['username'].""; ?>
<? chdir("/home/sites/<sitename>/public_html/dev"); ?>
I say its connecting in ok because it returns "Your vBul user id is: 0 and your username is Unregistered" where as if it wasn't it would return to blank spaces. The problem is its returning 0 and unregistered despite my definitely being logged in on the forums.
Any suggestions?
Just realised no one ever answer this, so here is my own solution:
#grab global.php to access vbuls user systems
chdir("../forum/");
require("./global.php");
require_once('includes/functions_login.php');
#sanatize all variables for easier use
$username = $vbulletin->userinfo['username'];
$userid = $vbulletin->userinfo['userid'];
$loggouthash = $vbulletin->userinfo['logouthash'];
chdir("../dev/");
This sorts it nicely, I know I dont NEED to sanatize the variables like that, but its a personal preference.

Categories