Foro de elhacker.net

Programación => Programación Visual Basic => Mensaje iniciado por: HaDeS, - en 3 Noviembre 2007, 04:32 am



Título: Winsock + Protocolos mas usados versión 1 (HTTP)
Publicado por: HaDeS, - en 3 Noviembre 2007, 04:32 am
(Cabe aclarar que los contenidos son básicos, así que ¡no se aceptan críticas destructivas!, de seguro también me equivoque por ahí, así que los errores me los envían al privado)

Protocolo HTTP
Es un protocolo donde se debe seguir el esquema de cliente-servidor (Donde el cliente se conecta al servidor, hace una petición, y el servidor responde de acuerdo a la estructura de esa petición), luego de que el servidor procesa la petición, se cierra la conexión, aunque el cliente también la puede cerrar. Como este protocolo no es un protocolo de estado, esto es que no guarda información que haya mandado el cliente, entonces se recurre a las cookies como archivo temporal para hacer esto.

Cliente
Existe un formato estándar para la petición que realiza el cliente, así:
El crlf significa retorno de carro y avance de línea [enter]
Código
  1. (Método) (Archivo o recurso) (Versión protocolo)(crlf)
  2. (Cabecera1)(:) (Valor)(crlf)
  3. (Cabecera2)(:) (Valor)(crlf)
  4. (CabeceraN)(:) (Valor)(crlf)
  5. (crlf)
  6. (Cuerpo del mensaje)
  7.  

Metodos::
Los métodos dependen del servidor y pueden ser definidos por el programador, aunque los que se usan comúnmente o los “necesarios” por así decir son el método GET y POST. También existen varios como OPTIONS, HEAD, TRACE, PUT, pero no los vamos a tratar.
GET: Se utiliza para hacer petición de un archivo X indicado en la primera línea del formato de petición del cliente.
POST: Se utiliza para enviar datos a un archivo X indicado en la primera línea del formato de petición el cliente.
OPTIONS: Se utiliza para hacer petición al servidor de los métodos que puede usar el cliente.

Cabeceras::
Son varias las cabeceras que necesitamos para realizar una petición correctamente. Entre ellas encontramos Host, User-Agent, Accept, Accept-Charset, Keep-Alive, Connection. Cabe decir que no son necesarias las cabeceras, ya que con solo la conexión y el método podemos hacer un request a una página.
Host: Indica el nombre de la “página web” a la que queremos acceder. Si el servidor aloja varias páginas web, se debe indicar esta cabecera, ya que si no lo hacemos se puede estar accediendo a otra parte del servidor.
User-Agent: Indica el nombre de la aplicación que usa el cliente en el momento de la conexión.
Accept: Indica los tipos de archivo que acepta el cliente.
Acept-Charset: Indica que tipo de caracteres acepta el servidor.
Connection: Indica si la conexión se cierra al momento de procesar la petición, o si queda a la escucha de mas peticiones. Si es así se indica la cabecera keep-alive.
Keep-Alive: Indica el tiempo en milisegundos de espera del servidor en escucha de más peticiones. Se usa en conexiones persistentes, y sirve para hace peticiones sobre múltiples objetos.

Servidor:
La respuesta del servidor al cliente va así:
Código
  1. (Respuesta)(crlf)
  2. (Cabeceras del servidor)(crlf)
  3. (crlf)
  4. (Cuerpo del mensaje)
  5.  

Respuesta:
Indica la versión y un código de estado. Los códigos más comunes son:
200 = Indica que todo va bien
300 = Que existen múltiples archivos con algún nombre
302 = Recurso movido temporalmente
400 = Mala petición
403 = Denegado
404 = No se encontró el recurso
500 = Error interno del servidor
501 = No implementado (Para los métodos)
Entre otros.

Cabeceras del servidor:
En estas cabeceras se puede encontrar información acerca del servidor, tal como el nombre mismo del servidor que se usa, el sistema operativo en el cual se encuentra (Aunque muchas veces no lo da), la fecha y hora en la que se encuentra, las cookies que el manda, el tipo de contenido que se envió, entre otros.

Cuerpo del mensaje:
En esta se encuentra la respuesta en si del servidor a un recurso que existe.


Para entenderlo todo mejor un ejemplo de las dos conexiones mas usadas, GET y POST.

Caso1
Tenemos un servidor donde esta alojado un archivo html llamado “ejemplo.html” que esta ubicado en la carpeta “ejemplos” de la carpeta raíz de tal servidor. Además de esto sabemos que el nombre del servidor es “ejemplo.co”

Petición del cliente:
Código
  1. GET /ejemplos/ejemplo.html http/1.1 (crlf)
  2. Host: ejemplo.co (crlf)
  3. Connection: Close (crlf)
  4. (crlf)
  5.  

A lo que el servidor respondería:
Código
  1. HTTP/1.1 200 OK (crlf)
  2. Server: Ejemplos/1.1 (crlf)
  3. Date: Fri 02 Nov 2007 00:00:03 GMT (crlf)
  4. Content-Length: 81 (crlf)
  5. (crlf)
  6. <html><head><title>Ejemplos</title></head><body><h1>Ejemplo!!</h1></body></html>
  7.  
El content-length indica cuantos bytes fueron transferidos en el cuerpo del mensaje.
Luego de esto se cerraría la conexión.

Acá entra el concepto de variables get usadas en php. Veamos:

Hola.php ubicado en la carpeta raiz de un servidor que se llama variables.com:
Código
  1. $mensaje = $_GET['msg'];
  2. Echo $mensaje;
  3.  

Petición:
Código
  1. GET /hola.php?msg=holaaaa HTTP/1.0 (crlf)
  2. Host: variables.com (crlf)
  3. Connection: Close (crlf)
  4. (crlf)
  5.  

Respuesta:
Código
  1. HTTP/1.0 200 OK
  2. Server: Ejemplos/1.1 (crlf)
  3. Date: Fri 02 Nov 2007 00:00:06 GMT (crlf)
  4. Content-Length: 7 (crlf)
  5. (crlf)
  6. holaaaa
  7.  

Vemos que en la petición, la variable get se envía en la primera línea, donde se hace petición del recurso. El recurso de separa de la variable con un signo de interrogación “?” y la variable tiene el formato: “Variable” “=” “Contenido”: hola.php?msg=holaaa.
El script obtiene el contenido de la variable “msg” y hace un echo con ella.
Se cierra la conexión.


Título: Winsock + Protocolos mas usados versión 1 (HTTP)
Publicado por: HaDeS, - en 3 Noviembre 2007, 04:34 am
Caso2
Acá implementaremos el método POST. Tenemos un archivo php llamado datos el cual recibe el nombre, apellido, y teléfono de una persona X. No esta ubicado en ningún host, así que vamos a acceder por la dirección IP.

Datos.php:
Código
  1. $nombre = $_POST['name'];
  2. $apellido = $_POST['lname'];
  3. $telefono = $_POST['tel'];
  4.  
  5. $a = fopen("buscar.php", "a");
  6. fwrite($a, $nombre . " .. " . $apellido . " .. " . $telefono . "<br>");
  7. fclose($a);
  8. echo "Bien :)";
  9.  

La petición iría así:
Código
  1. POST /datos.php HTTP/1.1 (crlf)
  2. Content-Length: 37 (crlf)
  3. (crlf)
  4. name=maría&lname=cristina&tel=2880000
  5.  

No contiene la cabecera host, por lo que dije antes, de que solo se conectaría al ip.
Y la respuesta del servidor:
Código
  1. HTTP/1.1 200 OK
  2. Server: Ejemplos/1.1 (crlf)
  3. Date: Fri 02 Nov 2007 00:00:09 GMT (crlf)
  4. Content-Length: 7 (crlf)
  5. (crlf)
  6. Bien :)
  7.  

El script guardaría en el archivo “Buscar.php” el nombre, apellido y teléfono de la persona la cual ingreso los datos.
Ahora para hacer todo mas dinámico les propongo un ejercicio :P
Resulta que el archivo “buscar.php” no estaba vació del todo, el programador se ingenuo una forma para hacer que él solo ingresara a ese archivo, pero no se percato de que el archivo podría salirse de sus manos y parar en las mías :D
Ahora este es el código de buscar.php:
Código
  1. $acceso = 0;
  2. $var = $_SERVER['HTTP_MD5'];
  3. $var2 = $_POST['codigo'];
  4.  
  5. if($var2 == "HaDeS"){
  6. if( md5($var2) == $var){
  7. //Acceso, vista de datos y manejo de sesiones.
  8.            }else{ exit("Fuera!") };
  9. }else{ exit("Fuera!") };
  10. ?>
  11. maría .. cristina .. 2880000
  12.  
El ejercicio trata de fabricar la petición que nos dará acceso a la información que se guarda en este file… xD
Editado: También deberan encontrar la vulnerabilidad de algún archivo que publique mas arriba, y luego como explotarla!!

Y el segundo caso del segundo caso (envío de archivos):
Tenemos un archivo “subir.asp” con el siguiente code:
Código
  1. Dim Archivo
  2. Set Archivo = Server.CreateObject("Perits.Upload")
  3. Archivo.Save(Server.MapPath("\"))
  4. Set Archivo = Nothing
  5.  

Y tenemos el formulario de envío:
Código
  1. <form action=subir.asp method=post enctype=multipart/form-data>
  2. <input name=archivo type=file>
  3. <input type=submit name=Submit value=Mandar>
  4. </form>
  5.  

La petición, vamos a mandar un archivo de 25 bytes para no ampliarnos tanto:
Código
  1. POST /subir.asp HTTP/1.0 (crlf)
  2. Content-Type: multipart/form-data, boundary=tyoasEdRQLsovS3LUFPBS5Eyy7tOwzil (crlf)
  3. Content-Length: 197 (crlf)
  4. (crlf)
  5. --tyoasEdRQLsovS3LUFPBS5Eyy7tOwzil (crlf)
  6. Content-Disposition: form-data; name="archivo"; filename="imagen.jpg" (crlf)
  7. Content-Type: image/jpeg (crlf)
  8. (crlf)
  9. Soy un jpg modificado!!! (crlf)
  10. --tyoasEdRQLsovS3LUFPBS5Eyy7tOwzil—
  11.  

Como ven, ya se pone un poco complicada la cosa, pero miremos su estructura:
Código
  1. POST (Recurso) (Versión protocolo) (crlf)
  2. (Content-Type)(:) (Tipo de contenido)(,) (boundary)(=)(codigo) (crlf)
  3. (Content-Length)(:) (Longitud de datos del cuerpo del mensaje) (crlf)
  4. (crlf)
  5. (codigo) (crlf)
  6. (Content-Disposition)(:) (datos) (crlf)
  7. (Content-Type)(:) (Tipo archivo) (crlf)
  8. (crlf)
  9. (contenido archivo) (crlf)
  10. (codigo)
  11.  
Explico varias cosas:
El content-type varia por el tipo de archivo que mandamos, si estamos mandando varios post o varios archivos este tipo sera: multipart/form-data, si es otro tipo de archivos remitirse a: http://www.utoronto.ca/webdocs/HTMLdocs/Book/Book-3ed/appb/mimetype.html

El codigo sirve para separar los diferentes post que estamos mandando, diferentes archivos por ejemplo, seria:
Código
  1. (codigo)
  2. Archivo 1
  3. (codigo)
  4.  
  5. (codigo)
  6. Archivo 2
  7. (codigo)
  8.  

El content-Length es la longitud de los datos, pero no solo de los archivos si no de todo el cuerpo del mensaje, incluyendo los códigos.

Ja! No se que mas decir jaja, a ver, en el content-disposition de la petición que armamos “Content-Disposition: form-data; name="archivo"; filename="imagen.jpg"”, se distinguen varios puntos, el “name” que es la variable que estamos enviando, y el “filename” que supuestamente es el nombre del archivo que mandamos.

Y bueno, con esto se acaba la breve explicación del protocolo http, si quieren investigar y saber más acerca de este, existe el rfc: http://tools.ietf.org/html/rfc2616.


Título: Winsock + Protocolos mas usados versión 1 (HTTP)
Publicado por: HaDeS, - en 3 Noviembre 2007, 04:38 am
Código Visual Basic:
El código es lo mas sencillo de todo el proceso, voy a publicar solo la base, y luego el proyecto entero.

Necesitamos:
CommandButton: Nombre = Request
TextBox: Nombre = Url
TextBox: Nombre = Petición
                Multicine = True
TextBox: Nombre = Resp
                Multiline = True
Componente: Microsoft Winsock Control 6.0: Nombre = Ws

Código
  1. Private Sub Request_Click()
  2. Host = SepararHostdeUrl(Url.text)
  3. Ws.Connect Host, 80 ‘El puerto por defecto del servicio http es el 80
  4.  
  5. Volver:
  6. If Ws.State <> sckConnected Then ‘Si el cliente no esta conectado entonces va a el punto de referencia “Volver”
  7.       DoEvents
  8.       Goto Volver
  9. End If
  10. ‘Esto provocaría un loop infinito si no se hacen bien las cosas, en el código completo esta corregido el fallo.
  11.  
  12. Ws.Senddata Petición.text
  13. End Sub
  14.  
  15. Private Function SepararHostdeUrl(Url$) As String
  16. ‘Esta función sirve para separar el host de la URL
  17. Dim Host$, X%
  18. If Url <> "http://" Then
  19.    Host = Replace(Url, "http://", "")
  20.    X = InStr(1, Host, "/")
  21. Volver:
  22.    If X <> 1 Then
  23.        If X <> 0 And Len(Host) <> X Then
  24.            Host = Mid$(Host, 1, X - 1)
  25.        Else
  26.            Host = Replace(Host, "/", "")
  27.        End If
  28.    Else
  29.        Host = Mid$(Host, 2, Len(Host) - 1)
  30.        GoTo Volver
  31.    End If
  32.    X = InStr(1, Host, ".")
  33.    If X <> 0 And Len(Host) = X Then
  34.        Host = Replace(Host, ".", "")
  35.        Host = Host & ".com"
  36.    ElseIf X = 0 And Host <> "localhost" Then
  37.        Host = Host & ".com"
  38.    End If
  39. Volver2:
  40.    If InStr(1, UrlChars, Mid$(Host, 1, 1), vbTextCompare) = 0 Then
  41.        Host = Mid$(Host, 2, Len(Host) - 1)
  42.        GoTo Volver2
  43.    End If
  44. Volver3:
  45.    If InStr(1, Mid$(UrlChars, 1, 26), Mid$(Host, Len(Host), 1), vbTextCompare) = 0 Then
  46.        Host = Mid$(Host, 1, Len(Host) - 1)
  47.        GoTo Volver3
  48.    End If
  49. End If
  50. SepararHostdeUrl = Host
  51. End Function
  52.  
  53. Private Sub Ws_DataArrival(ByVal bytesTotal As Long)
  54. Dim Respuesta as string
  55. Ws.Getdata Respuesta, vbstring, bytestotal
  56. Resp.Text = Respuesta
  57. End Sub
  58.  

Explico varias cosas:
La función “SepararHostdeUrl” todavía no esta completamente terminada, me falta agregarle para que funcione con números ip.

Ws.Connect, se utiliza para conectar al servidor, el primer parámetro indica el host o Ip del servidor, y el segundo indica el puerto en el cual se esta brindando el servicio.

Ws.Senddata, se utiliza para enviar datos al servidor.

Ws.Getdata, se utiliza para recibir lo que nos manda el servidor, el primer parámetro es la variable en la cual se almacenara lo que este nos envié, el segundo parámetro es el tipo de dato que se esta recibiendo y el tercer dato es la longitud de los datos que recibimos.

El textbox “Petición” debe estar especialmente armada con la petición que queremos enviar. Ej:
Código
  1. GET / HTTP/1.1
  2.  
En la versión completa del minibrowser, esta implementadas algunas funciones como guardar la respuesta del servidor, editar variables, construirlas, manejo de cookies.

Guardar respuesta del servidor:
Como vemos en las respuesta del servidor, podemos separar dos elementos claros, las cabeceras del servidor y el cuerpo del mensaje, los cuales están separados por un doble (crlf), para guardar la respuesta del servidor, por ejemplo un archivo .exe, lo unico que hacemos en el codigo es separar toda la respuesta en dos, la primera parte es la que desechamos que son las cabeceras del servidor, y la segunda la guardamos la cual es el archivo en si:
Código
  1. Ws.getdata Datos
  2. ...
  3. If InStr(1, Datos, vbCrLf & vbCrLf) Then ‘Si en los datos se encuentra el doble crlf
  4. Guardar = Split(Respuesta, vbCrLf & vbCrLf, 2)(1) ‘variable guardar es la segunda parte de la division de la respuesta teniendo encuenta el crlf
  5. Else
  6.    Guardar = Datos ‘si no se encuentra el doble crlf, la variable guardar son los datos
  7. End If
  8.    Canal = FreeFile ‘escogemos canal libre
  9.    Open App.path & “\archivo” For Binary Access Write As Canal ‘abrimos el archivo “archivo” en modo binari0, para los archivo como imagenes o ejecutables.
  10.    Put #Canal, LOF(Canal) + 1, Guardar ‘escribimos sobre el archivo
  11.    Close #Canal ‘cerramos canal
  12.  

Sin programación sería algo así:
HTTP/1.1 200 OK
Bla Bla
Bla Bla
Content-Length: 1024

BMP….

El código separaría las cabeceras que manda el servidor con el cuerpo del mensaje, y luego guardaría el cuerpo del mensaje en el archivo indicado. En este caso se guardaría un bmp de 1 mega.

Manejo de Cookies:
Para el manejo de cookies, nos debemos fijar en la cabecera que nos manda el servidor.
Un ejemplo:
Código
  1. HTTP/1.1 302 Found
  2. Date: Sat, 03 Nov 2007 02:03:25 GMT
  3. Server: Apache
  4. Expires: Thu, 19 Nov 1981 08:52:00 GMT
  5. Set-Cookie: pwl=4d186321c1a7f0f354b297e8914ab240; expires=Sat, 03 Nov 2007 03:03:26 GMT
  6. Content-Length: 0
  7.  

El valor de la cookie, nos la manda el servidor con la cabecera Set-Cookie, por lo cual si queremos manejar las cookies, debemos agregar un TextBox con el nombre Cookie.text, y el siguiente código meterlo en el Ws_DataArrival:
Código
  1. Ws.getdata Datos
  2. Parte1 = Split(Datos, vbCrLf) ‘dividimos la cabecera del servidor según el crlf
  3.    For i = 0 To UBound(Parte1) ‘recorremos todas las cabeceras
  4.        Parte2 = Split(Parte1(i), " ", 2) ‘cada cabecera la dividimos según la cabecera y contenido
  5.        If LCase$(Parte2(0)) = "set-cookie:" Then ‘si la cabecera es set-cookie
  6.            Parte3 = Split(Parte2(1), ";") ‘dividimos el contenido por “;”
  7.            For n = 0 To UBound(Parte3) ‘recorremos su contenido
  8.                If LCase$(Mid$(Trim$(Parte3(n)), 1, 8)) <> "expires=" And LCase$(Mid$(Trim$(Parte3(n)), 1, 6)) <> "path=/" Then ‘ignoramos los “expires” y los “path”
  9.                    If InStr(1, Cookie.Text, Parte3(n)) = 0 Then ‘si el contenido de la cookie ya estaba en el textbox se ignora el nuevo contenido
  10.                        If Cookie.Text = "" Then ‘si cookie.text esta vacío
  11.                            Cookie.Text = Parte3(n) ‘metemos la cookie
  12.                        Else
  13.                            Cookie.Text = Cookie.Text & "; " & Parte3(n) ‘si no esta vacío, ponemos el contenido de cookie mas un “; “ y luego metemos la cookie nueva
  14.                        End If
  15.                    End If
  16.                End If
  17.            Next n
  18.        End If
  19. Next i
  20.  

Bueno, es todo!! ya hare la versión dos para irc, o smtp no se xD
Adjunto el proyecto entero:
Esta todo comentado para que los que están comenzando con el visual basic lo entiendan.

Saludos :)


Título: Re: Winsock + Protocolos mas usados versión 1 (HTTP)
Publicado por: Hendrix en 3 Noviembre 2007, 18:36 pm
Agregado al post de recopilacion de manuales (https://foro.elhacker.net/index.php/topic,139885.0.html)  ;)


Título: Re: Winsock + Protocolos mas usados versión 1 (HTTP)
Publicado por: Ferсhu en 12 Noviembre 2007, 05:08 am
Muy buena info. Esta muy bueno el programa para manejar peticiones http  :D

ya no voy a usar mas el netcat jaja, ahora es mas facil.

Espero q le hagas le hagas mas modificaciones jaja ya sabes cuales.




Título: Re: Winsock + Protocolos mas usados versión 1 (HTTP)
Publicado por: LeandroA en 13 Noviembre 2007, 06:06 am
Exelente Trabajo muy bueno el aporte

Saludos y segui asi



Título: Re: Winsock + Protocolos mas usados versión 1 (HTTP)
Publicado por: Karcrack en 13 Noviembre 2007, 19:25 pm
Muchisimas gracias ;D Lo andaba buscando ;)