Безопасность данных Lisp / проверка

Это - действительно просто концептуальный вопрос для меня в этой точке.

В Lisp программы являются данными, и данные являются программами. REPL делает точно, что - чтения и затем оценивают.

Таким образом, как каждый идет о том, чтобы быть введенным от пользователя безопасным способом? Очевидно, это возможно - я имею в виду viaweb - теперь, Хранилища Yahoo! довольно безопасны, поэтому как это сделано?

7
задан Wayne Werner 8 June 2010 в 18:34
поделиться

5 ответов

REPL расшифровывается как Read Eval Print Loop.

(loop (print (eval (read))))

Выше только концептуально, реальный код REPL намного сложнее (с обработкой ошибок, отладкой, ...).

Вы можете читать в Лиспе все виды данных, не оценивая их. Оценка - это отдельный шаг, не зависящий от чтения данных.

В Лиспе есть все виды функций ввода-вывода. Наиболее сложной из представленных функций обычно является READ, которая читает s-выражения. В Common Lisp есть опция, которая позволяет выполнять оценку во время READ, но ее можно и нужно отключить при чтении данных.

Итак, данные в Лиспе не обязательно являются программой, и даже если данные являются программой, Лисп может читать программу как данные - без оценки. REPL должен использоваться только разработчиком и не должен предоставляться произвольным пользователям. Для получения данных от пользователей используются обычные функции ввода-вывода, включая такие функции, как READ, которые могут читать S-выражения, но не оценивают их.

Вот несколько вещей, которые НЕ следует делать:

  • используйте READ для чтения произвольных данных. READ for examples позволяет читать действительно большие данные - ограничений нет.

  • оценивают во время READ ('читать eval'). Это должно быть отключено.

  • читают символы из ввода / вывода и вызывают их символьные функции

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

  • не обрабатывать синтаксические ошибки во время чтения из данных.

16
ответ дан 6 December 2019 в 06:23
поделиться

Это убийственный вопрос, и я подумал о том же, когда читал о Лиспе. Хотя я не сделал ничего значимого в LISP, поэтому мой ответ очень ограничен.

Я могу сказать вам, что eval () неприятен . Есть поговорка, которая мне нравится: «Если eval - это ответ, значит, вы задаете неправильный вопрос». --Неизвестный.

Если злоумышленник может контролировать данные, которые затем анализируются, значит, у вас очень серьезная уязвимость удаленного выполнения кода. Это можно смягчить, и я покажу вам пример с PHP, потому что это то, что я знаю:

$id=addslashes($_GET['id']);
eval('$test="$id";');

Если бы вы не добавляли косые черты, злоумышленник мог бы получить удаленное выполнение кода, сделав следующее:

http://localhost?evil_eval.php?id="; phpinfo();/*

Но добавление косой черты превратит " в \" , тем самым не дав злоумышленнику «вырваться» из «данных» и получить возможность выполнить код. Что очень похоже на SQL-инъекцию.

2
ответ дан 6 December 2019 в 06:23
поделиться

Я нашел этот вопрос спорным. eval не будет оценивать ваш ввод, если вы явно не попросите об этом. Я имею в виду, что ваш ввод не будет рассматриваться как LISP-код, а как строка.

Не потому ли, что в вашем языке есть такая мощная концепция, как eval, он не является "безопасным".

Я думаю, что путаница происходит из SQL, где вы фактически рассматриваете входные данные как [часть] SQL.

(query (concatenate 'string "SELECT * FROM foo WHERE id = " input-id))

Здесь input-id оценивается SQL-движком. Это происходит потому, что у вас нет красивого способа написать SQL, или что-то еще, но суть в том, что ваш ввод становится частью того, что оценивается.

Так что eval не принесет вам опасности, если только вы не используете его с закрытыми глазами.

EDIT Забыл сказать, что это применимо к любому языку.

0
ответ дан 6 December 2019 в 06:23
поделиться

Вы делаете это так же, как и все остальные. Вы читаете строку данных из потока, анализируете ее на предмет своих команд и параметров, проверяете команды и параметры и интерпретируете команды и параметры.

Здесь нет никакой магии.

Проще говоря, чего вы НЕ ДЕЛАЕТЕ, так это то, что вы не открываете свой слушатель Lisp непроверенному, незащищенному источнику данных.

Как уже упоминалось, REPL читается - eval - print. @The Rook сосредоточен на eval (не без причины), но не сбрасывает со счетов READ. READ - ОЧЕНЬ мощная команда в Common Lisp. Читатель может оценить код сам по себе, прежде чем вы даже НАЙДЕТЕ на "eval".

НЕ подвергайте READ тому, чему вы не доверяете.

При достаточной работе вы могли бы создать собственный пакет, ограничить набор функций, доступных для этого пакета, и т. Д. И т. Д. Но я думаю, что это больше работы, чем просто написать простой анализатор команд и не беспокоиться о некоторых побочных эффектах, которые Я скучал.

6
ответ дан 6 December 2019 в 06:23
поделиться
  1. Создайте свою собственную таблицу чтения и заполните ее необходимыми крючками: SET-MACRO-CHARACTER, SET-DISPATCH-MACRO-CHARACTER и т.д.
  2. Привяжите READTABLE к вашей собственной таблице чтения.
  3. Привяжите READ-EVAL к nil, чтобы предотвратить #. (может не понадобиться, если шаг 1 выполнен правильно)
  4. READ

Возможно, что-то еще.

Также есть хитрость в интернировании символов во временном пакете при чтении.

Если данные не LL(1)-ish, просто напишите обычный парсер.

4
ответ дан 6 December 2019 в 06:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: