Adding extra lesson for order by clauses
This commit is contained in:
@ -27,6 +27,84 @@
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content12.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content12a.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_order_by.adoc"></div>
|
||||
<script th:src="@{/lesson_js/assignment12.js}" language="JavaScript"></script>
|
||||
<div class="attack-container">
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="POST" name="form"
|
||||
action="/WebGoat/SqlInjection/attack12a"
|
||||
enctype="application/json;charset=UTF-8">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3>List of servers
|
||||
<div class="pull-right">
|
||||
<button id="btn-admin" class="btn btn-default"><span
|
||||
class="glyphicon glyphicon-pencil"></span> Edit
|
||||
</button>
|
||||
</div>
|
||||
</h3>
|
||||
</div>
|
||||
<div id="toolbar-admin" class="panel-body">
|
||||
<div class="btn-toolbar" role="toolbar" aria-label="admin">
|
||||
<div class="btn-group pull-right" role="group">
|
||||
<button id="btn-online" type="button" class="btn btn-success">Online</button>
|
||||
<button id="btn-offline" type="button" class="btn btn-warning">Offline</button>
|
||||
<button id="btn-out-of-order" type="button" class="btn btn-danger">Out Of Order
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-check"></th>
|
||||
<th></th>
|
||||
<th>Hostname <span onclick="getServers('hostname')"><i
|
||||
class="fa fa-fw fa-sort"></i></span>
|
||||
</th>
|
||||
<th>IP <span onclick="getServers('ip')"><i class="fa fa-fw fa-sort"></i></span></th>
|
||||
<th>MAC <span onclick="getServers('mac')"><i class="fa fa-fw fa-sort"></i></span></th>
|
||||
<th>Status <span onclick="getServers('status')"><i class="fa fa-fw fa-sort"></i></span>
|
||||
</th>
|
||||
<th>Description <span onclick="getServers('description')"><i
|
||||
class="fa fa-fw fa-sort"></i></span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="servers">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
</form>
|
||||
<form class="attack-form" method="POST" name="form" action="SqlInjection/attack12a">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">IP address webgoat-prd server:</div>
|
||||
<input type="text" class="form-control" id="ip" name="ip"
|
||||
placeholder="192.1.0.12"/>
|
||||
</div>
|
||||
<div class="input-group" style="margin-top: 10px">
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:SqlInjection_content13.adoc"></div>
|
||||
</div>
|
||||
|
@ -9,6 +9,10 @@ SqlStringInjectionHint4=Try entering [ smith' OR '1' = '1 ].
|
||||
SqlStringInjectionHint5=First try to find out the number of columns by adding a group by 1,2,3 etc to the query.
|
||||
SqlStringInjectionHint6=Try adding a union to the query, the number of columns should match.
|
||||
SqlStringInjectionHint7=Try entering [ Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data -- ].
|
||||
SqlStringInjectionHint8=Try sorting and look at the request
|
||||
SqlStringInjectionHint9=Intercept the request and try to specify a different order by
|
||||
SqlStringInjectionHint10=Use for example "(case when (true) then hostname else id end)" in the order by and see what happens
|
||||
SqlStringInjectionHint11=Use for example "(case when (true) then hostname else id end)" in the order by and see what happens
|
||||
|
||||
sql-injection.5a.success=You have succeed: {0}
|
||||
sql-injection.5a.no.results=No results matched. Try Again.
|
||||
|
@ -0,0 +1,61 @@
|
||||
$(function () {
|
||||
$('.col-check').hide();
|
||||
$('#btn-admin').on('click', function () {
|
||||
if ($("#toolbar-admin").is(":visible")) {
|
||||
$("#toolbar-admin").hide();
|
||||
$(".col-check").hide();
|
||||
}
|
||||
else {
|
||||
$("#toolbar-admin").show();
|
||||
$(".col-check").show();
|
||||
}
|
||||
});
|
||||
|
||||
$('#btn-online').on('click', function () {
|
||||
$('table tr').filter(':has(:checkbox:checked)').find('td').parent().removeClass().addClass('success');
|
||||
$('table tr').filter(':has(:checkbox:checked)').find('td.status').text('online');
|
||||
});
|
||||
$('#btn-offline').on('click', function () {
|
||||
$('table tr').filter(':has(:checkbox:checked)').find('td').parent().removeClass().addClass('warning');
|
||||
$('table tr').filter(':has(:checkbox:checked)').find('td.status').text('offline');
|
||||
});
|
||||
$('#btn-out-of-order').on('click', function () {
|
||||
$('table tr').filter(':has(:checkbox:checked)').find('td').parent().removeClass().addClass('danger');
|
||||
$('table tr').filter(':has(:checkbox:checked)').find('td.status').text('out of order');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$(document).ready(function () {
|
||||
getServers('id');
|
||||
});
|
||||
|
||||
var html = '<tr class="STATUS">' +
|
||||
'<td class="col-check"><input type="checkbox" class="form-check-input"/></td>' +
|
||||
'<td>HOSTNAME</td>' +
|
||||
'<td>IP</td>' +
|
||||
'<td>MAC</td>' +
|
||||
'<td class="status">ONLINE</td>' +
|
||||
'<td>DESCRIPTION</td>' +
|
||||
'</tr>';
|
||||
|
||||
function getServers(column) {
|
||||
$.get("SqlInjection/servers?column=" + column, function (result, status) {
|
||||
$("#servers").empty();
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var server = html.replace('ID', result[i].id);
|
||||
var status = "success";
|
||||
if (result[i].status === 'offline') {
|
||||
status = "danger";
|
||||
}
|
||||
server = server.replace('ONLINE', status);
|
||||
server = server.replace('STATUS', status);
|
||||
server = server.replace('HOSTNAME', result[i].hostname);
|
||||
server = server.replace('IP', result[i].ip);
|
||||
server = server.replace('MAC', result[i].mac);
|
||||
server = server.replace('DESCRIPTION', result[i].description);
|
||||
$("#servers").append(server);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
== Order by clause
|
||||
|
||||
Question: Does a preparared statement always prevent against an SQL injection?
|
||||
Answer: No it does not
|
||||
|
||||
Let's take a look at the following statement:
|
||||
|
||||
----
|
||||
select * from users order by lastname;
|
||||
----
|
||||
|
||||
If we look at the specification of the SQL grammar the definition is as follows:
|
||||
|
||||
----
|
||||
SELECT ...
|
||||
FROM tableList
|
||||
[WHERE Expression]
|
||||
[ORDER BY orderExpression [, ...]]
|
||||
|
||||
orderExpression:
|
||||
{ columnNr | columnAlias | selectExpression }
|
||||
[ASC | DESC]
|
||||
|
||||
selectExpression:
|
||||
{ Expression | COUNT(*) | {
|
||||
COUNT | MIN | MAX | SUM | AVG | SOME | EVERY |
|
||||
VAR_POP | VAR_SAMP | STDDEV_POP | STDDEV_SAMP
|
||||
} ([ALL | DISTINCT][2]] Expression) } [[AS] label]
|
||||
|
||||
Based on HSQLDB
|
||||
----
|
||||
|
||||
This means an `orderExpression` van be a `selectExpression` which can be a function as well, so for example with
|
||||
a `case` statement we might be able to ask the database some questions, like:
|
||||
|
||||
----
|
||||
select * from users order by
|
||||
(select case when (true) then lastname else firstname)
|
||||
----
|
||||
|
||||
So we can substitute any kind of boolean operation in the `when(....)` part. The statement will just work because
|
||||
it is a valid query whether you use a prepared statement or not an order by clause can by definition contain a
|
||||
expression.
|
||||
|
||||
=== Mitigation
|
||||
|
||||
If you need to provide a sorting column in your web application you should implement a whitelist to validate the value
|
||||
of the `order by` statement it should always be limited to something like 'firstname' or 'lastname'.
|
@ -1,11 +1,11 @@
|
||||
=== Blind SQL Injection
|
||||
== Blind SQL Injection
|
||||
|
||||
Blind SQL injection is a type of SQL injection attack that asks the database true or false
|
||||
questions and determines the answer based on the applications response. This attack is often used when the web
|
||||
application is configured to show generic error messages, but has not mitigated the code that is vulnerable to SQL
|
||||
injection.
|
||||
|
||||
==== Difference
|
||||
=== Difference
|
||||
|
||||
Let's first start with the difference between a normal SQL injection and a blind SQL injection. In a normal
|
||||
SQL injection the error messages from the database are displayed and gives enough information to find out how
|
||||
@ -16,7 +16,7 @@ based on a true or false statement. That's why a blind SQL injection is much mor
|
||||
There are several different types of blind SQL injections: content based and time based SQL injections.
|
||||
|
||||
|
||||
==== Example
|
||||
=== Example
|
||||
|
||||
In this case we are trying to ask the database a boolean question based on for example a unique id, for example
|
||||
suppose we have the following url: `https://my-shop.com?article=4`
|
||||
|
@ -0,0 +1,4 @@
|
||||
In this assignment try to perform an SQL injection through the ORDER BY field.
|
||||
Try to find the ip address of the `webgoat-prd` server.
|
||||
|
||||
Note: The submit field of this assignment is *NOT* vulnerable for an SQL injection.
|
Reference in New Issue
Block a user