Skip to content

Commit

Permalink
Fix Guard bypass in Eloquent models in laravel/framework
Browse files Browse the repository at this point in the history
  • Loading branch information
freescout-help-desk committed Sep 22, 2023
1 parent 1e87181 commit 21d8632
Show file tree
Hide file tree
Showing 5 changed files with 481 additions and 2 deletions.
4 changes: 4 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,10 @@
"Illuminate\\Support\\": "overrides/laravel/framework/src/Illuminate/Support/",
"Illuminate\\Http\\": "overrides/laravel/framework/src/Illuminate/Http/",
"Illuminate\\Database\\Eloquent\\": "overrides/laravel/framework/src/Illuminate/Database/Eloquent/",
"Illuminate\\Database\\Eloquent\\Concerns\\": "overrides/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/",
"Illuminate\\Pagination\\": "overrides/laravel/framework/src/Illuminate/Pagination/",
"Illuminate\\Session\\": "overrides/laravel/framework/src/Illuminate/Session/",
"Illuminate\\Queue\\": "overrides/laravel/framework/src/Illuminate/Queue/",
"Carbon\\": "overrides/nesbot/carbon/src/Carbon/",
"Illuminate\\Cache\\": "overrides/laravel/framework/src/Illuminate/Cache/",
"Illuminate\\Config\\": "overrides/laravel/framework/src/Illuminate/Config/",
Expand Down Expand Up @@ -220,11 +222,13 @@
"vendor/symfony/http-foundation/FileBag.php",
"vendor/symfony/http-foundation/Request.php",
"vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php",
"vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php",
"vendor/laravel/framework/src/Illuminate/Pagination/AbstractPaginator.php",
"vendor/laravel/framework/src/Illuminate/Pagination/Paginator.php",
"vendor/laravel/framework/src/Illuminate/Pagination/LengthAwarePaginator.php",
"vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php",
"vendor/laravel/framework/src/Illuminate/Session/FileSessionHandler.php",
"vendor/laravel/framework/src/Illuminate/Queue/Listener.php",
"vendor/nesbot/carbon/src/Carbon/Carbon.php",
"vendor/laravel/framework/src/Illuminate/Cache/Repository.php",
"vendor/laravel/framework/src/Illuminate/Config/Repository.php",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
<?php

namespace Illuminate\Database\Eloquent\Concerns;

use Illuminate\Support\Str;

trait GuardsAttributes
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [];

/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = ['*'];

/**
* Indicates if all mass assignment is enabled.
*
* @var bool
*/
protected static $unguarded = false;

/**
* The actual columns that exist on the database and can be guarded.
*
* @var array
*/
protected static $guardableColumns = [];

/**
* Get the fillable attributes for the model.
*
* @return array
*/
public function getFillable()
{
return $this->fillable;
}

/**
* Set the fillable attributes for the model.
*
* @param array $fillable
* @return $this
*/
public function fillable(array $fillable)
{
$this->fillable = $fillable;

return $this;
}

/**
* Get the guarded attributes for the model.
*
* @return array
*/
public function getGuarded()
{
return $this->guarded;
}

/**
* Set the guarded attributes for the model.
*
* @param array $guarded
* @return $this
*/
public function guard(array $guarded)
{
$this->guarded = $guarded;

return $this;
}

/**
* Disable all mass assignable restrictions.
*
* @param bool $state
* @return void
*/
public static function unguard($state = true)
{
static::$unguarded = $state;
}

/**
* Enable the mass assignment restrictions.
*
* @return void
*/
public static function reguard()
{
static::$unguarded = false;
}

/**
* Determine if current state is "unguarded".
*
* @return bool
*/
public static function isUnguarded()
{
return static::$unguarded;
}

/**
* Run the given callable while being unguarded.
*
* @param callable $callback
* @return mixed
*/
public static function unguarded(callable $callback)
{
if (static::$unguarded) {
return $callback();
}

static::unguard();

try {
return $callback();
} finally {
static::reguard();
}
}

/**
* Determine if the given attribute may be mass assigned.
*
* @param string $key
* @return bool
*/
public function isFillable($key)
{
if (static::$unguarded) {
return true;
}

// If the key is in the "fillable" array, we can of course assume that it's
// a fillable attribute. Otherwise, we will check the guarded array when
// we need to determine if the attribute is black-listed on the model.
if (in_array($key, $this->getFillable())) {
return true;
}

// If the attribute is explicitly listed in the "guarded" array then we can
// return false immediately. This means this attribute is definitely not
// fillable and there is no point in going any further in this method.
if ($this->isGuarded($key)) {
return false;
}

return empty($this->getFillable()) &&
strpos($key, '.') === false &&
! Str::startsWith($key, '_');
}

/**
* Determine if the given key is guarded.
*
* @param string $key
* @return bool
*/
public function isGuarded($key)
{
//return in_array($key, $this->getGuarded()) || $this->getGuarded() == ['*'];

if (empty($this->getGuarded())) {
return false;
}

return $this->getGuarded() == ['*'] ||
! empty(preg_grep('/^'.preg_quote($key).'$/i', $this->getGuarded())) ||
! $this->isGuardableColumn($key);
}

/**
* Determine if the given column is a valid, guardable column.
*
* @param string $key
* @return bool
*/
protected function isGuardableColumn($key)
{
if (! isset(static::$guardableColumns[get_class($this)])) {
static::$guardableColumns[get_class($this)] = $this->getConnection()
->getSchemaBuilder()
->getColumnListing($this->getTable());
}

return in_array($key, static::$guardableColumns[get_class($this)]);
}

/**
* Determine if the model is totally guarded.
*
* @return bool
*/
public function totallyGuarded()
{
return count($this->getFillable()) == 0 && $this->getGuarded() == ['*'];
}

/**
* Get the fillable attributes of a given array.
*
* @param array $attributes
* @return array
*/
protected function fillableFromArray(array $attributes)
{
if (count($this->getFillable()) > 0 && ! static::$unguarded) {
return array_intersect_key($attributes, array_flip($this->getFillable()));
}

return $attributes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ public function qualifyColumn($column)
*/
protected function removeTableFromKey($key)
{
return Str::contains($key, '.') ? last(explode('.', $key)) : $key;
//return Str::contains($key, '.') ? last(explode('.', $key)) : $key;
return $key;
}

/**
Expand Down
Loading

0 comments on commit 21d8632

Please sign in to comment.