19 смертных грехов, угрожающих безопасности программ. Майкл ХовардЧитать онлайн книгу.
= $HTTP_GET_VARS["id"];
$qry = "SELECT ccnum FROM cust WHERE id = %$id%";
$result = mysql_query($qry,$db);
if ($result) {
echo mysql_result($result,0,"ccnum");
} else {
echo "No result! " . mysql_error();
}
?>
Греховность Perl/CGI
И снова тот же дефект, но на этот раз в программе на достопочтенном Perl:
#!/usr/bin/perl
use DBI;
use CGI;
print CGI::header();
$cgi = new CGI;
$id = $cgi->param('id');
$dbh = DBI->connect('DBI:mysql:Shipping:localhost',
'root',
'$3cre+')
or print "Ошибка connect : $DBI::errstr";
$sql = "SELECT ccnum FROM cust WHERE id = " . $id;
$sth = $dbh->prepare($sql)
or print "Ошибка prepare : $DBI::errstr";
$sth->execute()
or print "Ошибка execute : $DBI::errstr";
# Вывести данные
while (@row = $sth->fetchrow_array ) {
print "@row<br>";
}
$dbh->disconnect;
print "</body></html>";
exit;
Греховность Java
Еще один распространенный язык, Java. Подвержен внедрению SQL по той же схеме.
import java.*;
import java.sql.*;
...
public static boolean doQuery(String Id) {
Connection con = null;
try
{
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
con = DriverManager.getConnection("jdbc:microsoft:sqlserver: " +
"//localhost:1433", "sa", "$3cre+");
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("SELECT ccnum FROM cust WHERE id=" +
Id);
while (rx.next()) {
// Полюбоваться на результаты запроса
}
rs.close();
st.close();
}
catch (SQLException e)
{
// Ой!
return false;
}
catch (ClassNotFoundException e)
{
// Не найден класс
return false;
}
finally
{
try
{
con.close();
} catch(SQLException e) {}
}
return true;
}
Греховность SQL
Подобный код встречается не так часто, но автор пару раз наталкивался на него в промышленных системах. Показанная ниже хранимая процедура просто принимает строку в качестве параметра и исполняет ее!
CREATE PROCEDURE dbo.doQuery(@query nchar(128))
AS
exec(@query)
RETURN
А вот следующий код распространен куда шире и не менее опасен:
CREATE PROCEDURE dbo.doQuery(@id nchar(128))
AS
DECLARE @query nchar(256)
SELECT @query = 'select ccnum from cust where id = ''' + @id + ''''
EXEC @query
RETURN
Здесь опасная конкатенация строк выполняется внутри процедуры. То есть вы по–прежнему совершаете постыдный грех, даже если процедура вызвана из корректного кода на языке высокого уровня.
Стоит поискать и другие операторы конкатенации, имеющиеся в SQL, а именно «+» и «||», а также функции CONCAT() и CONCATENATE().
Во всех этих примерах противник контролирует переменную Id. Важно всегда представлять себе, что именно контролирует атакующий, это поможет понять, есть реальная ошибка или нет. В данном случае противник может задать любое значение переменной Id, участвующей в запросе, и тем самым управлять видом строки запроса. Последствия могут оказаться катастрофическими.
Классическая атака состоит в том, чтобы видоизменить SQL–запрос, добавив лишние части и закомментарив «ненужные». Например, если противник контролирует переменную Id, то может задать в качестве ее значения строку 1 or 2>1 – – , тогда запрос примет такой вид:
SELECT ccnum FROM cust WHERE id=1 or 2>1 – –
Условие