Server-Side
ActiveX Dll Programming
مقدمه
با
قراردادن کدهای ASP درون component های
server side ، برنامه نويس نه تنها می تواند از قابليت های ويژوال
بيسيک در نوشتن کدهای خود استفاده کند بلکه سرعت load
صفحات ASP وی نيز افزايش می يابد . همچنين اين روش راهکاری
برای کپسوله سازی و حفاظت از کدهای ASP می
باشد .
در اين درس يک نمونه اکتيويکس server-side را توسط
ويژوال بيسيک ايجاد نموده و از آن در صفحات ASP
استفاده خواهيم کرد .
اجزای Server-Side
اکتيوکس های server-side بر خلاف اکتيوکس های
clict-side بر روی
سرور وب اجرا می شوند و بنابراين بايستی وب سرور مورد استفاده با اين
تکنولوژی سازگار باشد . زمانيکه وب سرور دستوری را برای پردازش
يکسری اطلاعات درون يک صفحه ASP دريافت می
کند دستوراتی که درون تگهای قرار دارند بررسی می شوند .
با استفاده از ويژوال بيسيک می توان يک اکتيوکس dll
ساخت که جايگزين اين کدهای ASP
شود . در اينصورت تنها کافيست يک شی از کلاسهای موجود در اين dll ساخته شود تا بتوان از قابليتهای آن استفاده نمود .
ايجاد ActiveX Dll در ويژوال بيسيک
برای ساخت يک اکتيواکس ويژوال بيسيک را اجرا کرده و توسط گزينه New Project پروژه ای از نوع ActiveX Dll
ايجاد کنيد . پس از اينکه شما روی آيکون ActiveX dll کليک کنيد ويژوال بيسيک پروژه ای پيش فرض بهمراه ي: کلاس
خالی برای شما ايجاد می کند . می توانيد هم نام پروژه و
هم نام کلاس را تغيير دهيد همچنين می توانيد کلاسهای ديگری به
پروژه اضافه کنيد .
حال برای اينکه بتوان دستورات ASP را استفاده
نموده بايستی از منوی Project وارد بخش References شده و مورد Microsoft Active Server Pages Object Library را انتخاب کنيد .
استفاده از متدهای ASP در کلاس های ActiveX
بمنظور استفاده از متدهای ASP در کلاسهای
ActiveX بايستی ابتدا روتينی به اسم OnStartPage در داخل کلاس تعريف کنيد . ساختار اين روتين بصورت زير است :
Public Sub OnStartPage(PassedScriptingContext As ScriptingContext)x
End
Sub
زمانيکه کاربر يک صفحه ASP را که شامل شی ای از کلاس
ما باشد فراخوانی کند IIS ، SciptingContext را به شی ما پاس می دهد . ScriptingContext حاوی تمام متدها و خصوصيات ASP می
باشد که برای استفاده در دسترس هستند . حال بايستی
در روتين OnStartPage
تمام اشيای ASP که توسط ScriptingContext
در دسترس هستند را به اشيايي از همان نوع assign
کنيم تا در صورت لزوم بتوانيم از آنها استفاده نمائيم . بنابراين قبل از نوشتن
روتين OnStartPage
متغيرهای زير را تعريف می کنيم :
Private MyScriptingContext
As ScriptingContext
Private MyApplication As Application
Private MyRequest As Request
Private MyResponse as Response
Private MyServer As Server
Private MySession As Session
حال در روتين OnStartPage
بايستی اشيا فوق را مقداردهی کنيد :
Public Sub OnStartPage(PassedScriptingContext As ScriptingContext)x
Set
MyScriptingContext=PassedScriptingContext
Set
MyApplication=MyScriptingContext.Application
Set
MyRequest=MyScriptingContext.Request
Set
MyResponse=MyScriptingContext.Response
Set
MyServer=MyScriptingContext.Server
Set
MySession=MyScriptingContext.Session
End Sub
از تمام اشيا فوق مشابه نوشتن صفحات ASP می
توانيم در متدهايي که برای کلاس می نويسيم استفاده کنيم . برای
مثال کد ASP زير را در نظر بگيريد :
حال فرض کنيد می خواهيم همين دستورات را در يک متد از کلاس بنويسيم :
Public Sub MyMethod()x
Dim MyTempVar As String
MyTempVar=MyRequest.Form(“username”)x
MyResponse.Write(“You Entered :
“ & MyTempVar)x
End Sub
نکته ديگری که بايد در نظر داشت نوشتن روتينی است که در زمان پايان
کار با شی فراخوانی می شود . اين روتين OnEndPage نام دارد و در آن اشيايي که در روتين OnStartPage مقداردهی کرده ايم را آزاد می کنيم :
Public Sub OnEndPage()x
Set
MyScriptingContext=Nothing
Set MyApplication= Nothing
Set MyRequest= Nothing
Set MyResponse= Nothing
Set MyServer= Nothing
Set MySession= Nothing
End Sub
پس از نوشتن متدهای موردنظرتان پروژه را ذخيره کنيد . حال برای
کامپايل پروژه از منوی File مورد File/Make Dll را انتخاب
نمائيد تا پروژه کامپايل شده و فايل dll
موردنظرتان ساخته شود . اين فايل را در دايرکتوريي که صفحات ASP
شما در آنجا قرار دارد کپی کنيد .
نکته ای که بايد مورد توجه قرار داد اينست که در صورتيکه می خواهيد از
اين dll در سيستم ديگری
استفاده کنيد ابتدا بايستی آنرا رجيستر کنيد .
برای
رجيستر کردن يک dll از برنامه regsvr32.exe موجود در دايرکتوری سيستم ويندوز استفاده می شود :
Regsvr32.exe C:\InetPub\wwwroot\Example\Example.dll
استفاده از ActiveX Dll در صفحات ASP
برای استفاده از کلاس نوشته شده در فايل dll در صفحات ASP ابتدا بايستی
يک شی از آن کلاس ايجاد کنيم :
پس از ساخت شی می توانيم از متدهای موجود در کلاس استفاده کنيم
----------------------------------
+COM چيست ؟
روشی
که برای دسترسی به Object های ASP در
درس گذشته بيان شد تا IIS 3.0 استفاده می شد . اين روش
استفاده از متدهای OnStart و OnEnd بود . البته گرچه هنوز اين روش از سوی IIS
ورژن ۵ پشتيبانی می شود اما دارای يک مشکل است :
اگر بخواهيد از يک کلاس در کلاس ديگری استفاده کنيد نمی توانيد در
کلاس مورد استفاده ، دو متد ذکر شده را قرار دهيد و بنابراين به اشيای ASP
دسترسی نخواهيد داشت .
راه حلی که برای اين مشکل ارائه شد تکنولوژی +COM می
باشد .
بطور خلاصه در اين تکنولوژی شیی به اسم ObjectContext وجود دارد که از طريق آن می توانيد به اشيای ASP
دسترسی داشته باشيد .
برای استفاده از تکنولوژی +COM ابتدا از منوی
Project ، References را انتخاب کرده و مورد زير را انتخاب کنيد :
COM+ Services
Type Library
سپس در کلاسهای خود متغيرهای زير را تعريف کنيد :
Dim Request As
ASPTypeLibrary.Request
Dim Response
As ASPTypeLibrary.Response
Dim Server
As ASPTypeLibrary.Server
Dim Session As
ASPTypeLibrary.Session
Dim
Application As
ASPTypeLibrary.Application
حال در متد Initialize هر کلاس بايستی شی ObjectContext را تعريف کرده و مقداردهی کنيد . سپس متغيرهای بالا
را با استفاده از اين شی مقداردهی نمائيد :
Private Sub Class_Initialize()x
Dim
objCtx As ObjectContext
Set objCtx = GetObjectContext
Set Request = objCtx.item("Request")x
Set Response =
objCtx.item("Response")x
Set Server = objCtx.item("Server")x
Set Session = objCtx.item("Session")x
Set
Application = objCtx.item("Application")x
End Sub
+ موضوع درس بعد : دسترسی به Database در کلاسهای
اکتيوايکس Server-Side
پاسخ به سوالات شما :
۱ - چه
جوری دکمه ها و ليست باکس ها در ويژوال بيسيک را شکل اکس پی
کنيم؟اصلان می شه؟
پاسخ : ؟؟؟؟
۲ - تويه
vb چطوری ميشه فايله اجرايیdllهاشو نخاد و بدونه اونا
اجرا بشه ؟
پاسخ : برنامه های اجرايي ويژوال بيسيک برای اجرا شدن به يکسری
فايلهای ديگه نياز دارند مثلاً Vb Runtime Dll . برای اينکه به اين فايلها نيازی نباشد بايستی
يک برنامه نصب setup
file برای پروژه تان بسازيد تا بتوان
برنامه را روی هر کامپيوتری نصب و اجرا کرد . ساده تري راه استفاده از
ابزار Package & Deployment موجود در
ويژوال استديو است . ابزارهای حرفه ای تر عبارتند از : InstallShield ، InstallWise ، Setup Factory و ...
۳ - اگه
ممکنه يه توضيحی درباره ی دي کد کردن دی ال ال mpr دهيد .
پاسخ : ؟؟؟؟
۴ - چطوری
ميشه تو يه تکس باکس در ويژوال بيسيک فرمان داد اينتر شود يعنی به خط بعدی
رود؟ ( يعنی زمانی که مولتی لاين است)
پاسخ : استفاده از کاراکتر vbCrLf
۵ - من
مي خوام با زبانهايي PHP و ASP
برنامه بنويسيم ولي تمامي اين زبانها Server_side هستند و من بايد روي سرور اين كار ها رو انجام بدم من مي خوامم
بدونم كه چه طوري مي تونم كامپيوتر خودمو وب سرور كنم البته يه چيزهاي مي دونم كه
بايد IIS
رو نصب كنم ولي نه به طور كامل خواهش مي كنم كمكم كنيد
پاسخ : بايستی ويندوز ۲۰۰۰ يا XP
نصب کرده و از IIS آنها استفاده کنيد . البته در ويندوزز ۲۰۰۰
IIS بطور اتوماتيک نصب نمی شود و بايد آنرا خودتان اضافه کنيد .
برای اطلاعات بيشتر در مورد کار با IIS به کتاب ها و
مراجع اينترنتی مراجعه کنيد مراجعه کنيد .
---------------------------------
خلاصه ای
بر چگونگی کار با بانک های اطلاعاتی ( Database ) در وی بی :
+ برای
آشنايي کامل با چگونگی کار با بانک های اطلاعاتی در ويژوال
بيسيک و بطور کلی Database Programming به کتاب
برنامه نويسی بانک های اطلاعاتی در ويژوال بيسيک انتشارات نص
رجوع کنيد .
قبل از اينکه چگونگی نوشتن يک کلاس Database
برای استفاده در ASP را آموزش دهم ، مقدمه ای بر
چگونگی کار با بانک های اطلاعاتی در وی بی را شروع
می کنم .
برای کار با بانک های اطلاعاتی در ويژوال بيسيک روشها و امکانات
مختلفی وجود دارد که يکی از بهترين آنها استفاده از تکنولوژی ( ADO ( ActiveX Data Object می باشد . بدون هيچ توضيحی در مورد ساختار اين
تکنولوژی و نيز ساير روشهای ديگر ، به سراغ روش استفاده از اين
تکنولوژی می روم :
- برایکار با ADODB ابتا بايستی از Reference ها مورد Microsoft ActiveX Data Object را انتخاب کرد .
- قدم بعد تعريف يک شی ADO Connection برای
اتصال به بانک اطلاعاتی است :
Dim cn As ADODB.Connection
- سپس بايستی اين شی ADO Connection را ايجاد نمود
:
Set cn = New
ADODB.Connection
- همچنين بايستی يک شی ADO Recordset برای گرفتن مجموعه ای از رکوردهای بانک اطلاعاتی
تعريف کرد :
Dim rs As ADODB.Recordset
- حال بايستی اتصال به بانک اطلاعاتی را باز نمود . در اين مرحله با
توجه به نوع بانک اطلاعاتی و اتصالی که می خواهيم داشته باشيم
عبارت اتصال ممکن است متفاوت باشد . فرض کنيم عبارت اتصال را در يک متغير نوع String به
اسم ConnString قرار دهيم :
• در صورتی که بانک اطلاعاتی مقصد SQL Server
باشد و بخواهيم بطور مستقيم و بدون استفاده از واسط ODBC به
آن متصل شويم :
ConnString=”Provider=SQLOLEDB.1;Password=yourpassowrd;Persist
Security Info=True;User ID=yourusername; Initial Catalog=yourDatabaseName;Data
Source=yourServerName”
• در صورتی که بانک اطلاعاتی مقصد SQL Server
باشد و بخواهيم با استفاده از واسط ODBC به آن متصل
شويم :
ConnString=”Provider=MSDASQL.1;Password=yourpassowrd;Persist
Security Info=True;UserID=yourusername;DataSource=yourODBC_DataSourceName;Mode=ReadWrite”
• در صورتی که بانک اطلاعاتی مقصد Access
باشد :
ConnString=” Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=yourDatabaseFilePath;Persist Security Info=False”
حال بايستی اين اتصال را باز نمود :
cn.Open(ConnString)x
- قدم بعدی ايجاد شی ADO Recordset می باشد :
Set rs = New ADODB.Recordset
- سپس بايستی با توجه به کاری که می خواهيم با جداول آن بانک
اطلاعاتی انجام دهيم يک sql query را
توسط شی Recordset به
آن بفرستيم :
rs.Open yourSQLquery,cn,OpenKeyset, adLockOptimistic
بعبارت ديگر نوع باز کردن Recordset متفاوت است و توسط query مورد نظر مشخص
می شود برای مثال برای انتخاب فيلدهای يک Table :
SELECT
DISTINCT yourfields from yourtable
WHERE yourcondition
نکته : نوع قفل کردن مجموعه رکورد می تواند adLockReadOnly نيز باشد .
- حال با استفاده از اين Recordset می توان يکسری کار را روی رکوردهای موجود
در جداول انجام داد برای مثال :
۱ – حرکت
به ابتدای مجموعه رکورد :
rs.MoveFirst
۲ – حرکت
در طول مجموعه رکورد :
Do
tmp = rs.fields(0)x
.
.
.
rs.MoveNext
Loop Until (rs.EOF)x
3 – بستن مجموعه رکورد و بستن اتصال به بانک اطلاعاتی :
rs.Close
cn.Close
4 – حذف رکورد جاری از مجموعه رکورد :
rs.delete
5 - ايجاد رکورد جديد در مجموعه رکورد :
Dim fields(RecordsetFieldsCount) As Variant
Dim values(RecordsetFieldsCount) As Variant
fields(0) =
Field 1 Name
fields(1) =
Field 2 Name
.
.
.
fields(n) = Field n Name
values(0) =
Field 1 Value
values(1) =
Field 2 Value
.
.
.
values(n)= Field n Value
rs.AddNew fields, values
rs.update
-------------------------
آشنايي با چند
query
برای کار با جداول بانک های اطلاعاتی
1- SELECT :
برای انتخاب رکوردها از يک جدول استفاده می شود . فرمت کلی اين
دستور بصورت زير است :
SELECT fieldnames
FROM
tablename WHERE condition
ORDER BY
fieldnames
مثال : فرض کنيد يک جدول به اسم mytable
داريم که دارای دو فيلد به نامهای id از
نوع integer و name از نوع string
باشد :
– انتخاب تمامی رکوردهای جدول :
query="Select * from mytable"x
- انتخاب فيلد name
تمام رکوردهای جدول :
query="Select name from mytable"x
- انتخاب رکوردهايي از جدول که فيلد id آنها برابر 2
باشد :
query="Select * from mytable where
id=2"x
- انتخاب رکوردهايي از جدول که فيلد name آنها برابر a
باشد :
query="Select * from mytable where name=’a’"x
توجه داشته باشيد که چون فيلد name از نوع string
است در دستور فوق از ‘ برای مقدار فيلد name
استفاده شده است .
- انتخاب رکوردهايي از جدول که فيلد id آنها برابر 2
و فيلد name آنها برابر a باشد و بر حسب
id مرتب شده باشند .
query="Select * from mytable where
id=2 and
name=’a’ order by id"x
نکته : در صورتيکه بخواهيم از يک متغير برای مقداردهی به يک فيلد در query
استفاده کنيد با توجه به اينکه آن متغير از نوع integer و
يا string است بايد بصورت زير عمل کنيم :
Dim mId as integer
Dim
mName as string
mId=1
mName="a"x
query="Select
* from mytable where id="
& str(mId) & " and name=’" &
mName &
"’"x
2 – INSERT
: اين دستور برای قرار دادن يک رکورد در جدول استفاده می
شود . فرمت کلی اين دستور بصورت زير است :
INSERT INTO tablename (field1name,field2name,…) VALUES (field1value,field2value,…)x
مثال :
query="Insert into mytable (id,name) values
(1,’a’)"x
3 – UPDATE : اين دستور برای تغيير مقادير يک رکورد از جدول استفاده می
شود . فرمت کلی اين دستور بصورت زير است :
UPDATE tablename
SET
field1name=field1value, field2name=field2value,…
مثال :
query="Update mytable set id=2 , name=’b’"x
4 – DELETE : اين دستور برای حذف يک يا چند رکورد از جدول استفاده می
شود . فرمت کلی اين دستور بصورت زير است :
DELETE FROM tablename
WHERE
condition
مثال :
query="Delete from mytable where
id=1"x
حال که با تکنولوژی ADODB و نيز query های
مختلف برای کار با جداول بانک های اطلاعاتی آشنا شديد می
توانيم کلاسی برای کار با بانک های اطلاعاتی بنويسيم و از
آن در صفحات asp استفاده کنيم اما همانطور که در قسمت قبل ديديد برای اتصال
به يک بانک اطلاعاتی نياز به يکسری اطلاعات مثل نام سرور ، نام بانک
اطلاعاتی و ... داريم . چند روش برای دادن اين اطلاعات وجود دارد :
1 – در کلاسی که می نويسيم اين مقادير را مشخص کنيم . اشکال اين روش
اينست که از کلاس نوشته شده تنها برای يک کاربرد خاص می توانيم استفاده
کنيم و در صورتيکه سرور بانک اطلاعاتی و يا نام بانک اطلاعاتی ويا username و password اتصال تغيير کند بايستی
در کلاس نوشته شده نيز تغييرات را اعمال کرده و مجدداً آنرا کامپايل کنيم .
2 – راه حل دوم اينست که پارامترها را از طريق asp به
متد اتصال موجود در کلاس بفرستيم برای مثال :
Set
db=server.createobject(“dbclass.database)x
Db.connect(servername,databasename,username,password)x
که coonect متد اتصال به
بانک اطلاعاتی در کلاس database می باشد
.
3 – روش سوم آنست که اين پارامترها را در يک فايل XML قراردهيم و در متد connect آنها را از
فايل بخوانيم . مزيت اين روش اينست که پارامترها هم به آسانی قابل تغيير
بوده و هم براحتی آنها می توان آنها را استخراج نمود .
برای اين منظور بايستی ابتدا يک کلاس برای خواندن اطلاعات از
فايل xml بنويسيم که موضوع درس بعد می باشد .
نکته : در صورتيکه با فرمت فايلهای xml آشنا نيستيد
پيشنهاد می کنم يک مطالعه مقدماتی در اين زمينه انجام دهيد .
----------------------
نوشتن کلاس Database - بخش اول :
پس از
مباحثی که در مورد شی ADODB و چگونگی
استفاده از آن در وی بی و نيز استفاده از فايلهای XML
داشتيم اکنون می توانيم يک کلاس کامل و قدرتمند برای کار با بانکهای
اطلاعاتی در ASP بنويسيم .
مراحل کار بصورت زير می باشد :
۱ - ابتدا
يک پروژه از نوع ActiveX
Dll ايجاد کنيد و
نام آنرا DBase بگذاريد .
۲ - از
بخش References مواردی را که در مباحث قبلی گفته شد به پروژه اضافه
کنيد .
۳ -
متغير Cn را برای
کلاس بصورت زير تعريف کنيد :
Private Cn As ADODB.Connection
۴ - ابتدا
يک متد به اسم InitialConnection
برای کلاس می نويسيم . در اين متد ابتدا پارامترهای اتصال به
بانک اطلاعاتی را مشابه آنچه در درس قبل گفته شد از يک فايل XML به
اسم config.xml می
خوانيم و با استفاده از آنها اتصال به بانک اطلاعاتی را باز می کنيم :
Public Sub
InitialConnection()x
Dim userName, Password, database_name, server_name
Dim xmlf As NewXMLReader
Call
xmlf.Initiate("config.xml")x
userName = xmlf.getvalue("DataBaseID") x
Password = xmlf.getvalue("DataBasePassword")
x
database_name = xmlf.getvalue("DataBaseName")
x
server_name = xmlf.getvalue("ServerAddress")x
Set Cn = CreateObject("ADODB.Connection")x
Cn.ConnectionString = "Provider=SQLOLEDB.1;Password=" & Password & ";Persist Security
Info=True;User ID=" & userName & ";Initial Catalog="
& database_name
& ";Data
Source=" & server_name
Cn.Mode = adModeReadWrite
Cn.Open
End Sub
لازم به ذکر است که XMLReader
کلاس کار با فايلهای XML است که در
قسمت قبلی در مورد آن صحبت کرديم .
5 - برای بستن اتصال متد زير را به کلاس اضافه کنيد :
Public Sub
EndConnection()x
Cn.Close
Set Cn = Nothing
End Sub
6 - برای اجرای query هايي که نتيجه
آنها از نوع Boolean است ( مثل Insert و Delete )
متدی به اسم ExecuteUpdate را
به کلاس اضافه کنيد :
Public
Function ExecuteUpdate(ByVal squery
As String) As Boolean
Dim myrs As New Recordset
If Not (makesInjection(squery)) Then
myrs.LockType = adLockOptimistic
Set myrs = Cn.Execute(squery) x
ExecuteUpdate = True
Exit Function
Else
ExecuteUpdate = False
Exit Function
End
If
End Function
6 - برای اجرای query هايي که نتيجه
آنها از نوع RecordSet
است ( مثل Select ) متدی به اسم ExecuteQuery را به کلاس اضافه کنيد :
Public
Function ExecuteQuery(ByVal squery
As String) As Recordset
If
Not (makesInjection(squery)) Then
Set ExecuteQuery = Cn.Execute(squery)x
Exit Function
Else
Set ExecuteQuery = Nothing
Exit Function
End If
End Function
همانطور که می بينيد در دو متد ExecuteUpdate و ExecuteQuery از
تابعی به اسم makesInjection
استفاده شده است . اين تابع بررسی می کند که آيا در query
ورودی SQL-Injection وجود دارد يا نه .
- اين تابع موضوع قسمت بعدی اين سلسله مباحث می باشد .
------------------------------------------------
نوشتن کلاس Database : بخش دوم
sql-injection چيست ؟
همانطور که
می دانيد در اغلب برنامه های کاربردی تحت وب از بانکهای
اطلاعاتی استفاده می شود . اين برنامه ها داده های ورودی
کاربر را از طريق فرمهای html دريافت کرده و
بر اساس آن يک query توليد کرده و آنرا به بانک اطلاعاتی ارسال می کنند .
در واقع ارتباط بين برنامه تحت وب با بانک اطلاعاتی بر اساس توليد query از
داده های کاربر برقرار می شود . اکثر اين برنامه ها از زبان SQL
برای اين ارتباط استفاده می کنند . اما نکته ای که در اين بين
وجود دارد اينست که توليد query بر اساس داده
هايی که کاربر مستقيماً در فيلدهای ورودی صفحه وب وارد کرده می
تواند خطرناک باشد . بعبارت ديگر اگر برنامه محتويات يک فيلد را که توسط کاربر
وارد شده در جلوی يک دستور SQL بچسباند و آنرا جهت
اجرا روی بانک اطلاعاتی بفرستد در اينصورت يک هکر ماهر که با زبان SQL
آشنا باشد می تواند محتويات اين فيلدها را طوری با دستورات SQL پر
کند و چون ای داده ها مستقيماً برای توليد query
استفاده می شود ممکنست آن query تبديل به يک
فرمان مخرب شده و پس از اجرا ، اهداف نفوذگر را برآورده نمايد .
مثال : فرض کنيد دو فيلد به اسمهای
username
و password در يک فرم وب
قرار دارد که برای ورود به يک سايت استفاده می شود . همچنين فرض کنيد
از اطلاعات اين فيلدها بطور مستقيم يک query بصورت زير برای
بانک اطلاعاتی ارسال شود :
us=request.form("username")
psw=request.form("password")
query="SELECT * FROM Users WHERE username='"&us&"' AND
password='"&psw&"'"
حال در صورتيکه هکر يک username صحيح ( مثلاً xxx ) از سيستم را
بداند و در فيلد username مقدار صحيح را وارد کرده و
در فيلد password عبارت زير را وارد کند :
1111111' or username='xxx'
در اينصورت query
بصورت زير در می آيد :
SELECT *
FROM Users WHERE username='xxx' AND password='111111' or username='xxx'
در اينصورت هکر بدون دانستن يک password مجاز می تواند به سيستم وارد شود .
اين امر بخاطر آنست که چون فيلدهای وارد شده توسط کاربر بطور مستقيم در query قرار داده شده اند هکر توانسته کاراکتر ' را که در زبان SQL يک
کاراکتر کنترلی بوده و عملکرد خاصی دارد ( عمل خاتمه دادن به عبارت SQL )
را در در query بگنجاند و سپس با دادن دستورات SQL
مناسب کنترل را بدست بگيرد .
اين سناريو می تواند بسيار
خطرناکتر باشد زيرا هکر می تواند از ساير دستورات SQL
مثل INSERT و DELETE نيز استفاده کند .
-
در نگارش مطالب فوق از کتاب " نفوذگری در شبکه و روشهای
مقابله با آن " نوشته مهندس احسان ملکيان استفاده شده است . برای آشنايی
بيشتر با sql-injection و روشهای
مقابله با آن به صفحات ۳۲۰ تا ۳۲۸ اين کتاب مراجعه کنيد .
برای مقابله با اين حملات
بايستی از داده های ارسال شده توسط کاربر مستقيماً query
توليد نکنيم بلکه ابتدا عدم وجود کاراکترهای کنترلی مثل ' و " و
; و *و غيره را در آن بررسی کنيم . برنامه ابتدا بايد در query وجود چنين کاراکترهايی را در مکانهای غيرمجاز بررسی
کند . در بخش بعدی برنامه ای را جهت بررسی query های
SQL بمنظور مقابله با sql-injection
ارائه خواهم داد .
------------------------------
تابع بررسی وجود sql-injection که در قسمت قبل در آن صحبت کرديم بصورت زير است :
Private Function makesInjection(ByVal query As String) As Boolean
Dim specialCharacters() As String
Dim inQoute As Boolean
specialCharacters = "-- ;,"
inQoute = False
For i = 1 To Len(query)
Char = Mid(query, i,
1)
If Mid(query, i, 1) =
"'" And inQoute = False Then
inQoute
= True
GoTo
EndFor
End If
If Mid(query, i, 1) =
"'" And inQoute = True Then
inQoute
= False
GoTo
EndFor
End If
If inQoute = False
Then
For Index = 1 To UBound(specialCharacters)
schar = specialCharacters(Index)
cchar = Mid(query, i, Len(schar))
If schar = cchar Then
Exit For
End If
Next
If Index < UBound(specialCharacters) Then
makesInjection = True
Exit
Function
End If
End If
EndFor:
Next
If inQoute = True Then
makesInjection = True
Else
makesInjection = False
End If
End Function
ورودی اين تابع query
شما و خروجی آن false ياtrue
است .
عملکرد تابع بصورت زير است :
اين تابع در طول رشته query شروع به حرکت می کند و هر
کاراکتر از آنرا بررسی می نمايد . در صورتيکه کاراکتر جاری ‘
باشد و داخل ‘ ’ نباشيم متغير مربوط به آن true
شده و حلقه يکی بجلو می رود . اما در صورتيکه کاراکتر جاری ‘
باشد و داخل ‘ ’ باشيم متغير مربوط به آن false
شده و حلقه يکی بجلو می رود . سرانجام در صورتيکه داخل ‘ ’
نباشيم بررسی می شود که اين کاراکتر يکی از کاراکترهای
غير مجاز ( کاراکترهای موجود در رشته specialCharacters ) نباشد که اگر باشد تابع true بر می
گرداند .
پس از اتمام حلقه متغير مربوط به ‘ بررسی می شود که اگر true
باشد در صورت injection وجود داسته و تابع نيز true بر می
گرداند .
-----------------------
نکته ای
در مورد شی Recordset :
متد ExecuteQuery که در کلاس Database
نوشتيم يک رکوردست را بعنوان نتيجه انجام query ورودی
روی بانک اطلاعاتی شما برمی گرداند .
همانطور که می دانيد توسط خصوصيت RecordCount
می توان تعداد رکوردهای نتيجه شده از يک query را
که در رکوردست قرار دارند بدست آورد .
اما مشکلی وجود دارد اينست که با روشی که ما در قسمتهای قبل برای
اجرای query در اين متد استفاده کرده بوديم ( myrs = Cn.Execute
query ) نمی توان از خاصيت Recordcount رکوردست استفاده نمود زيرا هميشه ۱- برمی گرداند .
بعبارت ديگر در عبارت زير مقدار count هميشه ۱-
خواهد بود :
myrs.execute(query)
count=myrs.RecordCount
برای حل اين مشکل بايستی
رکوردست را با CursorType مساوی adOpenStatic باز کرد . بعبارت ديگر بجای دستورات فوق از دستور زير
استفاده کنيد :
myrs.Open squery,
Cn, adOpenStatic, adLockOptimistic
count=myrs.RecordCount
بازگشت به فهرست
بازگشت به صفحه نخست