Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
MetaGer
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
56
Issues
56
List
Boards
Labels
Service Desk
Milestones
Merge Requests
9
Merge Requests
9
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
open-source
MetaGer
Commits
29c3c29c
Commit
29c3c29c
authored
Aug 12, 2020
by
Dominik Hebeler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added interface to make dynamic bans
parent
e8b064cc
Changes
6
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
422 additions
and
11 deletions
+422
-11
app/Console/Commands/LoadSpam.php
app/Console/Commands/LoadSpam.php
+64
-0
app/Console/Kernel.php
app/Console/Kernel.php
+1
-1
app/Http/Controllers/AdminSpamController.php
app/Http/Controllers/AdminSpamController.php
+145
-0
app/Http/Controllers/HumanVerification.php
app/Http/Controllers/HumanVerification.php
+7
-10
resources/views/admin/spam.blade.php
resources/views/admin/spam.blade.php
+198
-0
routes/web.php
routes/web.php
+7
-0
No files found.
app/Console/Commands/LoadSpam.php
0 → 100644
View file @
29c3c29c
<?php
namespace
App\Console\Commands
;
use
Carbon
;
use
Illuminate\Console\Command
;
use
Illuminate\Support\Facades\Redis
;
class
LoadSpam
extends
Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected
$signature
=
'spam:load'
;
/**
* The console command description.
*
* @var string
*/
protected
$description
=
'Loads a list of current Spams into redis'
;
/**
* Create a new command instance.
*
* @return void
*/
public
function
__construct
()
{
parent
::
__construct
();
}
/**
* Execute the console command.
*
* @return mixed
*/
public
function
handle
()
{
$filePath
=
\
storage_path
(
'logs/metager/ban.txt'
);
$bans
=
[];
if
(
\
file_exists
(
$filePath
))
{
$bans
=
json_decode
(
file_get_contents
(
$filePath
),
true
);
}
$bansToLoad
=
[];
foreach
(
$bans
as
$ban
)
{
$bannedUntil
=
Carbon
::
createFromFormat
(
"Y-m-d H:i:s"
,
$ban
[
"banned-until"
]);
if
(
$bannedUntil
->
isAfter
(
Carbon
::
now
()))
{
$bansToLoad
[]
=
$ban
[
"regexp"
];
}
}
Redis
::
pipeline
(
function
(
$redis
)
use
(
$bansToLoad
)
{
$redis
->
del
(
"spam"
);
foreach
(
$bansToLoad
as
$ban
)
{
$redis
->
rpush
(
"spam"
,
$ban
);
}
});
}
}
app/Console/Kernel.php
View file @
29c3c29c
...
...
@@ -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'
);
...
...
app/Http/Controllers/AdminSpamController.php
0 → 100644
View file @
29c3c29c
<?php
namespace
App\Http\Controllers
;
use
Carbon
;
use
Illuminate\Http\Request
;
use
Illuminate\Support\Facades\Redis
;
class
AdminSpamController
extends
Controller
{
public
function
index
()
{
$queries
=
$this
->
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'
));
}
}
app/Http/Controllers/HumanVerification.php
View file @
29c3c29c
...
...
@@ -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
)
...
...
resources/views/admin/spam.blade.php
0 → 100644
View file @
29c3c29c
@
extends
(
'layouts.subPages'
)
@
section
(
'title'
,
$title
)
@
section
(
'content'
)
<
style
>
#head {
display
:
flex
;
align
-
items
:
center
;
margin
-
bottom
:
16
px
;
}
#head > button {
margin
-
left
:
16
px
;
}
#head > h1 {
margin
:
0
;
}
#queries {
display
:
flex
;
flex
-
wrap
:
wrap
;
justify
-
content
:
space
-
between
;
}
.
matches
{
background
-
color
:
#c9f4c9;
}
#block-requests {
margin
-
bottom
:
16
px
;
}
#regexp {
margin
-
bottom
:
8
px
;
}
#ban-time {
margin
-
bottom
:
8
px
;
}
</
style
>
<
div
id
=
"block-requests"
>
<
form
method
=
"post"
>
<
input
class
=
"form-control"
type
=
"text"
name
=
"regexp"
id
=
"regexp"
placeholder
=
"Type in regexp to match queries..."
>
<
select
name
=
"ban-time"
id
=
"ban-time"
class
=
"form-control"
>
<
option
value
=
"1 day"
>
Einen
Tag
</
option
>
<
option
value
=
"1 week"
>
Eine
Woche
</
option
>
<
option
value
=
"2 weeks"
>
Zwei
Wochen
</
option
>
<
option
value
=
"1 month"
selected
>
Einen
Monat
</
option
>
</
select
>
<
button
type
=
"submit"
class
=
"btn btn-default btn-sm"
>
Sperren
</
button
>
</
form
>
</
div
>
<
div
id
=
"head"
>
<
h1
>
Letzte
Suchanfragen
</
h1
>
<
button
type
=
"button"
class
=
"btn btn-success btn-sm"
>
Aktualisierung
stoppen
(
60
)
</
button
>
</
div
>
<
input
class
=
"form-control"
type
=
"text"
name
=
""
id
=
"check-against"
placeholder
=
"Match against..."
>
<
div
id
=
"queries"
>
@
foreach
(
$queries
as
$query
)
<
div
class
=
"query card"
>
{{
$query
}}
</
div
>
@
endforeach
</
div
>
<
div
id
=
"bans"
>
<
h1
>
Current
Bans
</
h1
>
<
table
class
=
"table table-striped"
>
<
thead
>
<
tr
>
<
td
>
Regexp
</
td
>
<
td
>
Banned
until
</
td
>
<
td
>
Actions
</
td
>
</
tr
>
</
thead
>
<
tbody
>
@
foreach
(
$bans
as
$ban
)
<
tr
>
<
td
>
{{
$ban
[
"regexp"
]
}}
</
td
>
<
td
>
{{
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
)
</
td
>
<
td
>
<
form
action
=
"{{ url("
admin
/
spam
/
deleteRegexp
") }}"
method
=
"post"
>
<
input
type
=
"hidden"
name
=
"regexp"
value
=
"{{
$ban["regexp"]
}}"
>
<
button
type
=
"submit"
>&
#128465;</button>
</
form
>
</
td
>
</
tr
>
@
endforeach
</
tbody
>
</
table
>
</
div
>
<
div
id
=
"loadedbans"
>
<
h1
>
Loaded
Bans
</
h1
>
<
table
class
=
"table table-striped"
>
<
thead
>
<
tr
>
<
td
>
Regexp
</
td
>
</
tr
>
</
thead
>
<
tbody
>
@
foreach
(
$loadedBans
as
$ban
)
<
tr
>
<
td
>
{{
$ban
}}
</
td
>
</
tr
>
@
endforeach
</
tbody
>
</
table
>
</
div
>
<
script
>
var
lastUpdate
=
Date
.
now
();
var
updating
=
true
;
var
buttonText
=
"Aktualisierung stoppen"
;
var
interval
=
setInterval
(
updateQueries
,
1000
);
$
(
"#regexp"
)
.
on
(
"input"
,
checkRegexp
);
$
(
"#check-against"
)
.
on
(
"input"
,
checkRegexp
);
$
(
document
)
.
ready
(
function
(){
checkRegexp
();
});
$
(
"#head > button"
)
.
click
(
function
()
{
if
(
!
updating
)
{
$
(
"#head > button"
)
.
removeClass
(
"btn-danger"
);
$
(
"#head > button"
)
.
addClass
(
"btn-success"
);
buttonText
=
"Aktualisierung stoppen"
;
interval
=
setInterval
(
updateQueries
,
1000
);
}
var
updateAt
=
lastUpdate
+
60000
;
var
updateIn
=
Math
.
round
((
updateAt
-
Date
.
now
())
/
1000
);
$
(
"#head > button"
)
.
html
(
buttonText
+
" ("
+
updateIn
+
")"
);
updating
=
!
updating
;
});
function
updateQueries
()
{
var
updateAt
=
lastUpdate
+
60000
;
var
updateIn
=
Math
.
round
((
updateAt
-
Date
.
now
())
/
1000
);
if
(
!
updating
){
$
(
"#head > button"
)
.
removeClass
(
"btn-success"
);
$
(
"#head > button"
)
.
addClass
(
"btn-danger"
);
buttonText
=
"Aktualisierung starten"
;
clearInterval
(
interval
);
}
$
(
"#head > button"
)
.
html
(
buttonText
+
" ("
+
updateIn
+
")"
);
if
(
updateAt
>
Date
.
now
()){
return
;
}
fetch
(
"{{ url('admin/spam/jsonQueries') }}"
)
.
then
(
response
=>
response
.
json
())
.
then
(
data
=>
{
$
(
"#queries"
)
.
html
(
""
);
$
(
data
)
.
each
(
function
(
index
,
el
){
$
(
"#queries"
)
.
append
(
"<div class=
\"
query card
\"
>"
+
el
+
"</div>"
);
});
lastUpdate
=
Date
.
now
();
checkRegexp
();
});
}
function
checkRegexp
()
{
var
val
=
$
(
"#regexp"
)
.
val
();
var
queries
=
[];
$
(
"#queries > .query"
)
.
each
(
function
(
index
,
el
){
queries
.
push
(
$
(
el
)
.
html
());
});
queries
.
push
(
$
(
"#check-against"
)
.
val
());
var
url
=
"{{ url('admin/spam/queryregexp') }}"
;
var
options
=
{
method
:
'POST'
,
body
:
JSON
.
stringify
({
"queries"
:
queries
,
"regexp"
:
val
}),
headers
:
{
'Content-Type'
:
'application/json'
}
};
fetch
(
url
,
options
)
.
then
(
response
=>
response
.
json
())
.
then
(
data
=>
{
$
(
"#queries > .query"
)
.
each
(
function
(
index
,
el
){
if
(
data
[
index
][
"matches"
]){
$
(
el
)
.
addClass
(
"matches"
);
}
else
{
$
(
el
)
.
removeClass
(
"matches"
);
}
});
if
(
data
[
data
.
length
-
1
][
"matches"
]){
$
(
"#check-against"
)
.
addClass
(
"matches"
);
}
else
{
$
(
"#check-against"
)
.
removeClass
(
"matches"
);
}
});
}
</
script
>
@
endsection
routes/web.php
View file @
29c3c29c
...
...
@@ -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
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment