jueves, 26 de octubre de 2017

Deshabilitar Cortana

Equipo\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Windows Search\AllowCortana

Si no existe “Windows Search” hay que crearlo.

AllowCortana es un DWORD con valor 0

viernes, 15 de septiembre de 2017

Cambiar resolución añadiendo modo de video (con xrandr) en Linux

Vamos a establecer un modo de 1680x1050.

Lo primero calculamos la la Modeline con la utilizada cvt (VESA Coordinated Video Timing)

$cvt 1680 1050
# 1680x1050 59.95 Hz (CVT 1.76MA) hsync: 65.29 kHz; pclk: 146.25 MHz
Modeline "1680x1050_60.00"  146.25  1680 1784 1960 2240  1050 1053 1059 1089 -hsync +vsync

Luego utilizamos el xrandr para poner nuestro modo deseado

$ xrandr --newmode "1680x1050_60.00"  146.25  1680 1784 1960 2240  1050 1053 1059 1089 -hsync +vsync
$ xrandr --output VGA1 --mode  "1680x1050_60.00"
$ xrandr --output VGA1 --mode "1680x1050_60.00"

Hay que sustituir el VGA1 por el output que corresponda en cada caso, si se hace un xrandr sin nada ya nos lo muestra así como los modos actuales que tiene soportados.

miércoles, 13 de septiembre de 2017

Bashware

Quedaos con la palabra que podría comprometer a millones de equipos con Windows 10
El WSL, el subsistema para Linux que nos permite la ejecución de algunas cosas de Linux en Windows (como la bash) de forma nativa, tiene un pequeño gran problema.

La mayoría de software de seguridad y antivirus no está diseñado para lidiar con procesos Linux en sistemas Windows, es por ello que un malware que se ejecute en dicho subsistema, a día de hoy, campará a sus anchas...

Podéis ver la demo de la gente de Check Point en este vídeo:

Para más info, un buen punto de partida es este


martes, 12 de septiembre de 2017

Seguridad bluetooth comprometida

Da igual de quién seas, de Windows, de Linux, de Android, de iOS o de lo que quieras, hay fallos de seguridad que nos afectan a todos.

Miles de dispositivos con conectividad bluetooth pueden ser atacados, en algún caso incluso sin que tengas que hacer nada.
Mantén tu dispositivo actualizado siempre con los últimos parches de seguridad proporcionados por el fabricante (y aún así, algún día te la colaran).

Para muestra un botón..


viernes, 8 de septiembre de 2017

Localizar puerto al que estamos conectado vía CDP con WinDump

Si el equipo al que estamos conectado es un Cisco con CDP habilitado, simplemente usando el WinDump (en el caso de Windows) podemos localizarlo fácilmente.

Esto es sumamente útil para localizar las tomas en los paneles de parcheo, luego sólo hay que seguir el cable. Si todo está bien documentado esto no sirve de nada, pero como en muchas instalaciones no es el caso, pues se puede aprovechar.

También si tenéis un equipo viejo de cisco que soporte CDP os puede servir poniéndolo temporalmente en el armario, en cualquier instalación para encontrar a que boca del panel va cada cable.
  1. Primero vemos como se llama nuestro Intefaz para el WinDump
windump -D
1.\Device\NPF_{C6ACD745-CF9B-4366-AAAF-DCFCD2108F11} (Microsoft)
2.\Device\NPF_{44EE031D-814E-4657-B0E8-7276996469F6} (TAP-Windows Adapter V9)
3.\Device\NPF_{290F16FC-3584-4FB5-A172-DAA2272A3491} (Intel(R) Ethernet Connection I219-V)
4.\Device\NPF_{D33776EB-C80E-44AE-B3E2-0EC0EA7D938E} (Microsoft)

  1. Luego ejecutamos el siguiente comando y esperamos respuesta


windump -nn -v -i \Device\NPF_{290F16FC-3584-4FB5-A172-DAA2272A3491} -s 1500 -c 1 "ether[20:2] == 0x2000"
windump: listening on \Device\NPF_{290F16FC-3584-4FB5-A172-DAA2272A3491}
12:30:11.644124 CDPv2, ttl: 180s, checksum: 692 (unverified), length 385
        Device-ID (0x01), length: 15 bytes: 'nombredemiequipo.loquesea.com'
        Version String (0x05), length: 182 bytes:
          Cisco IOS Software, C3560 Software (C3560-IPBASE-M), Version 12.2(35)SE5, RELEASE SOFTWARE (fc1)
          Copyright (c) 1986-2007 by Cisco Systems, Inc.
          Compiled Thu 19-Jul-07 18:15 by nachen
        Platform (0x06), length: 20 bytes: 'cisco WS-C3560G-48PS'
        Address (0x02), length: 13 bytes: IPv4 (1) 1.1.1.1
        Port-ID (0x03), length: 18 bytes: 'GigabitEthernet0/2'
        Capability (0x04), length: 4 bytes: (0x00000029): Router, L2 Switch, IGMP snooping
        Protocol-Hello option (0x08), length: 32 bytes:
        VTP Management Domain (0x09), length: 4 bytes: 'test'
        Native VLAN ID (0x0a), length: 2 bytes: 12
        Duplex (0x0b), length: 1 byte: full
        ATA-186 VoIP VLAN request (0x0e), length: 3 bytes: app 1, vlan 22
        AVVID trust bitmap (0x12), length: 1 byte: 0x00
        AVVID untrusted ports CoS (0x13), length: 1 byte: 0x00
        Management Addresses (0x16), length: 13 bytes: IPv4 (1) 2.2.2.2
        unknown field type (0x1a), length: 12 bytes:
          0x0000:  0000 0001 0000 0000 ffff ffff
1 packets captured
689 packets received by filter
0 packets dropped by kernel


lunes, 28 de agosto de 2017

Empezar a trabajar con .Net Core en Linux Ubuntu

Dado que .Net Core es multiplaforma, vamos a ver cómo podríamos realizar nuestro típico "hola mundo" usando .Net Core en Ubuntu.

Añadimos las claves de Microsoft a nuestro repositorio de claves, para ello hacemos:

wget -qO - https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -

Añadimos el repositorio, en este caso para una Ubuntu 17.04
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-zesty-prod zesty main" > /etc/apt/sources.list.d/dotnetdev.list'

Instalamos el .Net
sudo apt-get update
sudo apt-get install dotnet-sdk-2.0.0

Creamos nuestra primera nueva (new) aplicación de tipo consola (console) en C#  (por defecto). Se puede obtener ayuda de comando mediante dotnet hew help:
dotnet new console -o miholamundo

El -o miholamundo especifica el directorio de salida de la aplicación. Si vamos a este directorio podemos ver que nos ha generado lo siguiente:
fran$ ls
miholamundo.csproj  obj  Program.cs

Donde miholamundo.csproj es el fichero de configuración de nuestro proyecto, al uso:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>

</Project>
y el Program.cs, es nuestro primer programa:
using System;

namespace miholamundo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

Para ejecutar basta con que hagamos un donet run dentro del directorio:
fran$ dotnet run
Hello World!

Llegados a este punto, puedo utilizar cualquier editor para modificar el fichero, añadir otros al proyecto, etc., pero voy a aprovechar para instalar en mi entorno el Visual Studio Core, evidentemente también desde paquetes, para ello, antes de nada añadimos el repositorio, actualizamos e instalamos
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list'
sudo apt-get update
sudo apt-get install code

Una vez instalado basta con ejecutar code y ya está.

viernes, 25 de agosto de 2017

Utilizar .Net Core MVC con MySQL sin Entity Framework y con consultas SQL simples

Hola dejo aquí el cómo podemos utilizar el .Net Core MVC pero pasando del Entity Framework para las conexiones a la DB y teniendo así un poco más de flexibilidad, que aunque no es quizás, tan puritano como algunos querrían, suele dar más versatilidad, y, en algunos proyectos suele ser más efectivo; sobre todo si tenemos programadores que saben de bases de datos y de SQL.

Premisas:

  • Tengo un servidor MySql instalado en local con un esquema test1 y una tabla data, que contienen dos campos id (entero sin signo, autoincremental) y dato (varchar de 45), usuario test1 con clave test1.
  • Voy a utilizar Visual Studio Community 2017 para todo el proceso, ya que está lo aprovechamos.

Creamos proyecto .Net Core MVC





Añadimos paquete Nuget del conector MySQL 

Botón derecho encima de la solución -> Administrar paquetes NuGet para la solución
Pestaña examinar Buscar Mysql

Presionar Instalar

Leemos y aceptamos si estamos de acuerdo con lo que pregunta (deberíamos):



Et voilà

Nota importante: la versión estable instalada en el momento de hacer este documento no funcionó bien y tuve que marcar la casilla de "Incluir versiones preliminares" y actualizar a la 6.10.3rc, posiblemente cuando leáis esto ya la versión que esté subida como estable será buena, por lo tanto he preferido mantener el artículo con la instalación de estable.



Añadimos el ConnectionString al fichero de configuración:

"ConnectionStrings": {
    "DefaultConnection": "server=localhost;port=3306;database=test1;user=test1;password=test1"
  }

Modelo de datos

Vamos a crear el modelo de datos, para ello creamos una nueva clase dentro de la carpeta Models que defina nuestro modelo de datos
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace test1.Models
{
    public class Dato
    {
        private string _dato;
        public int id { get; set; }
        public string dato
        {
            get { return _dato; }
            set
            {
                if (value.Length < 45)
                    _dato = value.Substring(0, 45);
                else
                    _dato = value;
            }
        }
      
    }
}


Nota importante: en el código vemos que el dato del id es tipo int, mientras que en la base de datos es uint, esto lo he puesto así, porque para el paso siguiente lo vamos a necesitar así, sino falla el asistente, pero luego hay que acordarse de cambiarlo de nuevo a uint porque no estamos usando EF.

Controlador, contexto y vistas


Vamos a añadir el controlador tal y como si estuviésemos usando Entity Framework, porque esto nos va a ahorrar escribir unas cuantas líneas.

Por lo tanto vamos a presionar con el botón derecho encima de la carpeta Controllers y darle a la opción Agregar -> Controlador y seleccionamos "Controlador MVC con ... Entity Framework"

Pulsamos "Agregar"
Completamos los datos, la clase modelo está clara en este caso es nuestra clase Dato, al seleccionarla nos pone un nombre de controlador, en mi caso lo he modificado para que se llame DatoControler   en clase de contexto pulsamos el "+" 
Elegimos el nombre de nuestro contexto de datos, en este caso le dejo el que está y pulsamos Agregar
Volvemos a pulsar Agregar

Bien si todo va bien, vemos que tendríamos, según el log de salida:
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
      User profile is available. Using 'C:\Users\francisco.counago\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
Added DbContext : '\Data\test1Context.cs'
info: Microsoft.EntityFrameworkCore.Infrastructure[100403]
      Entity Framework Core 2.0.0-rtm-26452 initialized 'test1Context' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
Added Controller : '\Controllers\DatoController.cs'.
Added View : \Views\Dato\Create.cshtml
Added View : \Views\Dato\Edit.cshtml
Added View : \Views\Dato\Details.cshtml
Added View : \Views\Dato\Delete.cshtml
Added View : \Views\Dato\Index.cshtml


Es decir el esqueleto de todo lo que necesitamos. 

Nota: cambiar el int a uint de la clase dato, porque ya podemos hacerlo.

Además si abrimos el Startup.cs veremos que ha añadido una línea para registrar nuestro contexto

¿Cuál es el problema?, nosotros no vamos a usar un contexto al uso por lo tanto debemos cambiar, algunas cosas, primero, nuestro contexto "text1Context" no viene de una clase DbContext, por lo tanto vamos a eliminar está herencia, cambiamos:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace test1.Models
{
    public class test1Context : DbContext
    {
        public test1Context (DbContextOptions options)
            : base(options)
        {
        }

        public DbSet Dato { get; set; }
    }
}

Por esto, esqueleto básico de nuestro Contexto

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace test1.Models
{
    public class test1Context
    {
        public test1Context (string pConexion)            
        {
        }        
    }
}

Por lo tanto como tampoco nos podemos añadir como un services.AddDbContext sino como un nuevo servicio, para ello cambiamos en el Startup.cs:
esto

public void ConfigureServices(IServiceCollection services)
{
            services.AddMvc();

            services.AddDbContext(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("test1Context")));
          
}

por esto
 public void ConfigureServices(IServiceCollection services)
 {
            services.AddMvc();
            services.Add(new ServiceDescriptor(typeof(test1Context), new test1Context(Configuration.GetConnectionString("DefaultConnection"))));            
 }

Con esto nos hemos desecho del DbContext del EF, realmente todo esto puede hacerse a mano sin el asistente del EF, pero he preferido hacerlo así, para que se vea que generamos lo mismo que con el EF.
Si queremos aprovechar lo máximo las vistas generadas para el EF, sólo tenemos que hacer métodos dentro de nuestro contexto que llamaremos desde el controlador.

No me voy a parar en todos los detalles (se puede ver en el código), básicamente lo que voy a hacer es cambiar este controlador

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using test1.Models;

namespace test1.Controllers
{
    public class DatoController : Controller
    {
        private readonly test1Context _context;

        public DatoController(test1Context context)
        {
            _context = context;
        }

        // GET: Dato
        public async Task Index()
        {
            return View(await _context.Dato.ToListAsync());
        }

        // GET: Dato/Details/5
        public async Task Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var dato = await _context.Dato
                .SingleOrDefaultAsync(m => m.id == id);
            if (dato == null)
            {
                return NotFound();
            }

            return View(dato);
        }

        // GET: Dato/Create
        public IActionResult Create()
        {
            return View();
        }

        // POST: Dato/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task Create([Bind("id,dato")] Dato dato)
        {
            if (ModelState.IsValid)
            {
                _context.Add(dato);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            return View(dato);
        }

        // GET: Dato/Edit/5
        public async Task Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var dato = await _context.Dato.SingleOrDefaultAsync(m => m.id == id);
            if (dato == null)
            {
                return NotFound();
            }
            return View(dato);
        }

        // POST: Dato/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task Edit(int id, [Bind("id,dato")] Dato dato)
        {
            if (id != dato.id)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(dato);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!DatoExists(dato.id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(Index));
            }
            return View(dato);
        }

        // GET: Dato/Delete/5
        public async Task Delete(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var dato = await _context.Dato
                .SingleOrDefaultAsync(m =>; m.id == id);
            if (dato == null)
            {
                return NotFound();
            }

            return View(dato);
        }

        // POST: Dato/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task DeleteConfirmed(int id)
        {
            var dato = await _context.Dato.SingleOrDefaultAsync(m => m.id == id);
            _context.Dato.Remove(dato);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }

        private bool DatoExists(int id)
        {
            return _context.Dato.Any(e => e.id == id);
        }
    }
}


por este
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using test1.Models;

namespace test1.Controllers
{
    public class DatoController : Controller
    {
        private readonly test1Context _context;

        public DatoController(test1Context context)
        {
            _context = context;
        }

        // GET: Dato
        public  IActionResult Index()
        {
            return View(_context.Listado());
        }

        //// GET: Dato/Details/5
        public IActionResult Details(uint? id)
        {
            if (id == null)
            {
                return NotFound();
            }
            Dato datoAux = _context.dame(id.Value);
            if (datoAux == null)
            {
                return NotFound();
            }
            return View(datoAux);
        }

        // GET: Dato/Create
        public IActionResult Create()
        {
            return View();
        }

        // POST: Dato/Create
        [HttpPost]
        public IActionResult Create(String dato)
        {
            if(dato==null)
            {
                return RedirectToAction(nameof(Create));
            }
            String strDato = dato;
            if(_context.Add(strDato))
            {
                return RedirectToAction(nameof(Index));
            }
            return View(new Dato { dato = strDato });
        }

        //// GET: Dato/Edit/5
        public IActionResult Edit(uint? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            Dato datoAux = _context.dame(id.Value);
            if (datoAux == null)
          {
               return NotFound();
          }
            return View(datoAux);
        }

        //// POST: Dato/Edit/5
        [HttpPost]    
        public  IActionResult Edit(uint? id, string dato)
        {
            if (id ==null)
            {
                return NotFound();
            }
            uint uiId = id.Value;
            if (dato == null)
            {
                return RedirectToAction(nameof(Edit), new { id =uiId });
            }
            String strDato = dato;
            if (_context.Update(uiId,strDato))
            {
                return RedirectToAction(nameof(Index));
            }
            return View(new Dato { dato = strDato, id=uiId });
        }

        //// GET: Dato/Delete/5
        public IActionResult Delete(uint? id)
        {
            if (id == null)
            {
                return NotFound();
            }
            Dato datoAux = _context.dame(id.Value);
            if (datoAux == null)
            {
                return NotFound();
            }
            return View(datoAux);
        }

        //// POST: Dato/Delete/5
        [HttpPost, ActionName("Delete")]

        public IActionResult DeleteConfirmed(uint? id)
        {
            if (id == null)
            {
                return NotFound();
            }
            uint uiId = id.Value;
            if (_context.Delete(uiId))
            {
                return RedirectToAction(nameof(Index));
            }
            return RedirectToAction(nameof(Delete),new { id = uiId });
        }       
    }
}




y añadir a nuestro contexto las funciones necesarias, quedando de esta forma





using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;


namespace test1.Models
{
    public class test1Context
    {
        private string strCnnString;
        public test1Context (string pstrConexion)            
        {
            strCnnString = pstrConexion;        
        }
        private List hazConsulta(string pstrConsulta)
        {
            List lstDato = new List();
            using (MySqlConnection cnn = new MySqlConnection(strCnnString))
            {
                cnn.Open();
                using (MySqlDataReader drAux = (new MySqlCommand(pstrConsulta, cnn).ExecuteReader()))
                {
                    while (drAux.Read())
                    {
                        lstDato.Add(new Dato()
                        {
                            id = drAux.GetUInt32("id"),
                            dato = drAux.GetString("dato")
                        });
                    }
                }
            }
            return lstDato;
        }
        private int ejecutaSQL(string pstrConsulta)
        {
            int iFilas = 0;
            using (MySqlConnection cnn = new MySqlConnection(strCnnString))
            {
                cnn.Open();
                iFilas = (new MySqlCommand(pstrConsulta, cnn).ExecuteNonQuery());
            }
            return iFilas;
        }
        public bool  Add(string pDato)
        {
  
            if (pDato==null || pDato.Trim().Length < 1)
                return false;
            try
            {
                return (ejecutaSQL($"insert into dato (dato) values (\"{pDato}\")") > 0) ? true : false;                
            }catch
            {
                return false;
            }
        }
        public bool Update(uint puiId,string pDato)
        {

            if (pDato == null || pDato.Trim().Length < 1)
                return false;
            try
            {
                return (ejecutaSQL($"update dato set dato= \"{pDato}\" where id={puiId}") > 0) ? true : false;
            }
            catch
            {
                return false;
            }
        }
        public bool Delete(uint puiId)
        {
            
            try
            {
                return (ejecutaSQL($"delete from dato where id={puiId}") > 0) ? true : false;
            }
            catch
            {
                return false;
            }
        }
        public List Listado()
        {

            return hazConsulta("select * from dato");
        }
        public Dato dame(uint puiId)
        {
            try
            {
                return hazConsulta($"select * from dato where id={puiId}")[0];
            }
            catch
            {
                return null;
            }              
        }


    }
}




Con esto podríamos acceder perfectamente a todas las funcionalidades "autogeneradas" pero sin EF, teniendo de esta forma mayor control sobre lo que queremos hacer, ojo, mayor control implica mayor responsabilidad a la hora de controlar los datos que si lo hacemos con el EF y un mayor control de errores, pero estas cosas están fuera del ámbito de este artículo. Podemos darle a Ejecutar en IISExpress y vemos nuestro resultado a través de URL/dato







Como podemos concluir, podemos prescindir del EF para hacer las cosas y aprovechar ciertas ventajas que nos proporciona el Visual Studio como si estuviésemos usándolo. 



L2TP Ipsec Windows to Mikrotik eror 789

 Add this to registry REG ADD HKLM\SYSTEM\CurrentControlSet\Services\PolicyAgent /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d...