Статьи

SQL-инъекция в приложении Java

В этом посте мы обсудим, что такое SQL-инъекция . и как это может повлиять на любое веб-приложение, использующее внутреннюю базу данных. Здесь я сосредоточен на веб-приложении Java. В Open Project Security Project Project (OWAP) указано, что SQL-инъекция является главной уязвимостью для веб-приложений. Хакер Внедряет код SQL в веб-запросе в веб-приложение и получает контроль над внутренней базой данных, даже если эта внутренняя база данных не подключена напрямую к Интернету. И мы увидим, как решить и предотвратить SQL-инъекцию в Java-приложении.

Для этого нам понадобится 1 инструмент. эти инструменты полностью с открытым исходным кодом. Карта SQL — SqlMap — это инструмент для тестирования на проникновение с открытым исходным кодом, который автоматизирует процесс обнаружения и использования SQL-инъекций. мы можем получить это отсюда .

SQLInjection

SQL-инъекция — это метод извлечения информации из базы данных через веб-приложение.
Сценарий:

У нас есть один сервер базы данных [MySQL] и сервер веб-приложений [Tomcat]. Учтите, что сервер базы данных не подключен к Интернету. но это связано с сервером приложений. Теперь мы увидим с помощью веб-приложения, как извлечь информацию с помощью метода sql-инъекций.

Прежде чем увидеть sql-инъекцию, мы создаем небольшое веб-приложение. Он содержит одну страницу JSP, как это

1
2
3
4
5
6
7
<form action='userCheck'>
 
<input type='text' name='user' value=''/>
 
<input type='submit' value='Submit'/>
 
</form>

В userCheck Servlet получает поле ввода пользователя и подключается к серверу базы данных и запускает SQL-запрос на основе ввода пользователя, получает ResultSet и повторяет его печать на веб-странице.
userCheck сервлет

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
protected void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        response.setContentType('text/html;charset=UTF-8');
        PrintWriter out = response.getWriter();
        try {
 
            String user = request.getParameter('user');
            Connection conn = null;
            String url = 'jdbc:mysql://192.168.2.128:3306/';
            String dbName = 'anvayaV2';
            String driver = 'com.mysql.jdbc.Driver';
            String userName = 'root';
            String password = '';
            try {
                Class.forName(driver).newInstance();
                conn = DriverManager.getConnection(url + dbName, userName, password);
 
                Statement st = conn.createStatement();
                String query = 'SELECT * FROM  User where userId='' + user + ''';
                out.println('Query : ' + query);
                System.out.printf(query);
                ResultSet res = st.executeQuery(query);
 
                out.println('Results');
                while (res.next()) {
                    String s = res.getString('username');
                    out.println('\t\t' + s);
                }
                conn.close();
 
            } catch (Exception e) {
                e.printStackTrace();
            }
        } finally {
            out.close();
        }

Когда мы выполняем приведенный выше код. В обычном исполнении ввода выглядит следующим образом

Когда мы даем нормальное значение, такое как «ramki», затем нажимаем кнопку «Отправить»

Это совершенно правильно в нормальном поведении. Что происходит, когда я помещаю какой-то специальный символ или SQL-оператор в поле ввода, как это

когда мы нажимаем кнопку отправки, то все строки в моей таблице отображаются следующим образом

Это большое нарушение безопасности в моем приложении. что случилось … это один вид инъекций sql.

Посмотрим, что случилось.

Когда я вписываю нормальное значение в поле ввода, мой сервлет получает и подставляет в запрос sql и выполняет его.

1
SELECT * FROM User where userId='ramki'

это правильно, и мы получили правильный вывод.

Что происходит, когда я ставлю sdfssd ‘или’ 1 ‘=’ 1

SELECT * FROM Пользователь, где userId = ‘ sdfssd’ или ‘1’ = ‘1

это значит

1
SELECT * FROM User where userId ='sdfssd' or '1'='1'

как это. Таким образом, наш запрос изменен. теперь новый запрос имеет 2 условия. 2-е условие всегда верно. 1-е условие может быть или не быть правдой. но эти 2 условия связаны с логикой. Так что условие where всегда верно для всех строк. В результате они приносят все строки из наших таблиц.

Это называется слепой инъекцией sql. Если вы хотите больше подробностей о внедрении SQL, проверьте здесь

Теперь мы можем ввести оператор SQL прямо в поле ввода

лайк

ramki ‘UNION SELECT * FROM mysql.user` u —

затем

SELECT * FROM Пользователь, где userId = ‘ ramki’ UNION SELECT * FROM mysql.user` u —

тогда его средства

1
SELECT * FROM User where userId ='ramki' UNION SELECT * FROM mysql.`user` u --'

Здесь они не будут использовать *, потому что они не соответствуют первой таблице. Таким образом, они находят, сколько столбцов затем используют Union со второй таблицей. В результате информация пользователя базы данных get mysql раскрывается через наше веб-приложение.

sqlmap

Он поставляется с мощным механизмом обнаружения, множеством нишевых функций для окончательного тестера на проникновение и широким диапазоном переключателей, начиная от дактилоскопии базы данных и заканчивая извлечением данных из базы данных.

Установите sqlmap в вашей системе или используйте BackTrack Linux

Здесь я использовал backtrack linux, потому что уже предустановлено множество приложений, таких как sqlmap.

В обратном направлении, sqlmap находится в / pentest / web / scanner / sqlmap

команды sqlmap

восстановить все базы данных

1
./sqlmap.py -u http://localhost:8080/SQLInject/userCheck?user=ramki --dbs

восстановить все таблицы

1
./sqlmap.py -u http://localhost:8080/SQLInject/userCheck?user=ramki -D test --tables

получить все столбцы из определенной таблицы

1
./sqlmap.py -u http://localhost:8080/SQLInject/userCheck?user=ramki -D test -T User --columns

Сбросить все значения столбца из определенной таблицы

1
./sqlmap.py -u http://localhost:8080/SQLInject/userCheck?user=ramki -D test -T User --dump

Дамп некоторого столбца, оцененного из определенной таблицы

1
./sqlmap.py -u http://localhost:8080/SQLInject/userCheck?user=ramki -D test -T User -C userId,password --dump

Смотрите видео для полной демонстрации (смотрите в HD):

http://www.youtube.com/watch?feature=player_embedded&v=C5PQ86nWMkM

Как предотвратить SQL-инъекцию

  • Прежде чем подставить в запрос, нам нужно сделать проверку. для удаления я избежал специальных символов, таких как одинарные кавычки, ключевые слова, такие как select, Union …
  • Использовать подготовленное заявление с заполнителем
1
2
PreparedStatement  preparedStatement=conn.prepareStatement('SELECT * FROM  usercheck where username=?') ;
preparedStatement.setString(1, user);

что метод setXXX () выполняет всю проверку и экранирование специального символа

Теперь, если использовать такой же слепой инъекции sql, как

sdfssd ‘или’ 1 ‘=’ 1 тогда

1
SELECT * FROM User where userId='sdfssd\' or \'1\'=\'1'

Здесь экранируются все специальные символы. Когда мы используем JPA-инструменты ORM, такие как Hibernate, EclipseLink, TopLink, то время также может стать возможным.

Чтобы предотвратить внедрение SQL, нам нужно использовать NamedQuery вместо обычного Query. Потому что NamedQuery внутренне использовал PreparedStement, но обычный запрос использовал Norma Stement в Java.

Нормальный запрос в JPA

1
2
3
String q='SELECT r FROM  User r where r.userId=''+user+''';
Query query=em.createQuery(q);
List users=query.getResultList();

Так что не используйте обычный запрос, используйте именованный запрос как этот

1
2
3
Query query=em.createNamedQuery('User.findByUserId');
query.setParameter('userId', user);
List users=query.getResultList();

Вы можете скачать демо-код с GitHub (или) Google code

Ссылка: Остерегайтесь SQLInjection в Java-приложении от нашего партнера по JCG Рамы Кришнана в блоге