mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-06 20:51:31 +00:00
Compare commits
539 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d465007dfe | ||
|
|
26c8423806 | ||
|
|
26cb07cc26 | ||
|
|
48c55d15ea | ||
|
|
1e03b23ccb | ||
|
|
70168855f9 | ||
|
|
7567ed2f71 | ||
|
|
33c110ac39 | ||
|
|
43eedb63a8 | ||
|
|
4eb5bbd75d | ||
|
|
07e6a0a079 | ||
|
|
4e938ea4fd | ||
|
|
fcb31b85b6 | ||
|
|
e0940438b3 | ||
|
|
01e915e199 | ||
|
|
ba7ab21596 | ||
|
|
bbf7472b42 | ||
|
|
ff61417fc0 | ||
|
|
14bf1e4ce7 | ||
|
|
c4e3ce1dac | ||
|
|
9a0a803025 | ||
|
|
9b46540e00 | ||
|
|
e7469ab570 | ||
|
|
10fe87fb4e | ||
|
|
bb7bd51d94 | ||
|
|
da15701a55 | ||
|
|
6b063e708e | ||
|
|
ba96261a28 | ||
|
|
552077f379 | ||
|
|
0f697418d9 | ||
|
|
bc5b643700 | ||
|
|
282d4b2bea | ||
|
|
9289939ced | ||
|
|
6831031cf7 | ||
|
|
6dc37628a0 | ||
|
|
7c7ecc75ec | ||
|
|
77cb85f2b8 | ||
|
|
9459d5ea15 | ||
|
|
1eeb6c1f5b | ||
|
|
bdf6452af6 | ||
|
|
3127d5bf54 | ||
|
|
9043d9dd05 | ||
|
|
faf154d2b3 | ||
|
|
9958d77572 | ||
|
|
dcb8025f30 | ||
|
|
4b0edeb199 | ||
|
|
ef42495318 | ||
|
|
4d93712c4d | ||
|
|
1ed59267df | ||
|
|
3cb48ffdc3 | ||
|
|
40393b29a0 | ||
|
|
1f0fb7ab48 | ||
|
|
05f92d5d45 | ||
|
|
89c6cc725b | ||
|
|
3275d9c709 | ||
|
|
f445fbe75b | ||
|
|
6b5db1f959 | ||
|
|
d3959e926e | ||
|
|
23ff1cadab | ||
|
|
dbd93e2670 | ||
|
|
89d13aaee4 | ||
|
|
09be7cb361 | ||
|
|
f8eed1f365 | ||
|
|
f82f1f912d | ||
|
|
015984a7f2 | ||
|
|
9b72545d09 | ||
|
|
4b020c4257 | ||
|
|
49586ad6dd | ||
|
|
83d79692ac | ||
|
|
afe497a954 | ||
|
|
915bc1fc99 | ||
|
|
e56c422a8c | ||
|
|
41c3139c01 | ||
|
|
b036fcc876 | ||
|
|
7356293007 | ||
|
|
c27820dc0e | ||
|
|
fbd42228f8 | ||
|
|
b278ee83c5 | ||
|
|
ffad7ed5fc | ||
|
|
557da5dee4 | ||
|
|
2f53014685 | ||
|
|
2dbd0267a1 | ||
|
|
b5c82c4685 | ||
|
|
df5a5c6fe8 | ||
|
|
95a28f2701 | ||
|
|
dc20c4f058 | ||
|
|
a21cbcb665 | ||
|
|
8d89389c36 | ||
|
|
4b75ca15e8 | ||
|
|
5037e43c99 | ||
|
|
e64cc86fc4 | ||
|
|
9387a005e3 | ||
|
|
9dcd18e41c | ||
|
|
2d129f3e58 | ||
|
|
5ced273b8a | ||
|
|
7d807bfdee | ||
|
|
5a71210c8a | ||
|
|
ef5cb9a460 | ||
|
|
14186d3150 | ||
|
|
8de2700edc | ||
|
|
bf3edcfc1c | ||
|
|
aa1020a3d1 | ||
|
|
e4d4861232 | ||
|
|
46ee69023e | ||
|
|
12602b8a51 | ||
|
|
87237c82d3 | ||
|
|
340e250fb1 | ||
|
|
3b3774abaa | ||
|
|
e7ffc8f9b1 | ||
|
|
bf83a4d1f8 | ||
|
|
8ed5e88be6 | ||
|
|
da1982c4af | ||
|
|
196ac25284 | ||
|
|
aecaa27839 | ||
|
|
eb62397c92 | ||
|
|
136342231e | ||
|
|
77e1383855 | ||
|
|
384f0b69ec | ||
|
|
49c1816f02 | ||
|
|
9da489a7de | ||
|
|
662a3c3d6f | ||
|
|
c7bb44b0a2 | ||
|
|
f4338952ac | ||
|
|
a3fe4be6c5 | ||
|
|
729247fd95 | ||
|
|
2647ac9abb | ||
|
|
9b9902bc6a | ||
|
|
6666188857 | ||
|
|
09e8c26f8a | ||
|
|
91348b28b4 | ||
|
|
663c15a1bf | ||
|
|
8189a10a5c | ||
|
|
f81e427353 | ||
|
|
3f6b53f5f3 | ||
|
|
59d97968a7 | ||
|
|
b1ef5d520c | ||
|
|
8cd257c893 | ||
|
|
10977ca530 | ||
|
|
cdd4007f11 | ||
|
|
c89c1e7abf | ||
|
|
9ba4da8820 | ||
|
|
58acc4a0bc | ||
|
|
034bac2a11 | ||
|
|
581e4103c0 | ||
|
|
eb862d03eb | ||
|
|
1248fe5eee | ||
|
|
daeb281e91 | ||
|
|
514ab3cc30 | ||
|
|
dc95558187 | ||
|
|
af890d639d | ||
|
|
8fe37f3564 | ||
|
|
9789d65c19 | ||
|
|
dfe6fe6060 | ||
|
|
ba883b77df | ||
|
|
27265f56ba | ||
|
|
ced9657d95 | ||
|
|
47edf134a2 | ||
|
|
8d46f67898 | ||
|
|
4d87b0ff67 | ||
|
|
6f750f9529 | ||
|
|
9562502744 | ||
|
|
b42c081c0e | ||
|
|
441a40e6e1 | ||
|
|
489390c3f8 | ||
|
|
5b382adc15 | ||
|
|
ab32ad4f48 | ||
|
|
0a42d91934 | ||
|
|
5eb9f5729c | ||
|
|
5b0d25ff25 | ||
|
|
4b00924826 | ||
|
|
f9ee0f4c0a | ||
|
|
5077844dd9 | ||
|
|
6fe827f0a4 | ||
|
|
683b587fa5 | ||
|
|
bd74a201d5 | ||
|
|
82aa481e06 | ||
|
|
1f375e418a | ||
|
|
ed26dc0235 | ||
|
|
e8f505b701 | ||
|
|
dddff45adb | ||
|
|
b3777995b2 | ||
|
|
a52328bfba | ||
|
|
a303d6712e | ||
|
|
e01a7908aa | ||
|
|
4b5457903a | ||
|
|
78da395506 | ||
|
|
44a8242d2f | ||
|
|
66e2fc302c | ||
|
|
bdc4457f34 | ||
|
|
ba356baab0 | ||
|
|
ae6235ce20 | ||
|
|
ef8530af5b | ||
|
|
3d88dc0a51 | ||
|
|
a31ac0376d | ||
|
|
8f13bda035 | ||
|
|
1adc66b763 | ||
|
|
2c270ed250 | ||
|
|
7074365f8e | ||
|
|
fd705c3dff | ||
|
|
db3bed3f44 | ||
|
|
7672b9a0a2 | ||
|
|
17b79cd21b | ||
|
|
36b69bbe79 | ||
|
|
daa915a6f2 | ||
|
|
01dba5c505 | ||
|
|
b5db4dc15a | ||
|
|
915d2bdec0 | ||
|
|
7eb45b9d8f | ||
|
|
669afdd81b | ||
|
|
21ce71bee8 | ||
|
|
40f067aa17 | ||
|
|
6cdb90ddf8 | ||
|
|
c0d4db3aba | ||
|
|
d086b2aca0 | ||
|
|
7cf4b0e1d2 | ||
|
|
660036c38b | ||
|
|
0a3144ebb5 | ||
|
|
02d66db7e0 | ||
|
|
c94bddd924 | ||
|
|
aea3749015 | ||
|
|
204c1950fc | ||
|
|
17be4d6374 | ||
|
|
d7ba7150ce | ||
|
|
d31d2eeb27 | ||
|
|
c74c58c47e | ||
|
|
d16252e959 | ||
|
|
9fef4336b0 | ||
|
|
aa7af33fd5 | ||
|
|
241c6b02f0 | ||
|
|
915ee5ce53 | ||
|
|
beee81697c | ||
|
|
880545cad4 | ||
|
|
5274c88c7d | ||
|
|
9a221470e7 | ||
|
|
256ec75580 | ||
|
|
debb64167a | ||
|
|
49514adcd9 | ||
|
|
02b78d2691 | ||
|
|
82e3c48c8c | ||
|
|
243b564b6a | ||
|
|
cb72223452 | ||
|
|
bf207a7ea6 | ||
|
|
3b4e44a38d | ||
|
|
97cf5b9ace | ||
|
|
ba617c49a4 | ||
|
|
929df9bc34 | ||
|
|
48cdc6a308 | ||
|
|
3b7ef42b30 | ||
|
|
bdddc5c333 | ||
|
|
8ceff3dcc7 | ||
|
|
fcfbc5d59f | ||
|
|
12883cac16 | ||
|
|
9f75fd4fb8 | ||
|
|
54d0678cbe | ||
|
|
30497acd0c | ||
|
|
ed0420e635 | ||
|
|
094ce29709 | ||
|
|
ddd8712c4f | ||
|
|
37449262df | ||
|
|
45c699e9cf | ||
|
|
e22fab1945 | ||
|
|
e3134cc965 | ||
|
|
5957aad738 | ||
|
|
4c4de54ad8 | ||
|
|
590e8ed5ae | ||
|
|
12427ff6f8 | ||
|
|
45d0010323 | ||
|
|
e18b41fc82 | ||
|
|
586c461ae6 | ||
|
|
c799e794f2 | ||
|
|
b31c264a59 | ||
|
|
a569f21ad7 | ||
|
|
8092551fa9 | ||
|
|
83972d405f | ||
|
|
de0df99d8e | ||
|
|
ddee027afb | ||
|
|
6ce0350abc | ||
|
|
37de01e993 | ||
|
|
63cca82288 | ||
|
|
7d1c2633c9 | ||
|
|
9564c8e8b1 | ||
|
|
5e099144d3 | ||
|
|
a007cd30e5 | ||
|
|
4c9e0b9f1e | ||
|
|
0c3fbc46df | ||
|
|
107d9f90ad | ||
|
|
daafe9b74a | ||
|
|
9727f0d691 | ||
|
|
61e0459ec8 | ||
|
|
c5802a5367 | ||
|
|
01d5da18e3 | ||
|
|
b288bfdbc3 | ||
|
|
1e508547d8 | ||
|
|
4fe4c582c1 | ||
|
|
28e7c8f378 | ||
|
|
c497aa98ed | ||
|
|
4ba9e9397c | ||
|
|
eedfa8c888 | ||
|
|
c224ea0e37 | ||
|
|
f544554475 | ||
|
|
c7c7e30130 | ||
|
|
d1426a023f | ||
|
|
83a1b9b2e7 | ||
|
|
38684ec220 | ||
|
|
2e5edce8b9 | ||
|
|
a02662f03f | ||
|
|
2c95b65eac | ||
|
|
e47c1aa61b | ||
|
|
f81062d595 | ||
|
|
ef911b6be4 | ||
|
|
4f1b0787ed | ||
|
|
070e173067 | ||
|
|
f04584bb68 | ||
|
|
66d26f67bf | ||
|
|
101d1f0d49 | ||
|
|
843126702d | ||
|
|
65f227fe65 | ||
|
|
536d9a597e | ||
|
|
0ce2128a9b | ||
|
|
e7ed2bbcbb | ||
|
|
560ff4154b | ||
|
|
1d0d5f1675 | ||
|
|
f1a3c81aec | ||
|
|
277a4fa402 | ||
|
|
037db0f4a0 | ||
|
|
3f1bf742fc | ||
|
|
abb911d741 | ||
|
|
dc5edf1a86 | ||
|
|
e11febdcbc | ||
|
|
f2af8861f9 | ||
|
|
2895e5c20f | ||
|
|
b1e8c75672 | ||
|
|
6cc52cc12a | ||
|
|
ddf353b86e | ||
|
|
e6535d359d | ||
|
|
90e381a5a5 | ||
|
|
e99e9919cd | ||
|
|
dbdfbcc425 | ||
|
|
1d6832a84a | ||
|
|
73d83280fe | ||
|
|
1bd8c519c3 | ||
|
|
a4fdbf1343 | ||
|
|
130879fbf3 | ||
|
|
db5ae9ae0b | ||
|
|
cc4833429f | ||
|
|
703b7079a4 | ||
|
|
ef52ee977f | ||
|
|
ba1b4c50be | ||
|
|
1e7dfe11b4 | ||
|
|
92febd22a8 | ||
|
|
83081b5e14 | ||
|
|
f2035145fe | ||
|
|
48b407c0fa | ||
|
|
4466504f30 | ||
|
|
dc65afe65a | ||
|
|
132e963b53 | ||
|
|
f52beff7c3 | ||
|
|
feb93dce44 | ||
|
|
e52422900e | ||
|
|
c045afd842 | ||
|
|
0d2db32539 | ||
|
|
77f4fd93e7 | ||
|
|
68f5597b4a | ||
|
|
411f56e710 | ||
|
|
fb95ab8c17 | ||
|
|
9f6e04b141 | ||
|
|
1f2bdf5a3d | ||
|
|
465a1e1a86 | ||
|
|
6af127cb64 | ||
|
|
880d438418 | ||
|
|
5efe3228f8 | ||
|
|
e005ba3f77 | ||
|
|
f2b4dc3ffc | ||
|
|
d1022f3f59 | ||
|
|
3984b94297 | ||
|
|
eba01ee74e | ||
|
|
36b660309b | ||
|
|
fd89fdf40b | ||
|
|
2e53096962 | ||
|
|
79e45bd8d7 | ||
|
|
ed5f4abebd | ||
|
|
03bbfdbc56 | ||
|
|
1b6365b195 | ||
|
|
d38a0542d8 | ||
|
|
9182b90b2b | ||
|
|
80af22435a | ||
|
|
065c5e8157 | ||
|
|
932aa8dd94 | ||
|
|
71208e891c | ||
|
|
3b369920a1 | ||
|
|
68a83098ab | ||
|
|
f4a0820dcb | ||
|
|
459e1dd9a4 | ||
|
|
4b698748f7 | ||
|
|
e697354765 | ||
|
|
721046831b | ||
|
|
a4068f9abf | ||
|
|
245c5e64e9 | ||
|
|
cd08d13647 | ||
|
|
8abae02111 | ||
|
|
dd9bfd13f2 | ||
|
|
0c7eecee9f | ||
|
|
3e72da66f9 | ||
|
|
ca9a56c0ff | ||
|
|
2d2b20344d | ||
|
|
a8a7dee800 | ||
|
|
35d9ed8476 | ||
|
|
a5e3dce26f | ||
|
|
71448b1c16 | ||
|
|
a633bc7f32 | ||
|
|
6697e49f75 | ||
|
|
db8bcd1d2e | ||
|
|
16c052ef13 | ||
|
|
a8c0722631 | ||
|
|
c9a73aeed1 | ||
|
|
470b68a83c | ||
|
|
f01ae291f8 | ||
|
|
c36749c3bb | ||
|
|
63b84c31e5 | ||
|
|
ec253dd5bd | ||
|
|
4c25a20efc | ||
|
|
2b56bdfaa6 | ||
|
|
c37014b8e8 | ||
|
|
349e9b9fa5 | ||
|
|
ac481492c0 | ||
|
|
91c5151770 | ||
|
|
ad5a731999 | ||
|
|
95be19a692 | ||
|
|
dbcf030743 | ||
|
|
fa3f3baf1e | ||
|
|
f125f64a80 | ||
|
|
12012b36b1 | ||
|
|
43c9e21c56 | ||
|
|
a831865633 | ||
|
|
578c41f6de | ||
|
|
dc01f2e773 | ||
|
|
db327a8538 | ||
|
|
aefb815064 | ||
|
|
014978cebc | ||
|
|
287371337d | ||
|
|
62a3618353 | ||
|
|
366a3f9336 | ||
|
|
74d2b60cf3 | ||
|
|
9e892e93f3 | ||
|
|
0bbf5f9467 | ||
|
|
8be4b29fd1 | ||
|
|
0507234add | ||
|
|
c3d9a1c2d4 | ||
|
|
9e8b28be7c | ||
|
|
f3f4a4cb37 | ||
|
|
2280f3ff2d | ||
|
|
d6cf038e48 | ||
|
|
2dfc383700 | ||
|
|
f20e7b403a | ||
|
|
36e62fe8a7 | ||
|
|
2542b6d241 | ||
|
|
bc13d8923b | ||
|
|
e51db6b355 | ||
|
|
6d28ca1f93 | ||
|
|
03e4741a69 | ||
|
|
b899ab9eb3 | ||
|
|
2e017eee99 | ||
|
|
a296d22195 | ||
|
|
ad11749b15 | ||
|
|
75a64245c5 | ||
|
|
9e00202823 | ||
|
|
df977d93d4 | ||
|
|
b0ca52086a | ||
|
|
af89137f2c | ||
|
|
1f9bf587b5 | ||
|
|
f0e4c20004 | ||
|
|
cef416559a | ||
|
|
ce47b6c76e | ||
|
|
39108bc100 | ||
|
|
f63ceaa0c1 | ||
|
|
1e60378fb2 | ||
|
|
22c7bc54b4 | ||
|
|
5f1bae86b0 | ||
|
|
a0cbf6991d | ||
|
|
9f2bc00426 | ||
|
|
6bb486c1bf | ||
|
|
741ce9e3f0 | ||
|
|
a479655097 | ||
|
|
4846d85ccd | ||
|
|
3c439c3929 | ||
|
|
5cc36a5736 | ||
|
|
29dcdd3bef | ||
|
|
53eadb0af8 | ||
|
|
7b705b94e3 | ||
|
|
558484644a | ||
|
|
e84142b6a9 | ||
|
|
b44551230e | ||
|
|
4ecf6eee05 | ||
|
|
57be1856a6 | ||
|
|
a424e4ab59 | ||
|
|
4660b816d5 | ||
|
|
f92e1ebc40 | ||
|
|
48cd0421a6 | ||
|
|
4b4f728d8e | ||
|
|
e8336ecfe1 | ||
|
|
38ea0686a8 | ||
|
|
73b0de67b5 | ||
|
|
fae97b3937 | ||
|
|
c0947846f4 | ||
|
|
5e2d0bd320 | ||
|
|
4badb54607 | ||
|
|
29aaec8925 | ||
|
|
27ff5d6fec | ||
|
|
72ff6e24ff | ||
|
|
717c451b8c | ||
|
|
e5968cae31 | ||
|
|
2b55ae3e2a | ||
|
|
8f4488d608 | ||
|
|
f1254fef4b | ||
|
|
ccda26a567 | ||
|
|
099110bc1f | ||
|
|
0265b3fcfa | ||
|
|
961d2b24d1 | ||
|
|
53578bcb7c | ||
|
|
756f02fb0e | ||
|
|
17c170e1f8 | ||
|
|
220c1be162 | ||
|
|
6b06332896 | ||
|
|
c268663bd9 | ||
|
|
a97fd1dede | ||
|
|
b93284530e | ||
|
|
cf4c263a4e | ||
|
|
23777143b6 | ||
|
|
9b397f00be | ||
|
|
d47c16e196 | ||
|
|
e0c7b5c63c | ||
|
|
091c8ab2dd | ||
|
|
86303bde55 | ||
|
|
c89f119e1a | ||
|
|
25369ca591 | ||
|
|
a399b65033 | ||
|
|
ed37ae1562 | ||
|
|
5381d4d5be | ||
|
|
c1825b2651 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -3,6 +3,8 @@
|
||||
*.md5 text eol=lf
|
||||
*.py text eol=lf
|
||||
*.xml text eol=lf
|
||||
LICENSE text eol=lf
|
||||
COMMITMENT text eol=lf
|
||||
|
||||
*_ binary
|
||||
*.dll binary
|
||||
|
||||
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@@ -19,7 +19,7 @@
|
||||
* Client OS (e.g. `Microsoft Windows 10`)
|
||||
* Program version (`python sqlmap.py --version` or `sqlmap --version` depending on installation):
|
||||
* Target DBMS (e.g. `Microsoft SQL Server`):
|
||||
* Detected WAF/IDS/IPS protection (e.g. `ModSecurity` or `unknown`):
|
||||
* Detected WAF/IPS protection (e.g. `ModSecurity` or `unknown`):
|
||||
* SQLi techniques found by sqlmap (e.g. `error-based` and `boolean-based blind`):
|
||||
* Results of manual target assessment (e.g. found that the payload `query=test' AND 4113 IN ((SELECT 'foobar'))-- qKLV` works):
|
||||
* Relevant console output (if any):
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,6 +1,8 @@
|
||||
*.py[cod]
|
||||
output/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.sqlmap_history
|
||||
traffic.txt
|
||||
*~
|
||||
req*.txt
|
||||
.idea/
|
||||
46
COMMITMENT
Normal file
46
COMMITMENT
Normal file
@@ -0,0 +1,46 @@
|
||||
GPL Cooperation Commitment
|
||||
Version 1.0
|
||||
|
||||
Before filing or continuing to prosecute any legal proceeding or claim
|
||||
(other than a Defensive Action) arising from termination of a Covered
|
||||
License, we commit to extend to the person or entity ('you') accused
|
||||
of violating the Covered License the following provisions regarding
|
||||
cure and reinstatement, taken from GPL version 3. As used here, the
|
||||
term 'this License' refers to the specific Covered License being
|
||||
enforced.
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly
|
||||
and finally terminates your license, and (b) permanently, if the
|
||||
copyright holder fails to notify you of the violation by some
|
||||
reasonable means prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you
|
||||
have received notice of violation of this License (for any work)
|
||||
from that copyright holder, and you cure the violation prior to 30
|
||||
days after your receipt of the notice.
|
||||
|
||||
We intend this Commitment to be irrevocable, and binding and
|
||||
enforceable against us and assignees of or successors to our
|
||||
copyrights.
|
||||
|
||||
Definitions
|
||||
|
||||
'Covered License' means the GNU General Public License, version 2
|
||||
(GPLv2), the GNU Lesser General Public License, version 2.1
|
||||
(LGPLv2.1), or the GNU Library General Public License, version 2
|
||||
(LGPLv2), all as published by the Free Software Foundation.
|
||||
|
||||
'Defensive Action' means a legal proceeding or claim that We bring
|
||||
against you in response to a prior proceeding or claim initiated by
|
||||
you or your affiliate.
|
||||
|
||||
'We' means each contributor to this repository as of the date of
|
||||
inclusion of this file, including subsidiaries of a corporate
|
||||
contributor.
|
||||
|
||||
This work is available under a Creative Commons Attribution-ShareAlike
|
||||
4.0 International license (https://creativecommons.org/licenses/by-sa/4.0/).
|
||||
2
LICENSE
2
LICENSE
@@ -1,7 +1,7 @@
|
||||
COPYING -- Describes the terms under which sqlmap is distributed. A copy
|
||||
of the GNU General Public License (GPL) is appended to this file.
|
||||
|
||||
sqlmap is (C) 2006-2018 Bernardo Damele Assumpcao Guimaraes, Miroslav Stampar.
|
||||
sqlmap is (C) 2006-2019 Bernardo Damele Assumpcao Guimaraes, Miroslav Stampar.
|
||||
|
||||
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
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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.
|
||||
|
||||
**The sqlmap project is sponsored by [Netsparker Web Application Security Scanner](https://www.netsparker.com/?utm_source=github.com&utm_medium=referral&utm_content=sqlmap+repo&utm_campaign=generic+advert).**
|
||||
**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).**
|
||||
|
||||
Screenshots
|
||||
----
|
||||
@@ -67,3 +67,4 @@ Translations
|
||||
* [Russian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ru-RUS.md)
|
||||
* [Spanish](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-es-MX.md)
|
||||
* [Turkish](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-tr-TR.md)
|
||||
* [Ukrainian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-uk-UA.md)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Implemented support for automatic decoding of page content through detected charset.
|
||||
* Implemented mechanism for proper data dumping on DBMSes not supporting `LIMIT/OFFSET` like mechanism(s) (e.g. Microsoft SQL Server, Sybase, etc.).
|
||||
* Major improvements to program stabilization based on user reports.
|
||||
* Added new tampering scripts avoiding popular WAF/IPS/IDS mechanisms.
|
||||
* Added new tampering scripts avoiding popular WAF/IPS mechanisms.
|
||||
* Fixed major bug with DNS leaking in Tor mode.
|
||||
* Added wordlist compilation made of the most popular cracking dictionaries.
|
||||
* Implemented multi-processor hash cracking routine(s).
|
||||
@@ -23,7 +23,7 @@
|
||||
* Added option `--csv-del` for manually setting delimiting character used in CSV output.
|
||||
* Added switch `--hex` for using DBMS hex conversion function(s) for data retrieval.
|
||||
* Added switch `--smart` for conducting through tests only in case of positive heuristic(s).
|
||||
* Added switch `--check-waf` for checking of existence of WAF/IPS/IDS protection.
|
||||
* Added switch `--check-waf` for checking of existence of WAF/IPS protection.
|
||||
* Added switch `--schema` to enumerate DBMS schema: shows all columns of all databases' tables.
|
||||
* Added switch `--count` to count the number of entries for a specific table or all database(s) tables.
|
||||
* Major improvements to switches `--tables` and `--columns`.
|
||||
@@ -55,7 +55,7 @@
|
||||
* Added option `--host` to set the HTTP Host header value.
|
||||
* Added switch `--hostname` to turn on retrieval of DBMS server hostname.
|
||||
* Added switch `--hpp` to turn on the usage of HTTP parameter pollution WAF bypass method.
|
||||
* Added switch `--identify-waf` for turning on the thorough testing of WAF/IPS/IDS protection.
|
||||
* Added switch `--identify-waf` for turning on the thorough testing of WAF/IPS protection.
|
||||
* Added switch `--ignore-401` to ignore HTTP Error Code 401 (Unauthorized).
|
||||
* Added switch `--invalid-bignum` for usage of big numbers while invalidating values.
|
||||
* Added switch `--invalid-logical` for usage of logical operations while invalidating values.
|
||||
@@ -78,7 +78,7 @@
|
||||
* Added option `--skip` to skip testing of given parameter(s).
|
||||
* Added switch `--skip-static` to skip testing parameters that not appear to be dynamic.
|
||||
* Added switch `--skip-urlencode` to skip URL encoding of payload data.
|
||||
* Added switch `--skip-waf` to skip heuristic detection of WAF/IPS/IDS protection.
|
||||
* Added switch `--skip-waf` to skip heuristic detection of WAF/IPS protection.
|
||||
* Added switch `--smart` to conduct thorough tests only if positive heuristic(s).
|
||||
* Added option `--sql-file` for setting file(s) holding SQL statements to be executed (in case of stacked SQLi).
|
||||
* Added switch `--sqlmap-shell` to turn on interactive sqlmap shell prompt.
|
||||
|
||||
@@ -565,6 +565,9 @@ Efrain Torres, <et(at)metasploit.com>
|
||||
* for helping out to improve the Metasploit Framework sqlmap auxiliary module and for committing it on the Metasploit official subversion repository
|
||||
* for his great Metasploit WMAP Framework
|
||||
|
||||
Jennifer Torres, <jtorresf42(at)gmail.com>
|
||||
* for contributing a tamper script luanginx.py
|
||||
|
||||
Sandro Tosi, <matrixhasu(at)gmail.com>
|
||||
* for helping to create sqlmap Debian package correctly
|
||||
|
||||
@@ -597,6 +600,7 @@ Carlos Gabriel Vergara, <carlosgabrielvergara(at)gmail.com>
|
||||
|
||||
Patrick Webster, <patrick(at)aushack.com>
|
||||
* for suggesting an enhancement
|
||||
* for donating to sqlmap development (from OSI.Security)
|
||||
|
||||
Ed Williams, <ed.williams(at)ngssecure.com>
|
||||
* for suggesting a minor enhancement
|
||||
@@ -760,6 +764,12 @@ ultramegaman, <seclists(at)ultramegaman.com>
|
||||
Vinicius, <viniciusmaxdaloop(at)gmail.com>
|
||||
* for reporting a minor bug
|
||||
|
||||
virusdefender
|
||||
* for contributing WAF scripts safeline.py
|
||||
|
||||
w8ay
|
||||
* for contributing an implementation for chunked transfer-encoding (switch --chunked)
|
||||
|
||||
wanglei, <wanglei(at)17uxi.cn>
|
||||
* for reporting a minor bug
|
||||
|
||||
|
||||
@@ -15,11 +15,6 @@ This file lists bundled packages and their associated licensing terms.
|
||||
Copyright (C) 2013, Jonathan Hartley.
|
||||
* The Fcrypt library located under thirdparty/fcrypt/.
|
||||
Copyright (C) 2000, 2001, 2004 Carey Evans.
|
||||
* The Odict library located under thirdparty/odict/.
|
||||
Copyright (C) 2005, Nicola Larosa, Michael Foord.
|
||||
* The Oset library located under thirdparty/oset/.
|
||||
Copyright (C) 2010, BlueDynamics Alliance, Austria.
|
||||
Copyright (C) 2009, Raymond Hettinger, and others.
|
||||
* The PrettyPrint library located under thirdparty/prettyprint/.
|
||||
Copyright (C) 2010, Chris Hall.
|
||||
* The SocksiPy library located under thirdparty/socks/.
|
||||
@@ -281,6 +276,10 @@ be bound by the terms and conditions of this License Agreement.
|
||||
|
||||
* The bottle web framework library located under thirdparty/bottle/.
|
||||
Copyright (C) 2012, Marcel Hellkamp.
|
||||
* The ordereddict library located under thirdparty/odict/.
|
||||
Copyright (C) 2009, Raymond Hettinger.
|
||||
* The six Python 2 and 3 compatibility library located under thirdparty/six/.
|
||||
Copyright (C) 2010-2018, Benjamin Peterson.
|
||||
* The Termcolor library located under thirdparty/termcolor/.
|
||||
Copyright (C) 2008-2011, Volvox Development Team.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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 e инструмент за тестване и проникване, с отворен код, който автоматизира процеса на откриване и използване на недостатъците на SQL база данните чрез SQL инжекция, която ги взима от сървъра. Снабден е с мощен детектор, множество специални функции за най-добрия тестер и широк спектър от функции, които могат да се използват за множество цели - извличане на данни от базата данни, достъп до основната файлова система и изпълняване на команди на операционната система.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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 es una herramienta para pruebas de penetración "penetration testing" de software libre que automatiza el proceso de detección y explotación de fallos mediante inyección de SQL además de tomar el control de servidores de bases de datos. Contiene un poderoso motor de detección, así como muchas de las funcionalidades escenciales para el "pentester" y una amplia gama de opciones desde la recopilación de información para identificar el objetivo conocido como "fingerprinting" mediante la extracción de información de la base de datos, hasta el acceso al sistema de archivos subyacente para ejecutar comandos en el sistema operativo a través de conexiones alternativas conocidas como "Out-of-band".
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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** est un outil Open Source de test d'intrusion. Cet outil permet d'automatiser le processus de détection et d'exploitation des failles d'injection SQL afin de prendre le contrôle des serveurs de base de données. __sqlmap__ dispose d'un puissant moteur de détection utilisant les techniques les plus récentes et les plus dévastatrices de tests d'intrusion comme L'Injection SQL, qui permet d'accéder à la base de données, au système de fichiers sous-jacent et permet aussi l'exécution des commandes sur le système d'exploitation.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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 είναι πρόγραμμα ανοιχτού κώδικα, που αυτοματοποιεί την εύρεση και εκμετάλλευση ευπαθειών τύπου SQL Injection σε βάσεις δεδομένων. Έρχεται με μια δυνατή μηχανή αναγνώρισης ευπαθειών, πολλά εξειδικευμένα χαρακτηριστικά για τον απόλυτο penetration tester όπως και με ένα μεγάλο εύρος επιλογών αρχίζοντας από την αναγνώριση της βάσης δεδομένων, κατέβασμα δεδομένων της βάσης, μέχρι και πρόσβαση στο βαθύτερο σύστημα αρχείων και εκτέλεση εντολών στο απευθείας στο λειτουργικό μέσω εκτός ζώνης συνδέσεων.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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 je alat namijenjen za penetracijsko testiranje koji automatizira proces detekcije i eksploatacije sigurnosnih propusta SQL injekcije te preuzimanje poslužitelja baze podataka. Dolazi s moćnim mehanizmom za detekciju, mnoštvom korisnih opcija za napredno penetracijsko testiranje te široki spektar opcija od onih za prepoznavanja baze podataka, preko dohvaćanja podataka iz baze, do pristupa zahvaćenom datotečnom sustavu i izvršavanja komandi na operacijskom sustavu korištenjem tzv. "out-of-band" veza.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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 merupakan alat _(tool)_ bantu _open source_ dalam melakukan tes penetrasi yang mengotomasi proses deteksi dan eksploitasi kelemahan _SQL injection_ dan pengambil-alihan server basisdata. sqlmap dilengkapi dengan pendeteksi canggih, fitur-fitur hanal bagi _penetration tester_, beragam cara untuk mendeteksi basisdata, hingga mengakses _file system_ dan mengeksekusi perintah dalam sistem operasi melalui koneksi _out-of-band_.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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 è uno strumento open source per il penetration testing. Il suo scopo è quello di rendere automatico il processo di scoperta ed exploit di vulnerabilità di tipo SQL injection al fine di compromettere database online. Dispone di un potente motore per la ricerca di vulnerabilità, molti strumenti di nicchia anche per il più esperto penetration tester ed un'ampia gamma di controlli che vanno dal fingerprinting di database allo scaricamento di dati, fino all'accesso al file system sottostante e l'esecuzione di comandi nel sistema operativo attraverso connessioni out-of-band.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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はオープンソースのペネトレーションテスティングツールです。SQLインジェクションの脆弱性の検出、活用、そしてデータベースサーバ奪取のプロセスを自動化します。
|
||||
強力な検出エンジン、ペネトレーションテスターのための多くのニッチ機能、持続的なデータベースのフィンガープリンティングから、データベースのデータ取得やアウトオブバンド接続を介したオペレーティング・システム上でのコマンド実行、ファイルシステムへのアクセスなどの広範囲に及ぶスイッチを提供します。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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 to open sourceowe narzędzie do testów penetracyjnych, które automatyzuje procesy detekcji, przejmowania i testowania odporności serwerów SQL na podatność na iniekcję niechcianego kodu. Zawiera potężny mechanizm detekcji, wiele niszowych funkcji dla zaawansowanych testów penetracyjnych oraz szeroki wachlarz opcji począwszy od identyfikacji bazy danych, poprzez wydobywanie z nich danych, a nawet pozwalającuch na dostęp do systemu plików o uruchamianie poleceń w systemie operacyjnym serwera poprzez niestandardowe połączenia.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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 - это инструмент для тестирования уязвимостей с открытым исходным кодом, который автоматизирует процесс обнаружения и использования ошибок SQL-инъекций и захвата серверов баз данных. Он оснащен мощным механизмом обнаружения, множеством приятных функций для профессионального тестера уязвимостей и широким спектром скриптов, которые упрощают работу с базами данных, от сбора данных из базы данных, до доступа к базовой файловой системе и выполнения команд в операционной системе через out-of-band соединение.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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 sql injection açıklarını otomatik olarak tespit ve istismar etmeye yarayan açık kaynak bir penetrasyon aracıdır. sqlmap gelişmiş tespit özelliğinin yanı sıra penetrasyon testleri sırasında gerekli olabilecek bir çok aracı, -uzak veritabınınından, veri indirmek, dosya sistemine erişmek, dosya çalıştırmak gibi - işlevleri de barındırmaktadır.
|
||||
|
||||
|
||||
50
doc/translations/README-uk-UA.md
Normal file
50
doc/translations/README-uk-UA.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# 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 - це інструмент для тестування вразливостей з відкритим сирцевим кодом, який автоматизує процес виявлення і використання дефектів SQL-ін'єкцій, а також захоплення серверів баз даних. Він оснащений потужним механізмом виявлення, безліччю приємних функцій для професійного тестувальника вразливостей і широким спектром скриптів, які спрощують роботу з базами даних - від відбитка бази даних до доступу до базової файлової системи та виконання команд в операційній системі через out-of-band з'єднання.
|
||||
|
||||
Скриншоти
|
||||
----
|
||||
|
||||

|
||||
|
||||
Ви можете ознайомитися з [колекцією скриншотів](https://github.com/sqlmapproject/sqlmap/wiki/Screenshots), які демонструють деякі функції в wiki.
|
||||
|
||||
Встановлення
|
||||
----
|
||||
|
||||
Ви можете завантажити останню версію tarball натиснувши [сюди](https://github.com/sqlmapproject/sqlmap/tarball/master) або останню версію zipball натиснувши [сюди](https://github.com/sqlmapproject/sqlmap/zipball/master).
|
||||
|
||||
Найкраще завантажити sqlmap шляхом клонування [Git](https://github.com/sqlmapproject/sqlmap) репозиторію:
|
||||
|
||||
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev
|
||||
|
||||
sqlmap «працює з коробки» з [Python](http://www.python.org/download/) версії **2.6.x** та **2.7.x** на будь-якій платформі.
|
||||
|
||||
Використання
|
||||
----
|
||||
|
||||
Щоб отримати список основних опцій і перемикачів, використовуйте:
|
||||
|
||||
python sqlmap.py -h
|
||||
|
||||
Щоб отримати список всіх опцій і перемикачів, використовуйте:
|
||||
|
||||
python sqlmap.py -hh
|
||||
|
||||
Ви можете знайти приклад виконання [тут](https://asciinema.org/a/46601).
|
||||
Для того, щоб ознайомитися з можливостями sqlmap, списком підтримуваних функцій та описом всіх параметрів і перемикачів, а також прикладами, вам рекомендується скористатися [інструкцією користувача](https://github.com/sqlmapproject/sqlmap/wiki/Usage).
|
||||
|
||||
Посилання
|
||||
----
|
||||
|
||||
* Основний сайт: http://sqlmap.org
|
||||
* Завантаження: [.tar.gz](https://github.com/sqlmapproject/sqlmap/tarball/master) або [.zip](https://github.com/sqlmapproject/sqlmap/zipball/master)
|
||||
* Канал новин RSS: https://github.com/sqlmapproject/sqlmap/commits/master.atom
|
||||
* Відстеження проблем: https://github.com/sqlmapproject/sqlmap/issues
|
||||
* Інструкція користувача: https://github.com/sqlmapproject/sqlmap/wiki
|
||||
* Поширенні питання (FAQ): https://github.com/sqlmapproject/sqlmap/wiki/FAQ
|
||||
* Twitter: [@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
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](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 是一个开源的渗透测试工具,可以用来自动化的检测,利用SQL注入漏洞,获取数据库服务器的权限。它具有功能强大的检测引擎,针对各种不同类型数据库的渗透测试的功能选项,包括获取数据库中存储的数据,访问操作系统文件甚至可以通过外带数据连接的方式执行操作系统命令。
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
"""
|
||||
beep.py - Make a beep sound
|
||||
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import wave
|
||||
|
||||
@@ -16,11 +15,11 @@ BEEP_WAV_FILENAME = os.path.join(os.path.dirname(__file__), "beep.wav")
|
||||
|
||||
def beep():
|
||||
try:
|
||||
if subprocess.mswindows:
|
||||
if sys.platform == "nt":
|
||||
_win_wav_play(BEEP_WAV_FILENAME)
|
||||
elif sys.platform == "darwin":
|
||||
_mac_beep()
|
||||
elif sys.platform == "linux2":
|
||||
elif sys.platform.startswith("linux"):
|
||||
_linux_wav_play(BEEP_WAV_FILENAME)
|
||||
else:
|
||||
_speaker_beep()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -3,24 +3,28 @@
|
||||
"""
|
||||
cloak.py - Simple file encryption/compression utility
|
||||
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
import zlib
|
||||
|
||||
from optparse import OptionError
|
||||
from optparse import OptionParser
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
xrange = range
|
||||
|
||||
def hideAscii(data):
|
||||
retVal = ""
|
||||
retVal = b""
|
||||
for i in xrange(len(data)):
|
||||
if ord(data[i]) < 128:
|
||||
retVal += chr(ord(data[i]) ^ 127)
|
||||
else:
|
||||
retVal += data[i]
|
||||
value = data[i] if isinstance(data[i], int) else ord(data[i])
|
||||
retVal += struct.pack('B', value ^ (127 if value < 128 else 0))
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -37,8 +41,9 @@ def decloak(inputFile=None, data=None):
|
||||
data = f.read()
|
||||
try:
|
||||
data = zlib.decompress(hideAscii(data))
|
||||
except:
|
||||
print 'ERROR: the provided input file \'%s\' does not contain valid cloaked content' % inputFile
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
print('ERROR: the provided input file \'%s\' does not contain valid cloaked content' % inputFile)
|
||||
sys.exit(1)
|
||||
finally:
|
||||
f.close()
|
||||
@@ -59,11 +64,11 @@ def main():
|
||||
if not args.inputFile:
|
||||
parser.error('Missing the input file, -h for help')
|
||||
|
||||
except (OptionError, TypeError), e:
|
||||
parser.error(e)
|
||||
except (OptionError, TypeError) as ex:
|
||||
parser.error(ex)
|
||||
|
||||
if not os.path.isfile(args.inputFile):
|
||||
print 'ERROR: the provided input file \'%s\' is non existent' % args.inputFile
|
||||
print('ERROR: the provided input file \'%s\' is non existent' % args.inputFile)
|
||||
sys.exit(1)
|
||||
|
||||
if not args.decrypt:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
"""
|
||||
dbgtool.py - Portable executable to ASCII debug script converter
|
||||
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import struct
|
||||
|
||||
from optparse import OptionError
|
||||
from optparse import OptionParser
|
||||
@@ -19,7 +20,7 @@ def convert(inputFile):
|
||||
fileSize = fileStat.st_size
|
||||
|
||||
if fileSize > 65280:
|
||||
print "ERROR: the provided input file '%s' is too big for debug.exe" % inputFile
|
||||
print("ERROR: the provided input file '%s' is too big for debug.exe" % inputFile)
|
||||
sys.exit(1)
|
||||
|
||||
script = "n %s\nr cx\n" % os.path.basename(inputFile.replace(".", "_"))
|
||||
@@ -32,7 +33,7 @@ def convert(inputFile):
|
||||
fileContent = fp.read()
|
||||
|
||||
for fileChar in fileContent:
|
||||
unsignedFileChar = struct.unpack("B", fileChar)[0]
|
||||
unsignedFileChar = fileChar if sys.version_info >= (3, 0) else ord(fileChar)
|
||||
|
||||
if unsignedFileChar != 0:
|
||||
counter2 += 1
|
||||
@@ -59,7 +60,7 @@ def convert(inputFile):
|
||||
|
||||
def main(inputFile, outputFile):
|
||||
if not os.path.isfile(inputFile):
|
||||
print "ERROR: the provided input file '%s' is not a regular file" % inputFile
|
||||
print("ERROR: the provided input file '%s' is not a regular file" % inputFile)
|
||||
sys.exit(1)
|
||||
|
||||
script = convert(inputFile)
|
||||
@@ -70,7 +71,7 @@ def main(inputFile, outputFile):
|
||||
sys.stdout.write(script)
|
||||
sys.stdout.close()
|
||||
else:
|
||||
print script
|
||||
print(script)
|
||||
|
||||
if __name__ == "__main__":
|
||||
usage = "%s -i <input file> [-o <output file>]" % sys.argv[0]
|
||||
@@ -86,8 +87,8 @@ if __name__ == "__main__":
|
||||
if not args.inputFile:
|
||||
parser.error("Missing the input file, -h for help")
|
||||
|
||||
except (OptionError, TypeError), e:
|
||||
parser.error(e)
|
||||
except (OptionError, TypeError) as ex:
|
||||
parser.error(ex)
|
||||
|
||||
inputFile = args.inputFile
|
||||
outputFile = args.outputFile
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
import os
|
||||
import select
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
def setNonBlocking(fd):
|
||||
@@ -37,7 +36,7 @@ def setNonBlocking(fd):
|
||||
fcntl.fcntl(fd, fcntl.F_SETFL, flags)
|
||||
|
||||
def main(src, dst):
|
||||
if subprocess.mswindows:
|
||||
if sys.platform == "nt":
|
||||
sys.stderr.write('icmpsh master can only run on Posix systems\n')
|
||||
sys.exit(255)
|
||||
|
||||
@@ -80,7 +79,7 @@ def main(src, dst):
|
||||
cmd = ''
|
||||
|
||||
# Wait for incoming replies
|
||||
if sock in select.select([ sock ], [], [])[0]:
|
||||
if sock in select.select([sock], [], [])[0]:
|
||||
buff = sock.recv(4096)
|
||||
|
||||
if 0 == len(buff):
|
||||
@@ -128,7 +127,7 @@ def main(src, dst):
|
||||
try:
|
||||
# Send it to the target host
|
||||
sock.sendto(ip.get_packet(), (dst, 0))
|
||||
except socket.error, ex:
|
||||
except socket.error as ex:
|
||||
sys.stderr.write("'%s'\n" % ex)
|
||||
sys.stderr.flush()
|
||||
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import re
|
||||
import urllib2
|
||||
import urlparse
|
||||
|
||||
from xml.dom.minidom import Document
|
||||
|
||||
# Path to the XML file with signatures
|
||||
MSSQL_XML = os.path.abspath("../../xml/banner/mssql.xml")
|
||||
|
||||
# Url to update Microsoft SQL Server XML versions file from
|
||||
MSSQL_VERSIONS_URL = "http://www.sqlsecurity.com/FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx"
|
||||
|
||||
def updateMSSQLXML():
|
||||
if not os.path.exists(MSSQL_XML):
|
||||
errMsg = "[ERROR] file '%s' does not exist. Please run the script from its parent directory" % MSSQL_XML
|
||||
print errMsg
|
||||
return
|
||||
|
||||
infoMsg = "[INFO] retrieving data from '%s'" % MSSQL_VERSIONS_URL
|
||||
print infoMsg
|
||||
|
||||
try:
|
||||
req = urllib2.Request(MSSQL_VERSIONS_URL)
|
||||
f = urllib2.urlopen(req)
|
||||
mssqlVersionsHtmlString = f.read()
|
||||
f.close()
|
||||
except urllib2.URLError:
|
||||
__mssqlPath = urlparse.urlsplit(MSSQL_VERSIONS_URL)
|
||||
__mssqlHostname = __mssqlPath[1]
|
||||
|
||||
warnMsg = "[WARNING] sqlmap was unable to connect to %s," % __mssqlHostname
|
||||
warnMsg += " check your Internet connection and retry"
|
||||
print warnMsg
|
||||
|
||||
return
|
||||
|
||||
releases = re.findall("class=\"BCC_DV_01DarkBlueTitle\">SQL Server\s(.+?)\sBuilds", mssqlVersionsHtmlString, re.I)
|
||||
releasesCount = len(releases)
|
||||
|
||||
# Create the minidom document
|
||||
doc = Document()
|
||||
|
||||
# Create the <root> base element
|
||||
root = doc.createElement("root")
|
||||
doc.appendChild(root)
|
||||
|
||||
for index in xrange(0, releasesCount):
|
||||
release = releases[index]
|
||||
|
||||
# Skip Microsoft SQL Server 6.5 because the HTML
|
||||
# table is in another format
|
||||
if release == "6.5":
|
||||
continue
|
||||
|
||||
# Create the <signatures> base element
|
||||
signatures = doc.createElement("signatures")
|
||||
signatures.setAttribute("release", release)
|
||||
root.appendChild(signatures)
|
||||
|
||||
startIdx = mssqlVersionsHtmlString.index("SQL Server %s Builds" % releases[index])
|
||||
|
||||
if index == releasesCount - 1:
|
||||
stopIdx = len(mssqlVersionsHtmlString)
|
||||
else:
|
||||
stopIdx = mssqlVersionsHtmlString.index("SQL Server %s Builds" % releases[index + 1])
|
||||
|
||||
mssqlVersionsReleaseString = mssqlVersionsHtmlString[startIdx:stopIdx]
|
||||
servicepackVersion = re.findall("</td><td>(7\.0|2000|2005|2008|2008 R2)*(.*?)</td><td.*?([\d\.]+)</td>[\r]*\n", mssqlVersionsReleaseString, re.I)
|
||||
|
||||
for servicePack, version in servicepackVersion:
|
||||
if servicePack.startswith(" "):
|
||||
servicePack = servicePack[1:]
|
||||
if "/" in servicePack:
|
||||
servicePack = servicePack[:servicePack.index("/")]
|
||||
if "(" in servicePack:
|
||||
servicePack = servicePack[:servicePack.index("(")]
|
||||
if "-" in servicePack:
|
||||
servicePack = servicePack[:servicePack.index("-")]
|
||||
if "*" in servicePack:
|
||||
servicePack = servicePack[:servicePack.index("*")]
|
||||
if servicePack.startswith("+"):
|
||||
servicePack = "0%s" % servicePack
|
||||
|
||||
servicePack = servicePack.replace("\t", " ")
|
||||
servicePack = servicePack.replace("No SP", "0")
|
||||
servicePack = servicePack.replace("RTM", "0")
|
||||
servicePack = servicePack.replace("TM", "0")
|
||||
servicePack = servicePack.replace("SP", "")
|
||||
servicePack = servicePack.replace("Service Pack", "")
|
||||
servicePack = servicePack.replace("<a href=\"http:", "")
|
||||
servicePack = servicePack.replace(" ", " ")
|
||||
servicePack = servicePack.replace("+ ", "+")
|
||||
servicePack = servicePack.replace(" +", "+")
|
||||
|
||||
if servicePack.endswith(" "):
|
||||
servicePack = servicePack[:-1]
|
||||
|
||||
if servicePack and version:
|
||||
# Create the main <card> element
|
||||
signature = doc.createElement("signature")
|
||||
signatures.appendChild(signature)
|
||||
|
||||
# Create a <version> element
|
||||
versionElement = doc.createElement("version")
|
||||
signature.appendChild(versionElement)
|
||||
|
||||
# Give the <version> elemenet some text
|
||||
versionText = doc.createTextNode(version)
|
||||
versionElement.appendChild(versionText)
|
||||
|
||||
# Create a <servicepack> element
|
||||
servicepackElement = doc.createElement("servicepack")
|
||||
signature.appendChild(servicepackElement)
|
||||
|
||||
# Give the <servicepack> elemenet some text
|
||||
servicepackText = doc.createTextNode(servicePack)
|
||||
servicepackElement.appendChild(servicepackText)
|
||||
|
||||
# Save our newly created XML to the signatures file
|
||||
mssqlXml = codecs.open(MSSQL_XML, "w", "utf8")
|
||||
doc.writexml(writer=mssqlXml, addindent=" ", newl="\n")
|
||||
mssqlXml.close()
|
||||
|
||||
infoMsg = "[INFO] done. retrieved data parsed and saved into '%s'" % MSSQL_XML
|
||||
print infoMsg
|
||||
|
||||
if __name__ == "__main__":
|
||||
updateMSSQLXML()
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
safe2bin.py - Simple safe(hex) to binary format converter
|
||||
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import binascii
|
||||
import re
|
||||
import string
|
||||
@@ -16,6 +18,14 @@ import sys
|
||||
from optparse import OptionError
|
||||
from optparse import OptionParser
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
xrange = range
|
||||
text_type = str
|
||||
string_types = (str,)
|
||||
else:
|
||||
text_type = unicode
|
||||
string_types = (basestring,)
|
||||
|
||||
# Regex used for recognition of hex encoded characters
|
||||
HEX_ENCODED_CHAR_REGEX = r"(?P<result>\\x[0-9A-Fa-f]{2})"
|
||||
|
||||
@@ -46,15 +56,15 @@ def safecharencode(value):
|
||||
|
||||
retVal = value
|
||||
|
||||
if isinstance(value, basestring):
|
||||
if any([_ not in SAFE_CHARS for _ in value]):
|
||||
if isinstance(value, string_types):
|
||||
if any(_ not in SAFE_CHARS for _ in value):
|
||||
retVal = retVal.replace(HEX_ENCODED_PREFIX, HEX_ENCODED_PREFIX_MARKER)
|
||||
retVal = retVal.replace('\\', SLASH_MARKER)
|
||||
|
||||
for char in SAFE_ENCODE_SLASH_REPLACEMENTS:
|
||||
retVal = retVal.replace(char, repr(char).strip('\''))
|
||||
|
||||
retVal = reduce(lambda x, y: x + (y if (y in string.printable or isinstance(value, unicode) and ord(y) >= 160) else '\\x%02x' % ord(y)), retVal, (unicode if isinstance(value, unicode) else str)())
|
||||
retVal = reduce(lambda x, y: x + (y if (y in string.printable or isinstance(value, text_type) and ord(y) >= 160) else '\\x%02x' % ord(y)), retVal, type(value)())
|
||||
|
||||
retVal = retVal.replace(SLASH_MARKER, "\\\\")
|
||||
retVal = retVal.replace(HEX_ENCODED_PREFIX_MARKER, HEX_ENCODED_PREFIX)
|
||||
@@ -70,13 +80,13 @@ def safechardecode(value, binary=False):
|
||||
"""
|
||||
|
||||
retVal = value
|
||||
if isinstance(value, basestring):
|
||||
if isinstance(value, string_types):
|
||||
retVal = retVal.replace('\\\\', SLASH_MARKER)
|
||||
|
||||
while True:
|
||||
match = re.search(HEX_ENCODED_CHAR_REGEX, retVal)
|
||||
if match:
|
||||
retVal = retVal.replace(match.group("result"), (unichr if isinstance(value, unicode) else chr)(ord(binascii.unhexlify(match.group("result").lstrip("\\x")))))
|
||||
retVal = retVal.replace(match.group("result"), (unichr if isinstance(value, text_type) else chr)(ord(binascii.unhexlify(match.group("result").lstrip("\\x")))))
|
||||
else:
|
||||
break
|
||||
|
||||
@@ -86,7 +96,7 @@ def safechardecode(value, binary=False):
|
||||
retVal = retVal.replace(SLASH_MARKER, '\\')
|
||||
|
||||
if binary:
|
||||
if isinstance(retVal, unicode):
|
||||
if isinstance(retVal, text_type):
|
||||
retVal = retVal.encode("utf8")
|
||||
|
||||
elif isinstance(value, (list, tuple)):
|
||||
@@ -108,11 +118,11 @@ def main():
|
||||
if not args.inputFile:
|
||||
parser.error('Missing the input file, -h for help')
|
||||
|
||||
except (OptionError, TypeError), e:
|
||||
parser.error(e)
|
||||
except (OptionError, TypeError) as ex:
|
||||
parser.error(ex)
|
||||
|
||||
if not os.path.isfile(args.inputFile):
|
||||
print 'ERROR: the provided input file \'%s\' is not a regular file' % args.inputFile
|
||||
print('ERROR: the provided input file \'%s\' is not a regular file' % args.inputFile)
|
||||
sys.exit(1)
|
||||
|
||||
f = open(args.inputFile, 'r')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Removes trailing spaces from blank lines inside project files
|
||||
|
||||
11
extra/shutils/drei.sh
Executable file
11
extra/shutils/drei.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Stress test against Python3
|
||||
|
||||
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
|
||||
unset SQLMAP_DREI
|
||||
source `dirname "$0"`"/junk.sh"
|
||||
@@ -1,27 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Removes duplicate entries in wordlist like files
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
if len(sys.argv) > 0:
|
||||
items = list()
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
items = list()
|
||||
|
||||
with open(sys.argv[1], 'r') as f:
|
||||
for item in f.readlines():
|
||||
item = item.strip()
|
||||
try:
|
||||
str.encode(item)
|
||||
if item in items:
|
||||
if item:
|
||||
print item
|
||||
else:
|
||||
items.append(item)
|
||||
except:
|
||||
pass
|
||||
with open(sys.argv[1], 'r') as f:
|
||||
for item in f.readlines():
|
||||
item = item.strip()
|
||||
try:
|
||||
str.encode(item)
|
||||
if item in items:
|
||||
if item:
|
||||
print(item)
|
||||
else:
|
||||
items.append(item)
|
||||
except:
|
||||
pass
|
||||
|
||||
with open(sys.argv[1], 'w+') as f:
|
||||
f.writelines("\n".join(items))
|
||||
with open(sys.argv[1], 'w+') as f:
|
||||
f.writelines("\n".join(items))
|
||||
|
||||
7
extra/shutils/junk.sh
Executable file
7
extra/shutils/junk.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
find . -type d -name "__pycache__" -exec rm -rf {} \; &>/dev/null
|
||||
find . -name "*.pyc" -exec rm -f {} \; &>/dev/null
|
||||
@@ -1,28 +1,27 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Runs pylint on all python scripts found in a directory tree
|
||||
# Reference: http://rowinggolfer.blogspot.com/2009/08/pylint-recursively.html
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
def check(filepath):
|
||||
if filepath.endswith(".py"):
|
||||
content = open(filepath, "rb").read()
|
||||
#if re.search(r"\r?\n\r?\n", content):
|
||||
if "\n\n\n" in content:
|
||||
index = content.find("\n\n\n")
|
||||
print filepath, repr(content[index-30:index+30])
|
||||
content = open(filepath, "rb").read()
|
||||
pattern = "\n\n\n".encode("ascii")
|
||||
|
||||
if pattern in content:
|
||||
index = content.find(pattern)
|
||||
print(filepath, repr(content[index - 30:index + 30]))
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
BASE_DIRECTORY = sys.argv[1]
|
||||
except IndexError:
|
||||
print "no directory specified, defaulting to current working directory"
|
||||
print("no directory specified, defaulting to current working directory")
|
||||
BASE_DIRECTORY = os.getcwd()
|
||||
|
||||
print "looking for *.py scripts in subdirectories of ", BASE_DIRECTORY
|
||||
print("looking for *.py scripts in subdirectories of '%s'" % BASE_DIRECTORY)
|
||||
for root, dirs, files in os.walk(BASE_DIRECTORY):
|
||||
if any(_ in root for _ in ("extra", "thirdparty")):
|
||||
continue
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Runs pep8 on all python files (prerequisite: apt-get install pep8)
|
||||
find . -wholename "./thirdparty" -prune -o -type f -iname "*.py" -exec pep8 '{}' \;
|
||||
@@ -1,6 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
: '
|
||||
cat > .git/hooks/post-commit << EOF
|
||||
#!/bin/bash
|
||||
|
||||
source ./extra/shutils/postcommit-hook.sh
|
||||
EOF
|
||||
|
||||
chmod +x .git/hooks/post-commit
|
||||
'
|
||||
|
||||
SETTINGS="../../lib/core/settings.py"
|
||||
PYPI="../../extra/shutils/pypi.sh"
|
||||
|
||||
declare -x SCRIPTPATH="${0}"
|
||||
|
||||
@@ -18,6 +29,6 @@ then
|
||||
git tag $NEW_TAG
|
||||
git push origin $NEW_TAG
|
||||
echo "Going to push PyPI package"
|
||||
/bin/bash ${SCRIPTPATH%/*}/pypi.sh
|
||||
/bin/bash ${SCRIPTPATH%/*}/$PYPI
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
: '
|
||||
cat > .git/hooks/pre-commit << EOF
|
||||
#!/bin/bash
|
||||
|
||||
source ./extra/shutils/precommit-hook.sh
|
||||
EOF
|
||||
|
||||
chmod +x .git/hooks/pre-commit
|
||||
'
|
||||
|
||||
PROJECT="../../"
|
||||
SETTINGS="../../lib/core/settings.py"
|
||||
CHECKSUM="../../txt/checksum.md5"
|
||||
|
||||
declare -x SCRIPTPATH="${0}"
|
||||
|
||||
PROJECT_FULLPATH=${SCRIPTPATH%/*}/$PROJECT
|
||||
SETTINGS_FULLPATH=${SCRIPTPATH%/*}/$SETTINGS
|
||||
CHECKSUM_FULLPATH=${SCRIPTPATH%/*}/$CHECKSUM
|
||||
|
||||
git diff $SETTINGS_FULLPATH | grep "VERSION =" > /dev/null && exit 0
|
||||
|
||||
@@ -16,7 +24,7 @@ if [ -f $SETTINGS_FULLPATH ]
|
||||
then
|
||||
LINE=$(grep -o ${SETTINGS_FULLPATH} -e 'VERSION = "[0-9.]*"')
|
||||
declare -a LINE
|
||||
INCREMENTED=$(python -c "import re, sys, time; version = re.search('\"([0-9.]*)\"', sys.argv[1]).group(1); _ = version.split('.'); _.append(0) if len(_) < 3 else _; _[-1] = str(int(_[-1]) + 1); month = str(time.gmtime().tm_mon); _[-1] = '0' if _[-2] != month else _[-1]; _[-2] = month; print sys.argv[1].replace(version, '.'.join(_))" "$LINE")
|
||||
INCREMENTED=$(python -c "import re, sys, time; version = re.search('\"([0-9.]*)\"', sys.argv[1]).group(1); _ = version.split('.'); _.extend([0] * (4 - len(_))); _[-1] = str(int(_[-1]) + 1); month = str(time.gmtime().tm_mon); _[-1] = '0' if _[-2] != month else _[-1]; _[-2] = month; print sys.argv[1].replace(version, '.'.join(_))" "$LINE")
|
||||
if [ -n "$INCREMENTED" ]
|
||||
then
|
||||
sed -i "s/${LINE}/${INCREMENTED}/" $SETTINGS_FULLPATH
|
||||
@@ -27,6 +35,3 @@ then
|
||||
fi
|
||||
git add "$SETTINGS_FULLPATH"
|
||||
fi
|
||||
|
||||
truncate -s 0 "$CHECKSUM_FULLPATH"
|
||||
cd $PROJECT_FULLPATH && for i in $(find . -name "*.py" -o -name "*.xml" -o -iname "*_" | sort); do git ls-files $i --error-unmatch &>/dev/null && md5sum $i | stdbuf -i0 -o0 -e0 sed 's/\.\///' >> "$CHECKSUM_FULLPATH"; git add "$CHECKSUM_FULLPATH"; done
|
||||
|
||||
7
extra/shutils/pycodestyle.sh
Executable file
7
extra/shutils/pycodestyle.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Runs pycodestyle on all python files (prerequisite: pip install pycodestyle)
|
||||
find . -wholename "./thirdparty" -prune -o -type f -iname "*.py" -exec pycodestyle --ignore=E501,E302,E305,E722,E402 '{}' \;
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Runs py2diatra on all python files (prerequisite: pip install pydiatra)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Runs pyflakes on all python files (prerequisite: apt-get install pyflakes)
|
||||
find . -wholename "./thirdparty" -prune -o -type f -iname "*.py" -exec pyflakes '{}' \;
|
||||
find . -wholename "./thirdparty" -prune -o -type f -iname "*.py" -exec pyflakes '{}' \; | grep -v "redefines '_'"
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# Runs pylint on all python scripts found in a directory tree
|
||||
# Reference: http://rowinggolfer.blogspot.com/2009/08/pylint-recursively.html
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
@@ -17,26 +19,26 @@ def check(module):
|
||||
|
||||
if module[-3:] == ".py":
|
||||
|
||||
print "CHECKING ", module
|
||||
print("CHECKING ", module)
|
||||
pout = os.popen("pylint --rcfile=/dev/null %s" % module, 'r')
|
||||
for line in pout:
|
||||
if re.match(r"\AE:", line):
|
||||
print line.strip()
|
||||
print(line.strip())
|
||||
if __RATING__ and "Your code has been rated at" in line:
|
||||
print line
|
||||
print(line)
|
||||
score = re.findall(r"\d.\d\d", line)[0]
|
||||
total += float(score)
|
||||
count += 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
print sys.argv
|
||||
print(sys.argv)
|
||||
BASE_DIRECTORY = sys.argv[1]
|
||||
except IndexError:
|
||||
print "no directory specified, defaulting to current working directory"
|
||||
print("no directory specified, defaulting to current working directory")
|
||||
BASE_DIRECTORY = os.getcwd()
|
||||
|
||||
print "looking for *.py scripts in subdirectories of ", BASE_DIRECTORY
|
||||
print("looking for *.py scripts in subdirectories of ", BASE_DIRECTORY)
|
||||
for root, dirs, files in os.walk(BASE_DIRECTORY):
|
||||
if any(_ in root for _ in ("extra", "thirdparty")):
|
||||
continue
|
||||
@@ -45,6 +47,6 @@ if __name__ == "__main__":
|
||||
check(filepath)
|
||||
|
||||
if __RATING__:
|
||||
print "==" * 50
|
||||
print "%d modules found" % count
|
||||
print "AVERAGE SCORE = %.02f" % (total / count)
|
||||
print("==" * 50)
|
||||
print("%d modules found" % count)
|
||||
print("AVERAGE SCORE = %.02f" % (total / count))
|
||||
|
||||
@@ -16,7 +16,7 @@ cat > $TMP_DIR/setup.py << EOF
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -25,10 +25,17 @@ from setuptools import setup, find_packages
|
||||
setup(
|
||||
name='sqlmap',
|
||||
version='$VERSION',
|
||||
description="Automatic SQL injection and database takeover tool",
|
||||
description='Automatic SQL injection and database takeover tool',
|
||||
long_description=open('README.rst').read(),
|
||||
long_description_content_type='text/x-rst',
|
||||
author='Bernardo Damele Assumpcao Guimaraes, Miroslav Stampar',
|
||||
author_email='bernardo@sqlmap.org, miroslav@sqlmap.org',
|
||||
url='https://sqlmap.org',
|
||||
url='http://sqlmap.org',
|
||||
project_urls={
|
||||
'Documentation': 'https://github.com/sqlmapproject/sqlmap/wiki',
|
||||
'Source': 'https://github.com/sqlmapproject/sqlmap/',
|
||||
'Tracker': 'https://github.com/sqlmapproject/sqlmap/issues',
|
||||
},
|
||||
download_url='https://github.com/sqlmapproject/sqlmap/archive/$VERSION.zip',
|
||||
license='GNU General Public License v2 (GPLv2)',
|
||||
packages=find_packages(),
|
||||
@@ -60,7 +67,7 @@ cat > sqlmap/__init__.py << EOF
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -152,7 +159,7 @@ Links
|
||||
- User's manual: https://github.com/sqlmapproject/sqlmap/wiki
|
||||
- Frequently Asked Questions (FAQ):
|
||||
https://github.com/sqlmapproject/sqlmap/wiki/FAQ
|
||||
- Twitter: [@sqlmap](https://twitter.com/sqlmap)
|
||||
- Twitter: https://twitter.com/sqlmap
|
||||
- Demos: http://www.youtube.com/user/inquisb/videos
|
||||
- Screenshots: https://github.com/sqlmapproject/sqlmap/wiki/Screenshots
|
||||
|
||||
@@ -170,7 +177,6 @@ Links
|
||||
EOF
|
||||
sed -i "s/^VERSION =.*/VERSION = \"$VERSION\"/g" sqlmap/lib/core/settings.py
|
||||
sed -i "s/^TYPE =.*/TYPE = \"$TYPE\"/g" sqlmap/lib/core/settings.py
|
||||
sed -i "s/.*lib\/core\/settings\.py/`md5sum sqlmap/lib/core/settings.py | cut -d ' ' -f 1` lib\/core\/settings\.py/g" sqlmap/txt/checksum.md5
|
||||
for file in $(find sqlmap -type f | grep -v -E "\.(git|yml)"); do echo include $file >> MANIFEST.in; done
|
||||
python setup.py sdist upload
|
||||
rm -rf $TMP_DIR
|
||||
rm -rf $TMP_DIR
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
import codecs
|
||||
import inspect
|
||||
import os
|
||||
import re
|
||||
import smtplib
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
|
||||
sys.path.append(os.path.normpath("%s/../../" % os.path.dirname(inspect.getfile(inspect.currentframe()))))
|
||||
|
||||
from lib.core.revision import getRevisionNumber
|
||||
|
||||
START_TIME = time.strftime("%H:%M:%S %d-%m-%Y", time.gmtime())
|
||||
SQLMAP_HOME = "/opt/sqlmap"
|
||||
|
||||
SMTP_SERVER = "127.0.0.1"
|
||||
SMTP_PORT = 25
|
||||
SMTP_TIMEOUT = 30
|
||||
FROM = "regressiontest@sqlmap.org"
|
||||
#TO = "dev@sqlmap.org"
|
||||
TO = ["bernardo.damele@gmail.com", "miroslav.stampar@gmail.com"]
|
||||
SUBJECT = "regression test started on %s using revision %s" % (START_TIME, getRevisionNumber())
|
||||
TARGET = "debian"
|
||||
|
||||
def prepare_email(content):
|
||||
global FROM
|
||||
global TO
|
||||
global SUBJECT
|
||||
|
||||
msg = MIMEMultipart()
|
||||
msg["Subject"] = SUBJECT
|
||||
msg["From"] = FROM
|
||||
msg["To"] = TO if isinstance(TO, basestring) else ','.join(TO)
|
||||
|
||||
msg.attach(MIMEText(content))
|
||||
|
||||
return msg
|
||||
|
||||
def send_email(msg):
|
||||
global SMTP_SERVER
|
||||
global SMTP_PORT
|
||||
global SMTP_TIMEOUT
|
||||
|
||||
try:
|
||||
s = smtplib.SMTP(host=SMTP_SERVER, port=SMTP_PORT, timeout=SMTP_TIMEOUT)
|
||||
s.sendmail(FROM, TO, msg.as_string())
|
||||
s.quit()
|
||||
# Catch all for SMTP exceptions
|
||||
except smtplib.SMTPException, e:
|
||||
print "Failure to send email: %s" % str(e)
|
||||
|
||||
def failure_email(msg):
|
||||
msg = prepare_email(msg)
|
||||
send_email(msg)
|
||||
sys.exit(1)
|
||||
|
||||
def main():
|
||||
global SUBJECT
|
||||
|
||||
content = ""
|
||||
test_counts = []
|
||||
attachments = {}
|
||||
|
||||
updateproc = subprocess.Popen("cd /opt/sqlmap/ ; python /opt/sqlmap/sqlmap.py --update", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = updateproc.communicate()
|
||||
|
||||
if stderr:
|
||||
failure_email("Update of sqlmap failed with error:\n\n%s" % stderr)
|
||||
|
||||
regressionproc = subprocess.Popen("python /opt/sqlmap/sqlmap.py --live-test", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False)
|
||||
stdout, stderr = regressionproc.communicate()
|
||||
|
||||
if stderr:
|
||||
failure_email("Execution of regression test failed with error:\n\n%s" % stderr)
|
||||
|
||||
failed_tests = re.findall("running live test case: (.+?) \((\d+)\/\d+\)[\r]*\n.+test failed (at parsing items: (.+))?\s*\- scan folder: (\/.+) \- traceback: (.*?)( - SQL injection not detected)?[\r]*\n", stdout)
|
||||
|
||||
for failed_test in failed_tests:
|
||||
title = failed_test[0]
|
||||
test_count = int(failed_test[1])
|
||||
parse = failed_test[3] if failed_test[3] else None
|
||||
output_folder = failed_test[4]
|
||||
traceback = False if failed_test[5] == "False" else bool(failed_test[5])
|
||||
detected = False if failed_test[6] else True
|
||||
|
||||
test_counts.append(test_count)
|
||||
|
||||
console_output_file = os.path.join(output_folder, "console_output")
|
||||
log_file = os.path.join(output_folder, TARGET, "log")
|
||||
traceback_file = os.path.join(output_folder, "traceback")
|
||||
|
||||
if os.path.exists(console_output_file):
|
||||
console_output_fd = codecs.open(console_output_file, "rb", "utf8")
|
||||
console_output = console_output_fd.read()
|
||||
console_output_fd.close()
|
||||
attachments[test_count] = str(console_output)
|
||||
|
||||
if os.path.exists(log_file):
|
||||
log_fd = codecs.open(log_file, "rb", "utf8")
|
||||
log = log_fd.read()
|
||||
log_fd.close()
|
||||
|
||||
if os.path.exists(traceback_file):
|
||||
traceback_fd = codecs.open(traceback_file, "rb", "utf8")
|
||||
traceback = traceback_fd.read()
|
||||
traceback_fd.close()
|
||||
|
||||
content += "Failed test case '%s' (#%d)" % (title, test_count)
|
||||
|
||||
if parse:
|
||||
content += " at parsing: %s:\n\n" % parse
|
||||
content += "### Log file:\n\n"
|
||||
content += "%s\n\n" % log
|
||||
elif not detected:
|
||||
content += " - SQL injection not detected\n\n"
|
||||
else:
|
||||
content += "\n\n"
|
||||
|
||||
if traceback:
|
||||
content += "### Traceback:\n\n"
|
||||
content += "%s\n\n" % str(traceback)
|
||||
|
||||
content += "#######################################################################\n\n"
|
||||
|
||||
end_string = "Regression test finished at %s" % time.strftime("%H:%M:%S %d-%m-%Y", time.gmtime())
|
||||
|
||||
if content:
|
||||
content += end_string
|
||||
SUBJECT = "Failed %s (%s)" % (SUBJECT, ", ".join("#%d" % count for count in test_counts))
|
||||
|
||||
msg = prepare_email(content)
|
||||
|
||||
for test_count, attachment in attachments.items():
|
||||
attachment = MIMEText(attachment)
|
||||
attachment.add_header("Content-Disposition", "attachment", filename="test_case_%d_console_output.txt" % test_count)
|
||||
msg.attach(attachment)
|
||||
|
||||
send_email(msg)
|
||||
else:
|
||||
SUBJECT = "Successful %s" % SUBJECT
|
||||
msg = prepare_email("All test cases were successful\n\n%s" % end_string)
|
||||
send_email(msg)
|
||||
|
||||
if __name__ == "__main__":
|
||||
log_fd = open("/tmp/sqlmapregressiontest.log", "wb")
|
||||
log_fd.write("Regression test started at %s\n" % START_TIME)
|
||||
|
||||
try:
|
||||
main()
|
||||
except Exception, e:
|
||||
log_fd.write("An exception has occurred:\n%s" % str(traceback.format_exc()))
|
||||
|
||||
log_fd.write("Regression test finished at %s\n\n" % time.strftime("%H:%M:%S %d-%m-%Y", time.gmtime()))
|
||||
log_fd.close()
|
||||
@@ -1,141 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import cookielib
|
||||
import re
|
||||
import socket
|
||||
import sys
|
||||
import urllib
|
||||
import urllib2
|
||||
import ConfigParser
|
||||
|
||||
from operator import itemgetter
|
||||
|
||||
TIMEOUT = 10
|
||||
CONFIG_FILE = 'sqlharvest.cfg'
|
||||
TABLES_FILE = 'tables.txt'
|
||||
USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskTB5.3)'
|
||||
SEARCH_URL = 'http://www.google.com/m?source=mobileproducts&dc=gorganic'
|
||||
MAX_FILE_SIZE = 2 * 1024 * 1024 # if a result (.sql) file for downloading is more than 2MB in size just skip it
|
||||
QUERY = 'CREATE TABLE ext:sql'
|
||||
REGEX_URLS = r';u=([^"]+?)&q='
|
||||
REGEX_RESULT = r'(?i)CREATE TABLE\s*(/\*.*\*/)?\s*(IF NOT EXISTS)?\s*(?P<result>[^\(;]+)'
|
||||
|
||||
def main():
|
||||
tables = dict()
|
||||
cookies = cookielib.CookieJar()
|
||||
cookie_processor = urllib2.HTTPCookieProcessor(cookies)
|
||||
opener = urllib2.build_opener(cookie_processor)
|
||||
opener.addheaders = [("User-Agent", USER_AGENT)]
|
||||
|
||||
conn = opener.open(SEARCH_URL)
|
||||
page = conn.read() # set initial cookie values
|
||||
|
||||
config = ConfigParser.ConfigParser()
|
||||
config.read(CONFIG_FILE)
|
||||
|
||||
if not config.has_section("options"):
|
||||
config.add_section("options")
|
||||
if not config.has_option("options", "index"):
|
||||
config.set("options", "index", "0")
|
||||
|
||||
i = int(config.get("options", "index"))
|
||||
|
||||
try:
|
||||
with open(TABLES_FILE, 'r') as f:
|
||||
for line in f.xreadlines():
|
||||
if len(line) > 0 and ',' in line:
|
||||
temp = line.split(',')
|
||||
tables[temp[0]] = int(temp[1])
|
||||
except:
|
||||
pass
|
||||
|
||||
socket.setdefaulttimeout(TIMEOUT)
|
||||
|
||||
files, old_files = None, None
|
||||
try:
|
||||
while True:
|
||||
abort = False
|
||||
old_files = files
|
||||
files = []
|
||||
|
||||
try:
|
||||
conn = opener.open("%s&q=%s&start=%d&sa=N" % (SEARCH_URL, QUERY.replace(' ', '+'), i * 10))
|
||||
page = conn.read()
|
||||
for match in re.finditer(REGEX_URLS, page):
|
||||
files.append(urllib.unquote(match.group(1)))
|
||||
if len(files) >= 10:
|
||||
break
|
||||
abort = (files == old_files)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
|
||||
except Exception, msg:
|
||||
print msg
|
||||
|
||||
if abort:
|
||||
break
|
||||
|
||||
sys.stdout.write("\n---------------\n")
|
||||
sys.stdout.write("Result page #%d\n" % (i + 1))
|
||||
sys.stdout.write("---------------\n")
|
||||
|
||||
for sqlfile in files:
|
||||
print sqlfile
|
||||
|
||||
try:
|
||||
req = urllib2.Request(sqlfile)
|
||||
response = urllib2.urlopen(req)
|
||||
|
||||
if "Content-Length" in response.headers:
|
||||
if int(response.headers.get("Content-Length")) > MAX_FILE_SIZE:
|
||||
continue
|
||||
|
||||
page = response.read()
|
||||
found = False
|
||||
counter = 0
|
||||
|
||||
for match in re.finditer(REGEX_RESULT, page):
|
||||
counter += 1
|
||||
table = match.group("result").strip().strip("`\"'").replace('"."', ".").replace("].[", ".").strip('[]')
|
||||
|
||||
if table and not any(_ in table for _ in ('>', '<', '--', ' ')):
|
||||
found = True
|
||||
sys.stdout.write('*')
|
||||
|
||||
if table in tables:
|
||||
tables[table] += 1
|
||||
else:
|
||||
tables[table] = 1
|
||||
if found:
|
||||
sys.stdout.write("\n")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
|
||||
except Exception, msg:
|
||||
print msg
|
||||
|
||||
else:
|
||||
i += 1
|
||||
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
finally:
|
||||
with open(TABLES_FILE, 'w+') as f:
|
||||
tables = sorted(tables.items(), key=itemgetter(1), reverse=True)
|
||||
for table, count in tables:
|
||||
f.write("%s,%d\n" % (table, count))
|
||||
|
||||
config.set("options", "index", str(i + 1))
|
||||
with open(CONFIG_FILE, 'w+') as f:
|
||||
config.write(f)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
174
extra/vulnserver/vulnserver.py
Normal file
174
extra/vulnserver/vulnserver.py
Normal file
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
vulnserver.py - Trivial SQLi vulnerable HTTP server (Note: for testing purposes)
|
||||
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import re
|
||||
import sqlite3
|
||||
import sys
|
||||
import threading
|
||||
import traceback
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
from http.client import FOUND
|
||||
from http.client import INTERNAL_SERVER_ERROR
|
||||
from http.client import NOT_FOUND
|
||||
from http.client import OK
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
from http.server import HTTPServer
|
||||
from socketserver import ThreadingMixIn
|
||||
from urllib.parse import parse_qs
|
||||
from urllib.parse import unquote_plus
|
||||
else:
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler
|
||||
from BaseHTTPServer import HTTPServer
|
||||
from httplib import FOUND
|
||||
from httplib import INTERNAL_SERVER_ERROR
|
||||
from httplib import NOT_FOUND
|
||||
from httplib import OK
|
||||
from SocketServer import ThreadingMixIn
|
||||
from urlparse import parse_qs
|
||||
from urllib import unquote_plus
|
||||
|
||||
SCHEMA = """
|
||||
CREATE TABLE users (
|
||||
id INTEGER,
|
||||
name TEXT,
|
||||
surname TEXT
|
||||
);
|
||||
INSERT INTO users (id, name, surname) VALUES (1, 'luther', 'blisset');
|
||||
INSERT INTO users (id, name, surname) VALUES (2, 'fluffy', 'bunny');
|
||||
INSERT INTO users (id, name, surname) VALUES (3, 'wu', '179ad45c6ce2cb97cf1029e212046e81');
|
||||
INSERT INTO users (id, name, surname) VALUES (4, 'sqlmap/1.0-dev (http://sqlmap.org)', 'user agent header');
|
||||
INSERT INTO users (id, name, surname) VALUES (5, NULL, 'nameisnull');
|
||||
"""
|
||||
|
||||
LISTEN_ADDRESS = "localhost"
|
||||
LISTEN_PORT = 8440
|
||||
|
||||
_conn = None
|
||||
_cursor = None
|
||||
_lock = None
|
||||
_server = None
|
||||
|
||||
def init(quiet=False):
|
||||
global _conn
|
||||
global _cursor
|
||||
global _lock
|
||||
|
||||
_conn = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False)
|
||||
_cursor = _conn.cursor()
|
||||
_lock = threading.Lock()
|
||||
|
||||
_cursor.executescript(SCHEMA)
|
||||
|
||||
if quiet:
|
||||
global print
|
||||
|
||||
def _(*args, **kwargs):
|
||||
pass
|
||||
|
||||
print = _
|
||||
|
||||
class ThreadingServer(ThreadingMixIn, HTTPServer):
|
||||
def finish_request(self, *args, **kwargs):
|
||||
try:
|
||||
HTTPServer.finish_request(self, *args, **kwargs)
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
|
||||
class ReqHandler(BaseHTTPRequestHandler):
|
||||
def do_REQUEST(self):
|
||||
path, query = self.path.split('?', 1) if '?' in self.path else (self.path, "")
|
||||
params = {}
|
||||
|
||||
if query:
|
||||
params.update(parse_qs(query))
|
||||
|
||||
if "<script>" in unquote_plus(query):
|
||||
self.send_response(INTERNAL_SERVER_ERROR)
|
||||
self.send_header("Connection", "close")
|
||||
self.end_headers()
|
||||
self.wfile.write("CLOUDFLARE_ERROR_500S_BOX".encode("utf8"))
|
||||
return
|
||||
|
||||
if hasattr(self, "data"):
|
||||
params.update(parse_qs(self.data))
|
||||
|
||||
for key in params:
|
||||
if params[key]:
|
||||
params[key] = params[key][-1]
|
||||
|
||||
self.url, self.params = path, params
|
||||
|
||||
if self.url == '/':
|
||||
if "id" not in params:
|
||||
self.send_response(FOUND)
|
||||
self.send_header("Connection", "close")
|
||||
self.send_header("Location", "/?id=1")
|
||||
self.end_headers()
|
||||
else:
|
||||
self.send_response(OK)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.send_header("Connection", "close")
|
||||
self.end_headers()
|
||||
|
||||
try:
|
||||
with _lock:
|
||||
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % self.params.get("id", ""))
|
||||
results = _cursor.fetchall()
|
||||
|
||||
output = "<b>SQL results:</b>\n"
|
||||
output += "<table border=\"1\">\n"
|
||||
for row in results:
|
||||
output += "<tr>"
|
||||
for value in row:
|
||||
output += "<td>%s</td>" % value
|
||||
output += "</tr>\n"
|
||||
output += "</table>\n"
|
||||
output += "</body></html>"
|
||||
except Exception as ex:
|
||||
output = "%s: %s" % (re.search(r"'([^']+)'", str(type(ex))).group(1), ex)
|
||||
|
||||
self.wfile.write(output.encode("utf8"))
|
||||
else:
|
||||
self.send_response(NOT_FOUND)
|
||||
self.send_header("Connection", "close")
|
||||
self.end_headers()
|
||||
|
||||
def do_GET(self):
|
||||
self.do_REQUEST()
|
||||
|
||||
def do_POST(self):
|
||||
length = int(self.headers.get("Content-length", 0))
|
||||
if length:
|
||||
data = self.rfile.read(length)
|
||||
data = unquote_plus(data.decode("utf8"))
|
||||
self.data = data
|
||||
self.do_REQUEST()
|
||||
|
||||
def log_message(self, format, *args):
|
||||
return
|
||||
|
||||
def run(address=LISTEN_ADDRESS, port=LISTEN_PORT):
|
||||
global _server
|
||||
try:
|
||||
_server = ThreadingServer((address, port), ReqHandler)
|
||||
print("[i] running HTTP server at '%s:%d'" % (address, port))
|
||||
_server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
_server.socket.close()
|
||||
raise
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
init()
|
||||
run(sys.argv[1] if len(sys.argv) > 1 else LISTEN_ADDRESS, int(sys.argv[2] if len(sys.argv) > 2 else LISTEN_PORT))
|
||||
except KeyboardInterrupt:
|
||||
print("\r[x] Ctrl-C received")
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -75,7 +75,7 @@ def action():
|
||||
if conf.getPasswordHashes:
|
||||
try:
|
||||
conf.dumper.userSettings("database management system users password hashes", conf.dbmsHandler.getPasswordHashes(), "password hash", CONTENT_TYPE.PASSWORDS)
|
||||
except SqlmapNoneDataException, ex:
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
@@ -83,7 +83,7 @@ def action():
|
||||
if conf.getPrivileges:
|
||||
try:
|
||||
conf.dumper.userSettings("database management system users privileges", conf.dbmsHandler.getPrivileges(), "privilege", CONTENT_TYPE.PRIVILEGES)
|
||||
except SqlmapNoneDataException, ex:
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
@@ -91,43 +91,93 @@ def action():
|
||||
if conf.getRoles:
|
||||
try:
|
||||
conf.dumper.userSettings("database management system users roles", conf.dbmsHandler.getRoles(), "role", CONTENT_TYPE.ROLES)
|
||||
except SqlmapNoneDataException, ex:
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.getDbs:
|
||||
conf.dumper.dbs(conf.dbmsHandler.getDbs())
|
||||
try:
|
||||
conf.dumper.dbs(conf.dbmsHandler.getDbs())
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.getTables:
|
||||
conf.dumper.dbTables(conf.dbmsHandler.getTables())
|
||||
try:
|
||||
conf.dumper.dbTables(conf.dbmsHandler.getTables())
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.commonTables:
|
||||
conf.dumper.dbTables(tableExists(paths.COMMON_TABLES))
|
||||
try:
|
||||
conf.dumper.dbTables(tableExists(paths.COMMON_TABLES))
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.getSchema:
|
||||
conf.dumper.dbTableColumns(conf.dbmsHandler.getSchema(), CONTENT_TYPE.SCHEMA)
|
||||
try:
|
||||
conf.dumper.dbTableColumns(conf.dbmsHandler.getSchema(), CONTENT_TYPE.SCHEMA)
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.getColumns:
|
||||
conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns(), CONTENT_TYPE.COLUMNS)
|
||||
try:
|
||||
conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns(), CONTENT_TYPE.COLUMNS)
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.getCount:
|
||||
conf.dumper.dbTablesCount(conf.dbmsHandler.getCount())
|
||||
try:
|
||||
conf.dumper.dbTablesCount(conf.dbmsHandler.getCount())
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.commonColumns:
|
||||
conf.dumper.dbTableColumns(columnExists(paths.COMMON_COLUMNS))
|
||||
try:
|
||||
conf.dumper.dbTableColumns(columnExists(paths.COMMON_COLUMNS))
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.dumpTable:
|
||||
conf.dbmsHandler.dumpTable()
|
||||
try:
|
||||
conf.dbmsHandler.dumpTable()
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.dumpAll:
|
||||
conf.dbmsHandler.dumpAll()
|
||||
try:
|
||||
conf.dbmsHandler.dumpAll()
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.search:
|
||||
conf.dbmsHandler.search()
|
||||
try:
|
||||
conf.dbmsHandler.search()
|
||||
except SqlmapNoneDataException as ex:
|
||||
logger.critical(ex)
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.query:
|
||||
conf.dumper.query(conf.query, conf.dbmsHandler.sqlQuery(conf.query))
|
||||
if conf.sqlQuery:
|
||||
conf.dumper.sqlQuery(conf.sqlQuery, conf.dbmsHandler.sqlQuery(conf.sqlQuery))
|
||||
|
||||
if conf.sqlShell:
|
||||
conf.dbmsHandler.sqlShell()
|
||||
@@ -140,11 +190,11 @@ def action():
|
||||
conf.dbmsHandler.udfInjectCustom()
|
||||
|
||||
# File system options
|
||||
if conf.rFile:
|
||||
conf.dumper.rFile(conf.dbmsHandler.readFile(conf.rFile))
|
||||
if conf.fileRead:
|
||||
conf.dumper.rFile(conf.dbmsHandler.readFile(conf.fileRead))
|
||||
|
||||
if conf.wFile:
|
||||
conf.dbmsHandler.writeFile(conf.wFile, conf.dFile, conf.wFileType)
|
||||
if conf.fileWrite:
|
||||
conf.dbmsHandler.writeFile(conf.fileWrite, conf.fileDest, conf.fileWriteType)
|
||||
|
||||
# Operating system options
|
||||
if conf.osCmd:
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import copy
|
||||
import httplib
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
@@ -21,6 +21,7 @@ from lib.core.agent import agent
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import extractTextTagContent
|
||||
from lib.core.common import filterNone
|
||||
from lib.core.common import findDynamicContent
|
||||
from lib.core.common import Format
|
||||
from lib.core.common import getFilteredPageContent
|
||||
@@ -47,7 +48,7 @@ from lib.core.common import unArrayizeValue
|
||||
from lib.core.common import urlencode
|
||||
from lib.core.common import wasLastResponseDBMSError
|
||||
from lib.core.common import wasLastResponseHTTPError
|
||||
from lib.core.convert import unicodeencode
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.defaults import defaults
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
@@ -68,11 +69,14 @@ from lib.core.enums import NULLCONNECTION
|
||||
from lib.core.enums import PAYLOAD
|
||||
from lib.core.enums import PLACE
|
||||
from lib.core.enums import REDIRECTION
|
||||
from lib.core.enums import WEB_PLATFORM
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from lib.core.exception import SqlmapDataException
|
||||
from lib.core.exception import SqlmapNoneDataException
|
||||
from lib.core.exception import SqlmapSilentQuitException
|
||||
from lib.core.exception import SqlmapSkipTargetException
|
||||
from lib.core.exception import SqlmapUserQuitException
|
||||
from lib.core.settings import BOUNDED_INJECTION_MARKER
|
||||
from lib.core.settings import CANDIDATE_SENTENCE_MIN_LENGTH
|
||||
from lib.core.settings import CHECK_INTERNET_ADDRESS
|
||||
from lib.core.settings import CHECK_INTERNET_VALUE
|
||||
@@ -82,16 +86,20 @@ from lib.core.settings import DUMMY_NON_SQLI_CHECK_APPENDIX
|
||||
from lib.core.settings import FI_ERROR_REGEX
|
||||
from lib.core.settings import FORMAT_EXCEPTION_STRINGS
|
||||
from lib.core.settings import HEURISTIC_CHECK_ALPHABET
|
||||
from lib.core.settings import IDS_WAF_CHECK_PAYLOAD
|
||||
from lib.core.settings import IPS_WAF_CHECK_PAYLOAD
|
||||
from lib.core.settings import IDS_WAF_CHECK_RATIO
|
||||
from lib.core.settings import IDS_WAF_CHECK_TIMEOUT
|
||||
from lib.core.settings import MAX_DIFFLIB_SEQUENCE_LENGTH
|
||||
from lib.core.settings import NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH
|
||||
from lib.core.settings import PRECONNECT_INCOMPATIBLE_SERVERS
|
||||
from lib.core.settings import SINGLE_QUOTE_MARKER
|
||||
from lib.core.settings import SLEEP_TIME_MARKER
|
||||
from lib.core.settings import SUHOSIN_MAX_VALUE_LENGTH
|
||||
from lib.core.settings import SUPPORTED_DBMS
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.settings import URI_HTTP_HEADER
|
||||
from lib.core.settings import UPPER_RATIO_BOUND
|
||||
from lib.core.settings import INFERENCE_EQUALS_CHAR
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.request.comparison import comparison
|
||||
@@ -99,6 +107,8 @@ from lib.request.inject import checkBooleanExpression
|
||||
from lib.request.templates import getPageTemplate
|
||||
from lib.techniques.union.test import unionTest
|
||||
from lib.techniques.union.use import configUnion
|
||||
from thirdparty import six
|
||||
from thirdparty.six.moves import http_client as _http_client
|
||||
|
||||
def checkSqlInjection(place, parameter, value):
|
||||
# Store here the details about boundaries and payload used to
|
||||
@@ -357,7 +367,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
|
||||
# Parse test's <request>
|
||||
comment = agent.getComment(test.request) if len(conf.boundaries) > 1 else None
|
||||
fstPayload = agent.cleanupPayload(test.request.payload, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) else None)
|
||||
fstPayload = agent.cleanupPayload(test.request.payload, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) and BOUNDED_INJECTION_MARKER not in (value or "") else None)
|
||||
|
||||
for boundary in boundaries:
|
||||
injectable = False
|
||||
@@ -419,11 +429,14 @@ def checkSqlInjection(place, parameter, value):
|
||||
templatePayload = None
|
||||
vector = None
|
||||
|
||||
origValue = value
|
||||
if kb.customInjectionMark in origValue:
|
||||
origValue = origValue.split(kb.customInjectionMark)[0]
|
||||
origValue = re.search(r"(\w*)\Z", origValue).group(1)
|
||||
|
||||
# Threat the parameter original value according to the
|
||||
# test's <where> tag
|
||||
if where == PAYLOAD.WHERE.ORIGINAL or conf.prefix:
|
||||
origValue = value
|
||||
|
||||
if kb.tamperFunctions:
|
||||
templatePayload = agent.payload(place, parameter, value="", newValue=origValue, where=where)
|
||||
elif where == PAYLOAD.WHERE.NEGATIVE:
|
||||
@@ -433,7 +446,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
|
||||
if conf.invalidLogical:
|
||||
_ = int(kb.data.randomInt[:2])
|
||||
origValue = "%s AND %s=%s" % (value, _, _ + 1)
|
||||
origValue = "%s AND %s LIKE %s" % (origValue, _, _ + 1)
|
||||
elif conf.invalidBignum:
|
||||
origValue = kb.data.randomInt[:6]
|
||||
elif conf.invalidString:
|
||||
@@ -468,13 +481,13 @@ def checkSqlInjection(place, parameter, value):
|
||||
# payload was successful
|
||||
# Parse test's <response>
|
||||
for method, check in test.response.items():
|
||||
check = agent.cleanupPayload(check, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) else None)
|
||||
check = agent.cleanupPayload(check, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) and BOUNDED_INJECTION_MARKER not in (value or "") else None)
|
||||
|
||||
# In case of boolean-based blind SQL injection
|
||||
if method == PAYLOAD.METHOD.COMPARISON:
|
||||
# Generate payload used for comparison
|
||||
def genCmpPayload():
|
||||
sndPayload = agent.cleanupPayload(test.response.comparison, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) else None)
|
||||
sndPayload = agent.cleanupPayload(test.response.comparison, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) and BOUNDED_INJECTION_MARKER not in (value or "") else None)
|
||||
|
||||
# Forge response payload by prepending with
|
||||
# boundary's prefix and appending the boundary's
|
||||
@@ -558,18 +571,18 @@ def checkSqlInjection(place, parameter, value):
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
trueSet = set(extractTextTagContent(trueRawResponse))
|
||||
trueSet = trueSet.union(__ for _ in trueSet for __ in _.split())
|
||||
trueSet |= set(__ for _ in trueSet for __ in _.split())
|
||||
|
||||
falseSet = set(extractTextTagContent(falseRawResponse))
|
||||
falseSet = falseSet.union(__ for _ in falseSet for __ in _.split())
|
||||
falseSet |= set(__ for _ in falseSet for __ in _.split())
|
||||
|
||||
if threadData.lastErrorPage and threadData.lastErrorPage[1]:
|
||||
errorSet = set(extractTextTagContent(threadData.lastErrorPage[1]))
|
||||
errorSet = errorSet.union(__ for _ in errorSet for __ in _.split())
|
||||
errorSet |= set(__ for _ in errorSet for __ in _.split())
|
||||
else:
|
||||
errorSet = set()
|
||||
|
||||
candidates = filter(None, (_.strip() if _.strip() in trueRawResponse and _.strip() not in falseRawResponse else None for _ in (trueSet - falseSet - errorSet)))
|
||||
candidates = filterNone(_.strip() if _.strip() in trueRawResponse and _.strip() not in falseRawResponse else None for _ in (trueSet - falseSet - errorSet))
|
||||
|
||||
if candidates:
|
||||
candidates = sorted(candidates, key=lambda _: len(_))
|
||||
@@ -583,7 +596,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
logger.info(infoMsg)
|
||||
|
||||
if not any((conf.string, conf.notString)):
|
||||
candidates = filter(None, (_.strip() if _.strip() in falseRawResponse and _.strip() not in trueRawResponse else None for _ in (falseSet - trueSet)))
|
||||
candidates = filterNone(_.strip() if _.strip() in falseRawResponse and _.strip() not in trueRawResponse else None for _ in (falseSet - trueSet))
|
||||
|
||||
if candidates:
|
||||
candidates = sorted(candidates, key=lambda _: len(_))
|
||||
@@ -608,7 +621,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
page, headers, _ = Request.queryPage(reqPayload, place, content=True, raise404=False)
|
||||
output = extractRegexResult(check, page, re.DOTALL | re.IGNORECASE)
|
||||
output = output or extractRegexResult(check, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None, re.DOTALL | re.IGNORECASE)
|
||||
output = output or extractRegexResult(check, listToStrValue((headers[key] for key in headers.keys() if key.lower() != URI_HTTP_HEADER.lower()) if headers else None), re.DOTALL | re.IGNORECASE)
|
||||
output = output or extractRegexResult(check, listToStrValue((headers[key] for key in headers if key.lower() != URI_HTTP_HEADER.lower()) if headers else None), re.DOTALL | re.IGNORECASE)
|
||||
output = output or extractRegexResult(check, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None, re.DOTALL | re.IGNORECASE)
|
||||
|
||||
if output:
|
||||
@@ -620,10 +633,10 @@ def checkSqlInjection(place, parameter, value):
|
||||
|
||||
injectable = True
|
||||
|
||||
except SqlmapConnectionException, msg:
|
||||
except SqlmapConnectionException as ex:
|
||||
debugMsg = "problem occurred most likely because the "
|
||||
debugMsg += "server hasn't recovered as expected from the "
|
||||
debugMsg += "error-based payload used ('%s')" % msg
|
||||
debugMsg += "error-based payload used ('%s')" % getSafeExString(ex)
|
||||
logger.debug(debugMsg)
|
||||
|
||||
# In case of time-based blind or stacked queries
|
||||
@@ -682,7 +695,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
# Test for UNION query SQL injection
|
||||
reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix)
|
||||
|
||||
if isinstance(reqPayload, basestring):
|
||||
if isinstance(reqPayload, six.string_types):
|
||||
infoMsg = "%s parameter '%s' is '%s' injectable" % (paramType, parameter, title)
|
||||
logger.info(infoMsg)
|
||||
|
||||
@@ -761,7 +774,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
infoMsg = "executing alerting shell command(s) ('%s')" % conf.alert
|
||||
logger.info(infoMsg)
|
||||
|
||||
process = subprocess.Popen(conf.alert, shell=True)
|
||||
process = subprocess.Popen(conf.alert.encode(sys.getfilesystemencoding() or UNICODE_ENCODING), shell=True)
|
||||
process.wait()
|
||||
|
||||
kb.alerted = True
|
||||
@@ -856,8 +869,8 @@ def heuristicCheckDbms(injection):
|
||||
if conf.noEscape and dbms not in FROM_DUMMY_TABLE:
|
||||
continue
|
||||
|
||||
if checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr1)):
|
||||
if not checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr2)):
|
||||
if checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr1, 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
|
||||
break
|
||||
|
||||
@@ -893,7 +906,7 @@ def checkFalsePositives(injection):
|
||||
|
||||
kb.injection = injection
|
||||
|
||||
for i in xrange(conf.level):
|
||||
for level in xrange(conf.level):
|
||||
while True:
|
||||
randInt1, randInt2, randInt3 = (_() for j in xrange(3))
|
||||
|
||||
@@ -903,27 +916,26 @@ def checkFalsePositives(injection):
|
||||
if randInt3 > randInt2 > randInt1:
|
||||
break
|
||||
|
||||
if not checkBooleanExpression("%d=%d" % (randInt1, randInt1)):
|
||||
if not checkBooleanExpression("%d%s%d" % (randInt1, INFERENCE_EQUALS_CHAR, randInt1)):
|
||||
retVal = False
|
||||
break
|
||||
|
||||
# Just in case if DBMS hasn't properly recovered from previous delayed request
|
||||
if PAYLOAD.TECHNIQUE.BOOLEAN not in injection.data:
|
||||
checkBooleanExpression("%d=%d" % (randInt1, randInt2))
|
||||
checkBooleanExpression("%d%s%d" % (randInt1, INFERENCE_EQUALS_CHAR, randInt2)) # just in case if DBMS hasn't properly recovered from previous delayed request
|
||||
|
||||
if checkBooleanExpression("%d=%d" % (randInt1, randInt3)): # this must not be evaluated to True
|
||||
if checkBooleanExpression("%d%s%d" % (randInt1, INFERENCE_EQUALS_CHAR, randInt3)): # this must not be evaluated to True
|
||||
retVal = False
|
||||
break
|
||||
|
||||
elif checkBooleanExpression("%d=%d" % (randInt3, randInt2)): # this must not be evaluated to True
|
||||
elif checkBooleanExpression("%d%s%d" % (randInt3, INFERENCE_EQUALS_CHAR, randInt2)): # this must not be evaluated to True
|
||||
retVal = False
|
||||
break
|
||||
|
||||
elif not checkBooleanExpression("%d=%d" % (randInt2, randInt2)): # this must be evaluated to True
|
||||
elif not checkBooleanExpression("%d%s%d" % (randInt2, INFERENCE_EQUALS_CHAR, randInt2)): # this must be evaluated to True
|
||||
retVal = False
|
||||
break
|
||||
|
||||
elif checkBooleanExpression("%d %d" % (randInt3, randInt2)): # this must not be evaluated to True (invalid statement)
|
||||
elif checkBooleanExpression("%d %d" % (randInt3, randInt2)): # this must not be evaluated to True (invalid statement)
|
||||
retVal = False
|
||||
break
|
||||
|
||||
@@ -989,11 +1001,6 @@ def checkFilteredChars(injection):
|
||||
kb.injection = popValue()
|
||||
|
||||
def heuristicCheckSqlInjection(place, parameter):
|
||||
if kb.nullConnection:
|
||||
debugMsg = "heuristic check skipped because NULL connection used"
|
||||
logger.debug(debugMsg)
|
||||
return None
|
||||
|
||||
if kb.heavilyDynamic:
|
||||
debugMsg = "heuristic check skipped because of heavy dynamicity"
|
||||
logger.debug(debugMsg)
|
||||
@@ -1051,9 +1058,19 @@ def heuristicCheckSqlInjection(place, parameter):
|
||||
kb.heuristicTest = HEURISTIC_TEST.CASTED if casting else HEURISTIC_TEST.NEGATIVE if not result else HEURISTIC_TEST.POSITIVE
|
||||
|
||||
if casting:
|
||||
errMsg = "possible %s casting " % ("integer" if origValue.isdigit() else "type")
|
||||
errMsg += "detected (e.g. \"$%s=intval($_REQUEST['%s'])\") " % (parameter, parameter)
|
||||
errMsg += "at the back-end web application"
|
||||
errMsg = "possible %s casting detected (e.g. '" % ("integer" if origValue.isdigit() else "type")
|
||||
|
||||
platform = conf.url.split('.')[-1].lower()
|
||||
if platform == WEB_PLATFORM.ASP:
|
||||
errMsg += "%s=CInt(request.querystring(\"%s\"))" % (parameter, parameter)
|
||||
elif platform == WEB_PLATFORM.ASPX:
|
||||
errMsg += "int.TryParse(Request.QueryString[\"%s\"], out %s)" % (parameter, parameter)
|
||||
elif platform == WEB_PLATFORM.JSP:
|
||||
errMsg += "%s=Integer.parseInt(request.getParameter(\"%s\"))" % (parameter, parameter)
|
||||
else:
|
||||
errMsg += "$%s=intval($_REQUEST[\"%s\"])" % (parameter, parameter)
|
||||
|
||||
errMsg += "') at the back-end web application"
|
||||
logger.error(errMsg)
|
||||
|
||||
if kb.ignoreCasted is None:
|
||||
@@ -1118,14 +1135,6 @@ def checkDynParam(place, parameter, value):
|
||||
try:
|
||||
payload = agent.payload(place, parameter, value, getUnicode(randInt))
|
||||
dynResult = Request.queryPage(payload, place, raise404=False)
|
||||
|
||||
if not dynResult:
|
||||
infoMsg = "confirming that %s parameter '%s' is dynamic" % (paramType, parameter)
|
||||
logger.info(infoMsg)
|
||||
|
||||
randInt = randomInt()
|
||||
payload = agent.payload(place, parameter, value, getUnicode(randInt))
|
||||
dynResult = Request.queryPage(payload, place, raise404=False)
|
||||
except SqlmapConnectionException:
|
||||
pass
|
||||
|
||||
@@ -1229,7 +1238,7 @@ def checkStability():
|
||||
logger.error(errMsg)
|
||||
|
||||
else:
|
||||
warnMsg = "target URL content is not stable. sqlmap will base the page "
|
||||
warnMsg = "target URL content is not stable (i.e. content differs). sqlmap will base the page "
|
||||
warnMsg += "comparison on a sequence matcher. If no dynamic nor "
|
||||
warnMsg += "injectable parameters are detected, or in case of "
|
||||
warnMsg += "junk results, refer to user's manual paragraph "
|
||||
@@ -1314,9 +1323,8 @@ def checkRegexp():
|
||||
rawResponse = "%s%s" % (listToStrValue(headers.headers if headers else ""), page)
|
||||
|
||||
if not re.search(conf.regexp, rawResponse, re.I | re.M):
|
||||
warnMsg = "you provided '%s' as the regular expression to " % conf.regexp
|
||||
warnMsg += "match, but such a regular expression does not have any "
|
||||
warnMsg += "match within the target URL raw response, sqlmap "
|
||||
warnMsg = "you provided '%s' as the regular expression " % conf.regexp
|
||||
warnMsg += "which does not have any match within the target URL raw response. sqlmap "
|
||||
warnMsg += "will carry on anyway"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
@@ -1331,11 +1339,14 @@ def checkWaf():
|
||||
if any((conf.string, conf.notString, conf.regexp, conf.dummy, conf.offline, conf.skipWaf)):
|
||||
return None
|
||||
|
||||
if kb.originalCode == _http_client.NOT_FOUND:
|
||||
return None
|
||||
|
||||
_ = hashDBRetrieve(HASHDB_KEYS.CHECK_WAF_RESULT, True)
|
||||
if _ is not None:
|
||||
if _:
|
||||
warnMsg = "previous heuristics detected that the target "
|
||||
warnMsg += "is protected by some kind of WAF/IPS/IDS"
|
||||
warnMsg += "is protected by some kind of WAF/IPS"
|
||||
logger.critical(warnMsg)
|
||||
return _
|
||||
|
||||
@@ -1343,11 +1354,11 @@ def checkWaf():
|
||||
return None
|
||||
|
||||
infoMsg = "checking if the target is protected by "
|
||||
infoMsg += "some kind of WAF/IPS/IDS"
|
||||
infoMsg += "some kind of WAF/IPS"
|
||||
logger.info(infoMsg)
|
||||
|
||||
retVal = False
|
||||
payload = "%d %s" % (randomInt(), IDS_WAF_CHECK_PAYLOAD)
|
||||
payload = "%d %s" % (randomInt(), IPS_WAF_CHECK_PAYLOAD)
|
||||
|
||||
if PLACE.URI in conf.parameters:
|
||||
place = PLACE.POST
|
||||
@@ -1357,7 +1368,12 @@ def checkWaf():
|
||||
value = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + DEFAULT_GET_POST_DELIMITER
|
||||
value += "%s=%s" % (randomStr(), agent.addPayloadDelimiters(payload))
|
||||
|
||||
pushValue(kb.redirectChoice)
|
||||
pushValue(kb.resendPostOnRedirect)
|
||||
pushValue(conf.timeout)
|
||||
|
||||
kb.redirectChoice = REDIRECTION.YES
|
||||
kb.resendPostOnRedirect = False
|
||||
conf.timeout = IDS_WAF_CHECK_TIMEOUT
|
||||
|
||||
try:
|
||||
@@ -1366,16 +1382,19 @@ def checkWaf():
|
||||
retVal = True
|
||||
finally:
|
||||
kb.matchRatio = None
|
||||
|
||||
conf.timeout = popValue()
|
||||
kb.resendPostOnRedirect = popValue()
|
||||
kb.redirectChoice = popValue()
|
||||
|
||||
if retVal:
|
||||
warnMsg = "heuristics detected that the target "
|
||||
warnMsg += "is protected by some kind of WAF/IPS/IDS"
|
||||
warnMsg += "is protected by some kind of WAF/IPS"
|
||||
logger.critical(warnMsg)
|
||||
|
||||
if not conf.identifyWaf:
|
||||
message = "do you want sqlmap to try to detect backend "
|
||||
message += "WAF/IPS/IDS? [y/N] "
|
||||
message += "WAF/IPS? [y/N] "
|
||||
|
||||
if readInput(message, default='N', boolean=True):
|
||||
conf.identifyWaf = True
|
||||
@@ -1399,7 +1418,7 @@ def identifyWaf():
|
||||
kb.testMode = True
|
||||
|
||||
infoMsg = "using WAF scripts to detect "
|
||||
infoMsg += "backend WAF/IPS/IDS protection"
|
||||
infoMsg += "backend WAF/IPS protection"
|
||||
logger.info(infoMsg)
|
||||
|
||||
@cachedmethod
|
||||
@@ -1407,16 +1426,24 @@ def identifyWaf():
|
||||
page, headers, code = None, None, None
|
||||
try:
|
||||
pushValue(kb.redirectChoice)
|
||||
kb.redirectChoice = REDIRECTION.NO
|
||||
pushValue(kb.resendPostOnRedirect)
|
||||
|
||||
kb.redirectChoice = REDIRECTION.YES
|
||||
kb.resendPostOnRedirect = True
|
||||
|
||||
if kwargs.get("get"):
|
||||
kwargs["get"] = urlencode(kwargs["get"])
|
||||
kwargs["raise404"] = False
|
||||
kwargs["silent"] = True
|
||||
kwargs["finalCode"] = True
|
||||
|
||||
page, headers, code = Request.getPage(*args, **kwargs)
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
kb.resendPostOnRedirect = popValue()
|
||||
kb.redirectChoice = popValue()
|
||||
|
||||
return page or "", headers or {}, code
|
||||
|
||||
retVal = []
|
||||
@@ -1426,9 +1453,9 @@ def identifyWaf():
|
||||
continue
|
||||
|
||||
try:
|
||||
logger.debug("checking for WAF/IPS/IDS product '%s'" % product)
|
||||
logger.debug("checking for WAF/IPS product '%s'" % product)
|
||||
found = function(_)
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
errMsg = "exception occurred while running "
|
||||
errMsg += "WAF script for '%s' ('%s')" % (product, getSafeExString(ex))
|
||||
logger.critical(errMsg)
|
||||
@@ -1436,19 +1463,19 @@ def identifyWaf():
|
||||
found = False
|
||||
|
||||
if found:
|
||||
errMsg = "WAF/IPS/IDS identified as '%s'" % product
|
||||
errMsg = "WAF/IPS identified as '%s'" % product
|
||||
logger.critical(errMsg)
|
||||
|
||||
retVal.append(product)
|
||||
|
||||
if retVal:
|
||||
if kb.wafSpecificResponse and len(retVal) == 1 and "unknown" in retVal[0].lower():
|
||||
if kb.wafSpecificResponse and "You don't have permission to access" not in kb.wafSpecificResponse and len(retVal) == 1 and "unknown" in retVal[0].lower():
|
||||
handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.SPECIFIC_RESPONSE)
|
||||
os.close(handle)
|
||||
with openFile(filename, "w+b") as f:
|
||||
f.write(kb.wafSpecificResponse)
|
||||
|
||||
message = "WAF/IPS/IDS specific response can be found in '%s'. " % filename
|
||||
message = "WAF/IPS specific response can be found in '%s'. " % filename
|
||||
message += "If you know the details on used protection please "
|
||||
message += "report it along with specific response "
|
||||
message += "to '%s'" % DEV_EMAIL_ADDRESS
|
||||
@@ -1465,7 +1492,7 @@ def identifyWaf():
|
||||
if not choice:
|
||||
raise SqlmapUserQuitException
|
||||
else:
|
||||
warnMsg = "WAF/IPS/IDS product hasn't been identified"
|
||||
warnMsg = "WAF/IPS product hasn't been identified"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
kb.testType = None
|
||||
@@ -1482,46 +1509,59 @@ def checkNullConnection():
|
||||
if conf.data:
|
||||
return False
|
||||
|
||||
infoMsg = "testing NULL connection to the target URL"
|
||||
logger.info(infoMsg)
|
||||
_ = hashDBRetrieve(HASHDB_KEYS.CHECK_NULL_CONNECTION_RESULT, True)
|
||||
if _ is not None:
|
||||
kb.nullConnection = _
|
||||
|
||||
pushValue(kb.pageCompress)
|
||||
kb.pageCompress = False
|
||||
if _:
|
||||
dbgMsg = "resuming NULL connection method '%s'" % _
|
||||
logger.debug(dbgMsg)
|
||||
|
||||
try:
|
||||
page, headers, _ = Request.getPage(method=HTTPMETHOD.HEAD, raise404=False)
|
||||
else:
|
||||
infoMsg = "testing NULL connection to the target URL"
|
||||
logger.info(infoMsg)
|
||||
|
||||
if not page and HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
|
||||
kb.nullConnection = NULLCONNECTION.HEAD
|
||||
pushValue(kb.pageCompress)
|
||||
kb.pageCompress = False
|
||||
|
||||
infoMsg = "NULL connection is supported with HEAD method ('Content-Length')"
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
page, headers, _ = Request.getPage(auxHeaders={HTTP_HEADER.RANGE: "bytes=-1"})
|
||||
try:
|
||||
page, headers, _ = Request.getPage(method=HTTPMETHOD.HEAD, raise404=False)
|
||||
|
||||
if page and len(page) == 1 and HTTP_HEADER.CONTENT_RANGE in (headers or {}):
|
||||
kb.nullConnection = NULLCONNECTION.RANGE
|
||||
if not page and HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
|
||||
kb.nullConnection = NULLCONNECTION.HEAD
|
||||
|
||||
infoMsg = "NULL connection is supported with GET method ('Range')"
|
||||
infoMsg = "NULL connection is supported with HEAD method ('Content-Length')"
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
_, headers, _ = Request.getPage(skipRead=True)
|
||||
page, headers, _ = Request.getPage(auxHeaders={HTTP_HEADER.RANGE: "bytes=-1"})
|
||||
|
||||
if HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
|
||||
kb.nullConnection = NULLCONNECTION.SKIP_READ
|
||||
if page and len(page) == 1 and HTTP_HEADER.CONTENT_RANGE in (headers or {}):
|
||||
kb.nullConnection = NULLCONNECTION.RANGE
|
||||
|
||||
infoMsg = "NULL connection is supported with 'skip-read' method"
|
||||
infoMsg = "NULL connection is supported with GET method ('Range')"
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
_, headers, _ = Request.getPage(skipRead=True)
|
||||
|
||||
except SqlmapConnectionException:
|
||||
pass
|
||||
if HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
|
||||
kb.nullConnection = NULLCONNECTION.SKIP_READ
|
||||
|
||||
finally:
|
||||
kb.pageCompress = popValue()
|
||||
infoMsg = "NULL connection is supported with 'skip-read' method"
|
||||
logger.info(infoMsg)
|
||||
|
||||
return kb.nullConnection is not None
|
||||
except SqlmapConnectionException:
|
||||
pass
|
||||
|
||||
finally:
|
||||
kb.pageCompress = popValue()
|
||||
kb.nullConnection = False if kb.nullConnection is None else kb.nullConnection
|
||||
hashDBWrite(HASHDB_KEYS.CHECK_NULL_CONNECTION_RESULT, kb.nullConnection, True)
|
||||
|
||||
return kb.nullConnection in getPublicTypeMembers(NULLCONNECTION, True)
|
||||
|
||||
def checkConnection(suppressOutput=False):
|
||||
threadData = getCurrentThreadData()
|
||||
|
||||
if not re.search(r"\A\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\Z", conf.hostname):
|
||||
if not any((conf.proxy, conf.tor, conf.dummy, conf.offline)):
|
||||
try:
|
||||
@@ -1531,10 +1571,14 @@ def checkConnection(suppressOutput=False):
|
||||
except socket.gaierror:
|
||||
errMsg = "host '%s' does not exist" % conf.hostname
|
||||
raise SqlmapConnectionException(errMsg)
|
||||
except socket.error, ex:
|
||||
except socket.error as ex:
|
||||
errMsg = "problem occurred while "
|
||||
errMsg += "resolving a host name '%s' ('%s')" % (conf.hostname, getSafeExString(ex))
|
||||
raise SqlmapConnectionException(errMsg)
|
||||
except UnicodeError as ex:
|
||||
errMsg = "problem occurred while "
|
||||
errMsg += "handling a host name '%s' ('%s')" % (conf.hostname, getSafeExString(ex))
|
||||
raise SqlmapDataException(errMsg)
|
||||
|
||||
if not suppressOutput and not conf.dummy and not conf.offline:
|
||||
infoMsg = "testing connection to the target URL"
|
||||
@@ -1542,11 +1586,14 @@ def checkConnection(suppressOutput=False):
|
||||
|
||||
try:
|
||||
kb.originalPageTime = time.time()
|
||||
page, headers, _ = Request.queryPage(content=True, noteResponseTime=False)
|
||||
kb.originalPage = kb.pageTemplate = page
|
||||
Request.queryPage(content=True, noteResponseTime=False)
|
||||
|
||||
kb.errorIsNone = False
|
||||
|
||||
if any(_ in (kb.serverHeader or "") for _ in PRECONNECT_INCOMPATIBLE_SERVERS):
|
||||
singleTimeWarnMessage("turning off pre-connect mechanism because of incompatible server ('%s')" % kb.serverHeader)
|
||||
conf.disablePrecon = True
|
||||
|
||||
if not kb.originalPage and wasLastResponseHTTPError():
|
||||
errMsg = "unable to retrieve page content"
|
||||
raise SqlmapConnectionException(errMsg)
|
||||
@@ -1562,16 +1609,14 @@ def checkConnection(suppressOutput=False):
|
||||
else:
|
||||
kb.errorIsNone = True
|
||||
|
||||
threadData = getCurrentThreadData()
|
||||
|
||||
if kb.redirectChoice == REDIRECTION.YES and threadData.lastRedirectURL and threadData.lastRedirectURL[0] == threadData.lastRequestUID:
|
||||
if (threadData.lastRedirectURL[1] or "").startswith("https://") and unicodeencode(conf.hostname) in threadData.lastRedirectURL[1]:
|
||||
if (threadData.lastRedirectURL[1] or "").startswith("https://") and conf.hostname in getUnicode(threadData.lastRedirectURL[1]):
|
||||
conf.url = re.sub(r"https?://", "https://", conf.url)
|
||||
match = re.search(r":(\d+)", threadData.lastRedirectURL[1])
|
||||
port = match.group(1) if match else 443
|
||||
conf.url = re.sub(r":\d+/", ":%s/" % port, conf.url)
|
||||
conf.url = re.sub(r":\d+(/|\Z)", ":%s\g<1>" % port, conf.url)
|
||||
|
||||
except SqlmapConnectionException, ex:
|
||||
except SqlmapConnectionException as ex:
|
||||
if conf.ipv6:
|
||||
warnMsg = "check connection to a provided "
|
||||
warnMsg += "IPv6 address with a tool like ping6 "
|
||||
@@ -1580,7 +1625,7 @@ def checkConnection(suppressOutput=False):
|
||||
warnMsg += "any addressing issues"
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
if any(code in kb.httpErrorCodes for code in (httplib.NOT_FOUND, )):
|
||||
if any(code in kb.httpErrorCodes for code in (_http_client.NOT_FOUND, )):
|
||||
errMsg = getSafeExString(ex)
|
||||
logger.critical(errMsg)
|
||||
|
||||
@@ -1594,6 +1639,9 @@ def checkConnection(suppressOutput=False):
|
||||
kb.ignoreNotFound = True
|
||||
else:
|
||||
raise
|
||||
finally:
|
||||
kb.originalPage = kb.pageTemplate = threadData.lastPage
|
||||
kb.originalCode = threadData.lastCode
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -40,6 +40,7 @@ from lib.core.common import safeCSValue
|
||||
from lib.core.common import showHttpErrorCodes
|
||||
from lib.core.common import urlencode
|
||||
from lib.core.common import urldecode
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
@@ -47,6 +48,7 @@ from lib.core.decorators import stackedmethod
|
||||
from lib.core.enums import CONTENT_TYPE
|
||||
from lib.core.enums import HASHDB_KEYS
|
||||
from lib.core.enums import HEURISTIC_TEST
|
||||
from lib.core.enums import HTTP_HEADER
|
||||
from lib.core.enums import HTTPMETHOD
|
||||
from lib.core.enums import NOTE
|
||||
from lib.core.enums import PAYLOAD
|
||||
@@ -56,9 +58,11 @@ from lib.core.exception import SqlmapNoneDataException
|
||||
from lib.core.exception import SqlmapNotVulnerableException
|
||||
from lib.core.exception import SqlmapSilentQuitException
|
||||
from lib.core.exception import SqlmapSkipTargetException
|
||||
from lib.core.exception import SqlmapSystemException
|
||||
from lib.core.exception import SqlmapValueException
|
||||
from lib.core.exception import SqlmapUserQuitException
|
||||
from lib.core.settings import ASP_NET_CONTROL_REGEX
|
||||
from lib.core.settings import CSRF_TOKEN_PARAMETER_INFIXES
|
||||
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
|
||||
from lib.core.settings import EMPTY_FORM_FIELDS_REGEX
|
||||
from lib.core.settings import IGNORE_PARAMETERS
|
||||
@@ -69,6 +73,7 @@ from lib.core.settings import REFERER_ALIASES
|
||||
from lib.core.settings import USER_AGENT_ALIASES
|
||||
from lib.core.target import initTargetEnv
|
||||
from lib.core.target import setupTargetEnv
|
||||
from lib.utils.hash import crackHashFile
|
||||
|
||||
def _selectInjection():
|
||||
"""
|
||||
@@ -87,7 +92,7 @@ def _selectInjection():
|
||||
if point not in points:
|
||||
points[point] = injection
|
||||
else:
|
||||
for key in points[point].keys():
|
||||
for key in points[point]:
|
||||
if key != 'data':
|
||||
points[point][key] = points[point][key] or injection[key]
|
||||
points[point]['data'].update(injection['data'])
|
||||
@@ -241,18 +246,22 @@ def _saveToResultsFile():
|
||||
if key not in results:
|
||||
results[key] = []
|
||||
|
||||
results[key].extend(injection.data.keys())
|
||||
results[key].extend(list(injection.data.keys()))
|
||||
|
||||
for key, value in results.items():
|
||||
place, parameter, notes = key
|
||||
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)
|
||||
try:
|
||||
for key, value in results.items():
|
||||
place, parameter, notes = key
|
||||
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)
|
||||
|
||||
if not results:
|
||||
line = "%s,,,,%s" % (conf.url, os.linesep)
|
||||
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:
|
||||
errMsg = "unable to write to the results file '%s' ('%s'). " % (conf.resultsFilename, getSafeExString(ex))
|
||||
raise SqlmapSystemException(errMsg)
|
||||
|
||||
@stackedmethod
|
||||
def start():
|
||||
@@ -262,6 +271,9 @@ def start():
|
||||
check if they are dynamic and SQL injection affected
|
||||
"""
|
||||
|
||||
if conf.hashFile:
|
||||
crackHashFile(conf.hashFile)
|
||||
|
||||
if conf.direct:
|
||||
initTargetEnv()
|
||||
setupTargetEnv()
|
||||
@@ -308,12 +320,20 @@ def start():
|
||||
conf.httpHeaders = list(initialHeaders)
|
||||
conf.httpHeaders.extend(targetHeaders or [])
|
||||
|
||||
if conf.randomAgent or conf.mobile:
|
||||
for header, value in initialHeaders:
|
||||
if header.upper() == HTTP_HEADER.USER_AGENT.upper():
|
||||
conf.httpHeaders.append((header, value))
|
||||
break
|
||||
|
||||
conf.httpHeaders = [conf.httpHeaders[i] for i in xrange(len(conf.httpHeaders)) if conf.httpHeaders[i][0].upper() not in (__[0].upper() for __ in conf.httpHeaders[i + 1:])]
|
||||
|
||||
initTargetEnv()
|
||||
parseTargetUrl()
|
||||
|
||||
testSqlInj = False
|
||||
|
||||
if PLACE.GET in conf.parameters and not any([conf.data, conf.testParameter]):
|
||||
if PLACE.GET in conf.parameters and not any((conf.data, conf.testParameter)):
|
||||
for parameter in re.findall(r"([^=]+)=([^%s]+%s?|\Z)" % (re.escape(conf.paramDel or "") or DEFAULT_GET_POST_DELIMITER, re.escape(conf.paramDel or "") or DEFAULT_GET_POST_DELIMITER), conf.parameters[PLACE.GET]):
|
||||
paramKey = (conf.hostname, conf.path, PLACE.GET, parameter[0])
|
||||
|
||||
@@ -416,7 +436,7 @@ def start():
|
||||
checkStability()
|
||||
|
||||
# Do a little prioritization reorder of a testable parameter list
|
||||
parameters = conf.parameters.keys()
|
||||
parameters = list(conf.parameters.keys())
|
||||
|
||||
# Order of testing list (first to last)
|
||||
orderList = (PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER, PLACE.URI, PLACE.POST, PLACE.GET)
|
||||
@@ -480,7 +500,7 @@ def start():
|
||||
elif parameter in conf.testParameter:
|
||||
pass
|
||||
|
||||
elif parameter == conf.rParam:
|
||||
elif parameter in conf.rParam:
|
||||
testSqlInj = False
|
||||
|
||||
infoMsg = "skipping randomizing %s parameter '%s'" % (paramType, parameter)
|
||||
@@ -498,14 +518,14 @@ def start():
|
||||
infoMsg = "skipping %s parameter '%s'" % (paramType, parameter)
|
||||
logger.info(infoMsg)
|
||||
|
||||
elif parameter == conf.csrfToken:
|
||||
elif conf.csrfToken and re.search(conf.csrfToken, parameter, re.I):
|
||||
testSqlInj = False
|
||||
|
||||
infoMsg = "skipping anti-CSRF token parameter '%s'" % parameter
|
||||
logger.info(infoMsg)
|
||||
|
||||
# Ignore session-like parameters for --level < 4
|
||||
elif conf.level < 4 and (parameter.upper() in IGNORE_PARAMETERS or parameter.upper().startswith(GOOGLE_ANALYTICS_COOKIE_PREFIX)):
|
||||
elif conf.level < 4 and (parameter.upper() in IGNORE_PARAMETERS or any(_ in parameter.lower() for _ in CSRF_TOKEN_PARAMETER_INFIXES) or parameter.upper().startswith(GOOGLE_ANALYTICS_COOKIE_PREFIX)):
|
||||
testSqlInj = False
|
||||
|
||||
infoMsg = "ignoring %s parameter '%s'" % (paramType, parameter)
|
||||
@@ -524,7 +544,7 @@ def start():
|
||||
|
||||
testSqlInj = False
|
||||
else:
|
||||
infoMsg = "%s parameter '%s' is dynamic" % (paramType, parameter)
|
||||
infoMsg = "%s parameter '%s' appears to be dynamic" % (paramType, parameter)
|
||||
logger.info(infoMsg)
|
||||
|
||||
kb.testedParams.add(paramKey)
|
||||
@@ -631,6 +651,9 @@ def start():
|
||||
errMsg += "involved (e.g. WAF) maybe you could try to use "
|
||||
errMsg += "option '--tamper' (e.g. '--tamper=space2comment')"
|
||||
|
||||
if not conf.randomAgent:
|
||||
errMsg += " and/or switch '--random-agent'"
|
||||
|
||||
raise SqlmapNotVulnerableException(errMsg.rstrip('.'))
|
||||
else:
|
||||
# Flush the flag
|
||||
@@ -675,7 +698,7 @@ def start():
|
||||
except SqlmapSilentQuitException:
|
||||
raise
|
||||
|
||||
except SqlmapBaseException, ex:
|
||||
except SqlmapBaseException as ex:
|
||||
errMsg = getSafeExString(ex)
|
||||
|
||||
if conf.multipleTargets:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -10,6 +10,7 @@ from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.dicts import DBMS_DICT
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
from lib.core.settings import ORACLE_ALIASES
|
||||
@@ -21,6 +22,7 @@ from lib.core.settings import MAXDB_ALIASES
|
||||
from lib.core.settings import SYBASE_ALIASES
|
||||
from lib.core.settings import DB2_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
|
||||
|
||||
@@ -46,6 +48,8 @@ from plugins.dbms.db2 import DB2Map
|
||||
from plugins.dbms.db2.connector import Connector as DB2Conn
|
||||
from plugins.dbms.hsqldb import HSQLDBMap
|
||||
from plugins.dbms.hsqldb.connector import Connector as HSQLDBConn
|
||||
from plugins.dbms.h2 import H2Map
|
||||
from plugins.dbms.h2.connector import Connector as H2Conn
|
||||
from plugins.dbms.informix import InformixMap
|
||||
from plugins.dbms.informix.connector import Connector as InformixConn
|
||||
|
||||
@@ -67,10 +71,11 @@ def setHandler():
|
||||
(DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn),
|
||||
(DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn),
|
||||
(DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn),
|
||||
(DBMS.H2, H2_ALIASES, H2Map, H2Conn),
|
||||
(DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn),
|
||||
]
|
||||
|
||||
_ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else None for _ in items)
|
||||
_ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else "" for _ in items) or None
|
||||
if _:
|
||||
items.remove(_)
|
||||
items.insert(0, _)
|
||||
@@ -90,29 +95,41 @@ def setHandler():
|
||||
conf.dbmsConnector = Connector()
|
||||
|
||||
if conf.direct:
|
||||
exception = None
|
||||
dialect = DBMS_DICT[dbms][3]
|
||||
|
||||
if dialect:
|
||||
sqlalchemy = SQLAlchemy(dialect=dialect)
|
||||
sqlalchemy.connect()
|
||||
try:
|
||||
sqlalchemy = SQLAlchemy(dialect=dialect)
|
||||
sqlalchemy.connect()
|
||||
|
||||
if sqlalchemy.connector:
|
||||
conf.dbmsConnector = sqlalchemy
|
||||
else:
|
||||
try:
|
||||
conf.dbmsConnector.connect()
|
||||
except NameError:
|
||||
pass
|
||||
else:
|
||||
conf.dbmsConnector.connect()
|
||||
if sqlalchemy.connector:
|
||||
conf.dbmsConnector = sqlalchemy
|
||||
except Exception as ex:
|
||||
exception = ex
|
||||
|
||||
if not dialect or exception:
|
||||
try:
|
||||
conf.dbmsConnector.connect()
|
||||
except Exception as ex:
|
||||
if exception:
|
||||
raise exception
|
||||
else:
|
||||
if not isinstance(ex, NameError):
|
||||
raise
|
||||
else:
|
||||
msg = "support for direct connection to '%s' is not available. " % dbms
|
||||
msg += "Please rerun with '--dependencies'"
|
||||
raise SqlmapConnectionException(msg)
|
||||
|
||||
if conf.forceDbms == dbms or handler.checkDbms():
|
||||
if kb.resolutionDbms:
|
||||
conf.dbmsHandler = max(_ for _ in items if _[0] == kb.resolutionDbms)[2]()
|
||||
conf.dbmsHandler._dbms = kb.resolutionDbms
|
||||
else:
|
||||
conf.dbmsHandler = handler
|
||||
conf.dbmsHandler._dbms = dbms
|
||||
|
||||
conf.dbmsHandler._dbms = dbms
|
||||
break
|
||||
else:
|
||||
conf.dbmsConnector = None
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import base64
|
||||
import re
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import filterNone
|
||||
from lib.core.common import getSQLSnippet
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.common import isDBMSVersionAtLeast
|
||||
@@ -23,6 +25,7 @@ from lib.core.common import splitFields
|
||||
from lib.core.common import unArrayizeValue
|
||||
from lib.core.common import urlencode
|
||||
from lib.core.common import zeroDepthSearch
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import queries
|
||||
@@ -43,6 +46,7 @@ from lib.core.settings import INFERENCE_MARKER
|
||||
from lib.core.settings import NULL
|
||||
from lib.core.settings import PAYLOAD_DELIMITER
|
||||
from lib.core.settings import REPLACEMENT_MARKER
|
||||
from lib.core.settings import SINGLE_QUOTE_MARKER
|
||||
from lib.core.settings import SLEEP_TIME_MARKER
|
||||
from lib.core.unescaper import unescaper
|
||||
|
||||
@@ -104,9 +108,9 @@ class Agent(object):
|
||||
if place == PLACE.URI:
|
||||
origValue = origValue.split(kb.customInjectionMark)[0]
|
||||
else:
|
||||
origValue = filter(None, (re.search(_, origValue.split(BOUNDED_INJECTION_MARKER)[0]) for _ in (r"\w+\Z", r"[^\"'><]+\Z", r"[^ ]+\Z")))[0].group(0)
|
||||
origValue = filterNone(re.search(_, origValue.split(BOUNDED_INJECTION_MARKER)[0]) for _ in (r"\w+\Z", r"[^\"'><]+\Z", r"[^ ]+\Z"))[0].group(0)
|
||||
origValue = origValue[origValue.rfind('/') + 1:]
|
||||
for char in ('?', '=', ':', ','):
|
||||
for char in ('?', '=', ':', ',', '&'):
|
||||
if char in origValue:
|
||||
origValue = origValue[origValue.rfind(char) + 1:]
|
||||
elif place == PLACE.CUSTOM_POST:
|
||||
@@ -142,7 +146,7 @@ class Agent(object):
|
||||
match = re.search(r"\A[^ ]+", newValue)
|
||||
newValue = newValue[len(match.group() if match else ""):]
|
||||
_ = randomInt(2)
|
||||
value = "%s%s AND %s=%s" % (origValue, match.group() if match else "", _, _ + 1)
|
||||
value = "%s%s AND %s LIKE %s" % (origValue, match.group() if match else "", _, _ + 1)
|
||||
elif conf.invalidBignum:
|
||||
value = randomInt(6)
|
||||
elif conf.invalidString:
|
||||
@@ -161,6 +165,11 @@ class Agent(object):
|
||||
|
||||
newValue = self.cleanupPayload(newValue, origValue)
|
||||
|
||||
if re.sub(r" \(.+", "", parameter) in conf.base64Parameter:
|
||||
# TODO: support for POST_HINT
|
||||
newValue = base64.b64encode(newValue)
|
||||
origValue = base64.b64encode(origValue)
|
||||
|
||||
if place in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER):
|
||||
_ = "%s%s" % (origValue, kb.customInjectionMark)
|
||||
if kb.postHint == POST_HINT.JSON and not isNumber(newValue) and not '"%s"' % _ in paramString:
|
||||
@@ -198,7 +207,7 @@ class Agent(object):
|
||||
regex = r"(\A|\b)%s=%s%s" % (re.escape(parameter), re.escape(origValue), r"(\Z|\b)" if origValue[-1].isalnum() else "")
|
||||
retVal = _(regex, "%s=%s" % (parameter, self.addPayloadDelimiters(newValue)), paramString)
|
||||
else:
|
||||
retVal = _(r"(\A|\b)%s=%s(\Z|%s|%s|\s)" % (re.escape(parameter), re.escape(origValue), DEFAULT_GET_POST_DELIMITER, DEFAULT_COOKIE_DELIMITER), "%s=%s\g<2>" % (parameter, self.addPayloadDelimiters(newValue)), paramString)
|
||||
retVal = _(r"(\A|\b)%s=%s(\Z|%s|%s|\s)" % (re.escape(parameter), re.escape(origValue), DEFAULT_GET_POST_DELIMITER, DEFAULT_COOKIE_DELIMITER), r"%s=%s\g<2>" % (parameter, self.addPayloadDelimiters(newValue)), paramString)
|
||||
|
||||
if retVal == paramString and urlencode(parameter) != parameter:
|
||||
retVal = _(r"(\A|\b)%s=%s" % (re.escape(urlencode(parameter)), re.escape(origValue)), "%s=%s" % (urlencode(parameter), self.addPayloadDelimiters(newValue)), paramString)
|
||||
@@ -246,6 +255,9 @@ class Agent(object):
|
||||
else:
|
||||
query = kb.injection.prefix or prefix or ""
|
||||
|
||||
if "SELECT '[RANDSTR]'" in query: # escaping of pre-WHERE prefixes
|
||||
query = query.replace("'[RANDSTR]'", unescaper.escape(randomStr(), quote=False))
|
||||
|
||||
if not (expression and expression[0] == ';') and not (query and query[-1] in ('(', ')') and expression and expression[0] in ('(', ')')) and not (query and query[-1] == '('):
|
||||
query += " "
|
||||
|
||||
@@ -294,16 +306,19 @@ class Agent(object):
|
||||
if payload is None:
|
||||
return
|
||||
|
||||
replacements = (
|
||||
("[DELIMITER_START]", kb.chars.start),
|
||||
("[DELIMITER_STOP]", kb.chars.stop),
|
||||
("[AT_REPLACE]", kb.chars.at),
|
||||
("[SPACE_REPLACE]", kb.chars.space),
|
||||
("[DOLLAR_REPLACE]", kb.chars.dollar),
|
||||
("[HASH_REPLACE]", kb.chars.hash_),
|
||||
("[GENERIC_SQL_COMMENT]", GENERIC_SQL_COMMENT)
|
||||
)
|
||||
payload = reduce(lambda x, y: x.replace(y[0], y[1]), replacements, payload)
|
||||
replacements = {
|
||||
"[DELIMITER_START]": kb.chars.start,
|
||||
"[DELIMITER_STOP]": kb.chars.stop,
|
||||
"[AT_REPLACE]": kb.chars.at,
|
||||
"[SPACE_REPLACE]": kb.chars.space,
|
||||
"[DOLLAR_REPLACE]": kb.chars.dollar,
|
||||
"[HASH_REPLACE]": kb.chars.hash_,
|
||||
"[GENERIC_SQL_COMMENT]": GENERIC_SQL_COMMENT
|
||||
}
|
||||
|
||||
for value in re.findall(r"\[[A-Z_]+\]", payload):
|
||||
if value in replacements:
|
||||
payload = payload.replace(value, replacements[value])
|
||||
|
||||
for _ in set(re.findall(r"(?i)\[RANDNUM(?:\d+)?\]", payload)):
|
||||
payload = payload.replace(_, str(randomInt()))
|
||||
@@ -311,9 +326,12 @@ class Agent(object):
|
||||
for _ in set(re.findall(r"(?i)\[RANDSTR(?:\d+)?\]", payload)):
|
||||
payload = payload.replace(_, randomStr())
|
||||
|
||||
if origValue is not None and "[ORIGVALUE]" in payload:
|
||||
if origValue is not None:
|
||||
origValue = getUnicode(origValue)
|
||||
payload = getUnicode(payload).replace("[ORIGVALUE]", origValue if origValue.isdigit() else unescaper.escape("'%s'" % origValue))
|
||||
if "[ORIGVALUE]" in payload:
|
||||
payload = getUnicode(payload).replace("[ORIGVALUE]", origValue if origValue.isdigit() else unescaper.escape("'%s'" % origValue))
|
||||
if "[ORIGINAL]" in payload:
|
||||
payload = getUnicode(payload).replace("[ORIGINAL]", origValue)
|
||||
|
||||
if INFERENCE_MARKER in payload:
|
||||
if Backend.getIdentifiedDbms() is not None:
|
||||
@@ -342,6 +360,7 @@ class Agent(object):
|
||||
|
||||
if payload:
|
||||
payload = payload.replace(SLEEP_TIME_MARKER, str(conf.timeSec))
|
||||
payload = payload.replace(SINGLE_QUOTE_MARKER, "'")
|
||||
|
||||
for _ in set(re.findall(r"\[RANDNUM(?:\d+)?\]", payload, re.I)):
|
||||
payload = payload.replace(_, str(randomInt()))
|
||||
@@ -535,7 +554,7 @@ class Agent(object):
|
||||
fieldsToCastStr = fieldsToCastStr or ""
|
||||
|
||||
# Function
|
||||
if re.search("\A\w+\(.*\)", fieldsToCastStr, re.I) or (fieldsSelectCase and "WHEN use" not in query) or fieldsSubstr:
|
||||
if re.search(r"\A\w+\(.*\)", fieldsToCastStr, re.I) or (fieldsSelectCase and "WHEN use" not in query) or fieldsSubstr:
|
||||
fieldsToCastList = [fieldsToCastStr]
|
||||
else:
|
||||
fieldsToCastList = splitFields(fieldsToCastStr)
|
||||
@@ -616,7 +635,7 @@ class Agent(object):
|
||||
elif fieldsNoSelect:
|
||||
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):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2):
|
||||
if fieldsExists:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
|
||||
concatenatedQuery += "||'%s'" % kb.chars.stop
|
||||
@@ -627,7 +646,7 @@ class Agent(object):
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
|
||||
_ = unArrayizeValue(zeroDepthSearch(concatenatedQuery, " FROM "))
|
||||
concatenatedQuery = "%s||'%s'%s" % (concatenatedQuery[:_], kb.chars.stop, concatenatedQuery[_:])
|
||||
concatenatedQuery = re.sub(r"('%s'\|\|)(.+)(%s)" % (kb.chars.start, re.escape(castedFields)), "\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:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
|
||||
concatenatedQuery += "||'%s'" % kb.chars.stop
|
||||
@@ -639,7 +658,7 @@ class Agent(object):
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.chars.start, 1)
|
||||
concatenatedQuery += "+'%s'" % kb.chars.stop
|
||||
elif fieldsSelectTop:
|
||||
topNum = re.search("\ASELECT\s+TOP\s+([\d]+)\s+", concatenatedQuery, re.I).group(1)
|
||||
topNum = re.search(r"\ASELECT\s+TOP\s+([\d]+)\s+", concatenatedQuery, re.I).group(1)
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, kb.chars.start), 1)
|
||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.chars.stop, 1)
|
||||
elif fieldsSelectCase:
|
||||
@@ -815,7 +834,7 @@ class Agent(object):
|
||||
limitRegExp2 = None
|
||||
|
||||
if (limitRegExp or limitRegExp2) or (Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2):
|
||||
limitGroupStart = queries[Backend.getIdentifiedDbms()].limitgroupstart.query
|
||||
limitGroupStop = queries[Backend.getIdentifiedDbms()].limitgroupstop.query
|
||||
|
||||
@@ -905,14 +924,14 @@ class Agent(object):
|
||||
fromFrom = limitedQuery[fromIndex + 1:]
|
||||
orderBy = None
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE):
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2):
|
||||
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1)
|
||||
limitedQuery += " %s" % limitStr
|
||||
|
||||
elif Backend.isDbms(DBMS.HSQLDB):
|
||||
match = re.search(r"ORDER BY [^ ]+", limitedQuery)
|
||||
if match:
|
||||
limitedQuery = re.sub(r"\s*%s\s*" % match.group(0), " ", limitedQuery).strip()
|
||||
limitedQuery = re.sub(r"\s*%s\s*" % re.escape(match.group(0)), " ", limitedQuery).strip()
|
||||
limitedQuery += " %s" % match.group(0)
|
||||
|
||||
if query.startswith("SELECT "):
|
||||
@@ -970,8 +989,7 @@ class Agent(object):
|
||||
limitedQuery = limitedQuery.replace(" (SELECT TOP %s" % startTopNums, " (SELECT TOP %d" % num)
|
||||
forgeNotIn = False
|
||||
else:
|
||||
topNum = re.search(r"TOP\s+([\d]+)\s+", limitedQuery, re.I).group(1)
|
||||
limitedQuery = limitedQuery.replace("TOP %s " % topNum, "")
|
||||
limitedQuery = re.sub(r"\bTOP\s+\d+\s*", "", limitedQuery, flags=re.I)
|
||||
|
||||
if forgeNotIn:
|
||||
limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1)
|
||||
@@ -1086,7 +1104,7 @@ class Agent(object):
|
||||
if conf.dumpWhere and query:
|
||||
prefix, suffix = query.split(" ORDER BY ") if " ORDER BY " in query else (query, "")
|
||||
|
||||
if "%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)
|
||||
elif re.search(r"(?i)\bWHERE\b", prefix):
|
||||
prefix += " AND %s" % conf.dumpWhere
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -16,6 +16,7 @@ import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.enums import MKSTEMP_PREFIX
|
||||
from lib.core.exception import SqlmapSystemException
|
||||
from lib.core.settings import BIGARRAY_CHUNK_SIZE
|
||||
@@ -87,7 +88,7 @@ class BigArray(list):
|
||||
try:
|
||||
with open(self.chunks[-1], "rb") as f:
|
||||
self.chunks[-1] = pickle.loads(bz2.decompress(f.read()))
|
||||
except IOError, ex:
|
||||
except IOError as ex:
|
||||
errMsg = "exception occurred while retrieving data "
|
||||
errMsg += "from a temporary file ('%s')" % ex.message
|
||||
raise SqlmapSystemException(errMsg)
|
||||
@@ -109,7 +110,7 @@ class BigArray(list):
|
||||
with open(filename, "w+b") as f:
|
||||
f.write(bz2.compress(pickle.dumps(chunk, pickle.HIGHEST_PROTOCOL), BIGARRAY_COMPRESS_LEVEL))
|
||||
return filename
|
||||
except (OSError, IOError), ex:
|
||||
except (OSError, IOError) as ex:
|
||||
errMsg = "exception occurred while storing data "
|
||||
errMsg += "to a temporary file ('%s'). Please " % ex.message
|
||||
errMsg += "make sure that there is enough disk space left. If problem persists, "
|
||||
@@ -126,7 +127,7 @@ class BigArray(list):
|
||||
try:
|
||||
with open(self.chunks[index], "rb") as f:
|
||||
self.cache = Cache(index, pickle.loads(bz2.decompress(f.read())), False)
|
||||
except IOError, ex:
|
||||
except Exception as ex:
|
||||
errMsg = "exception occurred while retrieving data "
|
||||
errMsg += "from a temporary file ('%s')" % ex.message
|
||||
raise SqlmapSystemException(errMsg)
|
||||
@@ -148,7 +149,7 @@ class BigArray(list):
|
||||
if y < 0:
|
||||
y += len(self)
|
||||
|
||||
index = y / self.chunk_length
|
||||
index = y // self.chunk_length
|
||||
offset = y % self.chunk_length
|
||||
chunk = self.chunks[index]
|
||||
|
||||
@@ -159,7 +160,7 @@ class BigArray(list):
|
||||
return self.cache.data[offset]
|
||||
|
||||
def __setitem__(self, y, value):
|
||||
index = y / self.chunk_length
|
||||
index = y // self.chunk_length
|
||||
offset = y % self.chunk_length
|
||||
chunk = self.chunks[index]
|
||||
|
||||
|
||||
1182
lib/core/common.py
1182
lib/core/common.py
File diff suppressed because it is too large
Load Diff
172
lib/core/compat.py
Normal file
172
lib/core/compat.py
Normal file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import binascii
|
||||
import os
|
||||
import random
|
||||
import uuid
|
||||
import sys
|
||||
|
||||
class WichmannHill(random.Random):
|
||||
"""
|
||||
Reference: https://svn.python.org/projects/python/trunk/Lib/random.py
|
||||
"""
|
||||
|
||||
VERSION = 1 # used by getstate/setstate
|
||||
|
||||
def seed(self, a=None):
|
||||
"""Initialize internal state from hashable object.
|
||||
|
||||
None or no argument seeds from current time or from an operating
|
||||
system specific randomness source if available.
|
||||
|
||||
If a is not None or an int or long, hash(a) is used instead.
|
||||
|
||||
If a is an int or long, a is used directly. Distinct values between
|
||||
0 and 27814431486575L inclusive are guaranteed to yield distinct
|
||||
internal states (this guarantee is specific to the default
|
||||
Wichmann-Hill generator).
|
||||
"""
|
||||
|
||||
if a is None:
|
||||
try:
|
||||
a = int(binascii.hexlify(os.urandom(16)), 16)
|
||||
except NotImplementedError:
|
||||
import time
|
||||
a = int(time.time() * 256) # use fractional seconds
|
||||
|
||||
if not isinstance(a, int):
|
||||
a = hash(a)
|
||||
|
||||
a, x = divmod(a, 30268)
|
||||
a, y = divmod(a, 30306)
|
||||
a, z = divmod(a, 30322)
|
||||
self._seed = int(x) + 1, int(y) + 1, int(z) + 1
|
||||
|
||||
self.gauss_next = None
|
||||
|
||||
def random(self):
|
||||
"""Get the next random number in the range [0.0, 1.0)."""
|
||||
|
||||
# Wichman-Hill random number generator.
|
||||
#
|
||||
# Wichmann, B. A. & Hill, I. D. (1982)
|
||||
# Algorithm AS 183:
|
||||
# An efficient and portable pseudo-random number generator
|
||||
# Applied Statistics 31 (1982) 188-190
|
||||
#
|
||||
# see also:
|
||||
# Correction to Algorithm AS 183
|
||||
# Applied Statistics 33 (1984) 123
|
||||
#
|
||||
# McLeod, A. I. (1985)
|
||||
# A remark on Algorithm AS 183
|
||||
# Applied Statistics 34 (1985),198-200
|
||||
|
||||
# This part is thread-unsafe:
|
||||
# BEGIN CRITICAL SECTION
|
||||
x, y, z = self._seed
|
||||
x = (171 * x) % 30269
|
||||
y = (172 * y) % 30307
|
||||
z = (170 * z) % 30323
|
||||
self._seed = x, y, z
|
||||
# END CRITICAL SECTION
|
||||
|
||||
# Note: on a platform using IEEE-754 double arithmetic, this can
|
||||
# never return 0.0 (asserted by Tim; proof too long for a comment).
|
||||
return (x / 30269.0 + y / 30307.0 + z / 30323.0) % 1.0
|
||||
|
||||
def getstate(self):
|
||||
"""Return internal state; can be passed to setstate() later."""
|
||||
return self.VERSION, self._seed, self.gauss_next
|
||||
|
||||
def setstate(self, state):
|
||||
"""Restore internal state from object returned by getstate()."""
|
||||
version = state[0]
|
||||
if version == 1:
|
||||
version, self._seed, self.gauss_next = state
|
||||
else:
|
||||
raise ValueError("state with version %s passed to "
|
||||
"Random.setstate() of version %s" %
|
||||
(version, self.VERSION))
|
||||
|
||||
def jumpahead(self, n):
|
||||
"""Act as if n calls to random() were made, but quickly.
|
||||
|
||||
n is an int, greater than or equal to 0.
|
||||
|
||||
Example use: If you have 2 threads and know that each will
|
||||
consume no more than a million random numbers, create two Random
|
||||
objects r1 and r2, then do
|
||||
r2.setstate(r1.getstate())
|
||||
r2.jumpahead(1000000)
|
||||
Then r1 and r2 will use guaranteed-disjoint segments of the full
|
||||
period.
|
||||
"""
|
||||
|
||||
if not n >= 0:
|
||||
raise ValueError("n must be >= 0")
|
||||
x, y, z = self._seed
|
||||
x = int(x * pow(171, n, 30269)) % 30269
|
||||
y = int(y * pow(172, n, 30307)) % 30307
|
||||
z = int(z * pow(170, n, 30323)) % 30323
|
||||
self._seed = x, y, z
|
||||
|
||||
def __whseed(self, x=0, y=0, z=0):
|
||||
"""Set the Wichmann-Hill seed from (x, y, z).
|
||||
|
||||
These must be integers in the range [0, 256).
|
||||
"""
|
||||
|
||||
if not type(x) == type(y) == type(z) == int:
|
||||
raise TypeError('seeds must be integers')
|
||||
if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
|
||||
raise ValueError('seeds must be in range(0, 256)')
|
||||
if 0 == x == y == z:
|
||||
# Initialize from current time
|
||||
import time
|
||||
t = int(time.time() * 256)
|
||||
t = int((t & 0xffffff) ^ (t >> 24))
|
||||
t, x = divmod(t, 256)
|
||||
t, y = divmod(t, 256)
|
||||
t, z = divmod(t, 256)
|
||||
# Zero is a poor seed, so substitute 1
|
||||
self._seed = (x or 1, y or 1, z or 1)
|
||||
|
||||
self.gauss_next = None
|
||||
|
||||
def whseed(self, a=None):
|
||||
"""Seed from hashable object's hash code.
|
||||
|
||||
None or no argument seeds from current time. It is not guaranteed
|
||||
that objects with distinct hash codes lead to distinct internal
|
||||
states.
|
||||
|
||||
This is obsolete, provided for compatibility with the seed routine
|
||||
used prior to Python 2.1. Use the .seed() method instead.
|
||||
"""
|
||||
|
||||
if a is None:
|
||||
self.__whseed()
|
||||
return
|
||||
a = hash(a)
|
||||
a, x = divmod(a, 256)
|
||||
a, y = divmod(a, 256)
|
||||
a, z = divmod(a, 256)
|
||||
x = (x + a) % 256 or 1
|
||||
y = (y + a) % 256 or 1
|
||||
z = (z + a) % 256 or 1
|
||||
self.__whseed(x, y, z)
|
||||
|
||||
# Reference: https://github.com/urllib3/urllib3/blob/master/src/urllib3/filepost.py
|
||||
def choose_boundary():
|
||||
return uuid.uuid4().hex
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
xrange = range
|
||||
else:
|
||||
xrange = xrange
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -9,18 +9,15 @@ try:
|
||||
import cPickle as pickle
|
||||
except:
|
||||
import pickle
|
||||
finally:
|
||||
import pickle as picklePy
|
||||
|
||||
import base64
|
||||
import json
|
||||
import re
|
||||
import StringIO
|
||||
import sys
|
||||
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.settings import PICKLE_REDUCE_WHITELIST
|
||||
from thirdparty import six
|
||||
|
||||
def base64decode(value):
|
||||
"""
|
||||
@@ -30,7 +27,7 @@ def base64decode(value):
|
||||
'foobar'
|
||||
"""
|
||||
|
||||
return base64.b64decode(value)
|
||||
return base64.b64decode(unicodeencode(value))
|
||||
|
||||
def base64encode(value):
|
||||
"""
|
||||
@@ -40,7 +37,7 @@ def base64encode(value):
|
||||
'Zm9vYmFy'
|
||||
"""
|
||||
|
||||
return base64.b64encode(value)
|
||||
return base64.b64encode(unicodeencode(value))
|
||||
|
||||
def base64pickle(value):
|
||||
"""
|
||||
@@ -66,7 +63,7 @@ def base64pickle(value):
|
||||
|
||||
return retVal
|
||||
|
||||
def base64unpickle(value, unsafe=False):
|
||||
def base64unpickle(value):
|
||||
"""
|
||||
Decodes value from Base64 to plain format and deserializes (with pickle) its content
|
||||
|
||||
@@ -76,26 +73,10 @@ def base64unpickle(value, unsafe=False):
|
||||
|
||||
retVal = None
|
||||
|
||||
def _(self):
|
||||
if len(self.stack) > 1:
|
||||
func = self.stack[-2]
|
||||
if func not in PICKLE_REDUCE_WHITELIST:
|
||||
raise Exception("abusing reduce() is bad, Mkay!")
|
||||
self.load_reduce()
|
||||
|
||||
def loads(str):
|
||||
f = StringIO.StringIO(str)
|
||||
if unsafe:
|
||||
unpickler = picklePy.Unpickler(f)
|
||||
unpickler.dispatch[picklePy.REDUCE] = _
|
||||
else:
|
||||
unpickler = pickle.Unpickler(f)
|
||||
return unpickler.load()
|
||||
|
||||
try:
|
||||
retVal = loads(base64decode(value))
|
||||
retVal = pickle.loads(base64decode(value))
|
||||
except TypeError:
|
||||
retVal = loads(base64decode(bytes(value)))
|
||||
retVal = pickle.loads(base64decode(bytes(value)))
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -108,7 +89,14 @@ def hexdecode(value):
|
||||
"""
|
||||
|
||||
value = value.lower()
|
||||
return (value[2:] if value.startswith("0x") else value).decode("hex")
|
||||
value = value[2:] if value.startswith("0x") else value
|
||||
|
||||
if six.PY2:
|
||||
retVal = value.decode("hex")
|
||||
else:
|
||||
retVal = bytes.fromhex(value)
|
||||
|
||||
return retVal
|
||||
|
||||
def hexencode(value, encoding=None):
|
||||
"""
|
||||
@@ -118,7 +106,14 @@ def hexencode(value, encoding=None):
|
||||
'666f6f626172'
|
||||
"""
|
||||
|
||||
return unicodeencode(value, encoding).encode("hex")
|
||||
retVal = unicodeencode(value, encoding)
|
||||
|
||||
if six.PY2:
|
||||
retVal = retVal.encode("hex")
|
||||
else:
|
||||
retVal = retVal.hex()
|
||||
|
||||
return retVal
|
||||
|
||||
def unicodeencode(value, encoding=None):
|
||||
"""
|
||||
@@ -129,11 +124,13 @@ def unicodeencode(value, encoding=None):
|
||||
"""
|
||||
|
||||
retVal = value
|
||||
if isinstance(value, unicode):
|
||||
|
||||
if isinstance(value, six.text_type):
|
||||
try:
|
||||
retVal = value.encode(encoding or UNICODE_ENCODING)
|
||||
except UnicodeEncodeError:
|
||||
retVal = value.encode(UNICODE_ENCODING, "replace")
|
||||
retVal = value.encode(encoding or UNICODE_ENCODING, "replace")
|
||||
|
||||
return retVal
|
||||
|
||||
def utf8encode(value):
|
||||
@@ -165,9 +162,11 @@ def htmlunescape(value):
|
||||
"""
|
||||
|
||||
retVal = value
|
||||
if value and isinstance(value, basestring):
|
||||
codes = (("<", '<'), (">", '>'), (""", '"'), (" ", ' '), ("&", '&'), ("'", "'"))
|
||||
retVal = reduce(lambda x, y: x.replace(y[0], y[1]), codes, retVal)
|
||||
if value and isinstance(value, six.string_types):
|
||||
replacements = (("<", '<'), (">", '>'), (""", '"'), (" ", ' '), ("&", '&'), ("'", "'"))
|
||||
for code, value in replacements:
|
||||
retVal = retVal.replace(code, value)
|
||||
|
||||
try:
|
||||
retVal = re.sub(r"&#x([^ ;]+);", lambda match: unichr(int(match.group(1), 16)), retVal)
|
||||
except ValueError:
|
||||
@@ -180,30 +179,26 @@ def singleTimeWarnMessage(message): # Cross-referenced function
|
||||
sys.stdout.flush()
|
||||
|
||||
def stdoutencode(data):
|
||||
retVal = None
|
||||
retVal = data
|
||||
|
||||
try:
|
||||
data = data or ""
|
||||
if six.PY2:
|
||||
try:
|
||||
retVal = unicodeencode(data or "", sys.stdout.encoding)
|
||||
|
||||
# Reference: http://bugs.python.org/issue1602
|
||||
if IS_WIN:
|
||||
output = data.encode(sys.stdout.encoding, "replace")
|
||||
# Reference: http://bugs.python.org/issue1602
|
||||
if IS_WIN:
|
||||
if '?' in retVal and '?' not in retVal:
|
||||
warnMsg = "cannot properly display Unicode characters "
|
||||
warnMsg += "inside Windows OS command prompt "
|
||||
warnMsg += "(http://bugs.python.org/issue1602). All "
|
||||
warnMsg += "unhandled occurrences will result in "
|
||||
warnMsg += "replacement with '?' character. Please, find "
|
||||
warnMsg += "proper character representation inside "
|
||||
warnMsg += "corresponding output files. "
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
if '?' in output and '?' not in data:
|
||||
warnMsg = "cannot properly display Unicode characters "
|
||||
warnMsg += "inside Windows OS command prompt "
|
||||
warnMsg += "(http://bugs.python.org/issue1602). All "
|
||||
warnMsg += "unhandled occurrences will result in "
|
||||
warnMsg += "replacement with '?' character. Please, find "
|
||||
warnMsg += "proper character representation inside "
|
||||
warnMsg += "corresponding output files. "
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
retVal = output
|
||||
else:
|
||||
retVal = data.encode(sys.stdout.encoding)
|
||||
except:
|
||||
retVal = data.encode(UNICODE_ENCODING) if isinstance(data, unicode) else data
|
||||
except:
|
||||
retVal = unicodeencode(data or "")
|
||||
|
||||
return retVal
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import collections
|
||||
import copy
|
||||
import types
|
||||
|
||||
from thirdparty.odict import OrderedDict
|
||||
|
||||
class AttribDict(dict):
|
||||
"""
|
||||
This class defines the sqlmap object, inheriting from Python data
|
||||
@@ -104,3 +107,95 @@ class InjectionDict(AttribDict):
|
||||
self.dbms = None
|
||||
self.dbms_version = None
|
||||
self.os = None
|
||||
|
||||
# Reference: https://www.kunxi.org/2014/05/lru-cache-in-python
|
||||
class LRUDict(object):
|
||||
def __init__(self, capacity):
|
||||
self.capacity = capacity
|
||||
self.cache = OrderedDict()
|
||||
|
||||
def __len__(self):
|
||||
return len(self.cache)
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.cache
|
||||
|
||||
def __getitem__(self, key):
|
||||
value = self.cache.pop(key)
|
||||
self.cache[key] = value
|
||||
return value
|
||||
|
||||
def get(self, key):
|
||||
return self.__getitem__(key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
try:
|
||||
self.cache.pop(key)
|
||||
except KeyError:
|
||||
if len(self.cache) >= self.capacity:
|
||||
self.cache.popitem(last=False)
|
||||
self.cache[key] = value
|
||||
|
||||
def set(self, key, value):
|
||||
self.__setitem__(key, value)
|
||||
|
||||
def keys(self):
|
||||
return self.cache.keys()
|
||||
|
||||
# Reference: https://code.activestate.com/recipes/576694/
|
||||
class OrderedSet(collections.MutableSet):
|
||||
def __init__(self, iterable=None):
|
||||
self.end = end = []
|
||||
end += [None, end, end] # sentinel node for doubly linked list
|
||||
self.map = {} # key --> [key, prev, next]
|
||||
if iterable is not None:
|
||||
self |= iterable
|
||||
|
||||
def __len__(self):
|
||||
return len(self.map)
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.map
|
||||
|
||||
def add(self, key):
|
||||
if key not in self.map:
|
||||
end = self.end
|
||||
curr = end[1]
|
||||
curr[2] = end[1] = self.map[key] = [key, curr, end]
|
||||
|
||||
def discard(self, key):
|
||||
if key in self.map:
|
||||
key, prev, next = self.map.pop(key)
|
||||
prev[2] = next
|
||||
next[1] = prev
|
||||
|
||||
def __iter__(self):
|
||||
end = self.end
|
||||
curr = end[2]
|
||||
while curr is not end:
|
||||
yield curr[0]
|
||||
curr = curr[2]
|
||||
|
||||
def __reversed__(self):
|
||||
end = self.end
|
||||
curr = end[1]
|
||||
while curr is not end:
|
||||
yield curr[0]
|
||||
curr = curr[1]
|
||||
|
||||
def pop(self, last=True):
|
||||
if not self:
|
||||
raise KeyError('set is empty')
|
||||
key = self.end[1][0] if last else self.end[2][0]
|
||||
self.discard(key)
|
||||
return key
|
||||
|
||||
def __repr__(self):
|
||||
if not self:
|
||||
return '%s()' % (self.__class__.__name__,)
|
||||
return '%s(%r)' % (self.__class__.__name__, list(self))
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, OrderedSet):
|
||||
return len(self) == len(other) and list(self) == list(other)
|
||||
return set(self) == set(other)
|
||||
|
||||
@@ -1,31 +1,51 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import functools
|
||||
import hashlib
|
||||
import threading
|
||||
|
||||
from lib.core.settings import MAX_CACHE_ITEMS
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.datatype import LRUDict
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
|
||||
def cachedmethod(f, cache={}):
|
||||
_lock = threading.Lock()
|
||||
|
||||
def cachedmethod(f, cache=LRUDict(capacity=MAX_CACHE_ITEMS)):
|
||||
"""
|
||||
Method with a cached content
|
||||
|
||||
Reference: http://code.activestate.com/recipes/325205-cache-decorator-in-python-24/
|
||||
"""
|
||||
|
||||
@functools.wraps(f)
|
||||
def _(*args, **kwargs):
|
||||
key = int(hashlib.md5("|".join(str(_) for _ in (f, args, kwargs))).hexdigest(), 16) & 0x7fffffffffffffff
|
||||
if key not in cache:
|
||||
cache[key] = f(*args, **kwargs)
|
||||
key = int(hashlib.md5("|".join(str(_) for _ in (f, args, kwargs)).encode(UNICODE_ENCODING)).hexdigest(), 16) & 0x7fffffffffffffff
|
||||
|
||||
return cache[key]
|
||||
try:
|
||||
with _lock:
|
||||
result = cache[key]
|
||||
except KeyError:
|
||||
result = f(*args, **kwargs)
|
||||
|
||||
with _lock:
|
||||
cache[key] = result
|
||||
|
||||
return result
|
||||
|
||||
return _
|
||||
|
||||
def stackedmethod(f):
|
||||
"""
|
||||
Method using pushValue/popValue functions (fallback function for stack realignment)
|
||||
"""
|
||||
|
||||
@functools.wraps(f)
|
||||
def _(*args, **kwargs):
|
||||
threadData = getCurrentThreadData()
|
||||
originalLevel = len(threadData.valueStack)
|
||||
@@ -38,4 +58,4 @@ def stackedmethod(f):
|
||||
|
||||
return result
|
||||
|
||||
return _
|
||||
return _
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.enums import CONTENT_TYPE
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.enums import OS
|
||||
from lib.core.enums import POST_HINT
|
||||
@@ -21,6 +22,7 @@ from lib.core.settings import MAXDB_ALIASES
|
||||
from lib.core.settings import SYBASE_ALIASES
|
||||
from lib.core.settings import DB2_ALIASES
|
||||
from lib.core.settings import HSQLDB_ALIASES
|
||||
from lib.core.settings import H2_ALIASES
|
||||
from lib.core.settings import INFORMIX_ALIASES
|
||||
|
||||
FIREBIRD_TYPES = {
|
||||
@@ -194,6 +196,7 @@ DBMS_DICT = {
|
||||
DBMS.SYBASE: (SYBASE_ALIASES, "python-pymssql", "https://github.com/pymssql/pymssql", "sybase"),
|
||||
DBMS.DB2: (DB2_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"),
|
||||
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.INFORMIX: (INFORMIX_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"),
|
||||
}
|
||||
|
||||
@@ -262,6 +265,10 @@ SQL_STATEMENTS = {
|
||||
"commit ",
|
||||
"rollback ",
|
||||
),
|
||||
|
||||
"SQL administration": (
|
||||
"set ",
|
||||
),
|
||||
}
|
||||
|
||||
POST_HINT_CONTENT_TYPES = {
|
||||
@@ -279,6 +286,8 @@ DEPRECATED_OPTIONS = {
|
||||
"--binary": "use '--binary-fields' instead",
|
||||
"--auth-private": "use '--auth-file' instead",
|
||||
"--ignore-401": "use '--ignore-code' instead",
|
||||
"--second-order": "use '--second-url' instead",
|
||||
"--purge-output": "use '--purge' instead",
|
||||
"--check-payload": None,
|
||||
"--check-waf": None,
|
||||
"--pickled-options": "use '--api -c ...' instead",
|
||||
@@ -293,3 +302,31 @@ DEFAULT_DOC_ROOTS = {
|
||||
OS.WINDOWS: ("C:/xampp/htdocs/", "C:/wamp/www/", "C:/Inetpub/wwwroot/"),
|
||||
OS.LINUX: ("/var/www/", "/var/www/html", "/usr/local/apache2/htdocs", "/var/www/nginx-default", "/srv/www") # Reference: https://wiki.apache.org/httpd/DistrosDefaultLayout
|
||||
}
|
||||
|
||||
PART_RUN_CONTENT_TYPES = {
|
||||
"checkDbms": CONTENT_TYPE.TECHNIQUES,
|
||||
"getFingerprint": CONTENT_TYPE.DBMS_FINGERPRINT,
|
||||
"getBanner": CONTENT_TYPE.BANNER,
|
||||
"getCurrentUser": CONTENT_TYPE.CURRENT_USER,
|
||||
"getCurrentDb": CONTENT_TYPE.CURRENT_DB,
|
||||
"getHostname": CONTENT_TYPE.HOSTNAME,
|
||||
"isDba": CONTENT_TYPE.IS_DBA,
|
||||
"getUsers": CONTENT_TYPE.USERS,
|
||||
"getPasswordHashes": CONTENT_TYPE.PASSWORDS,
|
||||
"getPrivileges": CONTENT_TYPE.PRIVILEGES,
|
||||
"getRoles": CONTENT_TYPE.ROLES,
|
||||
"getDbs": CONTENT_TYPE.DBS,
|
||||
"getTables": CONTENT_TYPE.TABLES,
|
||||
"getColumns": CONTENT_TYPE.COLUMNS,
|
||||
"getSchema": CONTENT_TYPE.SCHEMA,
|
||||
"getCount": CONTENT_TYPE.COUNT,
|
||||
"dumpTable": CONTENT_TYPE.DUMP_TABLE,
|
||||
"search": CONTENT_TYPE.SEARCH,
|
||||
"sqlQuery": CONTENT_TYPE.SQL_QUERY,
|
||||
"tableExists": CONTENT_TYPE.COMMON_TABLES,
|
||||
"columnExists": CONTENT_TYPE.COMMON_COLUMNS,
|
||||
"readFile": CONTENT_TYPE.FILE_READ,
|
||||
"writeFile": CONTENT_TYPE.FILE_WRITE,
|
||||
"osCmd": CONTENT_TYPE.OS_CMD,
|
||||
"regRead": CONTENT_TYPE.REG_READ
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -17,16 +17,18 @@ from lib.core.common import Backend
|
||||
from lib.core.common import checkFile
|
||||
from lib.core.common import dataToDumpFile
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import getBytes
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.common import isListLike
|
||||
from lib.core.common import isMultiThreadMode
|
||||
from lib.core.common import normalizeUnicode
|
||||
from lib.core.common import openFile
|
||||
from lib.core.common import prioritySortColumns
|
||||
from lib.core.common import randomInt
|
||||
from lib.core.common import safeCSValue
|
||||
from lib.core.common import unicodeencode
|
||||
from lib.core.common import unsafeSQLIdentificatorNaming
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
@@ -47,7 +49,9 @@ from lib.core.settings import MIN_BINARY_DISK_DUMP_SIZE
|
||||
from lib.core.settings import TRIM_STDOUT_DUMP_SIZE
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.settings import UNSAFE_DUMP_FILEPATH_REPLACEMENT
|
||||
from lib.core.settings import VERSION_STRING
|
||||
from lib.core.settings import WINDOWS_RESERVED_NAMES
|
||||
from thirdparty import six
|
||||
from thirdparty.magic import magic
|
||||
|
||||
from extra.safe2bin.safe2bin import safechardecode
|
||||
@@ -73,16 +77,17 @@ class Dump(object):
|
||||
if console:
|
||||
dataToStdout(text)
|
||||
|
||||
if kb.get("multiThreadMode"):
|
||||
multiThreadMode = isMultiThreadMode()
|
||||
if multiThreadMode:
|
||||
self._lock.acquire()
|
||||
|
||||
try:
|
||||
self._outputFP.write(text)
|
||||
except IOError, ex:
|
||||
except IOError as ex:
|
||||
errMsg = "error occurred while writing to log file ('%s')" % getSafeExString(ex)
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
if kb.get("multiThreadMode"):
|
||||
if multiThreadMode:
|
||||
self._lock.release()
|
||||
|
||||
kb.dataOutputFlag = True
|
||||
@@ -98,7 +103,7 @@ class Dump(object):
|
||||
self._outputFile = os.path.join(conf.outputPath, "log")
|
||||
try:
|
||||
self._outputFP = openFile(self._outputFile, "ab" if not conf.flushSession else "wb")
|
||||
except IOError, ex:
|
||||
except IOError as ex:
|
||||
errMsg = "error occurred while opening log file ('%s')" % getSafeExString(ex)
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
@@ -109,8 +114,6 @@ class Dump(object):
|
||||
self._write(data, content_type=content_type)
|
||||
|
||||
def string(self, header, data, content_type=None, sort=True):
|
||||
kb.stickyLevel = None
|
||||
|
||||
if conf.api:
|
||||
self._write(data, content_type=content_type)
|
||||
return
|
||||
@@ -132,7 +135,7 @@ class Dump(object):
|
||||
if "\n" in _:
|
||||
self._write("%s:\n---\n%s\n---" % (header, _))
|
||||
else:
|
||||
self._write("%s: %s" % (header, ("'%s'" % _) if isinstance(data, basestring) else _))
|
||||
self._write("%s: %s" % (header, ("'%s'" % _) if isinstance(data, six.string_types) else _))
|
||||
else:
|
||||
self._write("%s:\tNone" % header)
|
||||
|
||||
@@ -141,7 +144,7 @@ class Dump(object):
|
||||
try:
|
||||
elements = set(elements)
|
||||
elements = list(elements)
|
||||
elements.sort(key=lambda _: _.lower() if isinstance(_, basestring) else _)
|
||||
elements.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _)
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -153,7 +156,7 @@ class Dump(object):
|
||||
self._write("%s [%d]:" % (header, len(elements)))
|
||||
|
||||
for element in elements:
|
||||
if isinstance(element, basestring):
|
||||
if isinstance(element, six.string_types):
|
||||
self._write("[*] %s" % element)
|
||||
elif isListLike(element):
|
||||
self._write("[*] " + ", ".join(getUnicode(e) for e in element))
|
||||
@@ -170,7 +173,7 @@ class Dump(object):
|
||||
def currentDb(self, data):
|
||||
if Backend.isDbms(DBMS.MAXDB):
|
||||
self.string("current database (no practical usage on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB):
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2):
|
||||
self.string("current schema (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||
else:
|
||||
self.string("current database", data, content_type=CONTENT_TYPE.CURRENT_DB)
|
||||
@@ -192,7 +195,7 @@ class Dump(object):
|
||||
userSettings = userSettings[0]
|
||||
|
||||
users = userSettings.keys()
|
||||
users.sort(key=lambda _: _.lower() if isinstance(_, basestring) else _)
|
||||
users.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _)
|
||||
|
||||
if conf.api:
|
||||
self._write(userSettings, content_type=content_type)
|
||||
@@ -239,7 +242,7 @@ class Dump(object):
|
||||
if table and isListLike(table):
|
||||
table = table[0]
|
||||
|
||||
maxlength = max(maxlength, len(unsafeSQLIdentificatorNaming(normalizeUnicode(table) or unicode(table))))
|
||||
maxlength = max(maxlength, len(unsafeSQLIdentificatorNaming(normalizeUnicode(table) or getUnicode(table))))
|
||||
|
||||
lines = "-" * (int(maxlength) + 2)
|
||||
|
||||
@@ -260,7 +263,7 @@ class Dump(object):
|
||||
table = table[0]
|
||||
|
||||
table = unsafeSQLIdentificatorNaming(table)
|
||||
blank = " " * (maxlength - len(normalizeUnicode(table) or unicode(table)))
|
||||
blank = " " * (maxlength - len(normalizeUnicode(table) or getUnicode(table)))
|
||||
self._write("| %s%s |" % (table, blank))
|
||||
|
||||
self._write("+%s+\n" % lines)
|
||||
@@ -286,7 +289,7 @@ class Dump(object):
|
||||
colType = None
|
||||
|
||||
colList = columns.keys()
|
||||
colList.sort(key=lambda _: _.lower() if isinstance(_, basestring) else _)
|
||||
colList.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _)
|
||||
|
||||
for column in colList:
|
||||
colType = columns[column]
|
||||
@@ -355,7 +358,7 @@ class Dump(object):
|
||||
for ctables in dbTables.values():
|
||||
for tables in ctables.values():
|
||||
for table in tables:
|
||||
maxlength1 = max(maxlength1, len(normalizeUnicode(table) or unicode(table)))
|
||||
maxlength1 = max(maxlength1, len(normalizeUnicode(table) or getUnicode(table)))
|
||||
|
||||
for db, counts in dbTables.items():
|
||||
self._write("Database: %s" % unsafeSQLIdentificatorNaming(db) if db else "Current database")
|
||||
@@ -378,10 +381,10 @@ class Dump(object):
|
||||
if count is None:
|
||||
count = "Unknown"
|
||||
|
||||
tables.sort(key=lambda _: _.lower() if isinstance(_, basestring) else _)
|
||||
tables.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _)
|
||||
|
||||
for table in tables:
|
||||
blank1 = " " * (maxlength1 - len(normalizeUnicode(table) or unicode(table)))
|
||||
blank1 = " " * (maxlength1 - len(normalizeUnicode(table) or getUnicode(table)))
|
||||
blank2 = " " * (maxlength2 - len(str(count)))
|
||||
self._write("| %s%s | %d%s |" % (table, blank1, count, blank2))
|
||||
|
||||
@@ -419,16 +422,16 @@ class Dump(object):
|
||||
except:
|
||||
warnFile = True
|
||||
|
||||
_ = unicodeencode(re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(db)))
|
||||
dumpDbPath = os.path.join(conf.dumpPath, "%s-%s" % (_, hashlib.md5(unicodeencode(db)).hexdigest()[:8]))
|
||||
_ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(db))
|
||||
dumpDbPath = os.path.join(conf.dumpPath, "%s-%s" % (_, hashlib.md5(getBytes(db)).hexdigest()[:8]))
|
||||
|
||||
if not os.path.isdir(dumpDbPath):
|
||||
try:
|
||||
os.makedirs(dumpDbPath)
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
try:
|
||||
tempDir = tempfile.mkdtemp(prefix="sqlmapdb")
|
||||
except IOError, _:
|
||||
except IOError as _:
|
||||
errMsg = "unable to write to the temporary directory ('%s'). " % _
|
||||
errMsg += "Please make sure that your disk is not full and "
|
||||
errMsg += "that you have sufficient write permissions to "
|
||||
@@ -453,8 +456,8 @@ class Dump(object):
|
||||
|
||||
_ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, normalizeUnicode(unsafeSQLIdentificatorNaming(table)))
|
||||
if len(_) < len(table) or IS_WIN and table.upper() in WINDOWS_RESERVED_NAMES:
|
||||
_ = unicodeencode(re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(table)))
|
||||
dumpFileName = os.path.join(dumpDbPath, "%s-%s.%s" % (_, hashlib.md5(unicodeencode(table)).hexdigest()[:8], conf.dumpFormat.lower()))
|
||||
_ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(table))
|
||||
dumpFileName = os.path.join(dumpDbPath, "%s-%s.%s" % (_, hashlib.md5(getBytes(table)).hexdigest()[:8], conf.dumpFormat.lower()))
|
||||
else:
|
||||
dumpFileName = os.path.join(dumpDbPath, "%s.%s" % (_, conf.dumpFormat.lower()))
|
||||
else:
|
||||
@@ -532,6 +535,7 @@ class Dump(object):
|
||||
elif conf.dumpFormat == DUMP_FORMAT.HTML:
|
||||
dataToDumpFile(dumpFP, "<!DOCTYPE html>\n<html>\n<head>\n")
|
||||
dataToDumpFile(dumpFP, "<meta http-equiv=\"Content-type\" content=\"text/html;charset=%s\">\n" % UNICODE_ENCODING)
|
||||
dataToDumpFile(dumpFP, "<meta name=\"generator\" content=\"%s\" />\n" % VERSION_STRING)
|
||||
dataToDumpFile(dumpFP, "<title>%s</title>\n" % ("%s%s" % ("%s." % db if METADB_SUFFIX not in db else "", table)))
|
||||
dataToDumpFile(dumpFP, HTML_DUMP_CSS_STYLE)
|
||||
dataToDumpFile(dumpFP, "\n</head>\n<body>\n<table>\n<thead>\n<tr>\n")
|
||||
@@ -622,8 +626,8 @@ class Dump(object):
|
||||
with open(filepath, "wb") as f:
|
||||
_ = safechardecode(value, True)
|
||||
f.write(_)
|
||||
except magic.MagicException, err:
|
||||
logger.debug(str(err))
|
||||
except magic.MagicException as ex:
|
||||
logger.debug(getSafeExString(ex))
|
||||
|
||||
if conf.dumpFormat == DUMP_FORMAT.CSV:
|
||||
if field == fields:
|
||||
@@ -700,7 +704,7 @@ class Dump(object):
|
||||
|
||||
self.dbTableColumns(_)
|
||||
|
||||
def query(self, query, queryRes):
|
||||
def sqlQuery(self, query, queryRes):
|
||||
self.string(query, queryRes, content_type=CONTENT_TYPE.SQL_QUERY)
|
||||
|
||||
def rFile(self, fileData):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -43,6 +43,7 @@ class DBMS:
|
||||
SQLITE = "SQLite"
|
||||
SYBASE = "Sybase"
|
||||
HSQLDB = "HSQLDB"
|
||||
H2 = "H2"
|
||||
INFORMIX = "Informix"
|
||||
|
||||
class DBMS_DIRECTORY_NAME:
|
||||
@@ -57,6 +58,7 @@ class DBMS_DIRECTORY_NAME:
|
||||
SQLITE = "sqlite"
|
||||
SYBASE = "sybase"
|
||||
HSQLDB = "hsqldb"
|
||||
H2 = "h2"
|
||||
INFORMIX = "informix"
|
||||
|
||||
class CUSTOM_LOGGING:
|
||||
@@ -154,13 +156,17 @@ class HASH:
|
||||
|
||||
# Reference: http://www.zytrax.com/tech/web/mobile_ids.html
|
||||
class MOBILES:
|
||||
BLACKBERRY = ("BlackBerry 9900", "Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.346 Mobile Safari/534.11+")
|
||||
GALAXY = ("Samsung Galaxy S", "Mozilla/5.0 (Linux; U; Android 2.2; en-US; SGH-T959D Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1")
|
||||
BLACKBERRY = ("BlackBerry Z10", "Mozilla/5.0 (BB10; Kbd) AppleWebKit/537.35+ (KHTML, like Gecko) Version/10.3.3.2205 Mobile Safari/537.35+")
|
||||
GALAXY = ("Samsung Galaxy S7", "Mozilla/5.0 (Linux; Android 7.0; SM-G930V Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36")
|
||||
HP = ("HP iPAQ 6365", "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; 240x320; HP iPAQ h6300)")
|
||||
HTC = ("HTC Sensation", "Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30")
|
||||
IPHONE = ("Apple iPhone 4s", "Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B179 Safari/7534.48.3")
|
||||
HTC = ("HTC 10", "Mozilla/5.0 (Linux; Android 8.0.0; HTC 10 Build/OPR1.170623.027) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36")
|
||||
HUAWEI = ("Huawei P8", "Mozilla/5.0 (Linux; Android 4.4.4; HUAWEI H891L Build/HuaweiH891L) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Mobile Safari/537.36")
|
||||
IPHONE = ("Apple iPhone 8", "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1")
|
||||
LUMIA = ("Microsoft Lumia 950", "Mozilla/5.0 (Windows Phone 10.0; Android 6.0.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Mobile Safari/537.36 Edge/15.14977")
|
||||
NEXUS = ("Google Nexus 7", "Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19")
|
||||
NOKIA = ("Nokia N97", "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/10.0.012; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) WicKed/7.1.12344")
|
||||
PIXEL = ("Google Pixel", "Mozilla/5.0 (Linux; Android 8.0.0; Pixel Build/OPR3.170623.013) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36")
|
||||
XIAOMI = ("Xiaomi Mi 3", "Mozilla/5.0 (Linux; U; Android 4.4.4; en-gb; MI 3W Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36 XiaoMi/MiuiBrowser/2.1.1")
|
||||
|
||||
class PROXY_TYPE:
|
||||
HTTP = "HTTP"
|
||||
@@ -225,6 +231,7 @@ class HASHDB_KEYS:
|
||||
DBMS = "DBMS"
|
||||
DBMS_FORK = "DBMS_FORK"
|
||||
CHECK_WAF_RESULT = "CHECK_WAF_RESULT"
|
||||
CHECK_NULL_CONNECTION_RESULT = "CHECK_NULL_CONNECTION_RESULT"
|
||||
CONF_TMP_PATH = "CONF_TMP_PATH"
|
||||
KB_ABS_FILE_PATHS = "KB_ABS_FILE_PATHS"
|
||||
KB_BRUTE_COLUMNS = "KB_BRUTE_COLUMNS"
|
||||
@@ -246,7 +253,7 @@ class PAYLOAD:
|
||||
2: "error-based",
|
||||
3: "inline query",
|
||||
4: "stacked queries",
|
||||
5: "AND/OR time-based blind",
|
||||
5: "time-based blind",
|
||||
6: "UNION query",
|
||||
}
|
||||
|
||||
@@ -256,6 +263,7 @@ class PAYLOAD:
|
||||
3: "LIKE single quoted string",
|
||||
4: "Double quoted string",
|
||||
5: "LIKE double quoted string",
|
||||
6: "Identifier (e.g. column name)",
|
||||
}
|
||||
|
||||
RISK = {
|
||||
@@ -275,6 +283,7 @@ class PAYLOAD:
|
||||
6: "TOP",
|
||||
7: "Table name",
|
||||
8: "Column name",
|
||||
9: "Pre-WHERE (non-query)",
|
||||
}
|
||||
|
||||
class METHOD:
|
||||
@@ -306,7 +315,7 @@ class ADJUST_TIME_DELAY:
|
||||
NO = 0
|
||||
YES = 1
|
||||
|
||||
class WEB_API:
|
||||
class WEB_PLATFORM:
|
||||
PHP = "php"
|
||||
ASP = "asp"
|
||||
ASPX = "aspx"
|
||||
@@ -340,34 +349,6 @@ class CONTENT_TYPE:
|
||||
OS_CMD = 24
|
||||
REG_READ = 25
|
||||
|
||||
PART_RUN_CONTENT_TYPES = {
|
||||
"checkDbms": CONTENT_TYPE.TECHNIQUES,
|
||||
"getFingerprint": CONTENT_TYPE.DBMS_FINGERPRINT,
|
||||
"getBanner": CONTENT_TYPE.BANNER,
|
||||
"getCurrentUser": CONTENT_TYPE.CURRENT_USER,
|
||||
"getCurrentDb": CONTENT_TYPE.CURRENT_DB,
|
||||
"getHostname": CONTENT_TYPE.HOSTNAME,
|
||||
"isDba": CONTENT_TYPE.IS_DBA,
|
||||
"getUsers": CONTENT_TYPE.USERS,
|
||||
"getPasswordHashes": CONTENT_TYPE.PASSWORDS,
|
||||
"getPrivileges": CONTENT_TYPE.PRIVILEGES,
|
||||
"getRoles": CONTENT_TYPE.ROLES,
|
||||
"getDbs": CONTENT_TYPE.DBS,
|
||||
"getTables": CONTENT_TYPE.TABLES,
|
||||
"getColumns": CONTENT_TYPE.COLUMNS,
|
||||
"getSchema": CONTENT_TYPE.SCHEMA,
|
||||
"getCount": CONTENT_TYPE.COUNT,
|
||||
"dumpTable": CONTENT_TYPE.DUMP_TABLE,
|
||||
"search": CONTENT_TYPE.SEARCH,
|
||||
"sqlQuery": CONTENT_TYPE.SQL_QUERY,
|
||||
"tableExists": CONTENT_TYPE.COMMON_TABLES,
|
||||
"columnExists": CONTENT_TYPE.COMMON_COLUMNS,
|
||||
"readFile": CONTENT_TYPE.FILE_READ,
|
||||
"writeFile": CONTENT_TYPE.FILE_WRITE,
|
||||
"osCmd": CONTENT_TYPE.OS_CMD,
|
||||
"regRead": CONTENT_TYPE.REG_READ
|
||||
}
|
||||
|
||||
class CONTENT_STATUS:
|
||||
IN_PROGRESS = 0
|
||||
COMPLETE = 1
|
||||
@@ -382,6 +363,7 @@ class AUTOCOMPLETE_TYPE:
|
||||
SQL = 0
|
||||
OS = 1
|
||||
SQLMAP = 2
|
||||
API = 3
|
||||
|
||||
class NOTE:
|
||||
FALSE_POSITIVE_OR_UNEXPLOITABLE = "false positive or unexploitable"
|
||||
@@ -396,8 +378,13 @@ class MKSTEMP_PREFIX:
|
||||
COOKIE_JAR = "sqlmapcookiejar-"
|
||||
BIG_ARRAY = "sqlmapbigarray-"
|
||||
SPECIFIC_RESPONSE = "sqlmapresponse-"
|
||||
PREPROCESS = "sqlmappreprocess-"
|
||||
|
||||
class TIMEOUT_STATE:
|
||||
NORMAL = 0
|
||||
EXCEPTION = 1
|
||||
TIMEOUT = 2
|
||||
|
||||
class HINT:
|
||||
PREPEND = 0
|
||||
APPEND = 1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -61,6 +61,7 @@ optDict = {
|
||||
"csrfToken": "string",
|
||||
"csrfUrl": "string",
|
||||
"forceSSL": "boolean",
|
||||
"chunked": "boolean",
|
||||
"hpp": "boolean",
|
||||
"evalCode": "string",
|
||||
},
|
||||
@@ -109,7 +110,8 @@ optDict = {
|
||||
"uChar": "string",
|
||||
"uFrom": "string",
|
||||
"dnsDomain": "string",
|
||||
"secondOrder": "string",
|
||||
"secondUrl": "string",
|
||||
"secondReq": "string",
|
||||
},
|
||||
|
||||
"Fingerprint": {
|
||||
@@ -148,7 +150,7 @@ optDict = {
|
||||
"limitStop": "integer",
|
||||
"firstChar": "integer",
|
||||
"lastChar": "integer",
|
||||
"query": "string",
|
||||
"sqlQuery": "string",
|
||||
"sqlShell": "boolean",
|
||||
"sqlFile": "string",
|
||||
},
|
||||
@@ -164,9 +166,9 @@ optDict = {
|
||||
},
|
||||
|
||||
"File system": {
|
||||
"rFile": "string",
|
||||
"wFile": "string",
|
||||
"dFile": "string",
|
||||
"fileRead": "string",
|
||||
"fileWrite": "string",
|
||||
"fileDest": "string",
|
||||
},
|
||||
|
||||
"Takeover": {
|
||||
@@ -191,7 +193,6 @@ optDict = {
|
||||
},
|
||||
|
||||
"General": {
|
||||
# "xmlFile": "string",
|
||||
"trafficFile": "string",
|
||||
"batch": "boolean",
|
||||
"binaryFields": "string",
|
||||
@@ -210,6 +211,8 @@ optDict = {
|
||||
"hexConvert": "boolean",
|
||||
"outputDir": "string",
|
||||
"parseErrors": "boolean",
|
||||
"preprocess": "string",
|
||||
"repair": "boolean",
|
||||
"saveConfig": "string",
|
||||
"scope": "string",
|
||||
"testFilter": "string",
|
||||
@@ -226,9 +229,10 @@ optDict = {
|
||||
"disableColoring": "boolean",
|
||||
"googlePage": "integer",
|
||||
"identifyWaf": "boolean",
|
||||
"listTampers": "boolean",
|
||||
"mobile": "boolean",
|
||||
"offline": "boolean",
|
||||
"purgeOutput": "boolean",
|
||||
"purge": "boolean",
|
||||
"skipWaf": "boolean",
|
||||
"smart": "boolean",
|
||||
"tmpDir": "string",
|
||||
|
||||
34
lib/core/patch.py
Normal file
34
lib/core/patch.py
Normal file
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import codecs
|
||||
|
||||
from lib.core.settings import IS_WIN
|
||||
from thirdparty.six.moves import http_client as _http_client
|
||||
|
||||
def dirtyPatches():
|
||||
"""
|
||||
Place for "dirty" Python related patches
|
||||
"""
|
||||
|
||||
# accept overly long result lines (e.g. SQLi results in HTTP header responses)
|
||||
_http_client._MAXLINE = 1 * 1024 * 1024
|
||||
|
||||
# add support for inet_pton() on Windows OS
|
||||
if IS_WIN:
|
||||
from thirdparty.wininetpton import win_inet_pton
|
||||
|
||||
# Reference: https://github.com/nodejs/node/issues/12786#issuecomment-298652440
|
||||
codecs.register(lambda name: codecs.lookup("utf-8") if name == "cp65001" else None)
|
||||
|
||||
# Reference: http://bugs.python.org/issue17849
|
||||
if hasattr(_http_client, "LineAndFileWrapper"):
|
||||
def _(self, *args):
|
||||
return self._readline()
|
||||
|
||||
_http_client.LineAndFileWrapper._readline = _http_client.LineAndFileWrapper.readline
|
||||
_http_client.LineAndFileWrapper.readline = _
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -9,7 +9,7 @@ import codecs
|
||||
import os
|
||||
import cProfile
|
||||
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import paths
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
@@ -25,8 +25,8 @@ def profile(profileOutputFile=None, dotOutputFile=None, imageOutputFile=None):
|
||||
from thirdparty.xdot import xdot
|
||||
import gtk
|
||||
import pydot
|
||||
except ImportError, e:
|
||||
errMsg = "profiling requires third-party libraries ('%s') " % getUnicode(e, UNICODE_ENCODING)
|
||||
except ImportError as ex:
|
||||
errMsg = "profiling requires third-party libraries ('%s') " % getSafeExString(ex)
|
||||
errMsg += "(Hint: 'sudo apt-get install python-pydot python-pyparsing python-profiler graphviz')"
|
||||
logger.error(errMsg)
|
||||
|
||||
@@ -50,7 +50,7 @@ def profile(profileOutputFile=None, dotOutputFile=None, imageOutputFile=None):
|
||||
if os.path.exists(imageOutputFile):
|
||||
os.remove(imageOutputFile)
|
||||
|
||||
infoMsg = "profiling the execution into file %s" % profileOutputFile
|
||||
infoMsg = "profiling the execution into file '%s'" % profileOutputFile
|
||||
logger.info(infoMsg)
|
||||
|
||||
# Start sqlmap main function and generate a raw profile file
|
||||
@@ -80,15 +80,20 @@ def profile(profileOutputFile=None, dotOutputFile=None, imageOutputFile=None):
|
||||
if isinstance(pydotGraph, list):
|
||||
pydotGraph = pydotGraph[0]
|
||||
|
||||
pydotGraph.write_png(imageOutputFile)
|
||||
try:
|
||||
pydotGraph.write_png(imageOutputFile)
|
||||
except OSError:
|
||||
errMsg = "profiling requires graphviz installed "
|
||||
errMsg += "(Hint: 'sudo apt-get install graphviz')"
|
||||
logger.error(errMsg)
|
||||
else:
|
||||
infoMsg = "displaying interactive graph with xdot library"
|
||||
logger.info(infoMsg)
|
||||
|
||||
infoMsg = "displaying interactive graph with xdot library"
|
||||
logger.info(infoMsg)
|
||||
|
||||
# Display interactive Graphviz dot file by using extra/xdot/xdot.py
|
||||
# http://code.google.com/p/jrfonseca/wiki/XDot
|
||||
win = xdot.DotWindow()
|
||||
win.connect('destroy', gtk.main_quit)
|
||||
win.set_filter("dot")
|
||||
win.open_file(dotOutputFile)
|
||||
gtk.main()
|
||||
# Display interactive Graphviz dot file by using extra/xdot/xdot.py
|
||||
# http://code.google.com/p/jrfonseca/wiki/XDot
|
||||
win = xdot.DotWindow()
|
||||
win.connect('destroy', gtk.main_quit)
|
||||
win.set_filter("dot")
|
||||
win.open_file(dotOutputFile)
|
||||
gtk.main()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -56,9 +56,7 @@ if PLATFORM == 'mac' and _readline:
|
||||
# http://mail.python.org/pipermail/python-dev/2003-August/037845.html
|
||||
# has the original discussion.
|
||||
if _readline:
|
||||
try:
|
||||
_readline.clear_history()
|
||||
except AttributeError:
|
||||
if not hasattr(_readline, "clear_history"):
|
||||
def clear_history():
|
||||
pass
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -27,7 +27,7 @@ class Replication(object):
|
||||
self.connection = sqlite3.connect(dbpath)
|
||||
self.connection.isolation_level = None
|
||||
self.cursor = self.connection.cursor()
|
||||
except sqlite3.OperationalError, ex:
|
||||
except sqlite3.OperationalError as ex:
|
||||
errMsg = "error occurred while opening a replication "
|
||||
errMsg += "file '%s' ('%s')" % (self.filepath, getSafeExString(ex))
|
||||
raise SqlmapConnectionException(errMsg)
|
||||
@@ -63,7 +63,7 @@ class Replication(object):
|
||||
self.execute('CREATE TABLE "%s" (%s)' % (self.name, ','.join('"%s" %s' % (unsafeSQLIdentificatorNaming(colname), coltype) for colname, coltype in self.columns)))
|
||||
else:
|
||||
self.execute('CREATE TABLE "%s" (%s)' % (self.name, ','.join('"%s"' % unsafeSQLIdentificatorNaming(colname) for colname in self.columns)))
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
errMsg = "problem occurred ('%s') while initializing the sqlite database " % getSafeExString(ex, UNICODE_ENCODING)
|
||||
errMsg += "located at '%s'" % self.parent.dbpath
|
||||
raise SqlmapGenericException(errMsg)
|
||||
@@ -82,7 +82,7 @@ class Replication(object):
|
||||
def execute(self, sql, parameters=[]):
|
||||
try:
|
||||
self.parent.cursor.execute(sql, parameters)
|
||||
except sqlite3.OperationalError, ex:
|
||||
except sqlite3.OperationalError as ex:
|
||||
errMsg = "problem occurred ('%s') while accessing sqlite database " % getSafeExString(ex, UNICODE_ENCODING)
|
||||
errMsg += "located at '%s'. Please make sure that " % self.parent.dbpath
|
||||
errMsg += "it's not used by some other program"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -44,9 +44,12 @@ def getRevisionNumber():
|
||||
break
|
||||
|
||||
if not retVal:
|
||||
process = subprocess.Popen("git rev-parse --verify HEAD", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, _ = process.communicate()
|
||||
match = re.search(r"(?i)[0-9a-f]{32}", stdout or "")
|
||||
retVal = match.group(0) if match else None
|
||||
try:
|
||||
process = subprocess.Popen("git rev-parse --verify HEAD", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, _ = process.communicate()
|
||||
match = re.search(r"(?i)[0-9a-f]{32}", stdout or "")
|
||||
retVal = match.group(0) if match else None
|
||||
except:
|
||||
pass
|
||||
|
||||
return retVal[:7] if retVal else None
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import subprocess
|
||||
import string
|
||||
import sys
|
||||
import types
|
||||
|
||||
from lib.core.datatype import AttribDict
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.enums import DBMS_DIRECTORY_NAME
|
||||
from lib.core.enums import OS
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.2.6.0"
|
||||
VERSION = "1.3.5.0"
|
||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||
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)
|
||||
DESCRIPTION = "automatic SQL injection and database takeover tool"
|
||||
SITE = "http://sqlmap.org"
|
||||
DEFAULT_USER_AGENT = "%s (%s)" % (VERSION_STRING, SITE)
|
||||
DEV_EMAIL_ADDRESS = "dev@sqlmap.org"
|
||||
ISSUES_PAGE = "https://github.com/sqlmapproject/sqlmap/issues/new"
|
||||
GIT_REPOSITORY = "https://github.com/sqlmapproject/sqlmap.git"
|
||||
@@ -38,17 +37,17 @@ BANNER = """\033[01;33m\
|
||||
___ ___[.]_____ ___ ___ \033[01;37m{\033[01;%dm%s\033[01;37m}\033[01;33m
|
||||
|_ -| . [.] | .'| . |
|
||||
|___|_ [.]_|_|_|__,| _|
|
||||
|_|V |_| \033[0m\033[4;37m%s\033[0m\n
|
||||
|_|V... |_| \033[0m\033[4;37m%s\033[0m\n
|
||||
""" % (TYPE_COLORS.get(TYPE, 31), VERSION_STRING.split('/')[-1], SITE)
|
||||
|
||||
# Minimum distance of ratio from kb.matchRatio to result in True
|
||||
DIFF_TOLERANCE = 0.05
|
||||
CONSTANT_RATIO = 0.9
|
||||
|
||||
# Ratio used in heuristic check for WAF/IPS/IDS protected targets
|
||||
# Ratio used in heuristic check for WAF/IPS protected targets
|
||||
IDS_WAF_CHECK_RATIO = 0.5
|
||||
|
||||
# Timeout used in heuristic check for WAF/IPS/IDS protected targets
|
||||
# Timeout used in heuristic check for WAF/IPS protected targets
|
||||
IDS_WAF_CHECK_TIMEOUT = 10
|
||||
|
||||
# Lower and upper values for match ratio in case of stable page
|
||||
@@ -66,11 +65,13 @@ ASTERISK_MARKER = "__ASTERISK_MARK__"
|
||||
REPLACEMENT_MARKER = "__REPLACEMENT_MARK__"
|
||||
BOUNDED_INJECTION_MARKER = "__BOUNDED_INJECTION_MARK__"
|
||||
SAFE_VARIABLE_MARKER = "__SAFE__"
|
||||
SAFE_HEX_MARKER = "__SAFE_HEX__"
|
||||
|
||||
RANDOM_INTEGER_MARKER = "[RANDINT]"
|
||||
RANDOM_STRING_MARKER = "[RANDSTR]"
|
||||
SLEEP_TIME_MARKER = "[SLEEPTIME]"
|
||||
INFERENCE_MARKER = "[INFERENCE]"
|
||||
SINGLE_QUOTE_MARKER = "[SINGLE_QUOTE]"
|
||||
|
||||
PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__"
|
||||
CHAR_INFERENCE_MARK = "%c"
|
||||
@@ -97,6 +98,9 @@ MAX_CONSECUTIVE_CONNECTION_ERRORS = 15
|
||||
# Timeout before the pre-connection candidate is being disposed (because of high probability that the web server will reset it)
|
||||
PRECONNECT_CANDIDATE_TIMEOUT = 10
|
||||
|
||||
# Servers known to cause issue with pre-connection mechanism (because of lack of multi-threaded support)
|
||||
PRECONNECT_INCOMPATIBLE_SERVERS = ("SimpleHTTP", "BaseHTTP")
|
||||
|
||||
# Maximum sleep time in "Murphy" (testing) mode
|
||||
MAX_MURPHY_SLEEP_TIME = 3
|
||||
|
||||
@@ -104,7 +108,7 @@ MAX_MURPHY_SLEEP_TIME = 3
|
||||
GOOGLE_REGEX = r"webcache\.googleusercontent\.com/search\?q=cache:[^:]+:([^+]+)\+&cd=|url\?\w+=((?![^>]+webcache\.googleusercontent\.com)http[^>]+)&(sa=U|rct=j)"
|
||||
|
||||
# Regular expression used for extracting results from DuckDuckGo search
|
||||
DUCKDUCKGO_REGEX = r'"u":"([^"]+)'
|
||||
DUCKDUCKGO_REGEX = r'<a class="result__url" href="(htt[^"]+)'
|
||||
|
||||
# Regular expression used for extracting results from Bing search
|
||||
BING_REGEX = r'<h2><a href="([^"]+)" h='
|
||||
@@ -161,6 +165,9 @@ MAX_TECHNIQUES_PER_VALUE = 2
|
||||
# In case of missing piece of partial union dump, buffered array must be flushed after certain size
|
||||
MAX_BUFFERED_PARTIAL_UNION_LENGTH = 1024
|
||||
|
||||
# Maximum size of cache used in @cachedmethod decorator
|
||||
MAX_CACHE_ITEMS = 256
|
||||
|
||||
# Suffix used for naming meta databases in DBMS(es) without explicit database name
|
||||
METADB_SUFFIX = "_masterdb"
|
||||
|
||||
@@ -170,11 +177,14 @@ PUSH_VALUE_EXCEPTION_RETRY_COUNT = 3
|
||||
# Minimum time response set needed for time-comparison based on standard deviation
|
||||
MIN_TIME_RESPONSES = 30
|
||||
|
||||
# Maximum time response set used during time-comparison based on standard deviation
|
||||
MAX_TIME_RESPONSES = 200
|
||||
|
||||
# Minimum comparison ratio set needed for searching valid union column number based on standard deviation
|
||||
MIN_UNION_RESPONSES = 5
|
||||
|
||||
# After these number of blanks at the end inference should stop (just in case)
|
||||
INFERENCE_BLANK_BREAK = 10
|
||||
INFERENCE_BLANK_BREAK = 5
|
||||
|
||||
# Use this replacement character for cases when inference is not able to retrieve the proper character value
|
||||
INFERENCE_UNKNOWN_CHAR = '?'
|
||||
@@ -207,23 +217,24 @@ DUMMY_USER_PREFIX = "__dummy__"
|
||||
DEFAULT_PAGE_ENCODING = "iso-8859-1"
|
||||
|
||||
try:
|
||||
unicode(DEFAULT_PAGE_ENCODING, DEFAULT_PAGE_ENCODING)
|
||||
codecs.lookup(DEFAULT_PAGE_ENCODING)
|
||||
except LookupError:
|
||||
DEFAULT_PAGE_ENCODING = "utf8"
|
||||
|
||||
# Marker for program piped input
|
||||
STDIN_PIPE_DASH = '-'
|
||||
|
||||
# URL used in dummy runs
|
||||
DUMMY_URL = "http://foo/bar?id=1"
|
||||
|
||||
# System variables
|
||||
IS_WIN = subprocess.mswindows
|
||||
|
||||
# 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
|
||||
PYVERSION = sys.version.split()[0]
|
||||
IS_WIN = PLATFORM == "nt"
|
||||
|
||||
# DBMS system databases
|
||||
MSSQL_SYSTEM_DBS = ("Northwind", "master", "model", "msdb", "pubs", "tempdb")
|
||||
MYSQL_SYSTEM_DBS = ("information_schema", "mysql", "performance_schema")
|
||||
MYSQL_SYSTEM_DBS = ("information_schema", "mysql", "performance_schema", "sys")
|
||||
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')
|
||||
SQLITE_SYSTEM_DBS = ("sqlite_master", "sqlite_temp_master")
|
||||
@@ -233,6 +244,7 @@ MAXDB_SYSTEM_DBS = ("SYSINFO", "DOMAIN")
|
||||
SYBASE_SYSTEM_DBS = ("master", "model", "sybsystemdb", "sybsystemprocs")
|
||||
DB2_SYSTEM_DBS = ("NULLID", "SQLJ", "SYSCAT", "SYSFUN", "SYSIBM", "SYSIBMADM", "SYSIBMINTERNAL", "SYSIBMTS", "SYSPROC", "SYSPUBLIC", "SYSSTAT", "SYSTOOLS")
|
||||
HSQLDB_SYSTEM_DBS = ("INFORMATION_SCHEMA", "SYSTEM_LOB")
|
||||
H2_SYSTEM_DBS = ("INFORMATION_SCHEMA")
|
||||
INFORMIX_SYSTEM_DBS = ("sysmaster", "sysutils", "sysuser", "sysadmin")
|
||||
|
||||
MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms")
|
||||
@@ -246,20 +258,21 @@ MAXDB_ALIASES = ("maxdb", "sap maxdb", "sap db")
|
||||
SYBASE_ALIASES = ("sybase", "sybase sql server")
|
||||
DB2_ALIASES = ("db2", "ibm db2", "ibmdb2")
|
||||
HSQLDB_ALIASES = ("hsql", "hsqldb", "hs", "hypersql")
|
||||
H2_ALIASES = ("h2",)
|
||||
INFORMIX_ALIASES = ("informix", "ibm informix", "ibminformix")
|
||||
|
||||
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 + INFORMIX_ALIASES
|
||||
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_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_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))
|
||||
|
||||
USER_AGENT_ALIASES = ("ua", "useragent", "user-agent")
|
||||
REFERER_ALIASES = ("ref", "referer", "referrer")
|
||||
HOST_ALIASES = ("host",)
|
||||
|
||||
HSQLDB_DEFAULT_SCHEMA = "PUBLIC"
|
||||
H2_DEFAULT_SCHEMA = HSQLDB_DEFAULT_SCHEMA = "PUBLIC"
|
||||
|
||||
# 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")
|
||||
@@ -317,17 +330,20 @@ CURRENT_DB = "CD"
|
||||
SESSION_SQLITE_FILE = "session.sqlite"
|
||||
|
||||
# Regular expressions used for finding file paths in error messages
|
||||
FILE_PATH_REGEXES = (r"<b>(?P<result>[^<>]+?)</b> on line \d+", r"in (?P<result>[^<>'\"]+?)['\"]? on line \d+", r"(?:[>(\[\s])(?P<result>[A-Za-z]:[\\/][\w. \\/-]*)", r"(?:[>(\[\s])(?P<result>/\w[/\w.~-]+)", r"href=['\"]file://(?P<result>/[^'\"]+)")
|
||||
FILE_PATH_REGEXES = (r"<b>(?P<result>[^<>]+?)</b> on line \d+", r"\bin (?P<result>[^<>'\"]+?)['\"]? on line \d+", r"(?:[>(\[\s])(?P<result>[A-Za-z]:[\\/][\w. \\/-]*)", r"(?:[>(\[\s])(?P<result>/\w[/\w.~-]+)", r"\bhref=['\"]file://(?P<result>/[^'\"]+)", r"\bin <b>(?P<result>[^<]+): line \d+")
|
||||
|
||||
# Regular expressions used for parsing error messages (--parse-errors)
|
||||
ERROR_PARSING_REGEXES = (
|
||||
r"<b>[^<]*(fatal|error|warning|exception)[^<]*</b>:?\s*(?P<result>.+?)<br\s*/?\s*>",
|
||||
r"\[Microsoft\]\[ODBC SQL Server Driver\]\[SQL Server\](?P<result>[^<]+)",
|
||||
r"<b>[^<]*(fatal|error|warning|exception)[^<]*</b>:?\s*(?P<result>[^<]+)",
|
||||
r"(?m)^\s*(fatal|error|warning|exception):?\s*(?P<result>[^\n]+?)$",
|
||||
r"(sql|dbc)[^>'\"]{0,32}(fatal|error|warning|exception)(</b>)?:\s*(?P<result>[^<>]+)",
|
||||
r"(?P<result>[^\n>]*SQL Syntax[^\n<]+)",
|
||||
r"<li>Error Type:<br>(?P<result>.+?)</li>",
|
||||
r"(?s)<li>Error Type:<br>(?P<result>.+?)</li>",
|
||||
r"CDbCommand (?P<result>[^<>\n]*SQL[^<>\n]+)",
|
||||
r"error '[0-9a-f]{8}'((<[^>]+>)|\s)+(?P<result>[^<>]+)",
|
||||
r"\[[^\n\]]+(ODBC|JDBC)[^\n\]]+\](\[[^\]]+\])?(?P<result>[^\n]+(in query expression|\(SQL| at /[^ ]+pdo)[^\n<]+)"
|
||||
r"\[[^\n\]]+(ODBC|JDBC)[^\n\]]+\](\[[^\]]+\])?(?P<result>[^\n]+(in query expression|\(SQL| at /[^ ]+pdo)[^\n<]+)",
|
||||
r"(?P<result>query error: SELECT[^<>]+)"
|
||||
)
|
||||
|
||||
# Regular expression used for parsing charset info from meta html headers
|
||||
@@ -349,7 +365,7 @@ COMMON_PASSWORD_SUFFIXES += ("!", ".", "*", "!!", "?", ";", "..", "!!!", ", ", "
|
||||
WEBSCARAB_SPLITTER = "### Conversation"
|
||||
|
||||
# Splitter used between requests in BURP log files
|
||||
BURP_REQUEST_REGEX = r"={10,}\s+[^=]+={10,}\s(.+?)\s={10,}"
|
||||
BURP_REQUEST_REGEX = r"={10,}\s+([A-Z]{3,} .+?)\s+={10,}"
|
||||
|
||||
# Regex used for parsing XML Burp saved history items
|
||||
BURP_XML_HISTORY_REGEX = r'<port>(\d+)</port>.+?<request base64="true"><!\[CDATA\[([^]]+)'
|
||||
@@ -364,10 +380,10 @@ URI_HTTP_HEADER = "URI"
|
||||
URI_INJECTABLE_REGEX = r"//[^/]*/([^\.*?]+)\Z"
|
||||
|
||||
# Regex used for masking sensitive data
|
||||
SENSITIVE_DATA_REGEX = "(\s|=)(?P<result>[^\s=]*%s[^\s]*)\s"
|
||||
SENSITIVE_DATA_REGEX = r"(\s|=)(?P<result>[^\s=]*\b%s\b[^\s]*)\s"
|
||||
|
||||
# Options to explicitly mask in anonymous (unhandled exception) reports (along with anything carrying the <hostname> inside)
|
||||
SENSITIVE_OPTIONS = ("hostname", "answers", "data", "dnsDomain", "googleDork", "authCred", "proxyCred", "tbl", "db", "col", "user", "cookie", "proxy", "rFile", "wFile", "dFile", "testParameter", "authCred")
|
||||
SENSITIVE_OPTIONS = ("hostname", "answers", "data", "dnsDomain", "googleDork", "authCred", "proxyCred", "tbl", "db", "col", "user", "cookie", "proxy", "fileRead", "fileWrite", "fileDest", "testParameter", "authCred", "sqlQuery")
|
||||
|
||||
# Maximum number of threads (avoiding connection issues and/or DoS)
|
||||
MAX_NUMBER_OF_THREADS = 10
|
||||
@@ -388,7 +404,7 @@ CANDIDATE_SENTENCE_MIN_LENGTH = 10
|
||||
CUSTOM_INJECTION_MARK_CHAR = '*'
|
||||
|
||||
# Other way to declare injection position
|
||||
INJECT_HERE_REGEX = '(?i)%INJECT[_ ]?HERE%'
|
||||
INJECT_HERE_REGEX = r"(?i)%INJECT[_ ]?HERE%"
|
||||
|
||||
# Minimum chunk length used for retrieving data over error based payloads
|
||||
MIN_ERROR_CHUNK_LENGTH = 8
|
||||
@@ -406,7 +422,7 @@ REFLECTED_VALUE_MARKER = "__REFLECTED_VALUE__"
|
||||
REFLECTED_BORDER_REGEX = r"[^A-Za-z]+"
|
||||
|
||||
# Regular expression used for replacing non-alphanum characters
|
||||
REFLECTED_REPLACEMENT_REGEX = r".+"
|
||||
REFLECTED_REPLACEMENT_REGEX = r"[^\n]{1,100}"
|
||||
|
||||
# Maximum time (in seconds) spent per reflective value(s) replacement
|
||||
REFLECTED_REPLACEMENT_TIMEOUT = 3
|
||||
@@ -426,8 +442,11 @@ DEFAULT_MSSQL_SCHEMA = "dbo"
|
||||
# Display hash attack info every mod number of items
|
||||
HASH_MOD_ITEM_DISPLAY = 11
|
||||
|
||||
# Display marker for (cracked) empty password
|
||||
HASH_EMPTY_PASSWORD_MARKER = "<empty>"
|
||||
|
||||
# Maximum integer value
|
||||
MAX_INT = sys.maxint
|
||||
MAX_INT = sys.maxsize
|
||||
|
||||
# Replacement for unsafe characters in dump table filenames
|
||||
UNSAFE_DUMP_FILEPATH_REPLACEMENT = '_'
|
||||
@@ -487,13 +506,11 @@ LEGAL_DISCLAIMER = "Usage of sqlmap for attacking targets without prior mutual c
|
||||
REFLECTIVE_MISS_THRESHOLD = 20
|
||||
|
||||
# Regular expression used for extracting HTML title
|
||||
HTML_TITLE_REGEX = "<title>(?P<result>[^<]+)</title>"
|
||||
HTML_TITLE_REGEX = r"<title>(?P<result>[^<]+)</title>"
|
||||
|
||||
# Table used for Base64 conversion in WordPress hash cracking routine
|
||||
ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
PICKLE_REDUCE_WHITELIST = (types.BooleanType, types.DictType, types.FloatType, types.IntType, types.ListType, types.LongType, types.NoneType, types.StringType, types.TupleType, types.UnicodeType, types.XRangeType, type(AttribDict()), type(set()))
|
||||
|
||||
# Chars used to quickly distinguish if the user provided tainted parameter values
|
||||
DUMMY_SQL_INJECTION_CHARS = ";()'"
|
||||
|
||||
@@ -512,25 +529,28 @@ BRUTE_TABLE_EXISTS_TEMPLATE = "EXISTS(SELECT %d FROM %s)"
|
||||
# Template used for common column existence check
|
||||
BRUTE_COLUMN_EXISTS_TEMPLATE = "EXISTS(SELECT %s FROM %s)"
|
||||
|
||||
# Payload used for checking of existence of IDS/IPS/WAF (dummier the better)
|
||||
IDS_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')#"
|
||||
|
||||
# Data inside shellcodeexec to be filled with random string
|
||||
SHELLCODEEXEC_RANDOM_STRING_MARKER = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
|
||||
# Period after last-update to start nagging about the old revision
|
||||
LAST_UPDATE_NAGGING_DAYS = 60
|
||||
|
||||
# Generic address for checking the Internet connection while using switch --check-internet
|
||||
CHECK_INTERNET_ADDRESS = "https://ipinfo.io/"
|
||||
|
||||
# Value to look for in response to CHECK_INTERNET_ADDRESS
|
||||
CHECK_INTERNET_VALUE = "IP Address Details"
|
||||
|
||||
# Vectors used for provoking specific WAF/IPS/IDS behavior(s)
|
||||
# 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')#"
|
||||
|
||||
# Vectors used for provoking specific WAF/IPS behavior(s)
|
||||
WAF_ATTACK_VECTORS = (
|
||||
"", # NIL
|
||||
"search=<script>alert(1)</script>",
|
||||
"file=../../../../etc/passwd",
|
||||
"q=<invalid>foobar",
|
||||
"id=1 %s" % IDS_WAF_CHECK_PAYLOAD
|
||||
"id=1 %s" % IPS_WAF_CHECK_PAYLOAD
|
||||
)
|
||||
|
||||
# Used for status representation in dictionary attack phase
|
||||
@@ -571,7 +591,7 @@ UNION_CHAR_REGEX = r"\A\w+\Z"
|
||||
UNENCODED_ORIGINAL_VALUE = "original"
|
||||
|
||||
# Common column names containing usernames (used for hash cracking in some cases)
|
||||
COMMON_USER_COLUMNS = ("login", "user", "username", "user_name", "user_login", "benutzername", "benutzer", "utilisateur", "usager", "consommateur", "utente", "utilizzatore", "usufrutuario", "korisnik", "usuario", "consumidor", "client", "cuser")
|
||||
COMMON_USER_COLUMNS = ("login", "user", "username", "user_name", "user_login", "benutzername", "benutzer", "utilisateur", "usager", "consommateur", "utente", "utilizzatore", "utilizator", "utilizador", "usufrutuario", "korisnik", "uporabnik", "usuario", "consumidor", "client", "cuser")
|
||||
|
||||
# Default delimiter in GET/POST values
|
||||
DEFAULT_GET_POST_DELIMITER = '&'
|
||||
@@ -583,7 +603,7 @@ DEFAULT_COOKIE_DELIMITER = ';'
|
||||
FORCE_COOKIE_EXPIRATION_TIME = "9999999999"
|
||||
|
||||
# Github OAuth token used for creating an automatic Issue for unhandled exceptions
|
||||
GITHUB_REPORT_OAUTH_TOKEN = "NTMyNWNkMmZkMzRlMDZmY2JkMmY0MGI4NWI0MzVlM2Q5YmFjYWNhYQ=="
|
||||
GITHUB_REPORT_OAUTH_TOKEN = "NTYzYjhmZWJjYzc0Njg2ODJhNzhmNDg1YzM0YzlkYjk3N2JiMzE3Nw=="
|
||||
|
||||
# Skip unforced HashDB flush requests below the threshold number of cached items
|
||||
HASHDB_FLUSH_THRESHOLD = 32
|
||||
@@ -598,7 +618,7 @@ HASHDB_RETRIEVE_RETRIES = 3
|
||||
HASHDB_END_TRANSACTION_RETRIES = 3
|
||||
|
||||
# Unique milestone value used for forced deprecation of old HashDB values (e.g. when changing hash/pickle mechanism)
|
||||
HASHDB_MILESTONE_VALUE = "dPHoJRQYvs" # python -c 'import random, string; print "".join(random.sample(string.ascii_letters, 10))'
|
||||
HASHDB_MILESTONE_VALUE = "BZzRotigLX" # python -c 'import random, string; print "".join(random.sample(string.ascii_letters, 10))'
|
||||
|
||||
# Warn user of possible delay due to large page dump in full UNION query injections
|
||||
LARGE_OUTPUT_THRESHOLD = 1024 ** 2
|
||||
@@ -631,7 +651,7 @@ BANNER = re.sub(r"\[.\]", lambda _: "[\033[01;41m%s\033[01;49m]" % random.sample
|
||||
DUMMY_NON_SQLI_CHECK_APPENDIX = "<'\">"
|
||||
|
||||
# Regular expression used for recognition of file inclusion errors
|
||||
FI_ERROR_REGEX = "(?i)[^\n]{0,100}(no such file|failed (to )?open)[^\n]{0,100}"
|
||||
FI_ERROR_REGEX = r"(?i)[^\n]{0,100}(no such file|failed (to )?open)[^\n]{0,100}"
|
||||
|
||||
# Length of prefix and suffix used in non-SQLI heuristic checks
|
||||
NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH = 6
|
||||
@@ -661,7 +681,10 @@ VALID_TIME_CHARS_RUN_THRESHOLD = 100
|
||||
CHECK_ZERO_COLUMNS_THRESHOLD = 10
|
||||
|
||||
# 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")
|
||||
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")
|
||||
|
||||
# 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")
|
||||
|
||||
# Generic www root directory names
|
||||
GENERIC_DOC_ROOT_DIRECTORY_NAMES = ("htdocs", "httpdocs", "public", "wwwroot", "www")
|
||||
@@ -673,7 +696,7 @@ MAX_HELP_OPTION_LENGTH = 18
|
||||
MAX_CONNECT_RETRIES = 100
|
||||
|
||||
# Strings for detecting formatting errors
|
||||
FORMAT_EXCEPTION_STRINGS = ("Type mismatch", "Error converting", "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", "DataTypeMismatchException", "CF_SQL_INTEGER", " for CFSQLTYPE ", "cfqueryparam cfsqltype", "InvalidParamTypeException", "Invalid parameter type", "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")
|
||||
|
||||
# Regular expression used for extracting ASP.NET view state values
|
||||
VIEWSTATE_REGEX = r'(?i)(?P<name>__VIEWSTATE[^"]*)[^>]+value="(?P<result>[^"]+)'
|
||||
@@ -693,6 +716,9 @@ RESTAPI_DEFAULT_ADDRESS = "127.0.0.1"
|
||||
# Default REST-JSON API server listen port
|
||||
RESTAPI_DEFAULT_PORT = 8775
|
||||
|
||||
# Use "Supplementary Private Use Area-A"
|
||||
INVALID_UNICODE_PRIVATE_AREA = False
|
||||
|
||||
# Format used for representing invalid unicode characters
|
||||
INVALID_UNICODE_CHAR_FORMAT = r"\x%02x"
|
||||
|
||||
@@ -741,14 +767,14 @@ METASPLOIT_SESSION_TIMEOUT = 120
|
||||
# Reference: http://www.postgresql.org/docs/9.0/static/catalog-pg-largeobject.html
|
||||
LOBLKSIZE = 2048
|
||||
|
||||
# Suffix used to mark variables having keyword names
|
||||
EVALCODE_KEYWORD_SUFFIX = "_KEYWORD"
|
||||
# Prefix used to mark special variables (e.g. keywords, having special chars, etc.)
|
||||
EVALCODE_ENCODED_PREFIX = "EVAL_"
|
||||
|
||||
# Reference: http://www.cookiecentral.com/faq/#3.5
|
||||
NETSCAPE_FORMAT_HEADER_COOKIES = "# Netscape HTTP Cookie File."
|
||||
|
||||
# Infixes used for automatic recognition of parameters carrying anti-CSRF tokens
|
||||
CSRF_TOKEN_PARAMETER_INFIXES = ("csrf", "xsrf")
|
||||
CSRF_TOKEN_PARAMETER_INFIXES = ("csrf", "xsrf", "token")
|
||||
|
||||
# Prefixes used in brute force search for web server document root
|
||||
BRUTE_DOC_ROOT_PREFIXES = {
|
||||
@@ -756,6 +782,9 @@ BRUTE_DOC_ROOT_PREFIXES = {
|
||||
OS.WINDOWS: ("/xampp", "/Program Files/xampp", "/wamp", "/Program Files/wampp", "/apache", "/Program Files/Apache Group/Apache", "/Program Files/Apache Group/Apache2", "/Program Files/Apache Group/Apache2.2", "/Program Files/Apache Group/Apache2.4", "/Inetpub/wwwroot", "/Inetpub/wwwroot/%TARGET%", "/Inetpub/vhosts/%TARGET%")
|
||||
}
|
||||
|
||||
# Table prefix to use in "takeover" functionalities (i.e. auxiliary tables used by sqlmap at the vulnerable DBMS)
|
||||
TAKEOVER_TABLE_PREFIX = "sqlmap"
|
||||
|
||||
# Suffixes used in brute force search for web server document root
|
||||
BRUTE_DOC_ROOT_SUFFIXES = ("", "html", "htdocs", "httpdocs", "php", "public", "src", "site", "build", "web", "www", "data", "sites/all", "www/build")
|
||||
|
||||
@@ -768,6 +797,9 @@ KB_CHARS_BOUNDARY_CHAR = 'q'
|
||||
# Letters of lower frequency used in kb.chars
|
||||
KB_CHARS_LOW_FREQUENCY_ALPHABET = "zqxjkvbp"
|
||||
|
||||
# SQL keywords used for splitting in HTTP chunked transfer encoded requests (switch --chunk)
|
||||
HTTP_CHUNKED_SPLIT_KEYWORDS = ("SELECT", "UPDATE", "INSERT", "FROM", "LOAD_FILE", "UNION", "information_schema", "sysdatabases", "msysaccessobjects", "msysqueries", "sysmodules")
|
||||
|
||||
# CSS style used in HTML dump format
|
||||
HTML_DUMP_CSS_STYLE = """<style>
|
||||
table{
|
||||
@@ -786,9 +818,26 @@ tr:nth-child(even) {
|
||||
background-color: #D3DFEE
|
||||
}
|
||||
td{
|
||||
font-size:10px;
|
||||
font-size:12px;
|
||||
}
|
||||
th{
|
||||
font-size:10px;
|
||||
font-size:12px;
|
||||
}
|
||||
</style>"""
|
||||
|
||||
# Leaving (dirty) possibility to change values from here (e.g. `export SQLMAP__MAX_NUMBER_OF_THREADS=20`)
|
||||
for key, value in os.environ.items():
|
||||
if key.upper().startswith("%s_" % SQLMAP_ENVIRONMENT_PREFIX):
|
||||
_ = key[len(SQLMAP_ENVIRONMENT_PREFIX) + 1:].upper()
|
||||
if _ in globals():
|
||||
globals()[_] = value
|
||||
|
||||
# Installing "reversible" unicode (decoding) error handler
|
||||
def _reversible(ex):
|
||||
if isinstance(ex, UnicodeDecodeError):
|
||||
if INVALID_UNICODE_PRIVATE_AREA:
|
||||
return ("".join(unichr(int('000f00%2x' % ord(_), 16)) for _ in ex.object[ex.start:ex.end]), ex.end)
|
||||
else:
|
||||
return ("".join(INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in ex.object[ex.start:ex.end]).decode(UNICODE_ENCODING), ex.end)
|
||||
|
||||
codecs.register_error("reversible", _reversible)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -9,6 +9,7 @@ import atexit
|
||||
import os
|
||||
|
||||
from lib.core import readlineng as readline
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import paths
|
||||
from lib.core.enums import AUTOCOMPLETE_TYPE
|
||||
@@ -53,28 +54,33 @@ def clearHistory():
|
||||
readline.clear_history()
|
||||
|
||||
def saveHistory(completion=None):
|
||||
if not readlineAvailable():
|
||||
return
|
||||
|
||||
if completion == AUTOCOMPLETE_TYPE.SQL:
|
||||
historyPath = paths.SQL_SHELL_HISTORY
|
||||
elif completion == AUTOCOMPLETE_TYPE.OS:
|
||||
historyPath = paths.OS_SHELL_HISTORY
|
||||
else:
|
||||
historyPath = paths.SQLMAP_SHELL_HISTORY
|
||||
|
||||
try:
|
||||
with open(historyPath, "w+"):
|
||||
if not readlineAvailable():
|
||||
return
|
||||
|
||||
if completion == AUTOCOMPLETE_TYPE.SQL:
|
||||
historyPath = paths.SQL_SHELL_HISTORY
|
||||
elif completion == AUTOCOMPLETE_TYPE.OS:
|
||||
historyPath = paths.OS_SHELL_HISTORY
|
||||
elif completion == AUTOCOMPLETE_TYPE.API:
|
||||
historyPath = paths.API_SHELL_HISTORY
|
||||
else:
|
||||
historyPath = paths.SQLMAP_SHELL_HISTORY
|
||||
|
||||
try:
|
||||
with open(historyPath, "w+"):
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
readline.set_history_length(MAX_HISTORY_LENGTH)
|
||||
try:
|
||||
readline.write_history_file(historyPath)
|
||||
except IOError, msg:
|
||||
warnMsg = "there was a problem writing the history file '%s' (%s)" % (historyPath, msg)
|
||||
logger.warn(warnMsg)
|
||||
readline.set_history_length(MAX_HISTORY_LENGTH)
|
||||
try:
|
||||
readline.write_history_file(historyPath)
|
||||
except IOError as ex:
|
||||
warnMsg = "there was a problem writing the history file '%s' (%s)" % (historyPath, getSafeExString(ex))
|
||||
logger.warn(warnMsg)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
def loadHistory(completion=None):
|
||||
if not readlineAvailable():
|
||||
@@ -86,14 +92,16 @@ def loadHistory(completion=None):
|
||||
historyPath = paths.SQL_SHELL_HISTORY
|
||||
elif completion == AUTOCOMPLETE_TYPE.OS:
|
||||
historyPath = paths.OS_SHELL_HISTORY
|
||||
elif completion == AUTOCOMPLETE_TYPE.API:
|
||||
historyPath = paths.API_SHELL_HISTORY
|
||||
else:
|
||||
historyPath = paths.SQLMAP_SHELL_HISTORY
|
||||
|
||||
if os.path.exists(historyPath):
|
||||
try:
|
||||
readline.read_history_file(historyPath)
|
||||
except IOError, msg:
|
||||
warnMsg = "there was a problem loading the history file '%s' (%s)" % (historyPath, msg)
|
||||
except IOError as ex:
|
||||
warnMsg = "there was a problem loading the history file '%s' (%s)" % (historyPath, getSafeExString(ex))
|
||||
logger.warn(warnMsg)
|
||||
|
||||
def autoCompletion(completion=None, os=None, commands=None):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -31,7 +31,7 @@ def blockingReadFromFD(fd):
|
||||
while True:
|
||||
try:
|
||||
output += os.read(fd, 8192)
|
||||
except (OSError, IOError), ioe:
|
||||
except (OSError, IOError) as ioe:
|
||||
if ioe.args[0] in (errno.EAGAIN, errno.EINTR):
|
||||
# Uncomment the following line if the process seems to
|
||||
# take a huge amount of cpu time
|
||||
@@ -52,7 +52,7 @@ def blockingWriteToFD(fd, data):
|
||||
try:
|
||||
data_length = len(data)
|
||||
wrote_data = os.write(fd, data)
|
||||
except (OSError, IOError), io:
|
||||
except (OSError, IOError) as io:
|
||||
if io.errno in (errno.EAGAIN, errno.EINTR):
|
||||
continue
|
||||
else:
|
||||
@@ -85,7 +85,7 @@ class Popen(subprocess.Popen):
|
||||
getattr(self, which).close()
|
||||
setattr(self, which, None)
|
||||
|
||||
if subprocess.mswindows:
|
||||
if IS_WIN:
|
||||
def send(self, input):
|
||||
if not self.stdin:
|
||||
return None
|
||||
@@ -95,8 +95,8 @@ class Popen(subprocess.Popen):
|
||||
(errCode, written) = WriteFile(x, input)
|
||||
except ValueError:
|
||||
return self._close('stdin')
|
||||
except (subprocess.pywintypes.error, Exception), why:
|
||||
if why[0] in (109, errno.ESHUTDOWN):
|
||||
except (subprocess.pywintypes.error, Exception) as ex:
|
||||
if ex[0] in (109, errno.ESHUTDOWN):
|
||||
return self._close('stdin')
|
||||
raise
|
||||
|
||||
@@ -116,8 +116,8 @@ class Popen(subprocess.Popen):
|
||||
(errCode, read) = ReadFile(x, nAvail, None)
|
||||
except (ValueError, NameError):
|
||||
return self._close(which)
|
||||
except (subprocess.pywintypes.error, Exception), why:
|
||||
if why[0] in (109, errno.ESHUTDOWN):
|
||||
except (subprocess.pywintypes.error, Exception) as ex:
|
||||
if ex[0] in (109, errno.ESHUTDOWN):
|
||||
return self._close(which)
|
||||
raise
|
||||
|
||||
@@ -134,8 +134,8 @@ class Popen(subprocess.Popen):
|
||||
|
||||
try:
|
||||
written = os.write(self.stdin.fileno(), input)
|
||||
except OSError, why:
|
||||
if why[0] == errno.EPIPE: # broken pipe
|
||||
except OSError as ex:
|
||||
if ex[0] == errno.EPIPE: # broken pipe
|
||||
return self._close('stdin')
|
||||
raise
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import functools
|
||||
import os
|
||||
import re
|
||||
@@ -13,7 +12,6 @@ import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import urlparse
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import getSafeExString
|
||||
@@ -28,6 +26,7 @@ from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.common import resetCookieJar
|
||||
from lib.core.common import urldecode
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
@@ -45,6 +44,7 @@ from lib.core.enums import POST_HINT
|
||||
from lib.core.exception import SqlmapFilePathException
|
||||
from lib.core.exception import SqlmapGenericException
|
||||
from lib.core.exception import SqlmapMissingPrivileges
|
||||
from lib.core.exception import SqlmapNoneDataException
|
||||
from lib.core.exception import SqlmapSystemException
|
||||
from lib.core.exception import SqlmapUserQuitException
|
||||
from lib.core.option import _setDBMS
|
||||
@@ -52,9 +52,11 @@ from lib.core.option import _setKnowledgeBaseAttributes
|
||||
from lib.core.option import _setAuthCred
|
||||
from lib.core.settings import ASTERISK_MARKER
|
||||
from lib.core.settings import CSRF_TOKEN_PARAMETER_INFIXES
|
||||
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
|
||||
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
|
||||
from lib.core.settings import HOST_ALIASES
|
||||
from lib.core.settings import ARRAY_LIKE_RECOGNITION_REGEX
|
||||
from lib.core.settings import INJECT_HERE_REGEX
|
||||
from lib.core.settings import JSON_RECOGNITION_REGEX
|
||||
from lib.core.settings import JSON_LIKE_RECOGNITION_REGEX
|
||||
from lib.core.settings import MULTIPART_RECOGNITION_REGEX
|
||||
@@ -71,7 +73,9 @@ from lib.core.settings import URI_INJECTABLE_REGEX
|
||||
from lib.core.settings import USER_AGENT_ALIASES
|
||||
from lib.core.settings import XML_RECOGNITION_REGEX
|
||||
from lib.utils.hashdb import HashDB
|
||||
from thirdparty.odict.odict import OrderedDict
|
||||
from thirdparty import six
|
||||
from thirdparty.odict import OrderedDict
|
||||
from thirdparty.six.moves import urllib as _urllib
|
||||
|
||||
def _setRequestParams():
|
||||
"""
|
||||
@@ -83,6 +87,7 @@ def _setRequestParams():
|
||||
conf.parameters[None] = "direct connection"
|
||||
return
|
||||
|
||||
hintNames = []
|
||||
testableParameters = False
|
||||
|
||||
# Perform checks on GET parameters
|
||||
@@ -101,7 +106,6 @@ def _setRequestParams():
|
||||
|
||||
if conf.data is not None:
|
||||
conf.method = HTTPMETHOD.POST if not conf.method or conf.method == HTTPMETHOD.GET else conf.method
|
||||
hintNames = []
|
||||
|
||||
def process(match, repl):
|
||||
retVal = match.group(0)
|
||||
@@ -148,8 +152,8 @@ def _setRequestParams():
|
||||
match = re.search(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data)
|
||||
if match and not (conf.testParameter and match.group("name") not in conf.testParameter):
|
||||
_ = match.group(2)
|
||||
_ = re.sub(r'("[^"]+)"', '\g<1>%s"' % kb.customInjectionMark, _)
|
||||
_ = re.sub(r'(\A|,|\s+)(-?\d[\d\.]*\b)', '\g<0>%s' % kb.customInjectionMark, _)
|
||||
_ = re.sub(r'("[^"]+)"', r'\g<1>%s"' % kb.customInjectionMark, _)
|
||||
_ = 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
|
||||
@@ -210,7 +214,7 @@ def _setRequestParams():
|
||||
if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
|
||||
conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data)
|
||||
conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
|
||||
conf.data = re.sub(r"(?si)((Content-Disposition[^\n]+?name\s*=\s*[\"']?(?P<name>[^\"'\r\n]+)[\"']?).+?)(((\r)?\n)+--)", functools.partial(process, repl=r"\g<1>%s\g<4>" % kb.customInjectionMark), conf.data)
|
||||
conf.data = re.sub(r"(?si)((Content-Disposition[^\n]+?name\s*=\s*[\"']?(?P<name>[^\"'\r\n]+)[\"']?).+?)((%s)+--)" % ("\r\n" if "\r\n" in conf.data else '\n'), functools.partial(process, repl=r"\g<1>%s\g<4>" % kb.customInjectionMark), conf.data)
|
||||
|
||||
kb.postHint = POST_HINT.MULTIPART
|
||||
|
||||
@@ -274,7 +278,7 @@ def _setRequestParams():
|
||||
|
||||
if not kb.processUserMarks:
|
||||
if place == PLACE.URI:
|
||||
query = urlparse.urlsplit(value).query
|
||||
query = _urllib.parse.urlsplit(value).query
|
||||
if query:
|
||||
parameters = conf.parameters[PLACE.GET] = query
|
||||
paramDict = paramToDict(PLACE.GET, parameters)
|
||||
@@ -344,7 +348,7 @@ def _setRequestParams():
|
||||
# Url encoding of the header values should be avoided
|
||||
# Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value
|
||||
|
||||
if httpHeader.title() == HTTP_HEADER.USER_AGENT:
|
||||
if httpHeader.upper() == HTTP_HEADER.USER_AGENT.upper():
|
||||
conf.parameters[PLACE.USER_AGENT] = urldecode(headerValue)
|
||||
|
||||
condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES, True)))
|
||||
@@ -353,7 +357,7 @@ def _setRequestParams():
|
||||
conf.paramDict[PLACE.USER_AGENT] = {PLACE.USER_AGENT: headerValue}
|
||||
testableParameters = True
|
||||
|
||||
elif httpHeader.title() == HTTP_HEADER.REFERER:
|
||||
elif httpHeader.upper() == HTTP_HEADER.REFERER.upper():
|
||||
conf.parameters[PLACE.REFERER] = urldecode(headerValue)
|
||||
|
||||
condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES, True)))
|
||||
@@ -362,7 +366,7 @@ def _setRequestParams():
|
||||
conf.paramDict[PLACE.REFERER] = {PLACE.REFERER: headerValue}
|
||||
testableParameters = True
|
||||
|
||||
elif httpHeader.title() == HTTP_HEADER.HOST:
|
||||
elif httpHeader.upper() == HTTP_HEADER.HOST.upper():
|
||||
conf.parameters[PLACE.HOST] = urldecode(headerValue)
|
||||
|
||||
condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES, True)))
|
||||
@@ -391,8 +395,8 @@ def _setRequestParams():
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
if conf.csrfToken:
|
||||
if not any(conf.csrfToken in _ for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))) and not re.search(r"\b%s\b" % re.escape(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
|
||||
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, {}):
|
||||
errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken._original
|
||||
errMsg += "found in provided GET, POST, Cookie or header values"
|
||||
raise SqlmapGenericException(errMsg)
|
||||
else:
|
||||
@@ -406,7 +410,10 @@ def _setRequestParams():
|
||||
message += "Do you want sqlmap to automatically update it in further requests? [y/N] "
|
||||
|
||||
if readInput(message, default='N', boolean=True):
|
||||
conf.csrfToken = getUnicode(parameter)
|
||||
class _(six.text_type):
|
||||
pass
|
||||
conf.csrfToken = _(re.escape(getUnicode(parameter)))
|
||||
conf.csrfToken._original = getUnicode(parameter)
|
||||
break
|
||||
|
||||
def _setHashDB():
|
||||
@@ -422,8 +429,8 @@ def _setHashDB():
|
||||
try:
|
||||
os.remove(conf.hashDBFile)
|
||||
logger.info("flushing session file")
|
||||
except OSError, msg:
|
||||
errMsg = "unable to flush the session file (%s)" % msg
|
||||
except OSError as ex:
|
||||
errMsg = "unable to flush the session file ('%s')" % getSafeExString(ex)
|
||||
raise SqlmapFilePathException(errMsg)
|
||||
|
||||
conf.hashDB = HashDB(conf.hashDBFile)
|
||||
@@ -467,7 +474,13 @@ def _resumeDBMS():
|
||||
value = hashDBRetrieve(HASHDB_KEYS.DBMS)
|
||||
|
||||
if not value:
|
||||
return
|
||||
if conf.offline:
|
||||
errMsg = "unable to continue in offline mode "
|
||||
errMsg += "because of lack of usable "
|
||||
errMsg += "session data"
|
||||
raise SqlmapNoneDataException(errMsg)
|
||||
else:
|
||||
return
|
||||
|
||||
dbms = value.lower()
|
||||
dbmsVersion = [UNKNOWN_DBMS_VERSION]
|
||||
@@ -547,7 +560,7 @@ def _setResultsFile():
|
||||
conf.resultsFilename = os.path.join(paths.SQLMAP_OUTPUT_PATH, time.strftime(RESULTS_FILE_FORMAT).lower())
|
||||
try:
|
||||
conf.resultsFP = openFile(conf.resultsFilename, "a", UNICODE_ENCODING, buffering=0)
|
||||
except (OSError, IOError), ex:
|
||||
except (OSError, IOError) as ex:
|
||||
try:
|
||||
warnMsg = "unable to create results file '%s' ('%s'). " % (conf.resultsFilename, getUnicode(ex))
|
||||
handle, conf.resultsFilename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.RESULTS, suffix=".csv")
|
||||
@@ -555,7 +568,7 @@ def _setResultsFile():
|
||||
conf.resultsFP = openFile(conf.resultsFilename, "w+", UNICODE_ENCODING, buffering=0)
|
||||
warnMsg += "Using temporary file '%s' instead" % conf.resultsFilename
|
||||
logger.warn(warnMsg)
|
||||
except IOError, _:
|
||||
except IOError as _:
|
||||
errMsg = "unable to write to the temporary directory ('%s'). " % _
|
||||
errMsg += "Please make sure that your disk is not full and "
|
||||
errMsg += "that you have sufficient write permissions to "
|
||||
@@ -571,7 +584,7 @@ def _createFilesDir():
|
||||
Create the file directory.
|
||||
"""
|
||||
|
||||
if not conf.rFile:
|
||||
if not conf.fileRead:
|
||||
return
|
||||
|
||||
conf.filePath = paths.SQLMAP_FILES_PATH % conf.hostname
|
||||
@@ -579,7 +592,7 @@ def _createFilesDir():
|
||||
if not os.path.isdir(conf.filePath):
|
||||
try:
|
||||
os.makedirs(conf.filePath)
|
||||
except OSError, ex:
|
||||
except OSError as ex:
|
||||
tempDir = tempfile.mkdtemp(prefix="sqlmapfiles")
|
||||
warnMsg = "unable to create files directory "
|
||||
warnMsg += "'%s' (%s). " % (conf.filePath, getUnicode(ex))
|
||||
@@ -601,7 +614,7 @@ def _createDumpDir():
|
||||
if not os.path.isdir(conf.dumpPath):
|
||||
try:
|
||||
os.makedirs(conf.dumpPath)
|
||||
except OSError, ex:
|
||||
except OSError as ex:
|
||||
tempDir = tempfile.mkdtemp(prefix="sqlmapdump")
|
||||
warnMsg = "unable to create dump directory "
|
||||
warnMsg += "'%s' (%s). " % (conf.dumpPath, getUnicode(ex))
|
||||
@@ -619,43 +632,15 @@ def _createTargetDirs():
|
||||
Create the output directory.
|
||||
"""
|
||||
|
||||
try:
|
||||
if not os.path.isdir(paths.SQLMAP_OUTPUT_PATH):
|
||||
os.makedirs(paths.SQLMAP_OUTPUT_PATH)
|
||||
|
||||
_ = os.path.join(paths.SQLMAP_OUTPUT_PATH, randomStr())
|
||||
open(_, "w+b").close()
|
||||
os.remove(_)
|
||||
|
||||
if conf.outputDir:
|
||||
warnMsg = "using '%s' as the output directory" % paths.SQLMAP_OUTPUT_PATH
|
||||
logger.warn(warnMsg)
|
||||
except (OSError, IOError), ex:
|
||||
try:
|
||||
tempDir = tempfile.mkdtemp(prefix="sqlmapoutput")
|
||||
except Exception, _:
|
||||
errMsg = "unable to write to the temporary directory ('%s'). " % _
|
||||
errMsg += "Please make sure that your disk is not full and "
|
||||
errMsg += "that you have sufficient write permissions to "
|
||||
errMsg += "create temporary files and/or directories"
|
||||
raise SqlmapSystemException(errMsg)
|
||||
|
||||
warnMsg = "unable to %s output directory " % ("create" if not os.path.isdir(paths.SQLMAP_OUTPUT_PATH) else "write to the")
|
||||
warnMsg += "'%s' (%s). " % (paths.SQLMAP_OUTPUT_PATH, getUnicode(ex))
|
||||
warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir)
|
||||
logger.warn(warnMsg)
|
||||
|
||||
paths.SQLMAP_OUTPUT_PATH = tempDir
|
||||
|
||||
conf.outputPath = os.path.join(getUnicode(paths.SQLMAP_OUTPUT_PATH), normalizeUnicode(getUnicode(conf.hostname)))
|
||||
|
||||
try:
|
||||
if not os.path.isdir(conf.outputPath):
|
||||
os.makedirs(conf.outputPath)
|
||||
except (OSError, IOError, TypeError), ex:
|
||||
except (OSError, IOError, TypeError) as ex:
|
||||
try:
|
||||
tempDir = tempfile.mkdtemp(prefix="sqlmapoutput")
|
||||
except Exception, _:
|
||||
except Exception as _:
|
||||
errMsg = "unable to write to the temporary directory ('%s'). " % _
|
||||
errMsg += "Please make sure that your disk is not full and "
|
||||
errMsg += "that you have sufficient write permissions to "
|
||||
@@ -669,14 +654,16 @@ def _createTargetDirs():
|
||||
|
||||
conf.outputPath = tempDir
|
||||
|
||||
conf.outputPath = getUnicode(conf.outputPath)
|
||||
|
||||
try:
|
||||
with codecs.open(os.path.join(conf.outputPath, "target.txt"), "w+", UNICODE_ENCODING) as f:
|
||||
with openFile(os.path.join(conf.outputPath, "target.txt"), "w+") as f:
|
||||
f.write(kb.originalUrls.get(conf.url) or conf.url or conf.hostname)
|
||||
f.write(" (%s)" % (HTTPMETHOD.POST if conf.data else HTTPMETHOD.GET))
|
||||
f.write(" # %s" % getUnicode(subprocess.list2cmdline(sys.argv), encoding=sys.stdin.encoding))
|
||||
if conf.data:
|
||||
f.write("\n\n%s" % getUnicode(conf.data))
|
||||
except IOError, ex:
|
||||
except IOError as ex:
|
||||
if "denied" in getUnicode(ex):
|
||||
errMsg = "you don't have enough permissions "
|
||||
else:
|
||||
@@ -689,6 +676,13 @@ def _createTargetDirs():
|
||||
_createFilesDir()
|
||||
_configureDumper()
|
||||
|
||||
def _setAuxOptions():
|
||||
"""
|
||||
Setup auxiliary (host-dependent) options
|
||||
"""
|
||||
|
||||
kb.aliasName = randomStr(seed=hash(conf.hostname or ""))
|
||||
|
||||
def _restoreMergedOptions():
|
||||
"""
|
||||
Restore merged options (command line, configuration file and default values)
|
||||
@@ -719,7 +713,7 @@ def initTargetEnv():
|
||||
_setDBMS()
|
||||
|
||||
if conf.data:
|
||||
class _(unicode):
|
||||
class _(six.text_type):
|
||||
pass
|
||||
|
||||
kb.postUrlEncode = True
|
||||
@@ -735,6 +729,9 @@ def initTargetEnv():
|
||||
setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
|
||||
kb.postSpaceToPlus = '+' in original
|
||||
|
||||
match = re.search(INJECT_HERE_REGEX, "%s %s %s" % (conf.url, conf.data, conf.httpHeaders))
|
||||
kb.customInjectionMark = match.group(0) if match else CUSTOM_INJECTION_MARK_CHAR
|
||||
|
||||
def setupTargetEnv():
|
||||
_createTargetDirs()
|
||||
_setRequestParams()
|
||||
@@ -742,3 +739,4 @@ def setupTargetEnv():
|
||||
_resumeHashDBValues()
|
||||
_setResultsFile()
|
||||
_setAuthCred()
|
||||
_setAuxOptions()
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import doctest
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from extra.beep.beep import beep
|
||||
from extra.vulnserver import vulnserver
|
||||
from lib.controller.controller import start
|
||||
from lib.core.common import clearConsoleLine
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readXmlFile
|
||||
from lib.core.common import shellExec
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import paths
|
||||
@@ -43,6 +47,49 @@ class Failures(object):
|
||||
|
||||
_failures = Failures()
|
||||
|
||||
def vulnTest():
|
||||
"""
|
||||
Runs the testing against 'vulnserver'
|
||||
"""
|
||||
|
||||
retVal = True
|
||||
count, length = 0, 6
|
||||
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()
|
||||
|
||||
for options, checks in (
|
||||
("--flush-session --identify-waf", ("CloudFlare",)),
|
||||
("--flush-session --parse-errors", (": syntax error", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "back-end DBMS: SQLite", "3 columns")),
|
||||
("--banner --schema --dump -T users --binary-fields=surname --where 'id>3'", ("banner: '3", "INTEGER", "TEXT", "id", "name", "surname", "2 entries", "6E616D6569736E756C6C")),
|
||||
("--all --tamper=between,randomcase", ("5 entries", "luther", "blisset", "fluffy", "179ad45c6ce2cb97cf1029e212046e81", "NULL", "nameisnull", "testpass")),
|
||||
("--technique=B --hex --fresh-queries --threads=4 --sql-query='SELECT 987654321'", ("length of query output", ": '987654321'",)),
|
||||
("--technique=T --fresh-queries --sql-query='SELECT 1234'", (": '1234'",)),
|
||||
):
|
||||
output = shellExec("%s %s -u http://%s:%d/?id=1 --batch %s" % (sys.executable, os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py"), address, port, options))
|
||||
output = getUnicode(output)
|
||||
|
||||
if not all(check in output for check in checks):
|
||||
retVal = False
|
||||
|
||||
count += 1
|
||||
status = '%d/%d (%d%%) ' % (count, length, round(100.0 * count / length))
|
||||
dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status))
|
||||
|
||||
clearConsoleLine()
|
||||
if retVal:
|
||||
logger.info("vuln test final result: PASSED")
|
||||
else:
|
||||
logger.error("vuln test final result: FAILED")
|
||||
|
||||
return retVal
|
||||
|
||||
def smokeTest():
|
||||
"""
|
||||
Runs the basic smoke testing of a program
|
||||
@@ -71,10 +118,10 @@ def smokeTest():
|
||||
try:
|
||||
__import__(path)
|
||||
module = sys.modules[path]
|
||||
except Exception, msg:
|
||||
except Exception as ex:
|
||||
retVal = False
|
||||
dataToStdout("\r")
|
||||
errMsg = "smoke test failed at importing module '%s' (%s):\n%s" % (path, os.path.join(root, filename), msg)
|
||||
errMsg = "smoke test failed at importing module '%s' (%s):\n%s" % (path, os.path.join(root, filename), ex)
|
||||
logger.error(errMsg)
|
||||
else:
|
||||
# Run doc tests
|
||||
@@ -271,10 +318,10 @@ def runCase(parse):
|
||||
result = start()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except SqlmapBaseException, e:
|
||||
handled_exception = e
|
||||
except Exception, e:
|
||||
unhandled_exception = e
|
||||
except SqlmapBaseException as ex:
|
||||
handled_exception = ex
|
||||
except Exception as ex:
|
||||
unhandled_exception = ex
|
||||
finally:
|
||||
sys.stdout.seek(0)
|
||||
console = sys.stdout.read()
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import difflib
|
||||
import random
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from lib.core.compat import WichmannHill
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.datatype import AttribDict
|
||||
from lib.core.enums import PAYLOAD
|
||||
from lib.core.exception import SqlmapBaseException
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from lib.core.exception import SqlmapThreadException
|
||||
from lib.core.exception import SqlmapUserQuitException
|
||||
@@ -54,7 +58,7 @@ class _ThreadData(threading.local):
|
||||
self.lastRequestMsg = None
|
||||
self.lastRequestUID = 0
|
||||
self.lastRedirectURL = None
|
||||
self.random = random.WichmannHill()
|
||||
self.random = WichmannHill()
|
||||
self.resumed = False
|
||||
self.retriesCount = 0
|
||||
self.seqMatcher = difflib.SequenceMatcher(None)
|
||||
@@ -91,11 +95,12 @@ def exceptionHandledFunction(threadFunction, silent=False):
|
||||
kb.threadContinue = False
|
||||
kb.threadException = True
|
||||
raise
|
||||
except Exception, ex:
|
||||
if not silent:
|
||||
logger.error("thread %s: %s" % (threading.currentThread().getName(), ex.message))
|
||||
except Exception as ex:
|
||||
if not silent and kb.get("threadContinue"):
|
||||
errMsg = ex.message if isinstance(ex, SqlmapBaseException) else "%s: %s" % (type(ex).__name__, ex.message)
|
||||
logger.error("thread %s: '%s'" % (threading.currentThread().getName(), errMsg))
|
||||
|
||||
if conf.verbose > 1:
|
||||
if conf.get("verbose") > 1 and not isinstance(ex, (SqlmapUserQuitException,)):
|
||||
traceback.print_exc()
|
||||
|
||||
def setDaemon(thread):
|
||||
@@ -108,7 +113,6 @@ def setDaemon(thread):
|
||||
def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardException=True, threadChoice=False, startThreadMsg=True):
|
||||
threads = []
|
||||
|
||||
kb.multiThreadMode = True
|
||||
kb.threadContinue = True
|
||||
kb.threadException = False
|
||||
|
||||
@@ -150,7 +154,7 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
|
||||
|
||||
try:
|
||||
thread.start()
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
errMsg = "error occurred while starting new thread ('%s')" % ex.message
|
||||
logger.critical(errMsg)
|
||||
break
|
||||
@@ -166,8 +170,9 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
|
||||
alive = True
|
||||
time.sleep(0.1)
|
||||
|
||||
except (KeyboardInterrupt, SqlmapUserQuitException), ex:
|
||||
print
|
||||
except (KeyboardInterrupt, SqlmapUserQuitException) as ex:
|
||||
print()
|
||||
kb.prependFlag = False
|
||||
kb.threadContinue = False
|
||||
kb.threadException = True
|
||||
|
||||
@@ -183,25 +188,24 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
|
||||
if forwardException:
|
||||
raise
|
||||
|
||||
except (SqlmapConnectionException, SqlmapValueException), ex:
|
||||
print
|
||||
except (SqlmapConnectionException, SqlmapValueException) as ex:
|
||||
print()
|
||||
kb.threadException = True
|
||||
logger.error("thread %s: %s" % (threading.currentThread().getName(), ex.message))
|
||||
|
||||
if conf.verbose > 1:
|
||||
if conf.get("verbose") > 1:
|
||||
traceback.print_exc()
|
||||
|
||||
except:
|
||||
from lib.core.common import unhandledExceptionMessage
|
||||
|
||||
print
|
||||
print()
|
||||
kb.threadException = True
|
||||
errMsg = unhandledExceptionMessage()
|
||||
logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg))
|
||||
traceback.print_exc()
|
||||
|
||||
finally:
|
||||
kb.multiThreadMode = False
|
||||
kb.bruteMode = False
|
||||
kb.threadContinue = True
|
||||
kb.threadException = False
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -17,6 +17,7 @@ import zipfile
|
||||
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import getLatestRevision
|
||||
from lib.core.common import pollProcess
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
@@ -25,6 +26,7 @@ from lib.core.data import paths
|
||||
from lib.core.revision import getRevisionNumber
|
||||
from lib.core.settings import GIT_REPOSITORY
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import VERSION
|
||||
from lib.core.settings import ZIPBALL_PAGE
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
|
||||
@@ -39,16 +41,21 @@ def update():
|
||||
warnMsg += "from GitHub (e.g. 'git clone --depth 1 %s sqlmap')" % GIT_REPOSITORY
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if VERSION == getLatestRevision():
|
||||
logger.info("already at the latest revision '%s'" % getRevisionNumber())
|
||||
return
|
||||
|
||||
message = "do you want to try to fetch the latest 'zipball' from repository and extract it (experimental) ? [y/N]"
|
||||
if readInput(message, default='N', boolean=True):
|
||||
directory = os.path.abspath(paths.SQLMAP_ROOT_PATH)
|
||||
|
||||
try:
|
||||
open(os.path.join(directory, "sqlmap.py"), "w+b")
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
errMsg = "unable to update content of directory '%s' ('%s')" % (directory, getSafeExString(ex))
|
||||
logger.error(errMsg)
|
||||
else:
|
||||
attrs = os.stat(os.path.join(directory, "sqlmap.py")).st_mode
|
||||
for wildcard in ('*', ".*"):
|
||||
for _ in glob.glob(os.path.join(directory, wildcard)):
|
||||
try:
|
||||
@@ -78,11 +85,16 @@ def update():
|
||||
version = re.search(r"(?m)^VERSION\s*=\s*['\"]([^'\"]+)", f.read()).group(1)
|
||||
logger.info("updated to the latest version '%s#dev'" % version)
|
||||
success = True
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
logger.error("update could not be completed ('%s')" % getSafeExString(ex))
|
||||
else:
|
||||
if not success:
|
||||
logger.error("update could not be completed")
|
||||
else:
|
||||
try:
|
||||
os.chmod(os.path.join(directory, "sqlmap.py"), attrs)
|
||||
except OSError:
|
||||
logger.warning("could not set the file attributes of '%s'" % os.path.join(directory, "sqlmap.py"))
|
||||
else:
|
||||
infoMsg = "updating sqlmap to the latest development revision from the "
|
||||
infoMsg += "GitHub repository"
|
||||
@@ -91,14 +103,14 @@ def update():
|
||||
debugMsg = "sqlmap will try to update itself using 'git' command"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
dataToStdout("\r[%s] [INFO] update in progress " % time.strftime("%X"))
|
||||
dataToStdout("\r[%s] [INFO] update in progress" % time.strftime("%X"))
|
||||
|
||||
try:
|
||||
process = subprocess.Popen("git checkout . && git pull %s HEAD" % GIT_REPOSITORY, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=paths.SQLMAP_ROOT_PATH.encode(sys.getfilesystemencoding() or UNICODE_ENCODING))
|
||||
pollProcess(process, True)
|
||||
stdout, stderr = process.communicate()
|
||||
success = not process.returncode
|
||||
except (IOError, OSError), ex:
|
||||
except (IOError, OSError) as ex:
|
||||
success = False
|
||||
stderr = getSafeExString(ex)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -43,7 +43,7 @@ class Wordlist(object):
|
||||
if os.path.splitext(self.current)[1].lower() == ".zip":
|
||||
try:
|
||||
_ = zipfile.ZipFile(self.current, 'r')
|
||||
except zipfile.error, ex:
|
||||
except zipfile.error as ex:
|
||||
errMsg = "something appears to be wrong with "
|
||||
errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex))
|
||||
errMsg += "sure that you haven't made any changes to it"
|
||||
@@ -68,15 +68,15 @@ class Wordlist(object):
|
||||
while True:
|
||||
self.counter += 1
|
||||
try:
|
||||
retVal = self.iter.next().rstrip()
|
||||
except zipfile.error, ex:
|
||||
retVal = next(self.iter).rstrip()
|
||||
except zipfile.error as ex:
|
||||
errMsg = "something appears to be wrong with "
|
||||
errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex))
|
||||
errMsg += "sure that you haven't made any changes to it"
|
||||
raise SqlmapInstallationException(errMsg)
|
||||
except StopIteration:
|
||||
self.adjust()
|
||||
retVal = self.iter.next().rstrip()
|
||||
retVal = next(self.iter).rstrip()
|
||||
if not self.proc_count or self.counter % self.proc_count == self.proc_id:
|
||||
break
|
||||
return retVal
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
@@ -20,6 +22,7 @@ from lib.core.common import checkSystemEncoding
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import expandMnemonics
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.data import cmdLineOptions
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
@@ -29,6 +32,7 @@ from lib.core.exception import SqlmapShellQuitException
|
||||
from lib.core.exception import SqlmapSyntaxException
|
||||
from lib.core.settings import BASIC_HELP_ITEMS
|
||||
from lib.core.settings import DUMMY_URL
|
||||
from lib.core.settings import INFERENCE_UNKNOWN_CHAR
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import MAX_HELP_OPTION_LENGTH
|
||||
from lib.core.settings import VERSION_STRING
|
||||
@@ -36,6 +40,7 @@ from lib.core.shell import autoCompletion
|
||||
from lib.core.shell import clearHistory
|
||||
from lib.core.shell import loadHistory
|
||||
from lib.core.shell import saveHistory
|
||||
from thirdparty.six.moves import input as _input
|
||||
|
||||
def cmdLineParser(argv=None):
|
||||
"""
|
||||
@@ -50,7 +55,7 @@ def cmdLineParser(argv=None):
|
||||
# Reference: https://stackoverflow.com/a/4012683 (Note: previously used "...sys.getfilesystemencoding() or UNICODE_ENCODING")
|
||||
_ = getUnicode(os.path.basename(argv[0]), encoding=sys.stdin.encoding)
|
||||
|
||||
usage = "%s%s [options]" % ("python " if not IS_WIN else "", "\"%s\"" % _ if " " in _ else _)
|
||||
usage = "%s%s [options]" % ("%s " % os.path.basename(sys.executable) if not IS_WIN else "", "\"%s\"" % _ if " " in _ else _)
|
||||
parser = OptionParser(usage=usage)
|
||||
|
||||
try:
|
||||
@@ -99,16 +104,16 @@ def cmdLineParser(argv=None):
|
||||
help="Force usage of given HTTP method (e.g. PUT)")
|
||||
|
||||
request.add_option("--data", dest="data",
|
||||
help="Data string to be sent through POST")
|
||||
help="Data string to be sent through POST (e.g. \"id=1\")")
|
||||
|
||||
request.add_option("--param-del", dest="paramDel",
|
||||
help="Character used for splitting parameter values")
|
||||
help="Character used for splitting parameter values (e.g. &)")
|
||||
|
||||
request.add_option("--cookie", dest="cookie",
|
||||
help="HTTP Cookie header value")
|
||||
help="HTTP Cookie header value (e.g. \"PHPSESSID=a8d127e..\")")
|
||||
|
||||
request.add_option("--cookie-del", dest="cookieDel",
|
||||
help="Character used for splitting cookie values")
|
||||
help="Character used for splitting cookie values (e.g. ;)")
|
||||
|
||||
request.add_option("--load-cookies", dest="loadCookies",
|
||||
help="File containing cookies in Netscape/wget format")
|
||||
@@ -144,7 +149,7 @@ def cmdLineParser(argv=None):
|
||||
help="HTTP authentication PEM cert/private key file")
|
||||
|
||||
request.add_option("--ignore-code", dest="ignoreCode", type="int",
|
||||
help="Ignore HTTP error code (e.g. 401)")
|
||||
help="Ignore (problematic) HTTP error code (e.g. 401)")
|
||||
|
||||
request.add_option("--ignore-proxy", dest="ignoreProxy", action="store_true",
|
||||
help="Ignore system default proxy settings")
|
||||
@@ -207,11 +212,14 @@ def cmdLineParser(argv=None):
|
||||
help="Parameter used to hold anti-CSRF token")
|
||||
|
||||
request.add_option("--csrf-url", dest="csrfUrl",
|
||||
help="URL address to visit to extract anti-CSRF token")
|
||||
help="URL address to visit for extraction of anti-CSRF token")
|
||||
|
||||
request.add_option("--force-ssl", dest="forceSSL", action="store_true",
|
||||
help="Force usage of SSL/HTTPS")
|
||||
|
||||
request.add_option("--chunked", dest="chunked", action="store_true",
|
||||
help="Use HTTP chunked transfer encoded (POST) requests")
|
||||
|
||||
request.add_option("--hpp", dest="hpp", action="store_true",
|
||||
help="Use HTTP parameter pollution method")
|
||||
|
||||
@@ -253,13 +261,13 @@ def cmdLineParser(argv=None):
|
||||
help="Regexp to exclude parameters from testing (e.g. \"ses\")")
|
||||
|
||||
injection.add_option("--dbms", dest="dbms",
|
||||
help="Force back-end DBMS to this value")
|
||||
help="Force back-end DBMS to provided value")
|
||||
|
||||
injection.add_option("--dbms-cred", dest="dbmsCred",
|
||||
help="DBMS authentication credentials (user:password)")
|
||||
|
||||
injection.add_option("--os", dest="os",
|
||||
help="Force back-end DBMS operating system to this value")
|
||||
help="Force back-end DBMS operating system to provided value")
|
||||
|
||||
injection.add_option("--invalid-bignum", dest="invalidBignum", action="store_true",
|
||||
help="Use big numbers for invalidating values")
|
||||
@@ -333,9 +341,12 @@ def cmdLineParser(argv=None):
|
||||
techniques.add_option("--dns-domain", dest="dnsDomain",
|
||||
help="Domain name used for DNS exfiltration attack")
|
||||
|
||||
techniques.add_option("--second-order", dest="secondOrder",
|
||||
techniques.add_option("--second-url", dest="secondUrl",
|
||||
help="Resulting page URL searched for second-order response")
|
||||
|
||||
techniques.add_option("--second-req", dest="secondReq",
|
||||
help="Load second-order HTTP request from file")
|
||||
|
||||
# Fingerprint options
|
||||
fingerprint = OptionGroup(parser, "Fingerprint")
|
||||
|
||||
@@ -400,7 +411,7 @@ def cmdLineParser(argv=None):
|
||||
help="Search column(s), table(s) and/or database name(s)")
|
||||
|
||||
enumeration.add_option("--comments", dest="getComments", action="store_true",
|
||||
help="Retrieve DBMS comments")
|
||||
help="Check for DBMS comments during enumeration")
|
||||
|
||||
enumeration.add_option("-D", dest="db",
|
||||
help="DBMS database to enumerate")
|
||||
@@ -438,7 +449,7 @@ def cmdLineParser(argv=None):
|
||||
enumeration.add_option("--last", dest="lastChar", type="int",
|
||||
help="Last query output word character to retrieve")
|
||||
|
||||
enumeration.add_option("--sql-query", dest="query",
|
||||
enumeration.add_option("--sql-query", dest="sqlQuery",
|
||||
help="SQL statement to be executed")
|
||||
|
||||
enumeration.add_option("--sql-shell", dest="sqlShell", action="store_true",
|
||||
@@ -468,13 +479,13 @@ def cmdLineParser(argv=None):
|
||||
# File system options
|
||||
filesystem = OptionGroup(parser, "File system access", "These options can be used to access the back-end database management system underlying file system")
|
||||
|
||||
filesystem.add_option("--file-read", dest="rFile",
|
||||
filesystem.add_option("--file-read", dest="fileRead",
|
||||
help="Read a file from the back-end DBMS file system")
|
||||
|
||||
filesystem.add_option("--file-write", dest="wFile",
|
||||
filesystem.add_option("--file-write", dest="fileWrite",
|
||||
help="Write a local file on the back-end DBMS file system")
|
||||
|
||||
filesystem.add_option("--file-dest", dest="dFile",
|
||||
filesystem.add_option("--file-dest", dest="fileDest",
|
||||
help="Back-end DBMS absolute filepath to write to")
|
||||
|
||||
# Takeover options
|
||||
@@ -581,7 +592,7 @@ def cmdLineParser(argv=None):
|
||||
help="Log all HTTP traffic into a HAR file")
|
||||
|
||||
general.add_option("--hex", dest="hexConvert", action="store_true",
|
||||
help="Use DBMS hex function(s) for data retrieval")
|
||||
help="Use hex conversion during data retrieval")
|
||||
|
||||
general.add_option("--output-dir", dest="outputDir", action="store",
|
||||
help="Custom output directory path")
|
||||
@@ -589,6 +600,12 @@ def cmdLineParser(argv=None):
|
||||
general.add_option("--parse-errors", dest="parseErrors", action="store_true",
|
||||
help="Parse and display DBMS error messages from responses")
|
||||
|
||||
general.add_option("--preprocess", dest="preprocess",
|
||||
help="Use given script(s) for preprocessing of response data")
|
||||
|
||||
general.add_option("--repair", dest="repair", action="store_true",
|
||||
help="Redump entries having unknown character marker (%s)" % INFERENCE_UNKNOWN_CHAR)
|
||||
|
||||
general.add_option("--save", dest="saveConfig",
|
||||
help="Save options to a configuration INI file")
|
||||
|
||||
@@ -614,7 +631,7 @@ def cmdLineParser(argv=None):
|
||||
help="Run host OS command(s) when SQL injection is found")
|
||||
|
||||
miscellaneous.add_option("--answers", dest="answers",
|
||||
help="Set question answers (e.g. \"quit=N,follow=N\")")
|
||||
help="Set predefined answers (e.g. \"quit=N,follow=N\")")
|
||||
|
||||
miscellaneous.add_option("--beep", dest="beep", action="store_true",
|
||||
help="Beep on question and/or when SQL injection is found")
|
||||
@@ -623,7 +640,7 @@ def cmdLineParser(argv=None):
|
||||
help="Clean up the DBMS from sqlmap specific UDF and tables")
|
||||
|
||||
miscellaneous.add_option("--dependencies", dest="dependencies", action="store_true",
|
||||
help="Check for missing (non-core) sqlmap dependencies")
|
||||
help="Check for missing (optional) sqlmap dependencies")
|
||||
|
||||
miscellaneous.add_option("--disable-coloring", dest="disableColoring", action="store_true",
|
||||
help="Disable console output coloring")
|
||||
@@ -632,7 +649,10 @@ def cmdLineParser(argv=None):
|
||||
help="Use Google dork results from specified page number")
|
||||
|
||||
miscellaneous.add_option("--identify-waf", dest="identifyWaf", action="store_true",
|
||||
help="Make a thorough testing for a WAF/IPS/IDS protection")
|
||||
help="Make a thorough testing for a WAF/IPS protection")
|
||||
|
||||
miscellaneous.add_option("--list-tampers", dest="listTampers", action="store_true",
|
||||
help="Display list of available tamper scripts")
|
||||
|
||||
miscellaneous.add_option("--mobile", dest="mobile", action="store_true",
|
||||
help="Imitate smartphone through HTTP User-Agent header")
|
||||
@@ -640,11 +660,11 @@ def cmdLineParser(argv=None):
|
||||
miscellaneous.add_option("--offline", dest="offline", action="store_true",
|
||||
help="Work in offline mode (only use session data)")
|
||||
|
||||
miscellaneous.add_option("--purge-output", dest="purgeOutput", action="store_true",
|
||||
help="Safely remove all content from output directory")
|
||||
miscellaneous.add_option("--purge", dest="purge", action="store_true",
|
||||
help="Safely remove all content from sqlmap data directory")
|
||||
|
||||
miscellaneous.add_option("--skip-waf", dest="skipWaf", action="store_true",
|
||||
help="Skip heuristic detection of WAF/IPS/IDS protection")
|
||||
help="Skip heuristic detection of WAF/IPS protection")
|
||||
|
||||
miscellaneous.add_option("--smart", dest="smart", action="store_true",
|
||||
help="Conduct thorough tests only if positive heuristic(s)")
|
||||
@@ -662,6 +682,14 @@ def cmdLineParser(argv=None):
|
||||
help="Simple wizard interface for beginner users")
|
||||
|
||||
# Hidden and/or experimental options
|
||||
parser.add_option("--base64", dest="base64Parameter",
|
||||
help=SUPPRESS_HELP)
|
||||
# help="Parameter(s) containing Base64 encoded values")
|
||||
|
||||
parser.add_option("--crack", dest="hashFile",
|
||||
help=SUPPRESS_HELP)
|
||||
# help="Load and crack hashes from a file (standalone)")
|
||||
|
||||
parser.add_option("--dummy", dest="dummy", action="store_true",
|
||||
help=SUPPRESS_HELP)
|
||||
|
||||
@@ -695,6 +723,9 @@ def cmdLineParser(argv=None):
|
||||
parser.add_option("--live-test", dest="liveTest", action="store_true",
|
||||
help=SUPPRESS_HELP)
|
||||
|
||||
parser.add_option("--vuln-test", dest="vulnTest", action="store_true",
|
||||
help=SUPPRESS_HELP)
|
||||
|
||||
parser.add_option("--stop-fail", dest="stopFail", action="store_true",
|
||||
help=SUPPRESS_HELP)
|
||||
|
||||
@@ -732,7 +763,7 @@ def cmdLineParser(argv=None):
|
||||
return retVal
|
||||
|
||||
parser.formatter._format_option_strings = parser.formatter.format_option_strings
|
||||
parser.formatter.format_option_strings = type(parser.formatter.format_option_strings)(_, parser, type(parser))
|
||||
parser.formatter.format_option_strings = type(parser.formatter.format_option_strings)(_, parser)
|
||||
|
||||
# Dirty hack for making a short option '-hh'
|
||||
option = parser.get_option("--hh")
|
||||
@@ -747,6 +778,7 @@ def cmdLineParser(argv=None):
|
||||
prompt = False
|
||||
advancedHelp = True
|
||||
extraHeaders = []
|
||||
tamperIndex = None
|
||||
|
||||
# Reference: https://stackoverflow.com/a/4012683 (Note: previously used "...sys.getfilesystemencoding() or UNICODE_ENCODING")
|
||||
for arg in argv:
|
||||
@@ -778,10 +810,10 @@ def cmdLineParser(argv=None):
|
||||
command = None
|
||||
|
||||
try:
|
||||
command = raw_input("sqlmap-shell> ").strip()
|
||||
command = _input("sqlmap-shell> ").strip()
|
||||
command = getUnicode(command, encoding=sys.stdin.encoding)
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
print
|
||||
print()
|
||||
raise SqlmapShellQuitException
|
||||
|
||||
if not command:
|
||||
@@ -803,7 +835,7 @@ def cmdLineParser(argv=None):
|
||||
try:
|
||||
for arg in shlex.split(command):
|
||||
argv.append(getUnicode(arg, encoding=sys.stdin.encoding))
|
||||
except ValueError, ex:
|
||||
except ValueError as ex:
|
||||
raise SqlmapSyntaxException("something went wrong during command line parsing ('%s')" % ex.message)
|
||||
|
||||
for i in xrange(len(argv)):
|
||||
@@ -818,14 +850,28 @@ def cmdLineParser(argv=None):
|
||||
elif re.search(r"\A-\w=.+", argv[i]):
|
||||
dataToStdout("[!] potentially miswritten (illegal '=') short option detected ('%s')\n" % argv[i])
|
||||
raise SystemExit
|
||||
elif argv[i].startswith("--tamper"):
|
||||
if tamperIndex is None:
|
||||
tamperIndex = i if '=' in argv[i] else (i + 1 if i + 1 < len(argv) and not argv[i + 1].startswith('-') else None)
|
||||
else:
|
||||
argv[tamperIndex] = "%s,%s" % (argv[tamperIndex], argv[i].split('=')[1] if '=' in argv[i] else (argv[i + 1] if i + 1 < len(argv) and not argv[i + 1].startswith('-') else ""))
|
||||
argv[i] = ""
|
||||
elif argv[i] == "-H":
|
||||
if i + 1 < len(argv):
|
||||
extraHeaders.append(argv[i + 1])
|
||||
elif argv[i] == "-r":
|
||||
for j in xrange(i + 2, len(argv)):
|
||||
value = argv[j]
|
||||
if os.path.isfile(value):
|
||||
argv[i + 1] += ",%s" % value
|
||||
argv[j] = ''
|
||||
else:
|
||||
break
|
||||
elif re.match(r"\A\d+!\Z", argv[i]) and argv[max(0, i - 1)] == "--threads" or re.match(r"\A--threads.+\d+!\Z", argv[i]):
|
||||
argv[i] = argv[i][:-1]
|
||||
conf.skipThreadCheck = True
|
||||
elif argv[i] == "--version":
|
||||
print VERSION_STRING.split('/')[-1]
|
||||
print(VERSION_STRING.split('/')[-1])
|
||||
raise SystemExit
|
||||
elif argv[i] in ("-h", "--help"):
|
||||
advancedHelp = False
|
||||
@@ -849,7 +895,7 @@ def cmdLineParser(argv=None):
|
||||
|
||||
try:
|
||||
(args, _) = parser.parse_args(argv)
|
||||
except UnicodeEncodeError, ex:
|
||||
except UnicodeEncodeError as ex:
|
||||
dataToStdout("\n[!] %s\n" % ex.object.encode("unicode-escape"))
|
||||
raise SystemExit
|
||||
except SystemExit:
|
||||
@@ -871,21 +917,21 @@ def cmdLineParser(argv=None):
|
||||
if args.dummy:
|
||||
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.liveTest, args.wizard, args.dependencies, args.purgeOutput, args.sitemapUrl)):
|
||||
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, -x, --wizard, --update, --purge-output or --dependencies), "
|
||||
errMsg += "use -h for basic or -hh for advanced help\n"
|
||||
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)):
|
||||
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, -x, --list-tampers, --wizard, --update, --purge or --dependencies). "
|
||||
errMsg += "Use -h for basic and -hh for advanced help\n"
|
||||
parser.error(errMsg)
|
||||
|
||||
return args
|
||||
|
||||
except (OptionError, TypeError), e:
|
||||
parser.error(e)
|
||||
except (OptionError, TypeError) as ex:
|
||||
parser.error(ex)
|
||||
|
||||
except SystemExit:
|
||||
# Protection against Windows dummy double clicking
|
||||
if IS_WIN:
|
||||
dataToStdout("\nPress Enter to continue...")
|
||||
raw_input()
|
||||
_input()
|
||||
raise
|
||||
|
||||
debugMsg = "parsing command line"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -39,7 +39,7 @@ def configFileProxy(section, option, datatype):
|
||||
value = config.getfloat(section, option) if config.get(section, option) else 0.0
|
||||
else:
|
||||
value = config.get(section, option)
|
||||
except ValueError, ex:
|
||||
except ValueError as ex:
|
||||
errMsg = "error occurred while processing the option "
|
||||
errMsg += "'%s' in provided configuration file ('%s')" % (option, getUnicode(ex))
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
@@ -71,7 +71,7 @@ def configFileParser(configFile):
|
||||
try:
|
||||
config = UnicodeRawConfigParser()
|
||||
config.readfp(configFP)
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
errMsg = "you have provided an invalid and/or unreadable configuration file ('%s')" % getSafeExString(ex)
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
@@ -35,7 +35,7 @@ class FingerprintHandler(ContentHandler):
|
||||
if key == "dbmsVersion":
|
||||
self._info[key] = value
|
||||
else:
|
||||
if key not in self._info.keys():
|
||||
if key not in self._info:
|
||||
self._info[key] = set()
|
||||
|
||||
for _ in value.split("|"):
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import itertools
|
||||
import os
|
||||
|
||||
from lib.core.common import parseXmlFile
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import paths
|
||||
from lib.parse.handler import FingerprintHandler
|
||||
from thirdparty.six.moves import filter as _filter
|
||||
|
||||
def headersParser(headers):
|
||||
"""
|
||||
@@ -30,7 +30,7 @@ def headersParser(headers):
|
||||
"x-powered-by": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "x-powered-by.xml"),
|
||||
}
|
||||
|
||||
for header in itertools.ifilter(lambda _: _ in kb.headerPaths, headers):
|
||||
for header in _filter(lambda _: _ in kb.headerPaths, headers):
|
||||
value = headers[header]
|
||||
xmlfile = kb.headerPaths[header]
|
||||
handler = FingerprintHandler(value, kb.headersFp)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from xml.etree import ElementTree as et
|
||||
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import paths
|
||||
from lib.core.datatype import AttribDict
|
||||
@@ -17,11 +19,14 @@ from lib.core.exception import SqlmapInstallationException
|
||||
from lib.core.settings import PAYLOAD_XML_FILES
|
||||
|
||||
def cleanupVals(text, tag):
|
||||
if tag == "clause" and '-' in text:
|
||||
text = re.sub(r"(\d+)-(\d+)", lambda match: ','.join(str(_) for _ in xrange(int(match.group(1)), int(match.group(2)) + 1)), text)
|
||||
|
||||
if tag in ("clause", "where"):
|
||||
text = text.split(',')
|
||||
|
||||
if isinstance(text, basestring):
|
||||
text = int(text) if text.isdigit() else text
|
||||
if hasattr(text, "isdigit") and text.isdigit():
|
||||
text = int(text)
|
||||
|
||||
elif isinstance(text, list):
|
||||
count = 0
|
||||
@@ -36,7 +41,7 @@ def cleanupVals(text, tag):
|
||||
return text
|
||||
|
||||
def parseXmlNode(node):
|
||||
for element in node.getiterator('boundary'):
|
||||
for element in node.getiterator("boundary"):
|
||||
boundary = AttribDict()
|
||||
|
||||
for child in element.getchildren():
|
||||
@@ -48,7 +53,7 @@ def parseXmlNode(node):
|
||||
|
||||
conf.boundaries.append(boundary)
|
||||
|
||||
for element in node.getiterator('test'):
|
||||
for element in node.getiterator("test"):
|
||||
test = AttribDict()
|
||||
|
||||
for child in element.getchildren():
|
||||
@@ -74,7 +79,7 @@ def parseXmlNode(node):
|
||||
def loadBoundaries():
|
||||
try:
|
||||
doc = et.parse(paths.BOUNDARIES_XML)
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
errMsg = "something appears to be wrong with "
|
||||
errMsg += "the file '%s' ('%s'). Please make " % (paths.BOUNDARIES_XML, getSafeExString(ex))
|
||||
errMsg += "sure that you haven't made any changes to it"
|
||||
@@ -89,7 +94,7 @@ def loadPayloads():
|
||||
|
||||
try:
|
||||
doc = et.parse(payloadFilePath)
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
errMsg = "something appears to be wrong with "
|
||||
errMsg += "the file '%s' ('%s'). Please make " % (payloadFilePath, getSafeExString(ex))
|
||||
errMsg += "sure that you haven't made any changes to it"
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import httplib
|
||||
import re
|
||||
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.datatype import OrderedSet
|
||||
from lib.core.exception import SqlmapSyntaxException
|
||||
from lib.request.connect import Connect as Request
|
||||
from thirdparty.oset.pyoset import oset
|
||||
from thirdparty.six.moves import http_client as _http_client
|
||||
|
||||
abortedFlag = None
|
||||
|
||||
@@ -26,11 +26,11 @@ def parseSitemap(url, retVal=None):
|
||||
try:
|
||||
if retVal is None:
|
||||
abortedFlag = False
|
||||
retVal = oset()
|
||||
retVal = OrderedSet()
|
||||
|
||||
try:
|
||||
content = Request.getPage(url=url, raise404=True)[0] if not abortedFlag else ""
|
||||
except httplib.InvalidURL:
|
||||
except _http_client.InvalidURL:
|
||||
errMsg = "invalid URL given for sitemap ('%s')" % url
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import gzip
|
||||
import io
|
||||
import logging
|
||||
import re
|
||||
import StringIO
|
||||
import struct
|
||||
import zlib
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import decodeHex
|
||||
from lib.core.common import extractErrorMessage
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import filterNone
|
||||
from lib.core.common import getBytes
|
||||
from lib.core.common import getPublicTypeMembers
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.common import isListLike
|
||||
from lib.core.common import randomStr
|
||||
@@ -35,19 +39,18 @@ from lib.core.enums import PLACE
|
||||
from lib.core.exception import SqlmapCompressionException
|
||||
from lib.core.settings import BLOCKED_IP_REGEX
|
||||
from lib.core.settings import DEFAULT_COOKIE_DELIMITER
|
||||
from lib.core.settings import DEV_EMAIL_ADDRESS
|
||||
from lib.core.settings import EVENTVALIDATION_REGEX
|
||||
from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE
|
||||
from lib.core.settings import META_CHARSET_REGEX
|
||||
from lib.core.settings import PARSE_HEADERS_LIMIT
|
||||
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.parse.headers import headersParser
|
||||
from lib.parse.html import htmlParser
|
||||
from lib.utils.htmlentities import htmlEntities
|
||||
from thirdparty import six
|
||||
from thirdparty.chardet import detect
|
||||
from thirdparty.odict.odict import OrderedDict
|
||||
from thirdparty.odict import OrderedDict
|
||||
|
||||
def forgeHeaders(items=None, base=None):
|
||||
"""
|
||||
@@ -57,7 +60,7 @@ def forgeHeaders(items=None, base=None):
|
||||
|
||||
items = items or {}
|
||||
|
||||
for _ in items.keys():
|
||||
for _ in list(items.keys()):
|
||||
if items[_] is None:
|
||||
del items[_]
|
||||
|
||||
@@ -100,7 +103,7 @@ def forgeHeaders(items=None, base=None):
|
||||
|
||||
if ("%s=" % getUnicode(cookie.name)) in getUnicode(headers[HTTP_HEADER.COOKIE]):
|
||||
if conf.loadCookies:
|
||||
conf.httpHeaders = filter(None, ((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:
|
||||
message = "you provided a HTTP %s header value. " % HTTP_HEADER.COOKIE
|
||||
message += "The target URL provided its own cookies within "
|
||||
@@ -154,6 +157,9 @@ def checkCharEncoding(encoding, warn=True):
|
||||
'utf8'
|
||||
"""
|
||||
|
||||
if isinstance(encoding, six.binary_type):
|
||||
encoding = getUnicode(encoding)
|
||||
|
||||
if isListLike(encoding):
|
||||
encoding = unArrayizeValue(encoding)
|
||||
|
||||
@@ -218,13 +224,13 @@ def checkCharEncoding(encoding, warn=True):
|
||||
# Reference: http://www.iana.org/assignments/character-sets
|
||||
# Reference: http://docs.python.org/library/codecs.html
|
||||
try:
|
||||
codecs.lookup(encoding.encode(UNICODE_ENCODING) if isinstance(encoding, unicode) else encoding)
|
||||
except (LookupError, ValueError):
|
||||
codecs.lookup(encoding)
|
||||
except:
|
||||
encoding = None
|
||||
|
||||
if encoding:
|
||||
try:
|
||||
unicode(randomStr(), encoding)
|
||||
six.text_type(getBytes(randomStr()), encoding)
|
||||
except:
|
||||
if warn:
|
||||
warnMsg = "invalid web page charset '%s'" % encoding
|
||||
@@ -257,12 +263,12 @@ def decodePage(page, contentEncoding, contentType):
|
||||
if not page or (conf.nullConnection and len(page) < 2):
|
||||
return getUnicode(page)
|
||||
|
||||
if isinstance(contentEncoding, basestring) and contentEncoding:
|
||||
if hasattr(contentEncoding, "lower"):
|
||||
contentEncoding = contentEncoding.lower()
|
||||
else:
|
||||
contentEncoding = ""
|
||||
|
||||
if isinstance(contentType, basestring) and contentType:
|
||||
if hasattr(contentType, "lower"):
|
||||
contentType = contentType.lower()
|
||||
else:
|
||||
contentType = ""
|
||||
@@ -273,18 +279,18 @@ def decodePage(page, contentEncoding, contentType):
|
||||
|
||||
try:
|
||||
if contentEncoding == "deflate":
|
||||
data = StringIO.StringIO(zlib.decompress(page, -15)) # Reference: http://stackoverflow.com/questions/1089662/python-inflate-and-deflate-implementations
|
||||
data = io.BytesIO(zlib.decompress(page, -15)) # Reference: http://stackoverflow.com/questions/1089662/python-inflate-and-deflate-implementations
|
||||
else:
|
||||
data = gzip.GzipFile("", "rb", 9, StringIO.StringIO(page))
|
||||
data = gzip.GzipFile("", "rb", 9, io.BytesIO(page))
|
||||
size = struct.unpack("<l", page[-4:])[0] # Reference: http://pydoc.org/get.cgi/usr/local/lib/python2.5/gzip.py
|
||||
if size > MAX_CONNECTION_TOTAL_SIZE:
|
||||
raise Exception("size too large")
|
||||
|
||||
page = data.read()
|
||||
except Exception, msg:
|
||||
except Exception as ex:
|
||||
if "<html" not in page: # in some cases, invalid "Content-Encoding" appears for plain HTML (should be ignored)
|
||||
errMsg = "detected invalid data for declared content "
|
||||
errMsg += "encoding '%s' ('%s')" % (contentEncoding, msg)
|
||||
errMsg += "encoding '%s' ('%s')" % (contentEncoding, getSafeExString(ex))
|
||||
singleTimeLogMessage(errMsg, logging.ERROR)
|
||||
|
||||
warnMsg = "turning off page compression"
|
||||
@@ -312,44 +318,41 @@ def decodePage(page, contentEncoding, contentType):
|
||||
kb.pageEncoding = conf.encoding
|
||||
|
||||
# can't do for all responses because we need to support binary files too
|
||||
if not isinstance(page, unicode) and "text/" in contentType:
|
||||
if kb.heuristicMode:
|
||||
kb.pageEncoding = kb.pageEncoding or checkCharEncoding(getHeuristicCharEncoding(page))
|
||||
page = getUnicode(page, kb.pageEncoding)
|
||||
else:
|
||||
# e.g. Ãëàâà
|
||||
if "&#" in page:
|
||||
page = re.sub(r"&#(\d{1,3});", lambda _: chr(int(_.group(1))) if int(_.group(1)) < 256 else _.group(0), page)
|
||||
if isinstance(page, six.binary_type) and "text/" in contentType:
|
||||
# e.g. 	Ãëàâà
|
||||
if b"&#" in 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 _: chr(int(_.group(1))) if int(_.group(1)) < 256 else _.group(0), page)
|
||||
|
||||
# e.g. %20%28%29
|
||||
if "%" in page:
|
||||
page = re.sub(r"%([0-9a-fA-F]{2})", lambda _: _.group(1).decode("hex"), page)
|
||||
# e.g. %20%28%29
|
||||
if b"%" in page:
|
||||
page = re.sub(b"%([0-9a-fA-F]{2})", lambda _: decodeHex(_.group(1)), page)
|
||||
|
||||
# e.g. &
|
||||
page = re.sub(r"&([^;]+);", lambda _: chr(htmlEntities[_.group(1)]) if htmlEntities.get(_.group(1), 256) < 256 else _.group(0), page)
|
||||
# e.g. &
|
||||
page = re.sub(b"&([^;]+);", lambda _: chr(htmlEntities[_.group(1)]) if htmlEntities.get(_.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":
|
||||
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)
|
||||
page = page[3:]
|
||||
if (kb.pageEncoding or "").lower() == "utf-8-sig":
|
||||
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)
|
||||
page = page[3:]
|
||||
|
||||
page = getUnicode(page, kb.pageEncoding)
|
||||
page = getUnicode(page, kb.pageEncoding)
|
||||
|
||||
# e.g. ’…™
|
||||
if "&#" in page:
|
||||
def _(match):
|
||||
retVal = match.group(0)
|
||||
try:
|
||||
retVal = unichr(int(match.group(1)))
|
||||
except ValueError:
|
||||
pass
|
||||
return retVal
|
||||
page = re.sub(r"&#(\d+);", _, page)
|
||||
# e.g. ’…™
|
||||
if "&#" in page:
|
||||
def _(match):
|
||||
retVal = match.group(0)
|
||||
try:
|
||||
retVal = unichr(int(match.group(1)))
|
||||
except (ValueError, OverflowError):
|
||||
pass
|
||||
return retVal
|
||||
page = re.sub(r"&#(\d+);", _, page)
|
||||
|
||||
# e.g. ζ
|
||||
page = re.sub(r"&([^;]+);", lambda _: unichr(htmlEntities[_.group(1)]) if htmlEntities.get(_.group(1), 0) > 255 else _.group(0), page)
|
||||
# e.g. ζ
|
||||
page = re.sub(r"&([^;]+);", lambda _: unichr(htmlEntities[_.group(1)]) if htmlEntities.get(_.group(1), 0) > 255 else _.group(0), page)
|
||||
|
||||
return page
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user