1919import urllib2
2020import urlparse
2121
22+ try :
23+ import websocket
24+ from websocket import WebSocketException
25+ except ImportError :
26+ class WebSocketException (Exception ):
27+ pass
28+
2229from extra .safe2bin .safe2bin import safecharencode
2330from lib .core .agent import agent
2431from lib .core .common import asciifyUrl
@@ -232,6 +239,7 @@ def getPage(**kwargs):
232239 retrying = kwargs .get ("retrying" , False )
233240 crawling = kwargs .get ("crawling" , False )
234241 skipRead = kwargs .get ("skipRead" , False )
242+ is_websocket = conf .url .startswith ("ws" )
235243
236244 if not urlparse .urlsplit (url ).netloc :
237245 url = urlparse .urljoin (conf .url , url )
@@ -364,7 +372,18 @@ def getPage(**kwargs):
364372 url = unicodeencode (url )
365373 post = unicodeencode (post , kb .pageEncoding )
366374
367- if method and method not in (HTTPMETHOD .GET , HTTPMETHOD .POST ):
375+ if is_websocket :
376+ # WebSocket will add Host field of headers automatically
377+ disallowed_headers = ['Host' ]
378+ ws = websocket .WebSocket ()
379+ ws .connect (url , header = ["%s: %s" % _ for _ in headers .items () if _ [0 ] not in disallowed_headers ], cookie = cookie )
380+ ws .send (urldecode (post ) if post else '' )
381+ response = ws .recv ()
382+ ws .close ()
383+ # WebSocket class does not have response headers
384+ return response , {}, 101
385+
386+ elif method and method not in (HTTPMETHOD .GET , HTTPMETHOD .POST ):
368387 method = unicodeencode (method )
369388 req = MethodRequest (url , post , headers )
370389 req .set_method (method )
@@ -538,13 +557,13 @@ def getPage(**kwargs):
538557 debugMsg = "got HTTP error code: %d (%s)" % (code , status )
539558 logger .debug (debugMsg )
540559
541- except (urllib2 .URLError , socket .error , socket .timeout , httplib .BadStatusLine , httplib .IncompleteRead , httplib .ResponseNotReady , struct .error , ProxyError , SqlmapCompressionException ), e :
560+ except (urllib2 .URLError , socket .error , socket .timeout , httplib .BadStatusLine , httplib .IncompleteRead , httplib .ResponseNotReady , struct .error , ProxyError , SqlmapCompressionException , WebSocketException ), e :
542561 tbMsg = traceback .format_exc ()
543562
544563 if "no host given" in tbMsg :
545564 warnMsg = "invalid URL address used (%s)" % repr (url )
546565 raise SqlmapSyntaxException (warnMsg )
547- elif "forcibly closed" in tbMsg :
566+ elif "forcibly closed" in tbMsg or "Connection is already closed" in tbMsg :
548567 warnMsg = "connection was forcibly closed by the target URL"
549568 elif "timed out" in tbMsg :
550569 if kb .testMode and kb .testType not in (None , PAYLOAD .TECHNIQUE .TIME , PAYLOAD .TECHNIQUE .STACKED ):
@@ -563,6 +582,10 @@ def getPage(**kwargs):
563582 elif "IncompleteRead" in tbMsg :
564583 warnMsg = "there was an incomplete read error while retrieving data "
565584 warnMsg += "from the target URL"
585+ elif "Handshake status" in tbMsg :
586+ status = re .search ("Handshake status ([\d]{3})" , tbMsg )
587+ errMsg = "websocket handshake status %s" % status .group (1 ) if status else 'unknown'
588+ raise SqlmapConnectionException (errMsg )
566589 else :
567590 warnMsg = "unable to connect to the target URL"
568591
0 commit comments