Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a0290a2

Browse files
committed
Added support to connect directly also to Oracle - see #158
1 parent 1416cd0 commit a0290a2

7 files changed

Lines changed: 98 additions & 12 deletions

File tree

lib/core/common.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ def parseTargetDirect():
628628
dbmsDict = { "Microsoft SQL Server": [MSSQL_ALIASES, "python-pymssql", "http://pymssql.sourceforge.net/"],
629629
"MySQL": [MYSQL_ALIASES, "python-mysqldb", "http://mysql-python.sourceforge.net/"],
630630
"PostgreSQL": [PGSQL_ALIASES, "python-psycopg2", "http://initd.org/psycopg/"],
631-
"Oracle": [ORACLE_ALIASES, "", ""],
631+
"Oracle": [ORACLE_ALIASES, "python cx_Oracle", "http://cx-oracle.sourceforge.net/"],
632632
"SQLite": [SQLITE_ALIASES, "", ""],
633633
"Access": [ACCESS_ALIASES, "", ""],
634634
"Firebird": [FIREBIRD_ALIASES, "", ""] }
@@ -642,6 +642,8 @@ def parseTargetDirect():
642642
import MySQLdb
643643
elif dbmsName == "PostgreSQL":
644644
import psycopg2
645+
elif dbmsName == "Oracle":
646+
import cx_Oracle
645647
except ImportError, _:
646648
errMsg = "sqlmap requires %s third-party library " % data[1]
647649
errMsg += "in order to directly connect to the database "

lib/request/connect.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ def queryPage(value=None, place=None, content=False, getSeqMatcher=False, silent
268268
values = None
269269
select = False
270270

271+
if kb.dbms == "Oracle" and value.startswith("SELECT ") and " FROM " not in value:
272+
value = "%s FROM DUAL" % value
273+
271274
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
272275
for sqlStatement in sqlStatements:
273276
if value.lower().startswith(sqlStatement) and sqlTitle == "SQL SELECT statement":

lib/request/inject.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,9 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
356356
values = None
357357
select = False
358358

359+
if kb.dbms == "Oracle" and expression.startswith("SELECT ") and " FROM " not in expression:
360+
expression = "%s FROM DUAL" % expression
361+
359362
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
360363
for sqlStatement in sqlStatements:
361364
if expression.lower().startswith(sqlStatement) and sqlTitle == "SQL SELECT statement":
@@ -419,6 +422,9 @@ def goStacked(expression, silent=False):
419422
values = None
420423
select = False
421424

425+
if kb.dbms == "Oracle" and expression.startswith("SELECT ") and " FROM " not in expression:
426+
expression = "%s FROM DUAL" % expression
427+
422428
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
423429
for sqlStatement in sqlStatements:
424430
if expression.lower().startswith(sqlStatement) and sqlTitle == "SQL SELECT statement":

plugins/dbms/oracle/connector.py

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,72 @@
2222
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2323
"""
2424

25+
try:
26+
import cx_Oracle
27+
except ImportError, _:
28+
pass
29+
30+
from lib.core.data import logger
31+
from lib.core.exception import sqlmapConnectionException
32+
2533
from plugins.generic.connector import Connector as GenericConnector
2634

2735
class Connector(GenericConnector):
2836
"""
29-
Homepage:
30-
User guide:
31-
API:
37+
Homepage: http://cx-oracle.sourceforge.net/
38+
User guide: http://cx-oracle.sourceforge.net/README.txt
39+
API: http://cx-oracle.sourceforge.net/html/index.html
40+
Debian package: -
41+
License: http://cx-oracle.sourceforge.net/LICENSE.txt
42+
43+
Possible connectors: -
3244
"""
3345

3446
def __init__(self):
3547
GenericConnector.__init__(self)
48+
49+
def connect(self):
50+
self.initConnection()
51+
self.__dsn = cx_Oracle.makedsn(self.hostname, self.port, self.db)
52+
53+
try:
54+
self.connector = cx_Oracle.connect(dsn=self.__dsn, user=self.user, password=self.password, mode=cx_Oracle.SYSDBA)
55+
logger.info("successfully connected as SYSDBA")
56+
except (cx_Oracle.OperationalError, cx_Oracle.DatabaseError), _:
57+
try:
58+
self.connector = cx_Oracle.connect(dsn=self.__dsn, user=self.user, password=self.password)
59+
except (cx_Oracle.OperationalError, cx_Oracle.DatabaseError), msg:
60+
raise sqlmapConnectionException, msg
61+
62+
self.setCursor()
63+
self.connected()
64+
65+
def fetchall(self):
66+
try:
67+
return self.cursor.fetchall()
68+
except cx_Oracle.InterfaceError, msg:
69+
logger.log(8, msg)
70+
return None
71+
72+
def execute(self, query):
73+
logger.debug(query)
74+
75+
try:
76+
self.cursor.execute(query)
77+
except (cx_Oracle.DatabaseError), msg:
78+
logger.log(8, msg)
79+
except cx_Oracle.InternalError, msg:
80+
raise sqlmapConnectionException, msg
81+
82+
self.connector.commit()
83+
84+
def select(self, query):
85+
self.execute(query)
86+
return self.fetchall()
87+
88+
def setCursor(self):
89+
self.cursor = self.connector.cursor()
90+
91+
def close(self):
92+
self.cursor.close()
93+
self.connector.close()

plugins/dbms/oracle/enumeration.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2323
"""
2424

25+
from lib.core.common import getRange
2526
from lib.core.data import conf
2627
from lib.core.data import kb
2728
from lib.core.data import logger
@@ -49,7 +50,7 @@ def getRoles(self, query2=False):
4950
# Set containing the list of DBMS administrators
5051
areAdmins = set()
5152

52-
if kb.unionPosition:
53+
if kb.unionPosition or conf.direct:
5354
if query2:
5455
query = rootQuery["inband"]["query2"]
5556
condition = rootQuery["inband"]["condition2"]

plugins/dbms/oracle/fingerprint.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ def getFingerprint(self):
7878
return value
7979

8080
def checkDbms(self):
81+
logMsg = "testing Oracle"
82+
logger.info(logMsg)
83+
84+
if conf.direct:
85+
conf.dbmsConnector.connect()
86+
8187
if conf.dbms in ORACLE_ALIASES:
8288
setDbms("Oracle")
8389

@@ -86,18 +92,25 @@ def checkDbms(self):
8692
if not conf.extensiveFp:
8793
return True
8894

89-
logMsg = "testing Oracle"
90-
logger.info(logMsg)
91-
92-
payload = agent.fullPayload(" AND ROWNUM=ROWNUM")
93-
result = Request.queryPage(payload)
95+
# NOTE: SELECT ROWNUM=ROWNUM FROM DUAL does not work connecting
96+
# directly to the Oracle database
97+
if conf.direct:
98+
result = True
99+
else:
100+
payload = agent.fullPayload(" AND ROWNUM=ROWNUM")
101+
result = Request.queryPage(payload)
94102

95103
if result:
96104
logMsg = "confirming Oracle"
97105
logger.info(logMsg)
98106

99-
payload = agent.fullPayload(" AND LENGTH(SYSDATE)=LENGTH(SYSDATE)")
100-
result = Request.queryPage(payload)
107+
# NOTE: SELECT LENGTH(SYSDATE)=LENGTH(SYSDATE) FROM DUAL does
108+
# not work connecting directly to the Oracle database
109+
if conf.direct:
110+
result = True
111+
else:
112+
payload = agent.fullPayload(" AND LENGTH(SYSDATE)=LENGTH(SYSDATE)")
113+
result = Request.queryPage(payload)
101114

102115
if not result:
103116
warnMsg = "the back-end DMBS is not Oracle"

sqlmap.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
import sys
2727
import time
2828
import traceback
29+
import warnings
30+
31+
warnings.filterwarnings(action="ignore", message=".*was already imported", category=UserWarning)
2932

3033
try:
3134
import psyco

0 commit comments

Comments
 (0)