Friday, May 09, 2008

SQL Injection

Computer Program ေတြ စေရးတုန္းက Senior Programmer ေတြက ကိုယ္ေရးထားတဲ့ Program ကို Test လုပ္ရင္ (ဥပမာ) Employer Name ဆိုတဲ့ Field ထဲမွာ Value ထည့္တဲ့ အခါ John လို႔ မထည့္ဘဲ John's လို႔ ထည့္လိုက္ရင္ Program က Error တက္သြားပါေရာ။ ဘာေၾကာင့္ ျဖစ္ရတာလဲဆိုေတာ့ SQL Statement ကို ရလာတဲ့ Value နဲ႔ Construct လုပ္ထားမိလို႔ပါ။ Source code က ဒီလိုမ်ိဳး

sql = "select * from emp where name = ' " + m_Name + " '"

အဲဒီ SQL ထဲကို John's ထည့္လိုက္ရင္ sql ရဲ႕ Value က ဒီလို ျဖစ္သြားပါတယ္။
select * from emp where name = 'John's'

အဲဒီေတာ့ SQL က Valid မျဖစ္ေတာ့ပါဘူး။ ဒီလုိမ်ိဳး မျဖစ္ေအာက္ ဘယ္လိုလုပ္ရသလဲ ဆိုေတာ့ SQL Parameter ေတြကို Bind လုပ္ယူရပါတယ္။
sql = "select * from emp where name = ?"
bindParmeter(1,m_Name)

အဲဒီလိုမ်ိဳးမွ ဘယ္လို value လာလာ Text (String) value ျဖစ္သြားၿပီး မွန္တဲ့ SQL Statement ကို ရပါတယ္။

ဒီအေလ့အက်င့္ဟာ အခု အသံုး၀င္လာပါတယ္။ ကုမၸဏီက System ေတြကို အစိုးရ႐ံုးေတြကို ေရာင္းတဲ့ အခါ Security နဲ႔ ပတ္သက္ၿပီး စစ္ေဆးပါတယ္။ ဥပမာ Credit Card နံပါတ္ေတြကို ေသေသခ်ာခ်ာ သိမ္းလား၊ Network Security ဘာညာေတြပါ။ စစ္တဲ့ အထဲမွာ ပါလာတာ SQL Injection အတြက္ေရာ ကာကြယ္ထားသလားေတြပါ။ SQL Injection ဆိုတာ အထက္က ေျပာသလိုပဲ Application မွာ String Value ထည့္ရမယ့္ ေနရာေတြမွာ SQL escape character ေတြသံုးၿပီး Application ကို မရည္႐ြယ္ထားတဲ့ အတိုင္း ျပဳမူ လုပ္ေဆာင္ေစတာပါ။ စနစ္တက် Develop မလုပ္ထားတဲ့ စနစ္ေတြဟာ ဒီနည္းအတိုင္း ေဖာက္ထြင္း ၀င္ေရာက္ ခံရႏိုင္ပါတယ္။ ဥပမာ Login Page မွာ User Name မွန္ မမွန္ကို ဒီလို Count က Zero မဟုတ္႐ံုနဲ႔ မွန္တယ္ စစ္ထားတယ္ ဆိုပါေတာ့
SELECT count(*) FROM users WHERE name=’FIELD_USERNAME’

အဲဒီလိုမ်ိဳးဆိုရင္ FIELD_USERNAME ရဲ႕ တန္ဖိုးကို John' or 'x' ='x လို႔ေပးလိုက္ရင္ SQL Statement က ဒီလိုမ်ိဳး ရပါမယ္။
SELECT count(*) FROM users WHERE name=’John' or 'x'='x'

အဲဒီေတာ့ ဒီ SQL မွာ WHERE Part က TRUE ျဖစ္တဲ့ အတြက္ FIELD_USERNAME အတြက္ ဘယ္လို တန္ဖိုးလာလာ အၿမဲတမ္း Run ေနေတာ့မွာပါ။ တကယ္လို႔ name ေရာ password ေရာ စစ္ထားတဲ့
SELECT count(*) FROM users WHERE name=’FIELD_USERNAME’ and password ='FIELD_PASSWORD'

လိုမ်ိဳးအတြက္ဆိုရင္ FIELD_USERNAME အတြက္ John' or 'x' ='x -- (ဒီေနရာမွာ -- က Comment ပိတ္တယ္လို႔ ယူဆမည္)
SELECT count(*) FROM users WHERE name=’John' or 'x'='x' -- and password ='FIELD_PASSWORD'

SQL Statement မွာ and ေ႐ွ႕က စၿပီး Comment ပိတ္လိုက္တဲ့ အတြက္ password ကို မွန္မမွန္ စစ္စရာ မလိုေတာ့ ပါဘူး။ ဒီလိုနည္း သံုးလိုက္ရင္ Table ေတြ Drop လုပ္ခ်င္လည္း ရလာပါတယ္။ ဥပမာ John'; DROP TABLE users; -- ဆိုရင္
SELECT count(*) FROM users WHERE name= 'John'; DROP TABLE users; -- and password ='FIELD_PASSWORD'
SQL Statement ႏွစ္ေၾကာင္း ျဖစ္သြားၿပီး တစ္ေၾကာင္းက SELECT ျဖစ္ၿပီး က်န္တဲ့ တစ္ေၾကာင္း DROP Statement ျဖစ္သြားပါတယ္။

ဒီလို လုပ္လို႔ ရတာေတြ အမ်ားႀကီး ႐ွိပါတယ္။ Google မွာ ႐ွာၾကည့္ႏိုင္ပါတယ္။

အဲဒီလို SQL Injection ေတြကုိ ကာကြယ္ဖို႔ နည္းလမ္းကေတာ့ Parameter ေတြကို Bind လုပ္ျခင္းျဖင့္ ကာကြယ္ႏိုင္ပါတယ္။ Prepared Statement ေတြ သံုးၿပီး ကာကြယ္ႏိုင္ပါတယ္။ ဥပမာ

PreparedStatement ps = con.prepareStatement("SELECT count(*) FROM users WHERE name=? and password =?");
prep.setString(1, m_UserName);
prep.setString(2, m_Password);
ps.executeQuery();

2 comments:

သဥၨာ - Thinzar - 5/12/08, 6:26 PM

thanks 4 this post =)

Anonymous - 9/18/08, 11:30 PM

ဒင္းေၾကာင့္ က်ေနာ္တို႔ဆို table ကို ထိေတာင္မထိဘူး။
view, sp တို႔နဲ႔ပဲ သြားတယ္။

Post a Comment

Many thanks for dropping a comment…

Film


Files