Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add payload and modify check function for <a> tags #2

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions ava/actives/xss.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import string
from urllib.parse import urlparse
from urllib.parse import urlparse, unquote
from bs4 import BeautifulSoup
from ava.common import utility
from ava.common.check import _ValueCheck
from ava.common.constant import HTTP
import re

# metadata
name = __name__
Expand Down Expand Up @@ -80,7 +81,9 @@ class CrossSiteScriptingLinkCheck(_ValueCheck):
def __init__(self):
"""Define static payload"""
payloads = [
"javascript:{}()"
"javascript:{}()",
"%22);{}();//",
"%27);{}();//"
]

# generate random and add to payloads
Expand All @@ -102,13 +105,14 @@ def check(self, response, payload):
if 'Content-Type' in response.headers and HTTP.CONTENT_TYPE.HTML not in response.headers['Content-Type']:
return False

# check <a href="">
# look for payload in href attribute which starts with "javascript:"
soup = BeautifulSoup(response.text, "html.parser")
tags = soup.find("a", attrs={"href": payload})
if tags:
return True
else:
return False
tags = soup.findAll("a", attrs={"href": re.compile(r"^javascript:")})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the re.compile() going to execute multiple times with it being there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is going to execute multiple times but once per an instance. We can't avoid that without declaring a compiled pattern as a global variable. I think it's fine to stay here.

for tag in tags:
text = unquote(tag["href"][len("javascript:"):])
if self._random in utility.parse_javascript(text):
return True
return False


class CrossSiteScriptingScriptSrcCheck(_ValueCheck):
Expand Down
21 changes: 20 additions & 1 deletion tests/actives/test_actives_xss.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ def test_check_true_negative(self, check, response):

class TestCrossSiteScriptingLinkCheck:
payloads = [
"javascript:avascan()"
"javascript:avascan()",
'");avascan();//',
"%22);avascan();//",
"');avascan();//",
"%27);avascan();//"
]

@pytest.fixture
Expand All @@ -103,6 +107,16 @@ def test_check_true_positive(self, check, response):
test = check.check(response, check._payloads[0])
assert test

# true positive
response.text = '<html><head></head><body><a href=\'javascript:console.log("ava");avascan();//ava\'>Link</a></body></html>'
test = check.check(response, check._payloads[1])
assert test

# true positive urlencode
response.text = '<html><head></head><body><a href=\'javascript:console.log("ava%22);avascan();//ava\'>Link</a></body></html>'
test = check.check(response, check._payloads[2])
assert test

def test_check_true_negative(self, check, response):
response.headers = {'Content-Type': ''}

Expand All @@ -122,6 +136,11 @@ def test_check_true_negative(self, check, response):
test = check.check(response, check._payloads[0])
assert not test

# true negative escape
response.text = '<html><head></head><body><a href=\'javascript:console.log("ava\\");avascan();//ava\'>Link</a></body></html>'
test = check.check(response, check._payloads[1])
assert not test

# true negative application/json
response.text = '{<a href="javascript:avascan()">}'
response.headers['Content-Type'] = "application/json"
Expand Down