English 中文(简体)
• 保护注射器免受注射吗?
原标题:Protects dplyr against SQL injections?

I would like to use R-Shiny to develop a web app that accesses an SQL database with sensitive data. So far I have written the database query as a pure SQL string. However, this approach is very susceptible to SQL injections. My intention is therefore to write the database query with dplyr, as the query is written in R and not in pure SQL. Unfortunately, I have not yet been able to find any more detailed information or an estimate on this topic online. Therefore I would like to clarify my request in this question.
So far I have only read a statement about the dbplyr::translate_sql() function that is supposed to protect SQL injections: https://dbplyr.tidyverse.org/articles/sql-translation.html#vectors
As my data is very confidential, dbplyr / dplyr should provide 100% protection against SQL injections.
I would be very pleased to receive further information and assessments on this topic.

UPDATE
As suggested in the comments, I have added an example for reproducibility: (adapted from: https://shiny.posit.co/r/articles/build/pool-dplyr/)

library(shiny)
library(DBI)
library(pool)
library(tidyverse)
library(dbplyr)

pool <- dbPool(
  drv = RMySQL::MySQL(),
  dbname = "shinydemo",
  host = "shiny-demo.csa7qlmguqrf.us-east-1.rds.amazonaws.com",
  username = "guest",
  password = "guest")

ui <- fluidPage(
  textInput("ID", "Enter your ID:", "5"),
  tableOutput("tbl"),
  numericInput("nrows", "How many cities to show?", 10),
  plotOutput("popPlot"))

server <- function(input, output, session) {
  output$tbl <- renderTable({
    pool %>% tbl("City") %>%
      filter(ID == !!input$ID)
  })
  output$popPlot <- renderPlot({
    df <- pool %>% tbl("City") %>%
      head(as.integer(input$nrows)[1]) %>% collect()
    pop <- df$Population
    names(pop) <- df$Name
    barplot(pop)
  })
}

shinyApp(ui, server)
问题回答

投射威胁取决于how,用户提供的文本已纳入动态的QQ。 因此,如果你试图防止注射,那么在查询数据库时,你需要评估用户投入的每一种方式。

In the example you have posted there are two pieces of user input:

  1. input$nrows which is limited to numeric by the input widget
  2. input$ID which is free text, and hence has greater risk of SQL injection.

您可以采用以下任何方法调查用户的投入。 总的来说,我选择的办法是宣传,然后审查。

回答的重点是你利用yr子从R-QL转换的情况。 如果使用其他方法进入数据库(例如书目表包),则需要采取不同的做法。


Option 1) Review the SQL query that is generated

考虑在什么地方使用<代码>Input$ID。

pool %>%
  tbl("City") %>%
  filter(ID == !!input$ID)

为了执行这一规定,dbplyr将发射机从R.K.转变为L.。 我们可以使用<代码>show_query/code>的指令来审查这一翻译。

pool %>%
  tbl("City") %>%
  filter(ID == !!input$ID) %>%
  show_query()

This will probably produce an SQL query similar to the following:

SELECT *
FROM city
WHERE ID ==  my_id_value 

你们不需要全方位 用于检测这一卡片的注射。 你们可以简单地改变这种态度,看一看发生什么。 例如,尝试一个简单的替代问题:

attempt_inject =  my_id_value;SELECT 123 
pool %>%
  tbl("City") %>%
  filter(ID == !!attempt_inject) %>%
  show_query()

I suspect this will produce SQL similar to the following:

SELECT *
FROM city
WHERE ID ==  my_id_value;SELECT 123 

这对卡片注入来说似乎是一种有效的预防。 但是,你们需要彻底测试,以确保你们有信心。


Option 2) Review source code

dbplyr包是公开来源,可在网上查阅。 您可以审查源代码,确认在翻译过程中如何处理投入。

我怀疑的是,除非投入类型sql,否则这些投入将作为案文或标语逃脱。

有一个<代码>sql()功能,将输入转换为<代码>sql。 其中一个用途是将电压器不翻译该功能的内容,而是将其用作消耗。 这意味着,如果贵国用户能够将R物体作为投入提交,那么这是一个重大的脆弱性领域。 然而,由于你的评估限制用户提交文字和数字投入,这种情况不太可能发生。


Option 3) Sanitise your inputs before passing them to dbplyr

R与纯粹的QL相比具有若干优势,因为你可以利用R验证用户的投入,然后将这种投入纳入yr门。

考虑这一替代案文,以替代您的<代码>output$tbl。 附录

output$tbl <- renderTable({
  current_ID = as.character(input$ID)
  acceptable_ids = pool %>%
    tbl("City") %>%
    select(ID) %>%
    distinct() %>%
    collect() %>%
    pull()
  req(current_ID %in% acceptable_ids)

  pool %>%
    tbl("City") %>%
    filter(ID == !!current_ID)
})

这种办法规定,用户投入转换为类型,在通过用户投入到灭.器之前,是国际发展法栏中发现的价值。

确切的检查选择将取决于用户投入的使用情况。 我常常包括一项检查,即用户投入不包含特殊特性(例如<代码>;{}[]*或空间)。

dbplyr includes commands to delimit certain inputs. Investigate and use these commands where applicable.

  • req is a Shiny command that stops execution of a component if the condition is not met. You can use stopifnot outside a Shiny context.
  • Fetching the list of acceptable ids within the renderTable statement is not efficient app design. This should be calculated once and reused multiple times.




相关问题
SQL SubQuery getting particular column

I noticed that there were some threads with similar questions, and I did look through them but did not really get a convincing answer. Here s my question: The subquery below returns a Table with 3 ...

难以执行 REGEXP_SUBSTR

I m 查询Oracle 10g。 我有两张表格(样本数据见下文)。 i m 试图提取一些领域

SQL Query Shortcuts

What are some cool SQL shorthands that you know of? For example, something I learned today is you can specify to group by an index: SELECT col1, col2 FROM table GROUP BY 2 This will group by col2

PHP array callback functions for cleaning output

I have an array of output from a database. I am wondering what the cleanest way to filter the values is example array Array ( [0] => Array ( [title] => title 1 ...

OracleParameter and DBNull.Value

we have a table in an Oracle Database which contains a column with the type Char(3 Byte). Now we use a parameterized sql to select some rows with a DBNull.Value and it doesn t work: OracleCommand ...

Running numbers in SQL

I have a SQL-statement like this: SELECT name FROM users WHERE deleted = 0; How can i create a result set with a running number in the first row? So the result would look like this: 1 Name_1 2 ...

How to get SQL queries for each user where env is production

I’m developing an application dedicated to generate statistical reports, I would like that user after saving their stat report they save sql queries too. To do that I wrote the following module: ...

热门标签