အခန်း ၁၆ :: Security

Web Developer ဖြစ်စေ mobile app developer ဖြစ်စေ security နှင့် ပတ်သက်ပြီးတော့ အခြေခံတွေကို နားလည် သိထားဖို့ လိုပါတယ်။ Mobile app ဖြစ်ပေမယ့် အသုံးပြုထားသည့် API call တွေဟာ အများအားဖြင့် web app နဲ့ ဖန်တီးထားတာတွေပါ။

SQL Injection

SQL Injection ကို လူတိုင်းကြားဖူးပါလိမ့်မယ်။ Website ဖန်တီးသည့် အခါ ဖြစ်ဖြစ် API ဖန်တီးသည့် အခါဖြစ်ဖြစ် SQL Injection ကို သိရှိထားဖို့ လိုပါတယ်။

http://www.example.com/search?q=hello

ဆိုသည့် URL က database ထဲမှာ hello ကို ရှာပေးပါသည်။

SELECT * from contents where text like "%hello%";

ဆိုပြီး SQL code ကို ပြန်ပြောင်းရေးထားသည်။

အကယ်၍သာ

http://www.example.com/search?q=";"SELECT * FROM contents";--

ဆိုပြီး ပြောင်းလိုက်မယ် ဆိုရင်

SELECT * from contents where text like "%";"SELECT * FROM contents";--hello%";

ဆိုပြီး ဖြစ်သွားပါမယ်။ -- ကတော့ comment ဖြစ်သည့်အတွက် --hello%"; က အလုပ်လုပ်မှာ မဟုတ်ပါဘူး။ ရှာမယ့် text အစား contents တွေ အကုန်ထွက်လာတာ သို့မဟုတ် နှစ်သက်ရာ SQL ကို နောက်မှာ အစားထိုးပြီး ရေးလို့ရသွားတာကို တွေ့ရပါလိမ့်မယ်။

ပုံမှန် အားဖြင့် PHP နဲ့ database ထဲက data ကို ဆွဲထုတ်မယ်ဆိုရင် အောက်ကလို ရေးကြပါတယ်။

$sql = "SELECT first_name, last_name FROM employees WHERE first_name = '".$_GET['name']."' OR last_name ='" . $_GET['name'] . "' LIMIT 5";

$result = $conn->query($sql);

Get Query string က နေ name နဲ့ ရှာထားတာပါ။

http://localhost/sqlinjection/index.php?name=Georgi&submit=Search

ဆိုပြီး ခေါ်ထားပါတယ်။ Database ထဲက အမည်ရှာပြီး ဆွဲထုတ်ပေးပါတယ်။ သို့ပေမယ့် query ကို အောက်ကလို ပြင်လိုက်မယ် ဆိုရင်

http://localhost/sqlinjection/index.php?name='%20OR%201=1%20LIMIT%2010;%20--%20&submit=Search

LIMIT 5 အစား LIMIT 10 ဖြစ်သွားပါလိမ့်မယ်။ URL Decode လုပ်ကြည့်လိုက်ရင် name က

' OR 1=1 LIMIT 10; -- 

ဆိုပြီး ထည့် လုပ်ထားတာပါ။

အဲဒီအခါ query က

SELECT first_name, last_name FROM employees WHERE first_name = '' OR 1=1 LIMIT 10; --

ပုံစံ ဖြစ်သွားပါတယ်။

ဒါကြောင့် query တွေ ကို ရေးသည့် အခါမှာ parameter binding ကို အသုံးပြုနိုင်ပါတယ်။

 $sql = "SELECT first_name, last_name FROM employees WHERE first_name = ? OR last_name = ? LIMIT 5";
    
    $stmt = $conn->prepare($sql);
    
    $stmt->bind_param("ss",$name,$name);
    
    $stmt->execute();
    
    $res = $stmt->get_result();

SQL Injection တွေကို ကာကွယ်ဖို့ အတွက် programming language တိုင်းမှာ parameter နှင့် passing လုပ်တာ ဒါမှမဟုတ် framework တွေကို အသုံးပြုတာ ဖြစ်ဖြစ် ကာကွယ်နိုင်ပါတယ်။

SQL Injection အတွက် sqlmap (http://sqlmap.org) ကို အသုံးပြုပြီး လွယ်လင့်တကူ တိုက်ခိုက်နိုင်ပါတယ်။​

 python sqlmap.py -u "http://localhost/sqlinjection/index.php?name=Georgi&submit=Search" --dbs

SQL Injection ရှိသည့် website တွေကို SQL Map ကို အသုံးပြုပြီးတော့ website ကိုသာမက system ထဲ အထိတောင် တိုက်ခိုင်နိုင်ပါတယ်။

Man-in-the-middle attack

ပုံမှန် အားဖြင့် Web App, Mobile App တွေမှာ API ဖြင့် သွားလာပါတယ်။

ပုံမှန် သွားနေကြသည့် ပုံစံပါ။

ကြားက တစ်ယောက်က ဝင်ပြီးတော့ server ဘက်က ပို့လိုက်သည့် data ကော server ဘက်က ပြန်လာသည့် data ကို ပြင်လိုက်လို့ရပါတယ်။ Man In Middle attack.ကို

Android OS 10 နောက်ပိုင်းမှာတော့ device ကို root မဖောက်ပဲနှင့် https certificate ကို ပြောင်းလဲလို့မရပါဘူး။ ကြားက data တွေကို ဖတ်လို့ရအောင် ပြင်လို့ရအောင် အတွက် ကြားခံ certificate ကိုပြင်ရပါတယ်။

Man In Attack ကို စမ်းသပ်ဖို့ proxy server တွေဖြစ်သည့်

အပြင် နှစ်သက်ရာ proxy နဲ့ စမ်းသပ်နိုင်ပါတယ်။ Mac မှာဆိုရင်တော့ Charles app ကို အသုံးပြုနိုင်ပါတယ်။

Website အတွက် ဆိုရင် https://requestly.io/ ကို recommend ပေးပါတယ်။​ ရိုးရှင်းလွယ်ကူသည့် အတွက် စမ်းသပ်ရသာ အဆင်ပြေပါတယ်။

ကျွန်တော်ကတော့ BurpSuite ကို အသုံးပြုပါတယ်။ Proxy တွေ ခံထားလိုက်ခြင်းအားဖြင့် App တွေ website တွေ နောက်က အသုံးပြုနေသည့် Request/Response တွေ အကုန်လုံးကို မြင်ရပါမယ်။

mitmproxy

Proxy ခံထားခြင်းအားဖြင့် နှစ်သက်ရာ request ကို ပြန်ပြီး ပြင်နိုင်ပါတယ်။ ပြန်လာသည့် response ကိုလည်း ပြင်နိုင်ပါတယ်။ ဥပမာ ECommerence website သို့မဟုတ် APP ဆိုပါဆို့။ 8,000 MMK  ကျသင့်တာကို server side ကို ပို့လိုက်သည့် အချိန်မှာ 1,000 MMK နဲ့ လို့ ပြောင်းပြီး ပို့လိုက်တယ်။ Payment Gateway ဘက်ကို ရောက်သည့် အခါမှာ 1,000 MMK နဲ့ ငွေရှင်းရပြီး success ဖြစ်သွားပါတယ်။

Customer ကို ပစ္စည်းမပေးရင် မင်းတို့ system က အလိုလို ဖြစ်သွားတာ ဆိုပြီး ပြန်ငြင်းနိုင်သည့် အတွက်ကြောင့် မလိုအပ်ပဲ ရှင်းနေရပါတယ်။ ဒါကြောင့် request တွေမှာ hashing နှင့် ဖြစ်နိုင်ရင် server side ဘက်မှာပဲ​ processing လုပ်ဖို့လိုပါတယ်။

တစ်ခါတစ်လေ ကျွန်တော်တို့တွေဟာ response တွေပေါ်မှာ မူတည်ပြီး စစ်ထားတာတွေ ရှိတတ်ပါတယ်။ ဥပမာ product ကို premium user တွေပဲ access ရမယ်။ Premium user ဟုတ်မဟုတ် ကို user profile response ကနေ ထိန်းထားတယ်။ အဲဒီ အခါမှာ response ကို ပြင်လိုက်ရုံနဲ့ product ကို access လုပ်လို့ရသွားနိုင်ပါတယ်။

ဒါကြောင့် response တွေကို အပြည့် မယုံကြည်ပဲ server side နဲ့ ပြန်ပြီး စစ်ဆေးဖို့ လုိပါတယ်။ ဥပမာ download ချသည့် အခါမှာ link ကို server side က နေ user ကို စစ်ပြီးမှ link ချပေးတာမျိုး ကို ထည့်သွင်း စဥ်းစားထားဖို့ လိုပါတယ်။

Encryption, Encoding, Hashing

Developer တစ်ယောက် အနေနဲ့ မဖြစ်မနေ

  • Hashing
  • Encoding
  • Encryption

ကို သိဖို့ လိုပါတယ်။ ဒါဟာ အရမ်းအခြေခံ ကျပါတယ်။ Junior Developer တွေ အနေနဲ့ အမြဲ ဒီ ၃ ခု ကို မှားယွင်းတတ် ရောထွေးနေတတ်ပါတယ်။

Encryption

Data ကို တစ်စုံတစ်ယောက်က ဖတ်လို့ မရအောင် ပြုလုပ်ချင်သည့် အခါမှာ Encryption ကို အသုံးပြုပါတယ်။ ဥပမာ သော့အိမ် နဲ့ သော့ လိုပါပဲ။ သေတ္တာကို သော့ နဲ့ ခတ်လိုက်တယ်။ သေတ္တာထဲမှာ ဘာရှိလဲ သိဖို့ အတွက် သော့ နဲ့ ပြန်ဖွင့် မှ ရတယ်။ ပုံမှန် အားဖြင့် Encryption ကို AES-128 Method နဲ့ အသုံးပြုကြတာ များပါတယ်။ AES-128 နဲ့ AES-256 မှာ အဓိက key ကွာပါတယ်။ 128 မှာ key က 16 လုံး ရှိရပါမယ်။ Vector လည်း ၁၆ လုံး ရှိဖို့ လိုတယ်။ AES-256 မှာတော့ key က 32 လုံး ရှိရပါမယ်။ Vector က ၁၆ လုံး ရှိရပါမယ်။ 128 , 256 ဆိုတာကိုတော့ bit ပါ။ ဒါကြောင့် key size က 8 နဲ့စားပြီးတော့ ဘယ်လောက် byte လည်း ဆိုတာ တွက် လို့ ရပါတယ်။ AES မှာ CFB နဲ့ CBC Mode ဆိုတာ ထပ်ရှိပါသေးတယ်။ AES ကို ပြန်ဖြည်မယ်ဆိုရင် ဘာ Mode လဲ ? CFB လား CBC လား ။ key က 16 လုံးလား 32 လုံးလား။ Vector ကကော ဘာလဲ စတာတွေ သိဖို့ လိုပါတယ်။ Encryption Method တွေက အများကြီးရှိပါတယ်။

AES ကတော့ Key , Vector သိရင်တော့ encryption က ဖြည်လို့ ရပါတယ်။ တနည်းပြောရင် Dictionary Attack နဲ့ ဖြည်ရင်တော့ ဖြစ်နိုင်ချေရှိပါတယ်။

Encryption မှာ symmetric နှင့် asymmetric encryption ၂ မျိုး ရှိပါတယ်။

Symmetric

Symmetric ကတော့ encrypt လုပ်ထားသည့် key နှင့် information တွေ အတိုင်း decrypt ပြန်လုပ်ရတယ်။ သော့ အိမ် တစ်ခု နဲ့ သော့ တစ်ချောင်း နဲ့ ပိတ်ပြီး အဲဒီ သော့ နဲ့ ပဲ ပြန်ဖွင့် သလိုပေါ့။ Symmetric မှာ AES, DES, 3DES, RC4 စတာတွေ ပါဝင်ပါတယ်။

Asymmetric

Asymmetric ကတော့ အနည်းငယ် ကွဲပြားပါတယ်။ သူက key pair နဲ့ အလုပ်လုပ်ပါတယ်။ Key Pair ဆိုတာကတော့ private key တစ်ခု public key တစ်ခု ပါသည့် key တစ်စုံပါ။

ဘာနဲ့ တူသလဲ ဆိုတော့ မောင်မောင် နဲ့ အောင်အောင် စာ အလဲအလှယ် လုပ်ကြတယ်။ မောင်မောင် မှာ အောင်အောင် ပေးထားသည့် သော့ဂလောက် ရှိတယ်။ အောင်အောင်မှာ မောင်မောင် ပေးထားသည့် သော့ဂလောက် ရှိတယ်။ မောင်မောင်မှာပဲ သူ့ သော့ဂလောက်ကို ဖြည်ဖို့ သော့ ရှိတယ်။ အောင်အောင်လည်း ထို့အတူပဲ။

မောင်မောင် က စာ ကို သေတ္တာထဲထည့်။ အောင်အောင်ပေးထားသည့် သော့ဂလောက် နဲ့ ပိတ်။ ပြီးတော့ ကြားလူကနေ အောင်အောင် ဆီကို ပို့ ။

အဲဒီ သော့ ကို အောင်အောင် မှာပဲ သော့ ရှိသည့် အတွက် ဖွင့်လို့ရ လိမ့်မယ်။ ပို့လိုက်သည့် မောင်မောင် ကိုယ်တိုင် ပြန်ဖွင့် လို့ မရတော့ဘူး။ အောင်အောင် ဆီ ရောက်လာမှ သူ့မှာ ရှိသည့် သော့ နဲ့ ဖွင့်။ ပြီးရင် မောင်မောင် သော့ဂလောက် နဲ့ ပြန် ပိတ် ပြီး ကြားလူကနေ မောင်မောင် ဆီ ကို စာပြန်ပို့ ။ အဲဒါမှ မောင်မောင် တစ်ယောက်ပဲ သော့ ဂလောက် ကို ဖွင့် ပြီး စာပြန် ဖတ်လို့ ရပါလိမ့်မယ်။

Private/Public Key Pair ဆိုတာ အထက်ပါ အတိုင်းပါပဲ။ ကျွန်တော်တို့က တစ်ဖက် ကို ပို့ချင်ရင် သူ့ဘက်က public key နဲ့ encrypt လုပ်ပြီး ကျွန်တော် တို့ ဆီ ဘက်ကို စာရောက်လာရင် ကျွန်တော် တို့ private key နဲ့ ပြန် decrypt လုပ်ပါတယ်။

Symmetric ထက် ပို လုံခြုံပါတယ်။ private key ကို ရမှ decrypt လုပ်နိုင်မှာ ဖြစ်ပြီး public key ကို ရမှ encrypt လုပ်နိုင်ပါလိမ့်မယ်။

Asymmetric အတွက် အများအားဖြင့် RSA ကို အသုံးပြုကြပါတယ်။ Apple pay မှာ token ကို elliptic curve cryptography (ECC) အသုံးပြုထားတာကိုလည်း တွေ့နိုင်ပါတယ်။

Encoding

Encoding ကတော့ data format တစ်ခု ကနေ နောက် တစ်ခုကို ကူးပြောင်းတာပါ။ မြင်အောင် ပြောရ ရင် byte data ကို base64 ပြောင်းသလိုမျိုးပေါ့။ Encoding ကို ကျွန်တော်တို့တွေ data transfer အဆင်ပြေဖို့ အဓိက အသုံးပြုပါတယ်။ ဥပမာ image upload တင်မယ် ဆိုရင် image ကို base64 ပြောင်းပြီး server ပေါ်ကို API နဲ့ တင်လိုက်တယ်။ server မှာ ရလာသည့် base64 ကို image format ပြန်ပြောင်းပြီး သိမ်းပါတယ်။ ပုံမှန် bytes array ကို API မှာ transfer လုပ်ဖို့ နည်းနည်း ရှုပ်ထွေးပါလိမ့်မယ်။ Encoding နဲ့ အတူ Decoding ကို ပါနားလည် ဖို့ လိုပါတယ်။ Encode ဆိုတာကတော့ data တစ်ခု ကနေ နောက်တစ်ခု ပြောင်းလဲ လိုက်တာပါ။ Decode ကတော့ ပြောင်းလဲထားသည့် data ကို နဂို data ပြန်ရအောင် လုပ်သလိုမျိုးပေါ့။

တစ်ခါတစ်လေ image အသေးလေးတွေကို database ထဲမှာ သိမ်းချင်တယ်။ BLOB သိမ်းနိုင်သလို base64 ပြောင်းပြီး text အနေနဲ့လည်း သိမ်းနိုင်ပါတယ်။ နောက်ပြီးတော့ encrypt လုပ်သည့် အခါမှာ ထွက်လာသည့် bytes data အစား base64 enocoding လုပ်ပြီး data ကို တစ်နေရာကနေ တစ်နေရာ transfer လုပ်နိုင်အောင် အသုံးပြုကြပါတယ်။ decrypt မဖြည်ခင်မှာ base64 ကို deocde ပြန်လုပ်ဖို့ လိုပါတယ်။

$data = openssl_encrypt("a","AES-128-CBC","aes1279ksamja89c",OPENSSL_RAW_DATA,"89729acedfa4eafa");
echo base64_encode($data);

ဒီ code ကို ကြည့်လိုက်ရင် AES-128-CBC နဲ့ encrypt လုပ်ထားပြီးတော့ base64 encode ပြန်လုပ်ထားပါတယ်။ encrypt result က RAW data ဖြစ်နေသည့် အတွက်ကြောင့် ဘယ် language နဲ့ မဆို အဆင်ပြေအောင် base 64 ပြန်ပြောင်းထားပါတယ်။ PHP က ထွက်သည့် RAW format နဲ့ .NET က ထွက်သည့် bytes format တွေက မတူညီပါဘူး။ ဒါကြောင့် အများအားဖြင့် base64 encoding ကို အသုံးပြုကြပါတယ်။

Hashing

Encrypt/Decrypt, Encoding/Decoding နဲ့မတူတာကတော့ hashing က မူရင်း data ကို ပြန်မရနိုင်ပါဘူး။ Hashing ကို မူရင်း data မသိမ်းထားပဲ data တိုက်ဖို့ အတွက် အသုံးပြုကြပါတယ်။ ဥပမာ Passowrd တွေကို MD5 နဲ့ သိမ်းထားပြီး user က data ပြန်ထည့်သည့် အခါမှာတော့ user ထည့်လိုက်သည့် password ကို MD5 ပြောင်း။ ပြီးမှ database မှာ သိမ်းထားသည့် MD5 နဲ့ တူသလား စစ်။ Hashing က Data ကို Hash လုပ်သည့်အခါမှာ စာလုံးအရေအတွက် စာလုံး မပြောင်းလဲပါဘူး။ ဥပမာ md5("a") ဟာ အမြဲတန်း 0cc175b9c0f1b6a831c399e269772661 ပါပဲ။ ကျွန်တော်တို့တွေ a ကို database မှာ သိမ်းမည့် အစား 0cc175b9c0f1b6a831c399e269772661 ဆိုပြီး သိမ်းထားပါမယ်။ User က a ထည့်သည့်အခါမှသာ MD5 နဲ့ Hash လုပ်ပြီးတော့ user ထည့်တာ မှန်မမှန် ပြန်စစ်သည့် သဘောပါ။ database ထဲမှာ hash ပဲ ထည့်ထားသည့် အတွက်ကြောင့် user password ကို developer ကိုယ်တိုင်မသိနိုင်ပါဘူး။​ datbase ပါသွားခဲ့ရင်တောင် user ရဲ့ password ကို သိဖို့ ခက်ပါတယ်။

md5("a") == "0cc175b9c0f1b6a831c399e269772661"
sha1("a") == "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8"

MD5 hashing ထက် ကျွန်တော်တို့တွေ SHA1 , SHA256 စတာတွေကိုလည်း အသုံးပြုနိုင်ပါတယ်။ Hashing မှာ key ပါထည့်သွင်းရသည့် HMAC hash နဲ့ Key မရှိသည့် MD5, SHA1, SHA256 လိုမျိုး alogrithm တွေ ရှိပါတယ်။

အများအားဖြင့် Request တစ်ခု ပို့လိုက်သည့် အခါမှာ data တွေ transfer လုပ်သည့် အခါမှာ ပို့လိုက်သည့် data က ကြားမှာ loss ဖြစ်သွားလား။ တစ်ယောက်ယောက်က ပြောင်းလိုက်သလား သိနိုင်ဖို့ Hashing ကို အသုံးပြုကြပါတယ်။ အသုံးများတာကတော့ HMAC နဲ့ secrect key ကို အသုံးပြုပြီး Hash လုပ်ပါတယ်။ အထူးသဖြင့် API call တွေမှာ Hashing ကို အသုံးပြုကြပါတယ်။ အဓိက ကတော့ data ကို safe ဖြစ်အောင် အတွက် အသုံးပြုကြပါတယ်။