crgd is a king

remotes/1693045480750635534/spooky-22
Aevann1 2022-05-25 20:29:22 +02:00
parent 3c691595e5
commit 386db76c10
9 changed files with 35 additions and 32 deletions

View File

@ -472,17 +472,17 @@ class Submission(Base):
@property
@lazy
def is_video(self):
return self.url and any((self.url.lower().endswith(x) for x in ('.mp4','.webm','.mov'))) and embed_fullmatch_regex.fullmatch(self.url)
return self.url and any((self.url.lower().endswith(x) for x in ('.mp4','.webm','.mov'))) and is_safe_url(self.url)
@property
@lazy
def is_audio(self):
return self.url and any((self.url.lower().endswith(x) for x in ('.mp3','.wav','.ogg','.aac','.m4a','.flac'))) and embed_fullmatch_regex.fullmatch(self.url)
return self.url and any((self.url.lower().endswith(x) for x in ('.mp3','.wav','.ogg','.aac','.m4a','.flac'))) and is_safe_url(self.url)
@property
@lazy
def is_image(self):
if self.url and (self.url.lower().endswith('.webp') or self.url.lower().endswith('.jpg') or self.url.lower().endswith('.png') or self.url.lower().endswith('.gif') or self.url.lower().endswith('.jpeg') or self.url.lower().endswith('?maxwidth=9999') or self.url.lower().endswith('&fidelity=high')) and (self.url.startswith('/') or self.url.startswith(f'{SITE_FULL}/') or embed_fullmatch_regex.fullmatch(self.url)):
if self.url and (self.url.lower().endswith('.webp') or self.url.lower().endswith('.jpg') or self.url.lower().endswith('.png') or self.url.lower().endswith('.gif') or self.url.lower().endswith('.jpeg') or self.url.lower().endswith('?maxwidth=9999') or self.url.lower().endswith('&fidelity=high')) and is_safe_url(self.url):
return True
return False

View File

@ -6,6 +6,7 @@ from files.__main__ import db_session
from files.classes.sub import Sub
from files.classes.marsey import Marsey
from flask import request
import tldextract
SITE = environ.get("DOMAIN", '').strip()
SITE_NAME = environ.get("SITE_NAME", '').strip()
@ -875,7 +876,7 @@ proxies = {"http":"http://127.0.0.1:18080","https":"http://127.0.0.1:18080"}
blackjack = environ.get("BLACKJACK", "").strip()
approved_embed_hosts = [
approved_embed_hosts = {
SITE,
'rdrama.net',
'pcmemes.net',
@ -935,14 +936,17 @@ approved_embed_hosts = [
'typekit.net',
'postimg.cc',
'archive.org'
]
}
def is_safe_url(url):
return '\\' not in url and (url.startswith('/') or tldextract.extract(url).registered_domain in approved_embed_hosts)
hosts = "|".join(approved_embed_hosts).replace('.','\.')
image_check_regex = re.compile(f'!\[\]\(((?!(https:\/\/([a-z0-9-]+\.)*({hosts})\/|\/)).*?)\)', flags=re.A)
embed_fullmatch_regex = re.compile(f'https:\/\/([a-z0-9-]+\.)*({hosts})\/[\w:~,()\-.#&\/=?@%;+]*', flags=re.A)
video_sub_regex = re.compile(f'(<p>[^<]*)(https:\/\/([a-z0-9-]+\.)*({hosts})\/[\w:~,()\-.#&\/=?@%;+]*?\.(mp4|webm|mov))', flags=re.A)
audio_sub_regex = re.compile(f'(<p>[^<]*)(https:\/\/([a-z0-9-]+\.)*({hosts})\/[\w:~,()\-.#&\/=?@%;+]*?\.(mp3|wav|ogg|aac|m4a|flac))', flags=re.A)

View File

@ -53,16 +53,13 @@ def allowed_attributes(tag, name, value):
return False
if tag == 'a':
if name == 'href': return True
if name == 'href' and '\\' not in value: return True
if name == 'rel' and value == 'nofollow noopener noreferrer': return True
if name == 'target' and value == '_blank': return True
return False
if tag == 'img':
if name in ['src','data-src']:
if value.startswith('/') or value.startswith(f'{SITE_FULL}/') or embed_fullmatch_regex.fullmatch(value): return True
else: return False
if name in ['src','data-src']: return is_safe_url(value)
if name == 'loading' and value == 'lazy': return True
if name == 'data-bs-toggle' and value == 'tooltip': return True
if name in ['g','b'] and not value: return True
@ -81,13 +78,12 @@ def allowed_attributes(tag, name, value):
return False
if tag == 'source':
if name == 'src' and embed_fullmatch_regex.fullmatch(value): return True
return False
if name == 'src': return is_safe_url(value)
if tag == 'audio':
if name == 'src': return is_safe_url(value)
if name == 'controls' and value == '': return True
if name == 'preload' and value == 'none': return True
if name == 'src' and embed_fullmatch_regex.fullmatch(value): return True
return False
if tag == 'p':
@ -349,7 +345,7 @@ def sanitize(sanitized, alert=False, comment=False, edit=False):
def allowed_attributes_emojis(tag, name, value):
if tag == 'img':
if name == 'src' and value.startswith('/'): return True
if name == 'src' and value.startswith('/') and '\\' not in value: return True
if name == 'loading' and value == 'lazy': return True
if name == 'data-bs-toggle' and value == 'tooltip': return True
if name == 'g' and not value: return True

View File

@ -660,6 +660,8 @@ def badge_grant_post(v):
if desc: new_badge.description = desc
url = request.values.get("url")
if '\\' in url: abort(400)
if url: new_badge.url = url
g.db.add(new_badge)

View File

@ -72,5 +72,5 @@ def allow_nsfw():
redir = request.values.get("redir")
if redir:
if redir.startswith(f'{SITE_FULL}/'): return redirect(redir)
if redir.startswith('/'): return redirect(f'{SITE_FULL}{redir}')
if redir.startswith('/') and '\\' not in redir: return redirect(f'{SITE_FULL}{redir}')
return redirect('/')

View File

@ -11,11 +11,11 @@ def login_get(v):
redir = request.values.get("redirect")
if redir:
redir = redir.replace("/logged_out", "").strip()
if not redir.startswith(f'{SITE_FULL}/') and not redir.startswith('/'): redir = None
if not redir.startswith(f'{SITE_FULL}/') and not (redir.startswith('/') and '\\' not in redir): redir = None
if v and redir:
if redir.startswith(f'{SITE_FULL}/'): return redirect(redir)
elif redir.startswith('/'): return redirect(f'{SITE_FULL}{redir}')
elif redir.startswith('/') and '\\' not in redir: return redirect(f'{SITE_FULL}{redir}')
return render_template("login.html", failed=False, redirect=redir)
@ -150,11 +150,11 @@ def login_post():
redir = request.values.get("redirect")
if redir:
redir = redir.replace("/logged_out", "").strip()
if not redir.startswith(f'{SITE_FULL}/') and not redir.startswith('/'): redir = '/'
if not redir.startswith(f'{SITE_FULL}/') and not (redir.startswith('/') and '\\' not in redir): redir = '/'
if redir:
if redir.startswith(f'{SITE_FULL}/'): return redirect(redir)
if redir.startswith('/'): return redirect(f'{SITE_FULL}{redir}')
if redir.startswith('/') and '\\' not in redir: return redirect(f'{SITE_FULL}{redir}')
return redirect('/')
@app.get("/me")

View File

@ -585,7 +585,7 @@ def thumbnail_thread(pid):
return f"https://{fragment_url.split('https://')[1]}"
elif fragment_url.startswith('//'):
return f"https:{fragment_url}"
elif fragment_url.startswith('/'):
elif fragment_url.startswith('/') and '\\' not in url:
parsed_url = urlparse(post_url)
return f"https://{parsed_url.netloc}{fragment_url}"
else:
@ -601,7 +601,8 @@ def thumbnail_thread(pid):
fetch_url = post.url
if fetch_url.startswith('/'): fetch_url = f"{SITE_FULL}{fetch_url}"
if fetch_url.startswith('/') and '\\' not in url:
fetch_url = f"{SITE_FULL}{fetch_url}"
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36"}
@ -854,9 +855,11 @@ def api_is_repost():
@auth_required
def submit_post(v, sub=None):
title = request.values.get("title", "").strip()[:500].replace('','')
url = request.values.get("url", "").strip()
if '\\' in url: abort(400)
title = request.values.get("title", "").strip()[:500].replace('','')
body = request.values.get("body", "").strip().replace('','')
@ -1516,7 +1519,7 @@ def api_pin_post(post_id, v):
def get_post_title(v):
url = request.values.get("url")
if not url: abort(400)
if not url or '\\' in url: abort(400)
try: x = requests.get(url, headers=titleheaders, timeout=5, proxies=proxies)
except: abort(400)

View File

@ -641,9 +641,8 @@ def settings_profilecss(v):
urls = list(css_regex.finditer(profilecss)) + list(css_regex2.finditer(profilecss))
for i in urls:
url = i.group(1)
if url.startswith('/'): continue
domain = tldextract.extract(url).registered_domain
if domain not in approved_embed_hosts:
if not is_safe_url(url):
domain = tldextract.extract(url).registered_domain
error = f"The domain '{domain}' is not allowed, please use one of these domains\n\n{approved_embed_hosts}."
return render_template("settings_profilecss.html", error=error, v=v)

View File

@ -341,9 +341,8 @@ def post_sub_css(v, sub):
urls = list(css_regex.finditer(css)) + list(css_regex2.finditer(css))
for i in urls:
url = i.group(1)
if url.startswith('/'): continue
domain = tldextract.extract(url).registered_domain
if domain not in approved_embed_hosts:
if not is_safe_url(url):
domain = tldextract.extract(url).registered_domain
error = f"The domain '{domain}' is not allowed, please use one of these domains\n\n{approved_embed_hosts}."
return render_template('sub/settings.html', v=v, sidebar=sub.sidebar, sub=sub, error=error)