add module .dorks and flask.harden()
This commit is contained in:
parent
ee36616b43
commit
e5ca63953d
13 changed files with 65 additions and 14 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -24,3 +24,4 @@ dist/
|
|||
.err
|
||||
.vscode
|
||||
/run.sh
|
||||
ROADMAP.md
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
+ Added `ValueProperty`, abstract superclass for `ConfigProperty`
|
||||
+ \[BREAKING] Changed the behavior of `makelist()`: now it's also a decorator, converting its return type to a list (revertable with `wrap=False`)
|
||||
+ New module `lex` with functions `symbol_table()` and `lex()` — make tokenization more affordable
|
||||
+ Add `dorks` module and `flask.harden()`
|
||||
+ Added `addattr()`
|
||||
|
||||
## 0.3.6
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ from .classtools import Wanted, Incomplete
|
|||
from .itertools import makelist, kwargs_prefix, ltuple, rtuple, additem
|
||||
from .i18n import I18n, JsonI18n, TomlI18n
|
||||
from .snowflake import Snowflake, SnowflakeGen
|
||||
from .lex import symbol_table, lex, ilex
|
||||
|
||||
__version__ = "0.4.0-dev28"
|
||||
|
||||
|
|
@ -36,7 +37,7 @@ __all__ = (
|
|||
'SiqType', 'Snowflake', 'SnowflakeGen', 'StringCase', 'TomlI18n', 'Wanted',
|
||||
'additem', 'b2048decode', 'b2048encode', 'b32ldecode', 'b32lencode',
|
||||
'b64encode', 'b64decode', 'cb32encode', 'cb32decode', 'count_ones',
|
||||
'deprecated', 'join_bits', 'jsonencode', 'kwargs_prefix', 'ltuple',
|
||||
'deprecated', 'ilex', 'join_bits', 'jsonencode', 'kwargs_prefix', 'lex', 'ltuple',
|
||||
'makelist', 'mask_shift', 'not_implemented', 'rtuple', 'split_bits',
|
||||
'ssv_list', 'want_bytes', 'want_str'
|
||||
'ssv_list', 'symbol_table', 'want_bytes', 'want_str'
|
||||
)
|
||||
|
|
|
|||
28
src/suou/dorks.py
Normal file
28
src/suou/dorks.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
"""
|
||||
Web app hardening and PT utilities.
|
||||
|
||||
---
|
||||
|
||||
Copyright (c) 2025 Sakuragasaki46.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
See LICENSE for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
This software is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
SENSITIVE_ENDPOINTS = """
|
||||
/.git
|
||||
/.gitignore
|
||||
/node_modules
|
||||
/wp-admin
|
||||
/wp-login.php
|
||||
/.ht
|
||||
/package.json
|
||||
/package-lock.json
|
||||
/composer.
|
||||
""".split()
|
||||
|
||||
|
|
@ -14,8 +14,6 @@ This software is distributed on an "AS IS" BASIS,
|
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
from .functools import deprecated
|
||||
|
||||
class MissingConfigError(LookupError):
|
||||
"""
|
||||
Config variable not found.
|
||||
|
|
@ -42,3 +40,7 @@ class InconsistencyError(RuntimeError):
|
|||
"""
|
||||
This program is in a state which it's not supposed to be in.
|
||||
"""
|
||||
|
||||
__all__ = (
|
||||
'MissingConfigError', 'MissingConfigWarning', 'LexError', 'InconsistencyError'
|
||||
)
|
||||
|
|
@ -15,9 +15,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
"""
|
||||
|
||||
from typing import Any
|
||||
from flask import Flask, current_app, g, request
|
||||
from flask import Flask, abort, current_app, g, request
|
||||
from .i18n import I18n
|
||||
from .configparse import ConfigOptions
|
||||
from .dorks import SENSITIVE_ENDPOINTS
|
||||
|
||||
|
||||
def add_context_from_config(app: Flask, config: ConfigOptions) -> Flask:
|
||||
|
|
@ -66,6 +67,21 @@ def get_flask_conf(key: str, default = None, *, app: Flask | None = None) -> Any
|
|||
app = current_app
|
||||
return app.config.get(key, default)
|
||||
|
||||
__all__ = ('add_context_from_config', 'add_i18n', 'get_flask_conf')
|
||||
## XXX UNTESTED!
|
||||
def harden(app: Flask):
|
||||
"""
|
||||
Make common "dork" endpoints unavailable
|
||||
"""
|
||||
i = 1
|
||||
for ep in SENSITIVE_ENDPOINTS:
|
||||
@app.route(f'{ep}<path:rest>', name=f'unavailable_{i}')
|
||||
def unavailable(rest):
|
||||
abort(403)
|
||||
i += 1
|
||||
|
||||
return app
|
||||
|
||||
# Optional dependency: do not import into __init__.py
|
||||
__all__ = ('add_context_from_config', 'add_i18n', 'get_flask_conf', 'harden')
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -74,5 +74,5 @@ class Api(_Api):
|
|||
super().__init__(*a, **ka)
|
||||
self.representations['application/json'] = output_json
|
||||
|
||||
|
||||
# Optional dependency: do not import into __init__.py
|
||||
__all__ = ('Api',)
|
||||
|
|
@ -76,5 +76,5 @@ def require_auth(cls: type[DeclarativeBase], db: SQLAlchemy) -> Callable[Any, Ca
|
|||
|
||||
return auth_required
|
||||
|
||||
|
||||
# Optional dependency: do not import into __init__.py
|
||||
__all__ = ('require_auth', )
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
'''
|
||||
|
||||
from functools import wraps
|
||||
from typing import Any, Iterable, MutableMapping, TypeVar
|
||||
from typing import Any, Callable, Iterable, MutableMapping, TypeVar
|
||||
import warnings
|
||||
|
||||
from suou.classtools import MISSING
|
||||
|
||||
_T = TypeVar('_T')
|
||||
|
||||
def makelist(l: Any, *, wrap: bool = True) -> list:
|
||||
def makelist(l: Any, *, wrap: bool = True) -> list | Callable[Any, list]:
|
||||
'''
|
||||
Make a list out of an iterable or a single value.
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ def symbol_table(*args: Iterable[tuple | TokenSym], whitespace: str | None = Non
|
|||
yield TokenSym('[' + re.escape(whitespace) + ']+', '', discard=True)
|
||||
|
||||
|
||||
symbol_table: Callable[..., list]
|
||||
|
||||
def ilex(text: str, table: Iterable[TokenSym], *, whitespace = False):
|
||||
"""
|
||||
|
|
@ -80,5 +81,6 @@ def ilex(text: str, table: Iterable[TokenSym], *, whitespace = False):
|
|||
raise InconsistencyError
|
||||
i = mo.end(0)
|
||||
|
||||
lex = makelist(ilex)
|
||||
lex: Callable[..., list] = makelist(ilex)
|
||||
|
||||
__all__ = ('symbol_table', 'lex', 'ilex')
|
||||
|
|
@ -117,6 +117,6 @@ class SiqField(Field):
|
|||
def python_value(self, value: bytes) -> Siq:
|
||||
return Siq.from_bytes(value)
|
||||
|
||||
|
||||
# Optional dependency: do not import into __init__.py
|
||||
__all__ = ('connect_reconnect', 'RegexCharField', 'SiqField')
|
||||
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ def require_auth_base(cls: type[DeclarativeBase], *, src: AuthSrc, column: str |
|
|||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
# Optional dependency: do not import into __init__.py
|
||||
__all__ = (
|
||||
'IdType', 'id_column', 'entity_base', 'declarative_base', 'token_signer', 'match_column', 'match_constraint',
|
||||
'author_pair', 'age_pair', 'require_auth_base', 'want_column'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
"""
|
||||
Utilities for marshmallow, a schema-agnostic serializer/deserializer.
|
||||
Miscellaneous validator closures.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue