-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathselenium-auth.py
More file actions
212 lines (174 loc) · 8.29 KB
/
selenium-auth.py
File metadata and controls
212 lines (174 loc) · 8.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# The sendingRequest and responseReceived functions will be called for all requests/responses sent/received by ZAP,
# including automated tools (e.g. active scanner, fuzzer, ...)
# Note that new HttpSender scripts will initially be disabled
# Right click the script in the Scripts tree and select "enable"
# 'initiator' is the component the initiated the request:
# 1 PROXY_INITIATOR
# 2 ACTIVE_SCANNER_INITIATOR
# 3 SPIDER_INITIATOR
# 4 FUZZER_INITIATOR
# 5 AUTHENTICATION_INITIATOR
# 6 MANUAL_REQUEST_INITIATOR
# 7 CHECK_FOR_UPDATES_INITIATOR
# 8 BEAN_SHELL_INITIATOR
# 9 ACCESS_CONTROL_SCANNER_INITIATOR
# For the latest list of values see the HttpSender class:
# https://github.com/zaproxy/zaproxy/blob/master/src/org/parosproxy/paros/network/HttpSender.java
# 'helper' just has one method at the moment: helper.getHttpSender() which returns the HttpSender
# instance used to send the request.
#
# New requests can be made like this:
# msg2 = msg.cloneAll() // msg2 can then be safely changed as required without affecting msg
# helper.getHttpSender().sendAndReceive(msg2, false)
# print 'msg2 response=' + str(msg2.getResponseHeader().getStatusCode())
def sendingRequest(msg, initiator, helper):
#print 'sendingRequest called for url=' + msg.getRequestHeader().getURI().toString()
pass
def regparser(logoutIndicators, msg):
import re
for indicatorDict in logoutIndicators:
matches = []
if "STATUS" in indicatorDict:
regex = re.compile(indicatorDict["STATUS"])
matches.append(re.search(regex, str(msg.getResponseHeader().getStatusCode())))
if "HEADER" in indicatorDict:
regex = re.compile(indicatorDict["HEADER"])
matches.append(re.search(regex, msg.getResponseHeader().toString()))
if "BODY" in indicatorDict:
regex = re.compile(indicatorDict["BODY"])
matches.append(re.search(regex, msg.getResponseBody().toString()))
if "HEADER/i" in indicatorDict:
regex = re.compile(indicatorDict["HEADER/i"],re.IGNORECASE)
matches.append(re.search(regex, msg.getResponseHeader().toString()))
if "BODY/i" in indicatorDict:
regex = re.compile(indicatorDict["BODY/i"],re.IGNORECASE)
matches.append(re.search(regex, msg.getResponseBody().toString()))
if all(None != s for s in matches):
return True
return False
def responseReceived(msg, initiator, helper):
#print 'responseReceived called for url=' + msg.getRequestHeader().getURI().toString()
if msg.isInScope():
if initiator == 2 or initiator == 3 or initiator == 4 or initiator == 6:
logoutIndicators = []
#########################################################################
import os
import org.parosproxy.paros.model.Model as sess
sfil = sess.getSingleton().getSession().getFileName()
if sfil != "":
divider = '/'
import platform
if 'Windows' in platform.platform():
divider = '\\'
patth = sfil.rpartition(divider)[0]
basename = sfil.split(divider)[-1].split(".session")[0]
import re
if not os.path.isfile(patth + divider + basename + ".json"):
print "SAVE AUTHENTICATION SETTINGS! OR DISABLE AUTH SCCRIPT"
return
f = open(patth + divider + basename + ".json", 'r')
text = f.read()
results = re.findall('{.*?}', text)
for result in results:
try:
eval("logoutIndicators.append(" + result + ")")
except SyntaxError:
print "The JSON is invalid! Please check your input!"
loginTestcase = patth + divider + basename + ".html"
loginVerificationRequest = patth + divider + basename + ".raw"
else:
print "Save session first!"
return
#########################################################################
errorScreens = divider.join(loginTestcase.split(divider)[0:-1]) + divider + "errorScreens"
if regparser(logoutIndicators, msg) is True:
print "Current request appears to be logged out"
verifyMsg = sendVerificationMessage(loginVerificationRequest, helper, msg)
if verifyMsg is None or regparser(logoutIndicators, verifyMsg) is True:
if os.path.isfile(loginTestcase):
authenticate(msg, initiator, helper, loginTestcase, errorScreens)
else:
print "Login Testcase is invalid"
else:
pass
print "Session is still valid!"
else:
pass
#print "rcv-ignore authenticated"
else:
pass
#print "via-proxy " + str(msg.getResponseHeader().getStatusCode())
else:
pass
#print "msg out of scope"
def sendVerificationMessage(verifyMsgPath, helper, msg):
import org.parosproxy.paros.network.HttpMessage
import org.parosproxy.paros.network.HttpRequestHeader
import os.path
verifyMsg = org.parosproxy.paros.network.HttpMessage()
f = open(verifyMsgPath, 'r')
verifyMsg.setRequestHeader(org.parosproxy.paros.network.HttpRequestHeader(str(f.read())))
if resendMessageWithSession(verifyMsg, helper, getZAPsessionSite(msg).getActiveSession()) is False:
print "Auth required"
return None
return verifyMsg
def authenticate(msg, initiator, helper, loginTestcase, errorScreens):
print "AUTHENTICATION REQUIRED! Your initiator is: " + str(initiator) + " URL: " + msg.getRequestHeader().getURI().toString()
sessionSite = getZAPsessionSite(msg)
seleniumSession = "Auth-Selenium"
import org.zaproxy.zap.extension.script.ScriptVars as vars
if vars.getGlobalVar("auth_running") == "True":
print "Another authentication is running... waiting..."
import time
mustend = time.time() + 30
while time.time() < mustend:
try:
time.sleep(1)
except:
print "Script was interruped, stop processing current message"
return
if vars.getGlobalVar("auth_running") != "True":
resendMessageWithSession(msg, helper, sessionSite.getHttpSession(seleniumSession))
return
print "Authentication timeout exceeded, discard message"
else:
#do auth
vars.setGlobalVar("auth_running", "True")
if sessionSite.getHttpSession(seleniumSession) is not None:
seleniumSession = "Re-Auth-Selenium " + str(sessionSite.getNextSessionId())
sessionSite.createEmptySession(seleniumSession)
firefoxBinary = 'FirefoxPortableDeveloper/linux/firefox'
import platform
if 'Windows' in platform.platform():
firefoxBinary = 'FirefoxPortable\FirefoxPortable.exe'
import subprocess as sub
#selenese = sub.Popen("java -jar selenese-runner-2.5.0.jar --strict-exit-code --proxy "+ str(getZAPproxy()) +" --no-proxy *.mozilla.com --screenshot-on-fail \"" + errorScreens + "\" --set-speed 100 --cli-args /private-window --cli-args about:blank \"" + loginTestcase + "\" --firefox " + firefoxBinary, stdout=sub.PIPE)
selenese = sub.Popen(["java", "-jar", "selenese-runner-2.5.0.jar", "--strict-exit-code", "--proxy", str(getZAPproxy()), "--no-proxy", "*.mozilla.com", "--screenshot-on-fail", errorScreens, "--set-speed", "100", "--cli-args", "-private-window", "--cli-args", "about:blank", loginTestcase, "--firefox", firefoxBinary], stdout=sub.PIPE)
output = selenese.communicate()[0]
returns = selenese.returncode
vars.setGlobalVar("auth_running", "False")
if returns != 0:
print "AUTHENTICATION FAILURE!"
print output
else:
print "Auth-SUCCESS"
resendMessageWithSession(msg, helper, sessionSite.getHttpSession(seleniumSession))
def resendMessageWithSession(msg, helper, httpSession):
if (httpSession is not None and httpSession.getTokenValuesCount() > 0):
import org.zaproxy.zap.session.CookieBasedSessionManagementHelper as sessionmgmt
sessionmgmt.processMessageToMatchSession(msg, httpSession)
helper.getHttpSender().sendAndReceive(msg, True);
#print 'Re-Send-Authenticated=' + str(msg.getResponseHeader().getStatusCode())
else:
print "There is no active session or the token is empty"
return False
def getZAPsessionSite(msg):
import org.parosproxy.paros.control.Control
import org.zaproxy.zap.extension.httpsessions.ExtensionHttpSessions
import org.zaproxy.zap.extension.httpsessions.HttpSessionsSite
zapsessions = org.parosproxy.paros.control.Control.getSingleton().getExtensionLoader().getExtension(org.zaproxy.zap.extension.httpsessions.ExtensionHttpSessions.NAME)
return zapsessions.getHttpSessionsSite(msg.getRequestHeader().getURI().getHost() + ":" + str(msg.getRequestHeader().getHostPort()), False)
def getZAPproxy():
import org.parosproxy.paros.model.Model
proxyConfig = org.parosproxy.paros.model.Model.getSingleton().getOptionsParam().getProxyParam();
return str(proxyConfig.getProxyIp()) + ":" + str(proxyConfig.getProxyPort())