Проблемы XSS при использовании OpenCPU и knitr для печати предоставленных пользователем данных
Я использую openCPU и knitr для создания пользовательских отзывов после опросов. С этой целью я в основном позволил разработчикам опросов указывать файлы rmd. В этом случае разработчикам опроса можно доверять, а участникам опроса - нет.
Я сейчас думаю о XSS. Это не большое беспокойство, поскольку отзывы пользователей, как правило, будут отображаться только пользователю, который ввел данные на дисплей, но, конечно, такие символы, как "<", будут использоваться по незлонамеренным причинам, и я хотел бы подумать об этом заранее и исследуйте некоторые испытания и трудности свободного смешивания R с веб-приложениями.
Knitr и R вообще не были сделаны с ненадежными пользователями и XSS в моем уме. OpenCPU устраняет многие проблемы с безопасностью, используя AppArmored-R в качестве API, но мне интересно, можно ли доказать такой подход с максимальной гибкостью, как мой.
Возможные точки, в которых можно разделить доверенную и ненадежную разметку:
- Перед вязанием, т.е. я передаю сбежавшие пользовательские данные в rmd-файл. Недостаток: забывший разработчик опроса может удалить его случайно или из-за того, что он раздражает в некотором контексте.
- Во время вязания. Я думаю, это было бы идеально, но я не знаю, возможно ли это, особенно если разработчик опроса потенциально может изменить настройки чанка.
- После вязания. Я думаю, что невозможно разграничить доверенную и ненадежную разметку пост-hoc.
Некоторый код для вставки в приложение knitr OpenCPU:
```{r}
good_userdata = 'I like brackets [].'
bad_userdata = 'some text should not be
[linked](javascript:location.href=\'http://example.com?secrets\';), <s>struck</s> or __bold__'
escape_html = highr:::escape_html
escape_md <- function(x){
x <- gsub('\\[', '\\\\[', x);
x <- gsub('_', '\\\\_', x);
x
}
good_userdata_escaped = escape_md(escape_html(good_userdata))
bad_userdata_escaped = escape_md(escape_html(bad_userdata))
```
## let's say survey devs wants to print text like this
```{r}
cat(good_userdata_escaped)
cat(bad_userdata_escaped) # doesn't know about text like this
```
## gets annoyed, does
```{r}
good_userdata_escaped <- gsub('\\\\', '', good_userdata_escaped);
bad_userdata_escaped <- gsub('\\\\', '', bad_userdata_escaped);
```
##
so that this looks nice
```{r}
cat(good_userdata_escaped)
```
## later renders the same text inline, so that is evaluated as markdown
`r good_userdata_escaped # doesn't look dangerous`
`r bad_userdata_escaped`
Редактировать 2
Извините, я предоставил только некоторые теги HTML, думая, что возможные атаки XSS очевидны. Мишель Фортин имел несколько примеров на своей странице.
1 ответ
Я не уверен на 100%, что понимаю вашу озабоченность. Если вы беспокоитесь о XSS, вы беспокоитесь о пользователях, включающих тег javascript или около того в уценке, верно?
```{r}
userdata = '<script>alert("I am evil")</script>'
```
```{r,results='asis'}
cat(userdata)
```
Вы можете предотвратить это, экранируя символы HTML. Я думаю, что есть раздел об этом в определении уценки. Таким образом, вам нужно было бы избежать любого пользовательского ввода, либо при вставке его в вашу БД, либо при его извлечении:
escape <- function(x){
x <- gsub("<", "<", x);
x <- gsub(">", ">", x);
x <- gsub("&", "&", x);
x
}
Попробуйте запустить следующее:
```{r output}
escape <- function(x){
x <- gsub("&", "&", x);
x <- gsub("<", "<", x);
x <- gsub(">", ">", x);
x
}
```
```{r}
userdata = escape('<script>alert("I am evil")</script>')
```
```{r,results='asis'}
cat(userdata)
```
Это должно заботиться о любом внедрении кода. Я не совсем уверен, как __bold__
Пример вызывает озабоченность, поскольку на самом деле это не может быть использовано для атаки XSS, так как нет сценариев. Но если вы хотите, чтобы пользователи тоже не связывались с макетом, вам следует избегать всех символов уценки, я полагаю.