quinta-feira, 17 de abril de 2008

Proteção Contra SQL Injection

Como é de comum a todos, ou deveria ser, os maiores ataques dos hackers aos sites são através de SQL Injection, venho por meio desse post ensinar a se defender desses ataques.

Se engana quem pense que os ataques são sempre feitos em formulários, os ataques mais fortes são feitos pela url, a famosa querystring.

Ex: www.dominio.com.br/index.asp?id=4

Isso é um perigo se estiver sem proteção, e a maioria dos sites hoje em dia estão desprotegidos a esse tipo de ataque, parece mentira, mas com esse ataque é possível dar updates e drops no banco, criar procedures e até mesmo copiar arquivos executaveis para dentro do servidor e executá-los! Mas é claro que não vou ensinar a fazer isso aqui, hehehe, esse artigo é para a proteção.

Uma das melhores proteções, é criar usuários diferentes no banco, um usuário para selects e outro para update/drop/delete, e usar nas páginas de consulta o usuario de select.

Mas vou mostrar também uma função bem útil quem ajuda muito a pegar os espertinhos, segue ela abaixo:


Sub Valida_Request()

Set objRegExpr = New RegExp
objRegExpr.Global = True
objRegExpr.IgnoreCase = True
objRegExpr.Pattern = """|'|;| delete |drop|insert|select|update|upload"

For Each obj In Request.Form
If objRegExpr.Test(Request.Form(obj)) Then
Response.Write "A palavra ou caractere "& Request.Form(obj) &" é invalido para o Campo " & obj & " favor substituí-lo ou retirá-lo."
Response.End
End If
Next

For Each obj In Request.QueryString
If objRegExpr.Test(Request.QueryString(obj)) Then
Response.Write "A palavra ou caractere "& Request.Form(obj) &" é invalido para o Campo " & obj & " favor substituí-lo ou retirá-lo."
Response.End
End If
Next

Set objRegExpr = Nothing

End Sub



Essa função deve ser chamada no topo de todas as paginas, ela evita que a comandos como delete|drop|insert|select|update|upload e caracteres como "|'|; sejam inseridos nos formularios e querystrings, esses são os principais comandos e caracteres usados pelos hackers para esse tipo de ataque.

Espero que tenham gostado da dica.

Abs a todos!

quarta-feira, 16 de abril de 2008

FrameWork Ajax no Domino

A muito quando descobri o Ajax e me interessei pelo assunto passava por maus "bocados" para utilizar a biblioteca de scripts dentro do domino.
Primeiro anexava dentro de uma base NSF os arquivos um a um para poder referencia-los dentro dos elementos de designer da aplicação. Depois em uma matéria do CODESTORE vi que poderia utilizar o WEBDAV para que através de um FTP anexar os arquivos transferindo como se fosse uma pasta normal. Achei isso um máximo. Sem falar nas possibilidade de um designer em outro local poder alterar uma aplicação.
Posso até estar atrasado no assunto, mais garanto que muitos colegas que trabalham com o Lotus Notes não sabe que podemos utilizar o recurso que vou explicar agora.
Para melhor utilizar a biblioteca de scripts seja ela qual for (Dojo, Yahoo! UI, scriptaculus e etc.) basta colocar a pasta de arquivos abaixo do seguinte caminho do servidor Domino: \Data\domino\html\
Assim podemos referenciar qualquer biblioteca que desejamos utilizar. Claro que é importante a organização dentro do diretório e muito cuidado para não acontecer acidentes. ;)

Veja como fiz com o DOJO.

Depois que adicionar a biblioteca na pasta html do servidor Domino podemos fazer referência aos arquivos dentro da pasta html.

E agora mãos a obra. Podemos brincar com as bibliotecas conforme nossa necessidade e utilizar duas ou mais bibliotecas dentro de uma mesma aplicação.

Download de algumas Bibliotecas:
Dojo ToolKit
Yahoo! UI
Scriptaculos
Ext JS

segunda-feira, 31 de março de 2008

Alternativa ao Embedded View

Todo desenvolvedor Lotus Notes sabe o quanto é demorado o refresh no browser quando tem que utilizar Embedded View. Especialmente em um formulário que precisamos armazenar uma tabela dinâmica. Pois é, também tive esse problema e procurei alternativas para resolver esse problema. No meu caso eu precisava fazer uma tabela dinâmica, mas não me interessava armazenar separadamente como um documento response já que iria ser visualizado somente no documento quando aberto. Claro que as boas idéias, são inspiradas em outras pré-existente e comigo não foi diferente. Navegando no site do CODESTORE tive a luz em uma solução que pra mim foi o pulo do gato.

1. Como quero que fique:
- No Formulário

- Dialogo de Inclusão















2. Como Faço:
Primeiramente crie no formulário os campos referente as colunas da tabela, pois cada coluna será armazenado por um campo multi-valor. Esses campos serão ocultos.
Agora crie a estrutura da tabela em HTML com a propriedade de texto Pass-Thru HTML marcada. Onde será o conteúdo da tabela adicione o Texto Computado. Conforme as imagens a seguir.


- No Formulário:

- No Texto Computado:

- Botão "Incluir"

DisableSelect(); //Desabilita os campo selected
//Ativa a DIV
PutClass('opacity','geral_opacity');
On('opacity');
On('dlgPassageiro'); // Exibe a DIV para adicionar os dados da linha a ser incluído.


- No Botão "OK"

var objForm = document.forms[0];
if(objForm.EditaAtividadeAtual.value != ''){
doAlteraAtividadeAtual(objForm.EditaAtividadeAtual.value);
}else if(objForm.EditaAtividadeProposta.value != ''){
doAddAtividadeAtual();
}

objForm.Atividade.value = '';
objForm.EditaAtividadeAtual.value = '';
objForm.EditaAtividadeProposta.value = '';

EnableSelect();
Off('opacity');
Off('dlgAtividades');


3. As Funções JavaScript:Todas as funções utilizadas são chamadas no HTML HEAD do Formulário. Segue abaixo:

- Global.js

/*
Objetivo: Funções globais da aplicação.
Autor: Renato Dalforne
Alterado: Ailton Nunes
Ajuda: Thiago Diniz (função lerCarcPos)
*/

function PutClass(campo, classe){
document.getElementById(campo).className=classe;
return;}
//==============================================================
function On(div) {
document.getElementById(div).style.visibility='visible';}
function Off(div) {
document.getElementById(div).style.visibility='hidden';}
function getID(id) {
return document.getElementById(id);}
function getTag(name) {
return document.getElementsByTagName(name);}
function makeElem(name){
return document.createElement(name);}
//==============================================================
//Implementa o método trim() no objeto String.
String.prototype.trim = trim;
function trim(){
return(this.replace(/^\s+|\s+$/gi,"").replace(/\s{2,}/gi," "))
}
//==============================================================
function DisableSelect(){
var a = getTag('select');
for(var i=0,b; b=a[i]; i++) b.style.visibility='hidden';
a=b=i=null;}
//==============================================================
function EnableSelect(){
var a = getTag('select');
for(var i=0,b; b=a[i]; i++) b.style.visibility='visible';
a=b=i=null;}
//==============================================================
function lerCarcPos(campo, marcador, Pos){
var x;
try{
var field = campo.value.split(marcador);
var retorno = field[Pos];
return(retorno);
}catch(x){
return(false);
};
}
//==============================================================

- addTabelaAtividade.js
  • doAddAtividadeAtual

/*
Objetivo: Adicionar, Remover e Alterar uma linha de uma tabela de atividades.
Autor; Ailton Nunes
*/
//==============================================================
function doAddAtividadeAtual(){

var f = document.forms[0];

caminho = (window.location.pathname.split('.nsf/'))[0];
servidor = (window.location.href.split(caminho))[0];

var currTotal=f.AtualAtividade.value.split(';').length;

if (f.dlgAtividade.value ==''){
f.AtualAtividade.value+='; -';
var txt1 = document.createTextNode('-');
}else{
f.AtualAtividade.value+='; '+ f.dlgAtividade.value;
var txt1 = document.createTextNode(f.dlgAtividade.value);
}

if (f.dlgAtor.value == ''){
f.AtualAtor.value+='; =';
var txt2 = document.createTextNode('-');
}else{
f.AtualAtor.value+='; '+ f.dlgAtor.value;
var txt2 = document.createTextNode(f.dlgAtor.value);
}

if (f.dlgRecurso.value == ''){
f.AtualRecurso.value+='; -';
var txt3 = document.createTextNode('-');
}else{
f.AtualRecurso.value+='; '+ f.dlgRecurso.value;
var txt3 = document.createTextNode(f.dlgRecurso.value);
}

if (f.dlgEntradas.value == ''){
f.AtualEntrada.value+='; -';
var txt4 = document.createTextNode('-');
}else{
f.AtualEntrada.value+='; '+ f.dlgEntradas.value;
var txt4 = document.createTextNode(f.dlgEntradas.value);
}

if (f.dlgSaidas.value == ''){
f.AtualSaida.value+='; -';
var txt5 = document.createTextNode('-');
}else{
f.AtualSaida.value+='; '+ f.dlgSaidas.value;
var txt5 = document.createTextNode(f.dlgSaidas.value);
}

var tr = document.createElement('tr');
var td0 = document.createElement('td');
var td1 = document.createElement('td');
var td2 = document.createElement('td');
var td3 = document.createElement('td');
var td4 = document.createElement('td');
var td5 = document.createElement('td');
var td6 = document.createElement('td');
var img = document.createElement('img');
var img2 = document.createElement('img');
var rem = document.createElement('a');
var edi = document.createElement('a');

img.setAttribute('src', servidor+caminho+'.nsf/remove.gif');
img.setAttribute('border', '0');

img2.setAttribute('src', servidor+caminho+'.nsf/edit.gif');
img2.setAttribute('border', '0');

rem.setAttribute("href","JavaScript:void(doRemoveAtividadeAtual("+currTotal+"));");
rem.appendChild(img);

edi.setAttribute("href","JavaScript:void(doEditaAtividadeAtual("+currTotal+"));");
edi.appendChild(img2);

var txt2 = document.createTextNode(f.dlgAtor.value);
var txt3 = document.createTextNode(f.dlgRecurso.value);
var txt4 = document.createTextNode(f.dlgEntradas.value);
var txt5 = document.createTextNode(f.dlgSaidas.value);*/

td0.appendChild(rem);
td1.appendChild(edi);

td2.appendChild(txt1);
td3.appendChild(txt2);
td4.appendChild(txt3);
td5.appendChild(txt4);
td6.appendChild(txt5);

tr.appendChild(td0);
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
tr.appendChild(td4);
tr.appendChild(td5);
tr.appendChild(td6);

tr.setAttribute('id','atividades-atual-'+currTotal);
tr.setAttribute('class','atividades-atual');

var container = document.getElementById('tab-atividades-atual');

container.appendChild(tr);

//Limpa os campos
f.dlgAtividade.value = '';
f.dlgAtor.value = '';
f.dlgRecurso.value = '';
f.dlgEntradas.value = '';
f.dlgSaidas.value = '';
}
  • doRemoveAtividadeAtual

function doRemoveAtividadeAtual(idx){
if (!confirm('Você tem certeza que deseja remover essa atividade?')) return;

var f = document.forms[0];

var currFiles1=f.AtualAtividade.value.split('; ');
var currFiles2=f.AtualAtor.value.split('; ');
var currFiles3=f.AtualRecurso.value.split('; ');
var currFiles4=f.AtualEntrada.value.split('; ');
var currFiles5=f.AtualSaida.value.split('; ');

//removes file
currFiles1[idx]="";
currFiles2[idx]="";
currFiles3[idx]="";
currFiles4[idx]="";
currFiles5[idx]="";

f.AtualAtividade.value = currFiles1.join('; ');
f.AtualAtor.value = currFiles2.join('; ');
f.AtualRecurso.value = currFiles3.join('; ');
f.AtualEntrada.value = currFiles4.join('; ');
f.AtualSaida.value = currFiles5.join('; ');

//remove tr container
tr=document.getElementById("atividades-atual-"+idx);

tr.parentNode.removeChild(tr);

}
  • doEditaAtividadeAtual

function doEditaAtividadeAtual(idx){
DisableSelect();
PutClass('opacity','geral_opacity');
On('opacity');
On('dlgAtividades');

var f = document.forms[0];

f.dlgAtividade.value = lerCarcPos(f.AtualAtividade, ';', idx).trim();
f.dlgAtor.value = lerCarcPos(f.AtualAtor, ';', idx).trim();
f.dlgRecurso.value = lerCarcPos(f.AtualRecurso, ';', idx).trim();
f.dlgEntradas.value = lerCarcPos(f.AtualEntrada, ';', idx).trim();
f.dlgSaidas.value = lerCarcPos(f.AtualSaida, ';', idx).trim();

f.EditaAtividadeAtual.value = idx;
}
  • doAlteraAtividadeAtual

function doAlteraAtividadeAtual(idx){
if (!confirm('Você tem certeza que deseja alterar essa atividade?')) return;

var f = document.forms[0];

caminho = (window.location.pathname.split('.nsf/'))[0];
servidor = (window.location.href.split(caminho))[0];

var currFiles1=f.AtualAtividade.value.split('; ');
var currFiles2=f.AtualAtor.value.split('; ');
var currFiles3=f.AtualRecurso.value.split('; ');
var currFiles4=f.AtualEntrada.value.split('; ');
var currFiles5=f.AtualSaida.value.split('; ');

if (document.forms[0].dlgAtividade.value ==''){
var txt1 = document.createTextNode('-');
}else{
var txt1 = document.createTextNode(document.forms[0].dlgAtividade.value);
}

if (document.forms[0].dlgAtor.value == ''){
var txt2 = document.createTextNode('-');
}else{
var txt2 = document.createTextNode(document.forms[0].dlgAtor.value);
}

if (document.forms[0].dlgRecurso.value == ''){
var txt3 = document.createTextNode('-');
}else{
var txt3 = document.createTextNode(document.forms[0].dlgRecurso.value);
}

if (document.forms[0].dlgEntradas.value == ''){
var txt4 = document.createTextNode('-');
}else{
var txt4 = document.createTextNode(document.forms[0].dlgEntradas.value);
}

if (document.forms[0].dlgSaidas.value == ''){
var txt5 = document.createTextNode('-');
}else{
var txt5 = document.createTextNode(document.forms[0].dlgSaidas.value);
}

//var txt = document.createTextNode(title);
var tr = document.createElement('tr');
var td0 = document.createElement('td');
var td1 = document.createElement('td');
var td2 = document.createElement('td');
var td3 = document.createElement('td');
var td4 = document.createElement('td');
var td5 = document.createElement('td');
var td6 = document.createElement('td');
var img = document.createElement('img');
var img2 = document.createElement('img');
var rem = document.createElement('a');
var edi = document.createElement('a');

//Atualiza linha
currFiles1[idx]=f.dlgAtividade.value;
currFiles2[idx]=f.dlgAtor.value;
currFiles3[idx]=f.dlgRecurso.value;
currFiles4[idx]=f.dlgEntradas.value;
currFiles5[idx]=f.dlgSaidas.value;

f.AtualAtividade.value = currFiles1.join('; ');
f.AtualAtor.value = currFiles2.join('; ');
f.AtualRecurso.value = currFiles3.join('; ');
f.AtualEntrada.value = currFiles4.join('; ');
f.AtualSaida.value = currFiles5.join('; ');

//remove tr container
tr=document.getElementById("atividades-atual-"+idx);

var count = tr.childNodes.length;
for (var i=0;i<count;i++){
var oChild=tr.children(0);
tr.removeChild(oChild);
}

img.setAttribute('src', servidor+caminho+'.nsf/remove.gif');
img.setAttribute('border', '0');

img2.setAttribute('src', servidor+caminho+'.nsf/edit.gif');
img2.setAttribute('border', '0');

rem.setAttribute("href","JavaScript:void(doRemoveAtividadeAtual("+idx+"));");
rem.appendChild(img);

edi.setAttribute("href","JavaScript:void(doEditaAtividadeAtual("+idx+"));");
edi.appendChild(img2);
td0.appendChild(rem);
td1.appendChild(edi);

td2.appendChild(txt1);
td3.appendChild(txt2);
td4.appendChild(txt3);
td5.appendChild(txt4);
td6.appendChild(txt5);

tr.appendChild(td0);
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
tr.appendChild(td4);
tr.appendChild(td5);
tr.appendChild(td6);

//Limpa os campos
f.dlgAtividade.value = '';
f.dlgAtor.value = '';
f.dlgRecurso.value = '';
f.dlgEntradas.value = '';
f.dlgSaidas.value = '';
f.EditaAtividadeAtual.value = ''}

Atenção:

Os campos adicionados para receberem as informações de cada coluna tem que ser campo Multi-Valor para armazenar os dados separadamente e explodir em cada linha.
Para garantir que isso ocorra adicione a formula @Trim(@ThisValue) no Input Translation de cada campo que irá compor a tabela.

Vou deixar o CSS por conta dos senhores. ;)

Imagens: