Prechádzať zdrojové kódy

FileContentProvider: prevent injection in sortOrder argument for query()

For this, allow strictly only valid grammar and column names

Signed-off-by: Álvaro Brey Vilas <alvaro.brey@nextcloud.com>
Álvaro Brey Vilas 3 rokov pred
rodič
commit
6aae8feeac

+ 25 - 4
src/androidTest/java/com/owncloud/android/providers/FileContentProviderIT.kt → src/androidTest/java/com/owncloud/android/providers/FileContentProviderVerificationIT.kt

@@ -28,7 +28,7 @@ import com.owncloud.android.utils.MimeTypeUtil
 import org.junit.Test
 
 @Suppress("FunctionNaming")
-class FileContentProviderIT {
+class FileContentProviderVerificationIT {
 
     companion object {
         private const val INVALID_COLUMN = "Invalid column"
@@ -58,15 +58,36 @@ class FileContentProviderIT {
     }
 
     @Test(expected = IllegalArgumentException::class)
-    fun verifyColumn_ContentValues_Exception() {
-        // with valid columns
+    fun verifyColumn_ContentValues_invalidColumn() {
+        // with invalid columns
         val contentValues = ContentValues()
         contentValues.put(INVALID_COLUMN, FILE_LENGTH)
         contentValues.put(ProviderMeta.ProviderTableMeta.FILE_CONTENT_TYPE, MimeTypeUtil.MIMETYPE_TEXT_MARKDOWN)
         FileContentProvider.VerificationUtils.verifyColumns(contentValues)
+    }
+
+    @Test
+    fun verifySortOrder_OK() {
+        // null
+        FileContentProvider.VerificationUtils.verifySortOrder(null)
 
         // empty
-        FileContentProvider.VerificationUtils.verifyColumns(ContentValues())
+        FileContentProvider.VerificationUtils.verifySortOrder("")
+
+        // valid sort
+        FileContentProvider.VerificationUtils.verifySortOrder(ProviderMeta.ProviderTableMeta.FILE_DEFAULT_SORT_ORDER)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun verifySortOrder_InvalidColumn() {
+        // with invalid column
+        FileContentProvider.VerificationUtils.verifySortOrder("$INVALID_COLUMN desc")
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun verifySortOrder_InvalidGrammar() {
+        // with invalid grammar
+        FileContentProvider.VerificationUtils.verifySortOrder("${ProviderMeta.ProviderTableMeta._ID} ;--foo")
     }
 
     // @Test

+ 24 - 1
src/main/java/com/owncloud/android/providers/FileContentProvider.java

@@ -33,10 +33,12 @@ import android.content.Context;
 import android.content.OperationApplicationException;
 import android.content.UriMatcher;
 import android.database.Cursor;
+import android.database.DatabaseUtils;
 import android.database.SQLException;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQuery;
 import android.database.sqlite.SQLiteQueryBuilder;
 import android.net.Uri;
 import android.os.Binder;
@@ -590,6 +592,9 @@ public class FileContentProvider extends ContentProvider {
                     break;
             }
         } else {
+            if (uriMatch == ROOT_DIRECTORY || uriMatch == SINGLE_FILE || uriMatch == DIRECTORY) {
+                VerificationUtils.verifySortOrder(sortOrder);
+            }
             order = sortOrder;
         }
 
@@ -1056,7 +1061,7 @@ public class FileContentProvider extends ContentProvider {
     static class VerificationUtils {
         @VisibleForTesting
         public static void verifyColumns(@Nullable ContentValues contentValues) {
-            if (contentValues == null) {
+            if (contentValues == null || contentValues.keySet().size() == 0) {
                 return;
             }
 
@@ -1100,6 +1105,24 @@ public class FileContentProvider extends ContentProvider {
             args[0] = uri.getPathSegments().get(1);
             return args;
         }
+
+        public static void verifySortOrder(@Nullable String sortOrder) {
+            if (TextUtils.isEmpty(sortOrder)) {
+                return;
+            }
+            for (String segment : sortOrder.split(" +")) {
+                switch (segment.toLowerCase(Locale.ROOT)) {
+                    case "asc":
+                    case "desc":
+                    case "collate":
+                    case "nocase":
+                        break;
+                    default:
+                        verifyColumnName(segment);
+                }
+            }
+
+        }
     }
 
     class DataBaseHelper extends SQLiteOpenHelper {