mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2025-11-04 14:49:58 +08:00
update xss filter
This commit is contained in:
parent
03cf356bab
commit
a5fea0c653
@ -66,10 +66,11 @@ class WebsiteConfigAPITest(APITestCase):
|
|||||||
self.create_super_admin()
|
self.create_super_admin()
|
||||||
url = self.reverse("website_config_api")
|
url = self.reverse("website_config_api")
|
||||||
data = {"website_base_url": "http://test.com", "website_name": "test name",
|
data = {"website_base_url": "http://test.com", "website_name": "test name",
|
||||||
"website_name_shortcut": "test oj", "website_footer": "<a>test</a>",
|
"website_name_shortcut": "test oj", "website_footer": "<img onerror=alert(1) src=#>",
|
||||||
"allow_register": True, "submission_list_show_all": False}
|
"allow_register": True, "submission_list_show_all": False}
|
||||||
resp = self.client.post(url, data=data)
|
resp = self.client.post(url, data=data)
|
||||||
self.assertSuccess(resp)
|
self.assertSuccess(resp)
|
||||||
|
self.assertEqual(SysOptions.website_footer, "<img src=\"#\" />")
|
||||||
|
|
||||||
def test_get_website_config(self):
|
def test_get_website_config(self):
|
||||||
# do not need to login
|
# do not need to login
|
||||||
|
|||||||
@ -13,6 +13,7 @@ from judge.languages import languages, spj_languages
|
|||||||
from options.options import SysOptions
|
from options.options import SysOptions
|
||||||
from utils.api import APIView, CSRFExemptAPIView, validate_serializer
|
from utils.api import APIView, CSRFExemptAPIView, validate_serializer
|
||||||
from utils.shortcuts import send_email
|
from utils.shortcuts import send_email
|
||||||
|
from utils.xss_filter import XSSHtml
|
||||||
from .models import JudgeServer
|
from .models import JudgeServer
|
||||||
from .serializers import (CreateEditWebsiteConfigSerializer,
|
from .serializers import (CreateEditWebsiteConfigSerializer,
|
||||||
CreateSMTPConfigSerializer, EditSMTPConfigSerializer,
|
CreateSMTPConfigSerializer, EditSMTPConfigSerializer,
|
||||||
@ -84,6 +85,9 @@ class WebsiteConfigAPI(APIView):
|
|||||||
@super_admin_required
|
@super_admin_required
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
for k, v in request.data.items():
|
for k, v in request.data.items():
|
||||||
|
if k == "website_footer":
|
||||||
|
with XSSHtml() as parser:
|
||||||
|
v = parser.clean(v)
|
||||||
setattr(SysOptions, k, v)
|
setattr(SysOptions, k, v)
|
||||||
return self.success()
|
return self.success()
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,10 @@
|
|||||||
from django.contrib.postgres.fields import JSONField # NOQA
|
from django.contrib.postgres.fields import JSONField # NOQA
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from utils.xss_filter import XssHtml
|
from utils.xss_filter import XSSHtml
|
||||||
|
|
||||||
|
|
||||||
class RichTextField(models.TextField):
|
class RichTextField(models.TextField):
|
||||||
def get_prep_value(self, value):
|
def get_prep_value(self, value):
|
||||||
if not value:
|
with XSSHtml() as parser:
|
||||||
value = ""
|
return parser.clean(value or "")
|
||||||
parser = XssHtml()
|
|
||||||
parser.feed(value)
|
|
||||||
parser.close()
|
|
||||||
return parser.getHtml()
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ import copy
|
|||||||
from html.parser import HTMLParser
|
from html.parser import HTMLParser
|
||||||
|
|
||||||
|
|
||||||
class XssHtml(HTMLParser):
|
class XSSHtml(HTMLParser):
|
||||||
allow_tags = ['a', 'img', 'br', 'strong', 'b', 'code', 'pre',
|
allow_tags = ['a', 'img', 'br', 'strong', 'b', 'code', 'pre',
|
||||||
'p', 'div', 'em', 'span', 'h1', 'h2', 'h3', 'h4',
|
'p', 'div', 'em', 'span', 'h1', 'h2', 'h3', 'h4',
|
||||||
'h5', 'h6', 'blockquote', 'ul', 'ol', 'tr', 'th', 'td',
|
'h5', 'h6', 'blockquote', 'ul', 'ol', 'tr', 'th', 'td',
|
||||||
@ -53,7 +53,17 @@ class XssHtml(HTMLParser):
|
|||||||
self.start = []
|
self.start = []
|
||||||
self.data = []
|
self.data = []
|
||||||
|
|
||||||
def getHtml(self):
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
super().close()
|
||||||
|
|
||||||
|
def clean(self, content):
|
||||||
|
self.feed(content)
|
||||||
|
return self.get_html()
|
||||||
|
|
||||||
|
def get_html(self):
|
||||||
"""
|
"""
|
||||||
Get the safe html code
|
Get the safe html code
|
||||||
"""
|
"""
|
||||||
@ -188,11 +198,11 @@ class XssHtml(HTMLParser):
|
|||||||
|
|
||||||
|
|
||||||
if "__main__" == __name__:
|
if "__main__" == __name__:
|
||||||
parser = XssHtml()
|
with XSSHtml() as parser:
|
||||||
parser.feed("""<p><img src=1 onerror=alert(/xss/)></p><div class="left">
|
ret = parser.clean("""<p><img src=1 onerror=alert(/xss/)></p><div class="left">
|
||||||
<a href='javascript:prompt(1)'><br />hehe</a></div>
|
<a href='javascript:prompt(1)'><br />hehe</a></div>
|
||||||
<p id="test" onmouseover="alert(1)">>M<svg>
|
<p id="test" onmouseover="alert(1)">>M<svg>
|
||||||
<a href="https://www.baidu.com" target="self">MM</a></p>
|
<a href="https://www.baidu.com" target="self">MM</a></p>
|
||||||
<embed src='javascript:alert(/hehe/)' allowscriptaccess=always />""")
|
<embed src='javascript:alert(/hehe/)' allowscriptaccess=always />
|
||||||
parser.close()
|
<img onerror=alert(1) src=#>""")
|
||||||
print(parser.getHtml())
|
print(ret)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user