diff --git a/app/Console/Commands/LoadSpam.php b/app/Console/Commands/LoadSpam.php new file mode 100644 index 0000000000000000000000000000000000000000..fbe636da3d7434ba6866fd18530ea44ccff6ba6b --- /dev/null +++ b/app/Console/Commands/LoadSpam.php @@ -0,0 +1,64 @@ +isAfter(Carbon::now())) { + $bansToLoad[] = $ban["regexp"]; + } + } + + Redis::pipeline(function ($redis) use ($bansToLoad) { + $redis->del("spam"); + foreach ($bansToLoad as $ban) { + $redis->rpush("spam", $ban); + } + }); + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 51233aaaee9bbf7bc976113e4e7bdbe32ca99a1b..65b76241cde59edb99cd5b29642e2bf72ca5eefc 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -28,7 +28,7 @@ class Kernel extends ConsoleKernel $schedule->command('requests:gather')->everyFifteenMinutes(); $schedule->command('requests:useragents')->everyFiveMinutes(); $schedule->command('logs:gather')->everyMinute(); - + $schedule->command('spam:load')->everyFiveMinutes(); $schedule->call(function () { DB::table('monthlyrequests')->truncate(); DB::disconnect('mysql'); diff --git a/app/Http/Controllers/AdminSpamController.php b/app/Http/Controllers/AdminSpamController.php new file mode 100644 index 0000000000000000000000000000000000000000..e4a514ce347b6dadf4141353316a7b315c187b37 --- /dev/null +++ b/app/Http/Controllers/AdminSpamController.php @@ -0,0 +1,145 @@ +getQueries(); + + $currentBans = $this->getBans(); + $loadedBans = Redis::lrange("spam", 0, -1); + + return view("admin.spam") + ->with('title', "Spam Konfiguration - MetaGer") + ->with('queries', $queries) + ->with('bans', $currentBans) + ->with('loadedBans', $loadedBans); + } + + public function ban(Request $request) + { + $banTime = $request->input('ban-time'); + $banRegexp = $request->input('regexp'); + + $file = storage_path('logs/metager/ban.txt'); + + $bans = []; + if (file_exists($file)) { + $bans = json_decode(file_get_contents($file), true); + } + + $bans[] = ["banned-until" => Carbon::now()->add($banTime)->format("Y-m-d H:i:s"), "regexp" => $banRegexp]; + + \file_put_contents($file, json_encode($bans)); + + return redirect(url('admin/spam')); + } + + public function jsonQueries() + { + $queries = $this->getQueries(); + return response()->json($queries); + } + + public function queryregexp(Request $request) + { + $data = json_decode($request->getContent(), true); + $queries = $data["queries"]; + $regexps = [$data["regexp"]]; + + $bans = $this->getBans(); + foreach ($bans as $ban) { + $regexps[] = $ban["regexp"]; + } + + $resultData = []; + + foreach ($queries as $query) { + $matches = false; + foreach ($regexps as $regexp) { + try { + if (preg_match($regexp, $query)) { + $matches = true; + } + } catch (\Exception $e) { + // Exceptions are expected when no valid regexp is given + } + } + $resultData[] = [ + "query" => $query, + "matches" => $matches, + ]; + } + + return response()->json($resultData); + + } + + private function getQueries() + { + $minuteToFetch = Carbon::now()->subMinutes(2); + $logFile = storage_path("logs/metager/" . $minuteToFetch->format("Y/m/d") . ".log"); + + $result = shell_exec("cat $logFile | grep " . $minuteToFetch->format("H:i:")); + $result = explode(PHP_EOL, $result); + + $queries = array(); + + foreach ($result as $line) { + if ($query = \preg_match("/.*eingabe=(.*)$/", $line, $matches)) { + $queries[] = $matches[1]; + } + } + return $queries; + } + + public function getBans() + { + $file = \storage_path('logs/metager/ban.txt'); + $bans = []; + + if (file_exists($file)) { + $tmpBans = json_decode(file_get_contents($file), true); + + foreach ($tmpBans as $ban) { + #dd($ban["banned-until"]); + $bannedUntil = Carbon::createFromFormat('Y-m-d H:i:s', $ban["banned-until"]); + if ($bannedUntil->isAfter(Carbon::now())) { + $bans[] = $ban; + } + } + } + + file_put_contents($file, json_encode($bans)); + + return $bans; + } + + public function deleteRegexp(Request $request) + { + $file = \storage_path('logs/metager/ban.txt'); + $bans = []; + + if (file_exists($file)) { + $bans = json_decode(file_get_contents($file), true); + } + + $regexpToDelete = $request->input('regexp'); + $newBans = []; + + foreach ($bans as $ban) { + if ($ban["regexp"] !== $regexpToDelete) { + $newBans[] = $ban; + } + } + + file_put_contents($file, json_encode($newBans)); + return redirect(url('admin/spam')); + } +} diff --git a/app/Http/Controllers/HumanVerification.php b/app/Http/Controllers/HumanVerification.php index 6b979855358f80b1bd2b195417e9a3d8f0e8899b..741e55fef5a42d6e28090e6660d2f9e1488b560d 100644 --- a/app/Http/Controllers/HumanVerification.php +++ b/app/Http/Controllers/HumanVerification.php @@ -7,6 +7,7 @@ use Carbon; use Illuminate\Hashing\BcryptHasher as Hasher; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Redis; use Input; class HumanVerification extends Controller @@ -198,20 +199,16 @@ class HumanVerification extends Controller public static function couldBeSpammer($ip) { - $possibleSpammer = false; - # Check for recent Spams $eingabe = \Request::input('eingabe'); - if (\preg_match("/^susimail\s+-site:[^\s]+\s-site:/si", $eingabe)) { - return true; - } else if (\preg_match("/^\s*site:\"linkedin\.com[^\"]*\"\s+/si", $eingabe)) { - return true; - } else if (\preg_match("/^\d+.(php|asp)\s+\?.*=.*/si", $eingabe)) { - return true; + $spams = Redis::lrange("spam", 0, -1); + foreach ($spams as $spam) { + if (\preg_match($spam, $eingabe)) { + return true; + } } - return $possibleSpammer; - + return false; } public function botOverview(Request $request) diff --git a/resources/views/admin/spam.blade.php b/resources/views/admin/spam.blade.php new file mode 100644 index 0000000000000000000000000000000000000000..ffcdfe2e98fc859a3ae351397c9d8bb76a21fd1e --- /dev/null +++ b/resources/views/admin/spam.blade.php @@ -0,0 +1,198 @@ +@extends('layouts.subPages') + +@section('title', $title ) + +@section('content') + +
+
+ + + +
+
+ + +
+ @foreach($queries as $query) +
{{$query}}
+ @endforeach +
+
+

Current Bans

+ + + + + + + + + + @foreach($bans as $ban) + + + + + + @endforeach + +
RegexpBanned untilActions
{{ $ban["regexp"] }}{{ Carbon::createFromFormat("Y-m-d H:i:s", $ban["banned-until"])->format("d.m.Y H:i:s")}} ({{ Carbon::createFromFormat("Y-m-d H:i:s", $ban["banned-until"])->diffInDays(Carbon::now()) }} Days) +
+ + +
+
+
+
+

Loaded Bans

+ + + + + + + + @foreach($loadedBans as $ban) + + + + @endforeach + +
Regexp
{{ $ban }}
+
+ +@endsection diff --git a/routes/web.php b/routes/web.php index e3c254a46f6b9ca85e1cfd781bba20d0dc4d936c..caf716a5e8aad65efd1db41fcf78f767980d6a89 100644 --- a/routes/web.php +++ b/routes/web.php @@ -182,6 +182,13 @@ Route::group( }); Route::get('bot', 'HumanVerification@botOverview'); Route::post('bot', 'HumanVerification@botOverviewChange'); + Route::group(['prefix' => 'spam'], function () { + Route::get('/', 'AdminSpamController@index'); + Route::post('/', 'AdminSpamController@ban'); + Route::get('jsonQueries', 'AdminSpamController@jsonQueries'); + Route::post('queryregexp', 'AdminSpamController@queryregexp'); + Route::post('deleteRegexp', 'AdminSpamController@deleteRegexp'); + }); }); Route::get('settings', function () {