#StackBounty: #php #cron #docker #alpine crond: can't set groups: Operation not permitted

Bounty: 50

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It’s run every minute allowing other scheduled work to be completed within the application itself. There’s nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it’s a Docker container.

cron is run in a container with the command crond -f -d 8. Here’s the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd 
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip 

        # needed for spatie/laravel-backup
        mysql-client 

        # needed for gd
        libpng-dev libjpeg-turbo-dev 

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd 

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I’ve ruled out that php artisan schedule:run is the cause since I can run it manually and everything’s fine. This means it’s something within cron.

What is cron doing under the covers that could cause this error?


Get this bounty!!!

#StackBounty: #php #cron #docker #alpine crond: can't set groups: Operation not permitted

Bounty: 50

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It’s run every minute allowing other scheduled work to be completed within the application itself. There’s nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it’s a Docker container.

cron is run in a container with the command crond -f -d 8. Here’s the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd 
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip 

        # needed for spatie/laravel-backup
        mysql-client 

        # needed for gd
        libpng-dev libjpeg-turbo-dev 

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd 

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I’ve ruled out that php artisan schedule:run is the cause since I can run it manually and everything’s fine. This means it’s something within cron.

What is cron doing under the covers that could cause this error?


Get this bounty!!!

#StackBounty: #php #cron #docker #alpine crond: can't set groups: Operation not permitted

Bounty: 50

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It’s run every minute allowing other scheduled work to be completed within the application itself. There’s nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it’s a Docker container.

cron is run in a container with the command crond -f -d 8. Here’s the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd 
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip 

        # needed for spatie/laravel-backup
        mysql-client 

        # needed for gd
        libpng-dev libjpeg-turbo-dev 

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd 

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I’ve ruled out that php artisan schedule:run is the cause since I can run it manually and everything’s fine. This means it’s something within cron.

What is cron doing under the covers that could cause this error?


Get this bounty!!!

#StackBounty: #php #cron #docker #alpine crond: can't set groups: Operation not permitted

Bounty: 50

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It’s run every minute allowing other scheduled work to be completed within the application itself. There’s nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it’s a Docker container.

cron is run in a container with the command crond -f -d 8. Here’s the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd 
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip 

        # needed for spatie/laravel-backup
        mysql-client 

        # needed for gd
        libpng-dev libjpeg-turbo-dev 

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd 

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I’ve ruled out that php artisan schedule:run is the cause since I can run it manually and everything’s fine. This means it’s something within cron.

What is cron doing under the covers that could cause this error?


Get this bounty!!!

#StackBounty: #php #cron #docker #alpine crond: can't set groups: Operation not permitted

Bounty: 50

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It’s run every minute allowing other scheduled work to be completed within the application itself. There’s nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it’s a Docker container.

cron is run in a container with the command crond -f -d 8. Here’s the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd 
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip 

        # needed for spatie/laravel-backup
        mysql-client 

        # needed for gd
        libpng-dev libjpeg-turbo-dev 

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd 

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I’ve ruled out that php artisan schedule:run is the cause since I can run it manually and everything’s fine. This means it’s something within cron.

What is cron doing under the covers that could cause this error?


Get this bounty!!!

#StackBounty: #php #cron #docker #alpine crond: can't set groups: Operation not permitted

Bounty: 50

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It’s run every minute allowing other scheduled work to be completed within the application itself. There’s nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it’s a Docker container.

cron is run in a container with the command crond -f -d 8. Here’s the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd 
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip 

        # needed for spatie/laravel-backup
        mysql-client 

        # needed for gd
        libpng-dev libjpeg-turbo-dev 

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd 

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I’ve ruled out that php artisan schedule:run is the cause since I can run it manually and everything’s fine. This means it’s something within cron.

What is cron doing under the covers that could cause this error?


Get this bounty!!!

#StackBounty: Laravel – Revised Authentication Controller

Bounty: 50

I’m developing a Social Engineering Awareness Training Application. This is the focus of my thesis for my undergraduate degree. This will be a multi-part review request, however, if you want to see the entire application, it can be found on GitHub. For this request, I’m looking to see how my revised AuthController (initial request) is set up and how effective you think it might be. I open to any and all suggestions about any facet of the code.

One question I still have, though, is there any benefit to having my application almost completely static?

Keep in mind that this application is nearly to testing, however, there are a few pieces that might not be polished.

AuthController

<?php

namespace AppHttpControllers;

use AppLibrariesCryptor;
use AppLibrariesErrorLogging;
use AppLibrariesRandomObjectGeneration;
use AppModelsSessions;
use AppModelsTwo_Factor;
use AppModelsUser;
use AppModelsUser_Permissions;
use IlluminateDatabaseQueryException;
use IlluminateHttpRequest;
use LeagueFlysystemException;

class AuthController extends Controller
{
/**
 * create
 * Create a new user instance after a valid registration.
 *
 * @param   Request         $request
 * @return  User
 */
public static function create(Request $request) {
    try {
        if($request->input('emailText') != $request->input('confirmEmailText')) {
            return redirect()->route('register');
        }

        $email = $request->input('emailText');
        $username = $request->input('usernameText');
        $password = RandomObjectGeneration::random_str(intval(getenv('DEFAULT_LENGTH_PASSWORDS')),true);

        $user = User::create([
            'username' => $username,
            'email' => $email,
            'first_name' => $request->input('firstNameText'),
            'last_name' => $request->input('lastNameText'),
            'middle_initial' => $request->input('middleInitialText'),
            'password' => password_hash($password,PASSWORD_DEFAULT),
            'two_factor_enabled' => 0,
        ]);

        EmailController::sendNewAccountEmail($user,$password);
        return redirect()->route('users');

    } catch(QueryException $qe) {
        if(strpos($qe->getMessage(),"1062 Duplicate entry 'admin'") !== false) {
            return redirect()->route('register'); //return with username exists error
        }
        return redirect()->route('register'); //return with unknown error

    } catch(Exception $e) {
        ErrorLogging::logError($e);
        return abort('500');
    }
}

/**
 * authenticate
 * Authenticates the user against the user's database object. Submits to 2FA if they have
 * the option enabled, otherwise logs the user in.
 *
 * @param   Request         $request
 * @return  IlluminateHttpRedirectResponse
 */
public static function authenticate(Request $request) {
    try {
        $user = User::where('username',$request->input('usernameText'))->first();
        $password = $request->input('passwordText');
        if(empty($user) || !password_verify($password,$user->password)) {
            return redirect()->route('login');
        }

        User::updateUser($user,$user->email,password_hash($password,PASSWORD_DEFAULT),$user->two_factor_enabled);

        $session = Sessions::where('user_id',$user->id)->first();
        if(!empty($session)) {
            $session->delete();
        }

        $ip = $_SERVER['REMOTE_ADDR'];
        $cryptor = new Cryptor();

        if($user->two_factor_enabled === 1) {
            $twoFactor = Two_Factor::where([
                'user_id' => $user->id, 'ip_address' => $ip
            ])->first();
            if(!empty($twoFactor)) {
                $twoFactor->delete();
            }

            $code = RandomObjectGeneration::random_str(6,false,'1234567890');
            $twoFactor = Two_Factor::create([
                'user_id' => $user->id,
                'ip_address' => $_SERVER['REMOTE_ADDR'],
                'code' => password_hash($code,PASSWORD_DEFAULT)
            ]);

            EmailController::sendTwoFactorEmail($user,$code);

            $newSession = Sessions::create([
                'user_id' => $user->id,
                'ip_address' => $ip,
                'two_factor_id' => $twoFactor->id,
                'authenticated' => 0
            ]);

            $encryptedSession = $cryptor->encrypt($newSession->id);
            Session::put('sessionId',$encryptedSession);

            return redirect()->route('2fa');
        }

        $newSession = Sessions::create([
            'user_id' => $user->id,
            'ip_address' => $ip,
            'authenticated' => 1
        ]);

        $encryptedSession = $cryptor->encrypt($newSession->id);
        Session::put('sessionId',$encryptedSession);

        $intended = Session::pull('intended');
        if($intended) {
            return redirect()->to($intended);
        }
        return redirect()->route('authHome');

    } catch(Exception $e) {
        ErrorLogging::logError($e);
        return abort('500');
    }
}

/**
 * generateTwoFactorPage
 * Route for generating the 2FA page.
 *
 * @return IlluminateHttpRedirectResponse | IlluminateViewView
 */
public static function generateTwoFactorPage() {
    try {
        if(Session::has('sessionId')) {
            $cryptor = new Cryptor();

            $sessionId = $cryptor->decrypt(Session::get('sessionId'));
            $session = Sessions::where('id',$sessionId)->first();

            $sessionCheck = self::activeSessionCheck($session);
            if(!is_null($sessionCheck)) {
                return $sessionCheck;
            }

            if(!is_null($session->two_factor_id)) {
                return view('auth.2fa');
            }
        }
        return redirect()->route('login');

    } catch(Exception $e) {
        ErrorLogging::logError($e);
        return abort('500');
    }
}

/**
 * twoFactorVerify
 * Validates the 2FA code to authenticate the user.
 *
 * @param   Request         $request
 * @return  IlluminateHttpRedirectResponse
 */
public static function twoFactorVerify(Request $request) {
    try {
        if(!Session::has('sessionId')) {
            return redirect()->route('login');
        }
        $cryptor = new Cryptor();

        $sessionId = $cryptor->decrypt(Session::get('sessionId'));
        $session = Sessions::where('id',$sessionId)->first();

        $sessionCheck = self::activeSessionCheck($session);
        if(!is_null($sessionCheck)) {
            return $sessionCheck;
        }

        $twoFactor = Two_Factor::where([
            'user_id' => $session->user_id, 'ip_address' => $_SERVER['REMOTE_ADDR']
        ])->first();

        if(!password_verify($request->input('codeText'),$twoFactor->code)) {
            return redirect()->route('2fa');
        }

        $session->update([
            'two_factor_id' => null,
            'authenticated' => 1
        ]);

        $twoFactor->delete();

        $intended = Session::pull('intended');
        if($intended) {
            return redirect()->to($intended);
        }
        return redirect()->route('authHome');

    } catch(Exception $e) {
        ErrorLogging::logError($e);
        return abort('500');
    }
}

/**
 * resend2FA
 * Generates and sends a new 2FA code.
 *
 * @return  IlluminateHttpRedirectResponse
 */
public static function resend2FA() {
    try {
        if(!Session::has('sessionId')) {
            return redirect()->route('login');
        }
        $cryptor = new Cryptor();

        $sessionId = $cryptor->decrypt(Session::get('sessionId'));
        $session = Sessions::where('id',$sessionId)->first();

        $sessionCheck = self::activeSessionCheck($session);
        if(!is_null($sessionCheck)) {
            return $sessionCheck;
        }

        $user = User::where('id',$session->user_id)->first();
        if(empty($user)) {
            return self::logout();
        }

        $twoFactor = Two_Factor::where([
            'user_id' => $session->user_id, 'ip_address' => $_SERVER['REMOTE_ADDR']
        ])->first();
        if(!empty($twoFactor)) {
            $twoFactor->delete();
        }

        $code = RandomObjectGeneration::random_str(6, '1234567890');
        Two_Factor::create([
            'user_id' => $session->user_id,
            'ip_address' => $_SERVER['REMOTE_ADDR'],
            'code' => password_hash($code,PASSWORD_DEFAULT)
        ]);

        EmailController::sendTwoFactorEmail($user,$code);
        return redirect()->route('2fa');

    } catch(Exception $e) {
        ErrorLogging::logError($e);
        return abort('500');
    }
}

/**
 * activeSessionCheck
 * Helper function to check session objects.
 *
 * @param   Sessions    $session            The session to check.
 * @return  IlluminateHttpRedirectResponse | null
 */
private static function activeSessionCheck(Sessions $session) {
    if($session->ip_address !== $_SERVER['REMOTE_ADDR']) {
        $session->delete();
        Session::forget('sessionId');
        return redirect()->route('login');
    }

    if($session->authenticated === 1) {
        return redirect()->route('authHome');
    }
    return null;
}

/**
 * check
 * Validates if the user is authenticated on this IP Address.
 *
 * @return  bool
 */
public static function check() {
    if(!Session::has('sessionId')) {
        return false;
    }
    $cryptor = new Cryptor();

    $sessionId = $cryptor->decrypt(Session::get('sessionId'));
    $session = Sessions::where('id', $sessionId)->first();

    if($session->ip_address !== $_SERVER['REMOTE_ADDR']) {
        $session->delete();
        Session::forget('sessionId');
        return false;
    }
    return true;
}

/**
 * adminCheck
 * Validates if the user is an authenticated admin user.
 *
 * @return bool
 */
public static function adminCheck() {
    $check = self::check();
    if(!$check) {
        return $check;
    }

    $cryptor = new Cryptor();

    $sessionId = $cryptor->decrypt(Session::get('sessionId'));
    $session = Sessions::where('id', $sessionId)->first();

    $user = User::where('id',$session->user_id)->first();
    if(empty($user)) {
        $session->delete();
        Session::forget('sessionId');
        return false;
    }

    if($user->user_type !== 1) {
        return false;
    }
    return true;
}

/**
 * logout
 * Removes session variables storing the authenticated account.
 *
 * @return  IlluminateHttpRedirectResponse
 */
public static function logout() {
    $cryptor = new Cryptor();

    $sessionId = $cryptor->decrypt(Session::get('sessionId'));
    Sessions::where('id', $sessionId)->first()->delete();
    Session::forget('sessionId');

    return redirect()->route('login');
}

/**
 * generateLogin
 * Generates the login page.
 *
 * @return IlluminateHttpRedirectResponse | IlluminateViewView
 */
public static function generateLogin() {
    if(self::check()) {
        return redirect()->route('authHome');
    }
    return view('auth.login');
}

/**
 * generateRegister
 * Generates the register page if the user is an admin.
 *
 * @return IlluminateHttpRedirectResponse | IlluminateViewView
 */
public static function generateRegister() {
    if(self::adminCheck()) {
        $permissions = User_Permissions::all();
        $variables = array('permissions'=>$permissions);
        return view('auth.register')->with($variables);
    }
    return abort('401');
}

/**
 * authRequired
 * Adds session variable for return redirect and then redirects to login page.
 *
 * @return  IlluminateHttpRedirectResponse
 */
public static function authRequired() {
    Session::put('intended',$_SERVER['REQUEST_URI']);
    return redirect()->route('login');
}
}

Random Object Generation Library

<?php

namespace AppLibraries;

use DoctrineInstantiatorExceptionInvalidArgumentException;


class RandomObjectGeneration
{
const KEYSPACE = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
const PASSWORD_KEYSPACE = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&';

/**
 * random_str
 * Generates a random string.
 *
 * @param   int                         $length         Length of string to be returned
 * @param   bool                        $passwordFlag   Boolean flag identifying whether string will be a password
 * @param   string                      $keyspace       Allowed characters to be used in string
 * @throws  InvalidArgumentException
 * @return  string
 */
public static function random_str($length, $passwordFlag = false, $keyspace = RandomObjectGeneration::KEYSPACE)
{
    if($passwordFlag) {
        $keyspace = RandomObjectGeneration::PASSWORD_KEYSPACE;
    }
    if(empty($length) || !is_int($length) || $length < 0) {
        $message = 'Random String Generation: Length is Invalid. Length must be a positive integer. Value Provided: ' .
            var_export($length);
        throw new InvalidArgumentException($message);
    }
    if(empty($keyspace) || !is_string($keyspace)) {
        $message = 'Random String Generation: Invalid Keyspace';
        throw new InvalidArgumentException($message);
    }
    $str = '';
    $max = mb_strlen($keyspace) - 1;
    for ($i = 0; $i < $length; ++$i) {
        $str .= $keyspace[random_int(0, $max)];
    }
    return $str;
}
}

Sessions Model

<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;

class Sessions extends Model
{
protected $table = 'sessions';

protected $primaryKey = 'id';

protected $fillable = ['user_id',
    'ip_address',
    'two_factor_id',
    'authenticated'
];
}

ErrorLogging

<?php

namespace AppLibraries;


use IlluminateSupportFacadesLog;

class ErrorLogging
{
public static function logError(Exception $e) {
    $message = $e->getCode() . ': ' . $e->getMessage() . PHP_EOL;
    $message .= $e->getTraceAsString() . PHP_EOL;
    $message .= str_repeat('-',100) . PHP_EOL . PHP_EOL;
    Log::error($message);
}
}


Get this bounty!!!

Create Virtual Hosts with Apache

Apache is very flexible, and it’s easy to configure Apache to handle several domains even when your Web server only has one IP address to share between them. You can use this to host multiple sites, or just to provide a sandbox for development rather than making changes on your live site. This weekend, we’ll learn how to create virtual hosts with Apache.

Setting up virtual hosts might seem like a big challenge, but it’s not. In fact, you can set up a virtual host with just a few edits to Apache’s configuration and by setting up additional directories for the documents. For this how to, I want to use an Apache installation on a Ubuntu server. Please be aware, the instructions for this may require modification if being done on a non-Debian distribution because of the way that Apache is packaged. However, the Apache directives should be standard across distributions and should work even if Apache isn’t running on Linux.

Creating the Directory Structure

Before the configurations can be tackled, the directory structure for the virtual site must be created. We are going to be working with Apache as installed on a Ubuntu server, so the Apache document root will be/var/www. The directory structure for the new Web site can be created anywhere. Some create those directories in their home (~/) directory, some create them in /usr/local/apache, and other, various locations. For the sake of simplicity, We are going to illustrate setting the virtual host in the document root of Apache (in Ubuntu that would be /var/www). By doing this, it will not be necessary to change ownership of the newly created directory or the parent directory housing the virtual host (since Apache must have access to the directories and files.)

We are going to set up the virtual host demosite.com. So to create the directories for the virtual host, the following commands must be run:

  • sudo mkdir /var/www/demosite.com
  • sudo chmod -R 755 /var/www/demosite.com

Now that the home directory for the virtual host is done, it’s time to start configuring Apache so it is aware of the new site. After configuring Apache, the site can then be built within /var/www/demosite.com.

Apache Configuration

The first step in the Apache configuration is to make sure Apache knows virtual hosts are enabled. In the Ubuntu set up look for a line (near the bottom) of /etc/apache/apache2.conf that looks like:

Include sites-enabled/

Make sure that line is not commented out (does not begin with a ‘#‘ character). That sites-enabled include points to /etc/apache/sites-enabled. A look in that directory will reveal a file called 000-default. That file should contain all of the directory containers needed for virtual sites on the server. To create a new virtual host (to map the example demosite.com), create a new file within sites-available called /etc/apache/sites-available/demosite.com. The contents of that file will look something similar to this (depending upon the needs and application of the virtual host):


<VirtualHost test.domain.com>
   ServerAdmin webmaster@localhost
   #We want to be able to access the web site using www.test.domain.com or test.domain.com
   ServerAlias www.test.domain.com
   DocumentRoot /var/www/demosite.com
   #log file for this server
   CustomLog /var/log/apache2/www.test.domain.com-access.log combined
</VirtualHost>

The above code assumes that domain.com is the actual domain to be used (insert proper domain where necessary). It’s almost ready to fire up, but we have two simple steps left before restarting Apache. The first step is to create a link in /etc/apache/sites-enabled to the file we just created. This is done with the following steps:

  1. Change to the /etc/apache/sites-enabled directory with the command cd /etc/apache/sites-enabled .
  2. Create the link with the command sudo ln -s /etc/apache/sites-available demosite.com .

It is also possible to create the links automatically with the command sudo a2ensite demosite.com and then, should the virtual site need to be disabled, remove the link with the command sudo a2dissite demosite.com.

The last step is to make sure the server knows that our new virtual site is to be found on the server and not out on the Internet. For this, do the following:

  • Open up the /etc/hosts file in a text editor (with administrative rights).
  • Add a line like 127.0.0.1 localhost.localdomain localhost test.domain.com www.demosite.com .
  • Save and close that file.

Now it’s time to restart Apache with the command sudo /etc/init.d/apache2 restart and test virtual host by pointing a browser to the address.

Non-Debian Servers

If the server hosting the virtual sites is a non-Debian distribution, the steps are different for hosting virtual sites. Here’s how it works:

  1. Create the directory container for the virtual site in /etc/httpd/conf/httpd.conf. This container will look similar to that used for the Debian-based server.
  2. Make sure the Apache configuration file is aware of virtual hosts by making sure the line Include conf.d/*.conf is not commented out.
  3. Create the new virtual hosts file (we’ll call it vhosts.conf) in /etc/httpd/conf.d/ .
  4. Add the virtual site to the /etc/hosts file.
  5. Restart Apache with the command /etc/rc.d/init.d/httpd restart.

The directory container, for the non-Debian host, will look similar to the very basic container below:


<VirtualHost *:80>
   ServerName demosite.com
   DocumentRoot /var/www/html/demosite.com
</VirtualHost>

The virtual hosts file mentioned above, will need to look like this:


<VirtualHost 127.0.0.1> 
   DocumentRoot /var/http/www/demosite.com
   ServerName www.demosite.com
</VirtualHost>  

<VirtualHost 127.0.0.1>
   DocumentRoot /var/http/www/demosite.com
   ServerName test.demosite.com
</VirtualHost>

Building Time

Now that the virtual host is up and running, it is now possible to build the site within the/var/www/demosite.com directory.

You can do this for as many virtual hosts as you need (assuming the server can take the added load).

Source

Simple way to generate a random password in PHP

When creating web apps, there’s often a need to generate a random password for your users. There are a number of ways to do this, but in needing to do it recently I came up with this very simple function that will generate a password (or other random string) of whatever length you wish. It’s particularly useful when generating passwords for users that they will then change in the future. It uses PHP’s handy str_shuffle() function:

<?php
    function random_password( $length = 8 ) {
         $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?";
         $index=rand($length,$length*$length);
         $password='';
         for($i=0;$i<$index;$i++){
            $password = substr( str_shuffle( $chars.$password ), 0, $length );
         }
         return $password;
    }

?>
<?php $password = random_password(8); ?>

NOTE: This method is better than the on posted in the Source. It randomizes the password generation process enough to be safe from brute force or predictability.