Тред начинается вот здесь. Я не собирался ни к кому придираться, но утверждение о предотвращении Heartbleed оказалось удачно сформулировано. В отличие от расплывчатых заявлений о безопасности работы с памятью в целом, конкретно данное утверждение можно протестировать.
Я не планирую реализовать весь стек TLS на Rust, поэтому срежу путь и уменьшу масштаб проблемы. Надеюсь, что моя модель сохранит суть проблемы. В двух словах, цель такова: написать программу, которая читает файл (пакет) из файловой системы (сети) и отправляет его обратно (этакий сетевой вариант echo). Длина echo-запроса будет закодирована одним байтом, за которым следуют данные. Это эквивалентно уязвимости TLS. Наша программа будет принимать пару таких пакетов, yourping и myping, и отвечать пакетами yourecho и myecho. Если какие-либо данные из пакета your просочатся в пакет my, у нас проблема: heartbleed1.
Начнём с простой программы на Rust.
use std::old_io::File; fn pingback(path : Path, outpath : Path, buffer : &mut[u8]) { let mut fd = File::open(&path); match fd.read(buffer) { Err(what) => panic!("say {}", what), Ok(x) => if x < 1 { return; } } let len = buffer[0] as usize; let mut outfd = File::create(&outpath); match outfd.write_all(&buffer[0 .. len]) { Err(what) => panic!("say {}", what), Ok(_) => () } } fn main() { let buffer = &mut[0u8; 256]; pingback(Path::new("yourping"), Path::new("yourecho"), buffer); pingback(Path::new("myping"), Path::new("myecho"), buffer); }
Программа компилируется, хотя и с предупреждениями из-за ламерского использования std::old_io. Не бог весть какой код, но и не самый ужасный. К примеру, мне удалось не использовать небезопасные межъязыковые интерфейсы (FFI) для вызова memcpy из C.
Давайте посмотрим, что программа делает с простыми входными данными.
$ echo \#i have many secrets. this is one. > yourping $ echo \#i know your > myping $ ./bleed $ cat yourecho #i have many secrets. this is one. $ cat myecho #i know your secrets. this is one.
Бинго! Секретные данные утекли.
Конечно же, настоящий программист на Rust никогда не напишет подобной программы, поэтому, вероятно, я ещё и не продемонстрировал Heartbleed на Rust.
Давайте отдохнём от Rust и рассмотрим эквивалентный код на C.
#include <fcntl.h> #include <unistd.h> #include <assert.h> void pingback(char *path, char *outpath, unsigned char *buffer) { int fd; if ((fd = open(path, O_RDONLY)) == -1) assert(!"open"); if (read(fd, buffer, 256) < 1) assert(!"read"); close(fd); size_t len = buffer[0]; if ((fd = creat(outpath, 0644)) == -1) assert(!"creat"); if (write(fd, buffer, len) != len) assert(!"write"); close(fd); } int main(int argc, char **argv) { unsigned char buffer[256]; pingback("yourping", "yourecho", buffer); pingback("myping", "myecho", buffer); }
Анкетирование показало, что ни один настоящий программист на C никогда не напишет такой программы. Что же мы имеем?
код, который не напишет ни один настоящий программист на C: heartbleed
код, который не напишет ни один настоящий программист на Rust: (задачка для читателя)
Смысл поста не в порицании Rust. Я мог бы написать похожую программу на Go, или даже на Haskell, если бы я был достаточно умён для понимания буррито. Смысл в том, что пока мы не поймём, что представляют собой уязвимости наподобие Heartbleed, мы едва ли сможем избежать их простым переключением на волшебный уязвимостойкий язык. Да, каждый слышал о Heartbleed, но это не обязательно делает его хорошим примером.
Возможно, аргумент о Heartbleed использовался не как отсылка к самому Heartbleed, а к пачке других больших и страшных проблем. Не уверен, что это делает аргумент лучше. «Уязвимости, подобные Heartbleed, но не слишком похожие» — плохо определённый класс проблем. Сложно оценить какие-либо утверждения о таком классе.
Говоря об уязвимостях и их разрешении, нам нужно быть точными и осторожными. Поднятый вокруг Heartbleed (Shellshock, и т.п.) хайп делает его привлекательной целью для построения аргументов, но стоит проверять сочетаемость примера и аргумента. Ошибочные примеры приводят к ошибочным решениям.
Примечания
1. bleed — сочиться, испускать
Ссылки
- Обсуждение на reddit
- Обсуждение на HackerNews (bonus: проштрафившийся пользователь принёс извинения)
- Wikipedia — Heartbleed
- The Rust Programming Language
-
Видео от Tom Scott о Heartbleed
ссылка на оригинал статьи http://habrahabr.ru/post/249537/
Добавить комментарий