Desenvolvimento - Javascript

Como ocultar seu código via Ajax

Veja neste artigo como você pode ocultar o seu código fonte usando Ajax.

por Gregory Monteiro



Você por acaso, já tentou visualizar o código-fonte de alguns sites e simplesmente não conseguiu entender algumas codificações ou como era praticamente impossível saber qual função fazia uma determinada ação no site?

Antes de explicar como usar Linguagens de programação junto com os códigos em JavaScript é necessário “quebrarmos tabus”:

O programador já deve estar acostumado a chamar um arquivo “.js” através do seguinte modo:

<script src="arquivo.js"></script>

Ao usar esse método você não está restrito a chamar somente arquivos com a extenção “.js”. Isso quer dizer que você pode chamar arquivos “.asp”, “.php”, “.aspx”, “.jsp” etc. Você também pode passar uma querystring:

<script src="arquivo.asp?id=1"></script>

Tendo isso em mente é muito simples bloquear o código para não aparecer, a não ser que seja solicitado pela sua aplicação.

Veja um exemplo simples:

Crie uma página html com o nome “teste.html” com o código da Listagem 1:

Listagem 1. Página “teste.html”

<html>
	<head>
		<title>teste.html</title>
		<script src="arquivo.asp"></script>
	</head>
	<body>
		aplicação teste
	</body>
</html>

A seguir, crie uma outra página com nome “arquivo.asp” com o código da Listagem 2:

Listagem 2. Página “arquivo.asp”

<%
Response.Charset="ISO-8859-1"
if request.ServerVariables("SERVER_NAME") <> "localhost" or request.ServerVariables("REQUEST_METHOD") <> "GET" or request.ServerVariables("HTTP_REFERER") = "" then
response.write "Você não tem permissão para visualizar esse conteúdo! :p"
response.end
end if
%>
alert("teste");

Na linha 2 é “setado” que o textos exibidos na página estarão no formato "ISO-8859-1".

Na linha 3 são feitas três condições:

  1. request.ServerVariables("SERVER_NAME") - retorna o nome do servidor que esta chamando a página.
  2. request.ServerVariables("REQUEST_METHOD") - retorna o método usado na requisição da página (GET ou POST).
  3. request.ServerVariables("HTTP_REFERER") - retorna o nome da página que referenciou a página sendo processada.

Então para o nosso exemplo se o nome do servidor for diferente de “localhost” ou o método for diferente de POST ou não tiver nenhuma página chamando a página “arquivo.asp” ocorrerá a exibição de uma mensagem e o conteúdo posterior não será exibido (linhas 4 e 5).

Nota: Qualquer linguagem de programação para web possuí essas características citadas acima. No PHP por exemplo, para saber se a página está sendo chamada por outra é só usar o código a seguir:

$_SERVER['HTTP_REFERER']

Visualize a página “teste.html” (ver Figura 1) no seu navegador, em seguida visualize a página “arquivo.asp” (ver Figura 2).

Página teste.html

Figura 1. Página “teste.html”

 Página arquivo.asp

Figura 2. Página “arquivo.asp”

Problemas em potencial

Agora temos que dar nossa atenção a três problemas acontecem nos browsers Firefox, Internet Explorer e Google Chrome.

1º problema:

Visualize o código-fonte da página “teste.html” no Firefox e perceba que há um link no arquivo.asp que ao ser clicado você consegue ver o código JavaScript que se encontra na página “arquivo.asp” (ver Figuras 3 e 4).

Código-fonte da página teste.asp

Figura 3. Código-fonte da página “teste.html”

Código-fonte da página arquivo.asp

Figura 4. Código-fonte da página “arquivo.asp”

Isso pode ser resolvido mudando a forma de chamar a página com o script da Listagem 3 (ver linhas 4 a 9).

Listagem 3. Página “teste.html”

  <html>
  	<head>
  		<title>teste.html</title>
  		<script>
  		 var novo = document.createElement('script');
  		 novo.setAttribute('type', 'text/javascript');
  		 novo.setAttribute('src', "arquivo.asp");
  		 document.getElementsByTagName('head')[0].appendChild(novo);
  		</script>
 	</head>
 	<body>
 		aplicação teste
 	</body>
 </html>

Nas linhas 4 a 9 é criado um novo elemento script que chama a página “arquivo.asp”. Veja como ficou o código-fonte agora, sem o link (ver Figura 5)!

Código-fonte da página teste.html alterado

Figuras 5. Código-fonte da página “teste.html” alterado

2º problema:

Para a nossa má sorte a Internet Explorer (assim como outros browsers) tem um depurador de script o nosso código continua a ser mostrado (ver Figura 6). Código-fonte da página arquivo.asp visto no Internet Explorer

Figuras 6. Código-fonte da página “arquivo.asp” visto no Internet Explorer

No entanto podemos usar o próprio Ajax para impedir essa visualização.

Para isso vamos criar um arquivo chamado “default.asp” com o código da Listagem 4.

Listagem 4. Página “default.asp”

  <%
  Response.Charset="ISO-8859-1"
  if request.ServerVariables("SERVER_NAME") <> "localhost" or request.ServerVariables("REQUEST_METHOD") <> "GET" or request.ServerVariables("HTTP_REFERER") = "" then
  	response.write "Você não tem permissão para visualizar esse conteúdo! :p"
 	response.end
  end if
 %>
  var xmlHttp;
  xmlHttp = GetXmlHttpObject();

function show() {
 	if (xmlHttp == null) {
 		alert ("Seu browser não suporta AJAX!");
 		return;
 	}else{
		var url = "arquivo.asp";
 		xmlHttp.onreadystatechange = stateChanged;
 		xmlHttp.open("GET",url,true);
		xmlHttp.send(null);
 	}
 }
 function stateChanged() {
	if (xmlHttp.readyState==1 || xmlHttp.readyState==2 || xmlHttp.readyState==3) {
 	}
 	if (xmlHttp.readyState==4) {
		extraiScript(xmlHttp.responseText);
	}
}

 function GetXmlHttpObject() {
 	var xmlHttp = null;
 	try {
 		// Firefox, Opera 8.0+, Safari
 		xmlHttp = new XMLHttpRequest();
 	} catch (e) {
 		// Internet Explorer
 		try {
 		xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
 		} catch (e) {
		xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
 		}
	}
 	return xmlHttp;
}

 function extraiScript(texto){
 	var ini = 0;
 	// loop enquanto achar um script
	while (ini!=-1){
 		// procura uma tag de script
		ini = texto.indexOf('<script', ini);
 		// se encontrar
 		if (ini >=0){
			// define o início para depois do fechamento dessa tag
 			ini = texto.indexOf('>', ini) + 1;
 			// procura o final do script
 			var fim = texto.indexOf('</script>', ini);
			// extrai apenas o script
 			codigo = texto.substring(ini,fim);
 			// executa o script
 			novo = document.createElement("script")
			novo.text = codigo;
 			document.body.appendChild(novo);
 		}
	}
 }

 show();

Perceba que das linhas 11 a 21 foi criada uma função chamando o JavaScript da página “arquivo.asp” e usei uma função extraiScript para “extrair” o script dessa página fazendo-o ser executado normalmente (linhas 47 a 66).

Precisamos também alterar as páginas “arquivo.asp” e “teste.html” (ver Listagens 5 e 6).

Listagem 5. Página “arquivo.asp”

 <%
 Response.Charset="ISO-8859-1"
 if request.ServerVariables("SERVER_NAME") <> "localhost" or request.ServerVariables("REQUEST_METHOD") <> "GET" or request.ServerVariables("HTTP_REFERER") = "" then
	response.write "Você não tem permissão para visualizar esse conteúdo! :p"
	response.end
 end if
 %>
<script>
 alert("teste");
 </script>

Perceba que o “alert” foi colocado dentro de tags Scripts, pois a função “extraiScript”, mostrada na Listagem 4, só executa scripts que estão dentro dessas tags

Listagem 6. Página “teste.html”

  <html>
  	<head>
  		<title>teste.html</title>
  		<script>
  		 var novo = document.createElement('script');
  		 novo.setAttribute('type', 'text/javascript');
  		 novo.setAttribute('src', "default.asp");
  		 document.getElementsByTagName('head')[0].appendChild(novo);
  		</script>
 	</head>
 	<body>
 		aplicação teste
 	</body>
 </html>

Alterei somente a linha 7 chamando a página “default.asp”. Agora veja que no Internet Explorer não há mais como ver o código-fonte da página “arquivo.asp”. Perceba que mesmo você podendo ver o código do arquivo “ajax.asp” não é possível ver o da página “arquivo.asp” (Ver Figura 7).

Código-fonte da página arquivo.asp visto no Internet Explorer

Figura 7. Código-fonte da página “arquivo.asp” visto no Internet Explorer

Nota: Apesar do trabalho, é bem importante essa prática, pois na página “arquivo.asp” é onde você colocará as suas funções que realmente farão a sua aplicação funcionar!

Bloqueando teclas e o menu de contexto

Você também pode “atrapalhar” o usuário um pouco mais esperto bloqueando algumas teclas e o menu de contexto (menu que aparece ao se clicar com o botão direito do mouse no browser). Para isso basta incluir o código da Listagem 7 na página “default.asp”.

Listagem 7. Código a ser incluído na página “default.asp”

  document.onkeydown = function(event){
  	if(navigator.appName == 'Microsoft Internet Explorer'){
  		if(window.event.keyCode == 123){
 			return false;
  		}
 	}else{
  		if(event.ctrlKey && event.shiftKey && event.keyCode == 74 || event.ctrlKey && 8.  event.keyCode == 85){
 			return false;
		}
	}
 }

 document.oncontextmenu = function(){
 	return false;
 }

Nas linhas 1 a 12 é verificado se o browser é o Internet Explorer e é bloqueado a tecla “F12” (tecla que abre o depurador de script). Se não for o IE ele bloqueia a seqüência de teclas “Ctrl + Shift + j” (console de erros no Firefox e depurador de script no Google Chrome) e “Ctrl + u” (visualizador de código-fonte no Firefox e no Google Chrome). Nas linhas 14 a 16 é bloqueado o menu de contexto (botão direito do mouse)!

3º e principal problema:

Alguns programadores devem saber que após carregada a página é possível inserir comandos script pela URL do browser. Na internet existe uns códigos usados para depurar aplicações web com Ajax:

javascript:'<xmp>'+window.document.body.outerHTML+'</xmp>'
javascript:'<xmp>'+window.document.body.innerHTML+'</xmp>'

Ao entramos com esse código na URL do nosso exemplo infelizmente acontece o que tentamos evitar, o código que tentamos ocultar é mostrado como nas figuras 8 e 9.

Nota: o código usado para depurar de páginas com Ajax não funciona no Firefox

Depuração feita com o outerHTML

Figura 8. Depuração feita com o “outerHTML”

Depuração feita com o innerHTML

Figura 9. Depuração feita com o “innerHTML”

Para resolver esse problema vamos criar uma página “teste.asp” (listagem 8) com o código semelhante a nossa antiga página “teste.html”.

Listagem 8. “teste.asp”

 <xmp></xmp>
 <html>
	<head>
		<script>
		<%if instr(lcase(request.ServerVariables("HTTP_USER_AGENT")),"firefox") = 0 Then%>
		if(window.document.body.outerHTML.indexOf("<body><xmp><body><xmp></xmp>") == 0 || window.document.body.outerHTML.indexOf("<body><xmp><xmp></xmp>") == 0 || window.document.body.outerHTML.indexOf("<BODY><XMP><BODY><XMP></XMP>") == 2 || window.document.body.outerHTML.indexOf("<BODY><XMP><XMP></XMP>") == 2){
			window.location="teste.asp";
		}
		<%end if%>
		var novo = document.createElement('script');
	novo.setAttribute('type', 'text/javascript');
		novo.setAttribute('src', "defatult.asp");
		document.getElementsByTagName('head')[0].appendChild(novo);
 		</script>
	</head>
	<body>
		aplicação teste
	</body>
 </html>

Perceba que na linha 1 esta o código que é o responsável por bloquear a depuração do nosso código. Nas linhas 6 a 8 criei um algoritmo simples para redirecionar a página, caso digitado na URL o código de depuração e coloquei uma condição (linha 5) para esse algoritmo não ser mostrado no Firefox já que não há necessidade.

Nota: A tag “xmp” é a responsável por mostrar o código, na integra, no browser.

Construindo a aplicação

Agora vamos construir uma aplicação simples, onde haverá um campo para você digitar um texto que será apresentado na tela à medida que digitado, usando Ajax.

Crie um arquivo com o nome “índex.asp” na raiz do seu site seguindo o código da listagem 9.

Os arquivos “default.asp”, “ajax.asp” e “getTexto.asp” tem de ser criados dentro de uma sub-pasta chamada “include” (Ver Listagens 9, 10, 11 e 12).

Listagem 9. Código da página “index.asp”

 <xmp></xmp>
 <html>
 <head>
 <title>SEGURANÇA CONTRA HACKER NO AJAX</title>
 <script>
	<%if instr(lcase(request.ServerVariables("HTTP_USER_AGENT")),"firefox") = 0 Then%>
	if(window.document.body.outerHTML.indexOf("<body><xmp><body><xmp></xmp>") == 0 || window.document.body.outerHTML.indexOf("<body><xmp><xmp></xmp>") == 0 || window.document.body.outerHTML.indexOf("<BODY><XMP><BODY><XMP></XMP>") == 2 || window.document.body.outerHTML.indexOf("<BODY><XMP><XMP></XMP>") == 2){
		window.location="index.asp";
	}
	<%end if%>
	var novo = document.createElement('script');
	novo.setAttribute('type', 'text/javascript');
	novo.setAttribute('src', "include");
	document.getElementsByTagName('head')[0].appendChild(novo);
 </script>
 </head>
 <body>
	<b>Digite um texto: </b>
	<input type="text" onKeyUp="showTexto(this.value);" />
	<span id="textoAjax"></span>
 </body>
 </html>

A Listagem 9 é a página principal composta do script que chama o arquivo “default.asp” (linhas 11 a 14) e um campo “input” onde será digitado o texto que aparecerá dentro da tag “span”.

Listagem 10. Código da página “default.asp”

  <%
  Response.Charset="ISO-8859-1"
  if request.ServerVariables("SERVER_NAME") <> "localhost" or request.ServerVariables("REQUEST_METHOD") <> "GET" or request.ServerVariables("HTTP_REFERER") = "" then
  	response.write "Você não tem permissão para visualizar esse conteúdo! :p"
 	response.end
  end if
  %>
  document.onkeydown = function(event){
 	if(navigator.appName == 'Microsoft Internet Explorer'){
		if(window.event.keyCode == 123){
 			return false;
		}
 	}else{
 		if(event.ctrlKey && event.shiftKey && event.keyCode == 74 || event.ctrlKey && 15. event.keyCode == 85){
 			return false;
 		}
	}
 }

document.oncontextmenu = function(){
 	return false;
 }

 var xmlHttp;
 xmlHttp = GetXmlHttpObject();

 function show() {
 	if (xmlHttp == null) {
		alert ("Seu browser não suporta AJAX!");
 		return;
 	}else{
 		var url = "include/ajax.asp";
 		xmlHttp.onreadystatechange = stateChanged;
		xmlHttp.open("POST",url,true);
 		xmlHttp.send(null);
 	}
 }

 function stateChanged() {
 	if (xmlHttp.readyState==1 || xmlHttp.readyState==2 || xmlHttp.readyState==3) {
	}
 	if (xmlHttp.readyState==4) {
 		extraiScript(xmlHttp.responseText);
 	}
}
.
 function GetXmlHttpObject() {
 	var xmlHttp = null;
 	try {
 		// Firefox, Opera 8.0+, Safari
 		xmlHttp = new XMLHttpRequest();
 	} catch (e) {
 		// Internet Explorer
 		try {
 		xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
 		} catch (e) {
 		xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
 		}
 	}
 	return xmlHttp;
 }

 function extraiScript(texto){
 	var ini = 0;
 	// loop enquanto achar um script
 	while (ini!=-1){
		// procura uma tag de script
	ini = texto.indexOf('<script', ini);
 		// se encontrar
 		if (ini >=0){
 			// define o inicio para depois do fechamento dessa tag
  			ini = texto.indexOf('>', ini) + 1;
			// procura o final do script
 			var fim = texto.indexOf('</script>', ini);
 			// extrai apenas o script
 			codigo = texto.substring(ini,fim);
			// executa o script
 			novo = document.createElement("script")
   		          novo.text = codigo;
 			document.body.appendChild(novo);
 		}
 	}
 }

 show();

Na Listagem 10 (assim como as Listagens 11 e 12) é composta do algoritmo que verifica se o nome do servidor o método que está a invocando e se está sendo referenciado por outra página (linhas 3 a 6). Também composta pelo script que bloqueia certas teclas e o menu de contexto no browser (linhas 8 a 23), a função show que chama a página “ajax.asp”, onde estarão os scripts que farão efetivamente a sua aplicação funcionar e a função extraiScript que executa o código script de arquivos que são chamados através do Ajax.

Listagem 11. Código da página “ajax.asp”

  <%
  Response.Charset="ISO-8859-1"
  if request.ServerVariables("SERVER_NAME") <> "localhost" or request.ServerVariables("REQUEST_METHOD") <> "POST" or request.ServerVariables("HTTP_REFERER") = "" then
  	response.write "Você não tem permissão para visualizar esse conteúdo! :p"
  	response.end
  end if
  %>
  <script>
 function showTexto(str) {
 	if (xmlHttp == null) {
 		alert ("Seu browser não suporta AJAX!");
 		return;
 	}else{
 		var url = "include/getTexto.asp";
 		var varStr;
 		varStr = "texto="+escape(str);
 		xmlHttp.onreadystatechange = stateChanged2;
 		xmlHttp.open("POST",url,true);
 		xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
 		xmlHttp.send(varStr);
 	}
 }

 function stateChanged2() {
 	if (xmlHttp.readyState==1 || xmlHttp.readyState==2 || xmlHttp.readyState==3) {
 		document.getElementById("textoAjax").style.display="none";
 	}
 	if (xmlHttp.readyState==4) {
 		document.getElementById("textoAjax").innerHTML=xmlHttp.responseText;
 		document.getElementById("textoAjax").style.display="block";
 	}
 }
 </script>

Na Listagem 11 está a função showTexto, que passa o valor digitado no campo input para a página “getTexto.asp” usando o método POST (linhas 9 a 22) e a função stateChanged2 que verifica os status de load da página “getTexto.asp” (linhas 24 a 32).

Nota: observe que na linha 16 da listagem 11 usei a função escape que codifica qualquer caractere especial, como acentos, pois se não for feito, ao se fazer o request desse conteúdo os caracteres especiais não serão interpretados corretamente.

Listagem 12. Código da página “getTexto.asp”

  <%
  Response.Charset="ISO-8859-1"
  if request.ServerVariables("SERVER_NAME") <> "localhost" or request.ServerVariables("REQUEST_METHOD") <> "POST" or request.ServerVariables("HTTP_REFERER") = "" then
  	response.write "Você não tem permissão para visualizar esse conteúdo! :p"
 	response.end
  end if
 
  response.write request.form("texto")
 %>

Na Listagem 12 é feito o tratamento dos caracteres especiais (linha 2) e mostrado na tela o valor digitado no campo input (linha 8). Execute a página “index.asp” para ver o resultado (Ver Figura 10).

Página index.asp em execução

Figura 10. Página “index.asp” em execução

Referência

Função “extraiScript”

http://forum.imasters.com.br/index.php?showtopic=165277

Fico por aqui e bons códigos.

Gregory Monteiro

Gregory Monteiro - Programador/administrador dos sites da DevMedia. Formado em sistemas de informação. Certificados SEO pela mestreseo e ietv. Certificado CMMI pela FIOCRUZ. Curso de web developer pela microcamp. Administrador de redes. Conhecimentos em C#, VB.NET, ASP, PHP, JSP, HTML, XHTML, HTML5, Ajax, CSS3, jQuery, JavaScript, SQL Server, MySQL, Firebird, IIS 6/7, NGINX, Linux, WPF