Ao ingressar em tabelas, uso modelos SQL do Zend Framework. Como exemplo, modifiquei meu código real, mas acho que você entenderá o ponto:
$this->getSelect()->join(
array('sections' => $sectionsTableName),
'main_table.banner_id = pages.banner_id',
array()
)
->where("sections.section= '$section' OR sections.section = '0' OR (sections.section = '6' AND ? LIKE main_table.url)",$url)
->group('main_table.banner_id');
A página é carregada com ajax e o parâmetro $ section é enviado como parâmetro GET ( www.example.com/controllerName/index/display/3?paremeter1=example§ion=www.example2.com
).
Agora, aqui está o problema se alguém executar algo parecido com isto:
www.example.com/controllerName/index/display/3?paremeter1=example&url=(SELECT 3630 FROM(SELECT COUNT(*),CONCAT(0x7170786a71,(SELECT (ELT(3630=3630,1))),0x717a716b71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)
Dessa maneira, o usuário pode despejar o banco de dados inteiro. Os dados não serão exibidos, mas o SQL ainda executará o dump, o que pode causar sobrecarga no sql.
Questões:
- Qual é a melhor maneira de evitar esse cenário?
- Agora estou preocupado com clientes anteriores. É possível com esse código executar ainda mais ações de risco, como excluir ou alterar tabela? Acho que não, porque você não pode colocar nenhuma outra instrução além de SELECT dentro da subseleção para que DELETE produza erro de sintaxe sql. Estou certo?
UPDATE: Meu exemplo não é uma ilustração adequada da injeção de SQL, porque há seções 'arround $' e, portanto, não será possível fazer a injeção. De qualquer forma, isso seria possível quando se espera um valor inteiro e quando você não filtra a entrada inteira. Veja meu comentário abaixo.
'
sinal antes do (
sinal e, portanto, (SELECT
ou qualquer outra coisa será apenas como string e não funcionará. Quando o campo é inteiro, '
não é necessário e torna possível esse cenário. Mas o número inteiro sempre deve ser filtrado com, intval()
para que isso também não seja problema.
'
? Então ' AND (SELECT ...) '
? A propósito, não acho que o Zend não esteja citando isso ... E se você usar ligações, o PDO cuidará disso. Apenas nunca use concatenações sting como esta:"sections.section= '$section'"
$db = Mage::getSingleton('core/resource')->getConnection('core_read');
e$db->quote()
mesmo no seu caso, veja$db->quoteInto
. Se$this
é um recurso, você pode fazer:$this->getConnection('core_read')->quoteInto()
se é uma coleção que você poderia fazer:$this->getResource()->getConnection('core_read')->quoteInto()
. nesse sentido. Se isso ajudar a guiá-lo em direção ao seu objetivo.