CVE-2022-4454 (published 2022-12-13T18:15Z)

A vulnerability, which was classified as critical, has been found in m0ver bible-online. Affected by this issue is the function query of the file src/main/java/custom/application/search.java of the component Search Handler. The manipulation leads to sql injection. The name of the patch is 6ef0aabfb2d4ccd53fcaa9707781303af357410e. It is recommended to apply a patch to fix this issue. The identifier of this vulnerability is VDB-215444.

CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-89
cwe_name: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/m0ver/bible-online
commit_details: repo_url: https://github.com/m0ver/bible-online
author: James ZHOU
author_date: 2022-10-02 14:51:52+08:00
msg: Fixed the SQL Injection issue.
repository: repo_url: https://github.com/m0ver/bible-online
repo_name: m0ver/bible-online
description: Open the source code of ingod.today project which is based on tinystruct2.0
repo_language: Java
owner: m0ver
file_changes: filename: search.java
change_type: ModificationType.MODIFY
diff: @@ -194,32 +194,24 @@ public class search extends AbstractApplication {
             return this;
         }
 
-        StringBuffer condition = new StringBuffer();
+        StringBuilder condition = new StringBuilder();
         int i = 0, j, k = 0;
-        String _keyword;
+        String[] _keywords = new String[keywords.length];
         while (i < keywords.length) {
-            _keyword = keywords[i];
-            if (_keyword.trim().length() > 0) {
-                if (condition.length() == 0) {
-                    condition.append(" bible.content like '%" + _keyword + "%' ");
-                } else {
-                    condition.append(" AND bible.content like '%" + _keyword + "%' ");
-                    /*
-                     * if(true)
-                     * condition.append(" AND bible.content like '%"+keywords[i]+"%' ");
-                     * else
-                     * condition.append(" OR bible.content like '%"+keywords[i]+"%' ");
-                     */
-                }
+            _keywords[i] = "%" + keywords[i] + "%";
+            if (condition.length() == 0) {
+                condition.append(" bible.content like ? ");
+            } else {
+                condition.append(" AND bible.content like ? ");
             }
             i++;
         }
 
         Locale locale = this.getLocale();
         if (condition.length() == 0)
-            condition.append(" book.language='" + locale + "' ");
+            condition.append(" book.language='").append(locale).append("' ");
         else
-            condition.append(" AND book.language='" + locale + "' ");
+            condition.append(" AND book.language='").append(locale).append("' ");
 
         book book = new book();
         bible bible = new bible();
@@ -240,7 +232,7 @@ public class search extends AbstractApplication {
                 + " as bible left join " + book.getTableName()
                 + " as book on bible.book_id=book.book_id where " + condition;
 
-        Table vtable = bible.find(SQL, new Object[]{});
+        Table vtable = bible.find(SQL, _keywords);
         boolean noResult = vtable.size() > 0;
 
         if (!noResult && query.length() > 0) {
@@ -266,7 +258,7 @@ public class search extends AbstractApplication {
             }
         }
 
-        Row found = bible.findOne(look, new Object[]{});
+        Row found = bible.findOne(look, _keywords);
 
         long startTime = System.currentTimeMillis();
         Pager pager = new Pager();
@@ -277,7 +269,7 @@ public class search extends AbstractApplication {
         Field field;
         int next = pager.getStartIndex();// 此位置即为当前页的第一条记录的ID
 
-        html.append("<ol class=\"searchresults\" start=\"" + next + "\">\r\n");
+        html.append("<ol class=\"searchresults\" start=\"").append(next).append("\">\r\n");
 
         String finded, word;
         Row row;
@@ -349,7 +341,7 @@ public class search extends AbstractApplication {
         html.append("<div class=\"pagination\" style=\"cursor:default\">"
                 + pager.getPageControlBar(actionURL) + "</div>\r\n");
         html.append("<!-- "
-                + String.valueOf(System.currentTimeMillis() - startTime) + " -->");
+                + (System.currentTimeMillis() - startTime) + " -->");
 
         int start = page - 1 == 0 ? 1 : (page - 1) * pageSize + 1, end = page
                 * pageSize;
@@ -381,7 +373,7 @@ public class search extends AbstractApplication {
     }
 
     public String feed(String query) throws ApplicationException {
-        StringBuffer xml = new StringBuffer();
+        StringBuilder xml = new StringBuilder();
         String finded = "";
         String[] keywords;
         boolean noResult = true;

programming_language: Java