Skip to content

Commit 1bb31a0

Browse files
committed
Update demo with timing code
1 parent e6eb230 commit 1bb31a0

18 files changed

+1250
-12
lines changed

.ropeproject/globalnames

-3
This file was deleted.
File renamed without changes.

csas/.ropeproject/globalnames

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
�}qUxss_demo_no_close]q(Usend_key_sequenceqUgenerate_all_payloadsqUCliqUCONTEXTSqUgenerate_payloadqU make_driverqU
2+
get_configq Umainq
3+
U handle_alertq es.
File renamed without changes.
File renamed without changes.

csas/run_csas.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env bash
2+
3+
dir=`pwd`
4+
5+
cd csas && vagrant up --provision
6+
7+
while true; do
8+
vagrant ssh -c 'mysql -uroot -pcsas -e "USE csas; TRUNCATE TABLE post;"'
9+
echo "Running demonstration with csas enabled"
10+
# Run the Python script to do the XSS injections
11+
python ${dir}/xss_demo.py --url http://localhost:8081
12+
done
13+

csas/xss_demo.py

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
#!/usr/bin/env python
2+
3+
4+
import argparse
5+
import os
6+
import random
7+
import subprocess
8+
import textwrap
9+
import time
10+
from argparse import RawTextHelpFormatter
11+
12+
import anyconfig
13+
from selenium import webdriver
14+
from selenium.webdriver.common.alert import Alert
15+
from selenium.common.exceptions import NoAlertPresentException
16+
17+
18+
CONTEXTS = [
19+
'HTML_PCDATA',
20+
'HTML_QUOTED',
21+
'HTML_UNQUOTED',
22+
'URL_START',
23+
'URL_QUERY',
24+
'URL_GENERAL',
25+
'JS_STRING',
26+
]
27+
28+
29+
class Cli:
30+
31+
def __init__(self):
32+
self.__parser = self.__setup_argparser()
33+
self.args = self.__parser.parse_args()
34+
35+
def __setup_argparser(self):
36+
parser = argparse.ArgumentParser(prog='php_csas_demo',
37+
formatter_class=RawTextHelpFormatter,
38+
description=textwrap.dedent('''\
39+
___ __ _____ ____________ ____
40+
/ _ \/ // / _ \____/ ___/ __/ _ | / __/
41+
/ ___/ _ / ___/___/ /___\ \/ __ |_\ \
42+
/_/ /_//_/_/ \___/___/_/ |_/___/
43+
44+
------------------------------------------
45+
PHP-CSAS DEMO
46+
Version: 0.1.0
47+
------------------------------------------
48+
'''),
49+
epilog=textwrap.dedent('''\
50+
Author: Jared M. Smith
51+
52+
''')
53+
)
54+
55+
parser.add_argument('--url', required=True, dest='url',
56+
help=textwrap.dedent('''\
57+
The URL of the address to test against. Don't put an ending '/' on it.
58+
'''))
59+
parser.add_argument('--csas', required=False, action='store_true',
60+
dest='csas', default=True,
61+
help=textwrap.dedent('''\
62+
Whether CSAS is enabled on site.'''))
63+
parser.add_argument('--browser', required=False,
64+
dest='browser', default='firefox',
65+
choices=('firefox', 'chrome', 'ie', 'opera'),
66+
help=textwrap.dedent('''\
67+
Which browser to test with. Options are:
68+
"firefox", "chrome", "ie", or "opera".'''))
69+
parser.add_argument('--quiet', required=False, action='store_false',
70+
dest='log', default=False,
71+
help=textwrap.dedent('''\
72+
Whether to silence logging.'''))
73+
parser.add_argument('--logfile', required=False,
74+
dest='logfile', default='/tmp/php_csas_demo_log.out', type=str,
75+
help=textwrap.dedent('''\
76+
If logging is enabled, log to
77+
this filename.'''))
78+
return parser
79+
80+
81+
def make_driver(browser):
82+
if browser == 'firefox':
83+
return webdriver.Firefox()
84+
elif browser == 'chrome':
85+
return webdriver.Chrome()
86+
elif browser == 'ie':
87+
return webdriver.Ie()
88+
elif browser == 'opera':
89+
return webdriver.Opera()
90+
91+
92+
def get_config(config_file):
93+
try:
94+
return anyconfig.get(config_file)
95+
except Exception:
96+
raise ValueError('Invalid configuration file type. Try JSON or YAML.')
97+
98+
99+
def generate_payload(context):
100+
if context == 'HTML_PCDATA':
101+
options = [
102+
# "<b> bolded all day every day</b>",
103+
# "<i> italics rule</i>",
104+
"<h1>HACKED</h1>",
105+
"<script> alert('YOU HAVE BEEN HACKED'); </script>",
106+
#'<input type="file" accept="video/*;capture=camcorder">',
107+
# '<input type="file" accept="audio/*;capture=microphone">',
108+
# '<img src="http://forklog.net/wp-content/uploads/2015/05/12035-hacked_article.jpg" />',
109+
# '<iframe width="420" height="315" src="https://www.youtube.com/embed/7t96m2ynKw0&autoplay=1" frameborder="0" allowfullscreen></iframe>'
110+
]
111+
return random.choice(options)
112+
elif context == 'HTML_QUOTED':
113+
return "xss\" onfocus=\"alert('HACKED AGAIN');"
114+
elif context == 'HTML_UNQUOTED':
115+
return "xss onfocus=alert('XSSSSSSS');"
116+
elif context == 'URL_START':
117+
return 'ftp://malware.net/h4xx0r_malware.exe'
118+
elif context == 'URL_GENERAL':
119+
return '&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3a;&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x27;&#x74;&#x72;&#x69;&#x63;&#x6b;&#x79;&#x20;&#x65;&#x6e;&#x63;&#x6f;&#x64;&#x69;&#x6e;&#x67;&#x21;&#x27;&#x29;&#x3b;'
120+
elif context == 'URL_QUERY':
121+
return 'javascript:alert(1337);'
122+
elif context == 'JS_STRING':
123+
options = [
124+
# '<script>alert(document.cookie + " YOU\'VE BEEN HACKED")</script>',
125+
'\'; alert(\'Hacked!\'); //',
126+
]
127+
return random.choice(options)
128+
129+
130+
def generate_all_payloads(contexts):
131+
for context in contexts:
132+
yield generate_payload(context)
133+
134+
135+
def send_key_sequence(element, sequence):
136+
for k in sequence:
137+
element.send_keys(k)
138+
139+
140+
def handle_alert(driver):
141+
# Maybe this should be Alert(driver).accept()
142+
try:
143+
Alert(driver).dismiss()
144+
except NoAlertPresentException:
145+
pass
146+
147+
148+
def main():
149+
global CONTEXTS
150+
cli = Cli()
151+
driver = make_driver(cli.args.browser)
152+
driver.maximize_window()
153+
driver.get(cli.args.url)
154+
handle_alert(driver)
155+
for i, payload in enumerate(generate_all_payloads(CONTEXTS)):
156+
subprocess.call(['vagrant ssh -c \'mysql -uroot -pcsas -e "USE csas; TRUNCATE TABLE post;"\''], shell=True)
157+
submit_form = True
158+
handle_alert(driver)
159+
160+
comment_form = driver.find_element_by_id('commentForm')
161+
comment_name = driver.find_element_by_name('commentName')
162+
comment_message = driver.find_element_by_name('message')
163+
comment_link = driver.find_element_by_name('link')
164+
165+
if i in [0, 6]:
166+
send_key_sequence(comment_message, payload)
167+
elif i == 1:
168+
submit_form = False
169+
send_key_sequence(comment_message, "Pre-filling the name field with a GET request in the URL parameters...")
170+
driver.get(cli.args.url + '/index.php?name=' + payload)
171+
time.sleep(1)
172+
comment_name = driver.find_element_by_name('commentName')
173+
comment_name.click()
174+
handle_alert(driver)
175+
elif i == 2:
176+
submit_form = False
177+
send_key_sequence(comment_name, "Pre-filling the message field with a GET request in the URL parameters...")
178+
driver.get(cli.args.url + '/index.php?msg=' + payload)
179+
time.sleep(1)
180+
comment_message = driver.find_element_by_name('message')
181+
comment_message.click()
182+
handle_alert(driver)
183+
elif i in [3, 4, 5]:
184+
send_key_sequence(comment_message, 'Check out this link!')
185+
send_key_sequence(comment_link, payload)
186+
else:
187+
send_key_sequence(comment_message, payload)
188+
send_key_sequence(comment_link, payload)
189+
190+
if submit_form:
191+
comment_form.submit()
192+
time.sleep(2)
193+
handle_alert(driver)
194+
195+
driver.close()
196+
197+
198+
if __name__ == '__main__':
199+
main()

0 commit comments

Comments
 (0)