পাঠ ৪৫ · ৬০-এর মধ্যে · মডিউল ৯

ফিশিং, স্পিয়ার-ফিশিং ও ভিশিং

Phishing, spear-phishing & vishing
৮ মিনিট পড়া মধ্যবর্তী · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • ফিশিং, স্পিয়ার-ফিশিং, হোয়েলিং ও ভিশিং-এর মধ্যে সুনির্দিষ্ট পার্থক্য
  • ফিশিং চেনার সাধারণ লাল পতাকা
  • লুকঅ্যালাইক ডোমেইন ঠিক কীভাবে কাজ করে (ক্যারেক্টার-প্রতিস্থাপন ও ভুয়া সাবডোমেইন কাঠামো)
  • একটি সত্যিকারের কার্যকর, সরলীকৃত check_url_for_lookalike ফাংশন তৈরি ও পরীক্ষা

১ · ফিশিং, স্পিয়ার-ফিশিং, হোয়েলিং ও ভিশিং

L44-এ আমরা দেখেছি সোশ্যাল ইঞ্জিনিয়ারিং কীভাবে মনস্তত্ত্ব কাজে লাগায়। ফিশিং হলো এর সবচেয়ে সাধারণ, স্কেলেবল রূপ — একই জাল বার্তা (ইমেইল/SMS/ইত্যাদি) হাজার হাজার প্রাপকের কাছে পাঠানো হয়, আশা করে কয়েকজন হলেও ক্লিক করবেন। বার্তাটি সাধারণত একটি লুকঅ্যালাইক লিংকে ক্লিক করতে বা সংযুক্তি খুলতে প্ররোচিত করে।

স্পিয়ার-ফিশিংSpear Phishingএকটি নির্দিষ্ট ব্যক্তি বা প্রতিষ্ঠানকে টার্গেট করে ব্যক্তিগতকৃত ফিশিং — আক্রমণকারী OSINT (L10) দিয়ে সংগ্রহ করা তথ্য (নাম, পদবি, সাম্প্রতিক প্রজেক্ট) ব্যবহার করে বার্তাটিকে অনেক বেশি বিশ্বাসযোগ্য বানায়। সাধারণ ফিশিংয়ের চেয়ে অনেক বেশি বিপজ্জনক কারণ এটি ব্যক্তিগতকৃত — যেমন প্রাপকের নাম, সাম্প্রতিক প্রজেক্ট, বা সহকর্মীর নাম উল্লেখ করা, যা OSINT থেকে সংগৃহীত। হোয়েলিংWhalingনির্বাহী কর্মকর্তা বা অন্য উচ্চ-মূল্যের টার্গেটদের বিরুদ্ধে চালানো স্পিয়ার-ফিশিং — নাম থেকেই বোঝা যায়, "বড় মাছ" শিকার। হলো নির্বাহী/উচ্চ-মূল্যের টার্গেটদের বিরুদ্ধে স্পিয়ার-ফিশিং। আর ভিশিংVishing (Voice Phishing)ভয়েস কলের মাধ্যমে চালানো ফিশিং — যেমন একজন আক্রমণকারী ব্যাংকের ফ্রড ডিপার্টমেন্ট পরিচয় দিয়ে ফোন করে "যাচাইয়ের জন্য" OTP বা কার্ড নম্বর চাওয়া। হলো একই ধরনের প্রতারণা, শুধু ইমেইল/SMS-এর বদলে ফোন কলে চালানো।

২ · সাধারণ লাল পতাকা

অমিল/লুকঅ্যালাইক ডোমেইন
প্রেরকের ইমেইল ডোমেইন বা লিংক আসল প্রতিষ্ঠানের ডোমেইনের সাথে সামান্য ভিন্ন।
তাড়াহুড়ো/হুমকির ভাষা
"২৪ ঘণ্টার মধ্যে অ্যাকাউন্ট বন্ধ হবে" — সতর্ক চিন্তাভাবনা বাইপাস করার চেষ্টা (ties L44)।
অপ্রত্যাশিত অ্যাটাচমেন্ট/লিংক
এমন কারো কাছ থেকে সংযুক্তি, যিনি সাধারণত এমন কিছু পাঠান না, বা প্রেক্ষাপটের সাথে অসামঞ্জস্যপূর্ণ।
লিংকের মাধ্যমে ক্রেডেনশিয়াল
সরাসরি টাইপ করা/বুকমার্ক করা URL দিয়ে লগইন করার বদলে, বার্তার লিংকে ক্লিক করে লগইন করতে বলা।

৩ · লুকঅ্যালাইক ডোমেইন ঠিক কীভাবে কাজ করে

একটি লুকঅ্যালাইক ডোমেইনLookalike Domainআসল, বৈধ ডোমেইনের সাথে দেখতে প্রায় অভিন্ন কিন্তু প্রকৃতপক্ষে ভিন্ন একটি ডোমেইন — চোখে দ্রুত পড়লে পার্থক্য ধরা কঠিন। সাধারণত দুটি উপায়ে তৈরি হয়। প্রথমত, ক্যারেক্টার-প্রতিস্থাপন — যেমন paypal.com-এর জায়গায় paypa1.com (l → 1) বা paypa1.com-এর মতো একটি অক্ষর বদলে দেওয়া। দ্বিতীয়ত, ভুয়া সাবডোমেইন কাঠামো — যেমন paypal.com.security-verify.ru, যেখানে আসল ডোমেইন নামটি (paypal.com) হোস্টনেমের মধ্যে দেখা যাচ্ছে ঠিকই, কিন্তু প্রকৃত (রেজিস্ট্রেবল) ডোমেইন আসলে security-verify.ru — ব্রাউজারের ঠিকানা বার দ্রুত চোখ বুলালে এই পার্থক্য সহজেই এড়িয়ে যায়।

৪ · একটি সত্যিকারের কার্যকর লুকঅ্যালাইক-ডিটেক্টর

নিচের কোড সেলটি একটি প্রকৃত, কার্যকরী (যদিও সরলীকৃত) check_url_for_lookalike ফাংশন তৈরি করে — এটি সত্যিকারের স্ট্রিং-তুলনা যুক্তি ব্যবহার করে, কোনো ভুয়া/স্থির ফলাফল নয়। এটি তিনটি ধাপে যাচাই করে: (১) সম্পূর্ণ মিল বা বৈধ সাবডোমেইন কি না, (২) আসল ডোমেইন নাম ভুয়া সাবডোমেইন কাঠামোর মধ্যে ডিকয় হিসেবে ব্যবহৃত হয়েছে কি না, (৩) Levenshtein edit distance (একটি স্ট্রিংকে আরেকটিতে রূপান্তর করতে ন্যূনতম কতগুলো অক্ষর যোগ/বাদ/প্রতিস্থাপন লাগে তার হিসাব) ছোট কি না, যা ক্যারেক্টার-প্রতিস্থাপন লুকঅ্যালাইক চিহ্নিত করে।

Python
import re

def extract_domain(url):
    """URL থেকে শুধু হোস্টনেম বের করে (স্কিম, পাথ, পোর্ট বাদ দিয়ে)।"""
    match = re.match(r"^(?:https?://)?([^/]+)", url)
    host = match.group(1) if match else url
    host = host.split("@")[-1]   # userinfo@host হলে host অংশ নেয়
    host = host.split(":")[0]    # পোর্ট নম্বর বাদ দেয়
    return host.lower()

def levenshtein(a, b):
    """দুটি স্ট্রিং-এর মধ্যে এডিট ডিস্ট্যান্স (Wagner–Fischer অ্যালগরিদম)।"""
    if len(a) < len(b):
        a, b = b, a
    prev_row = list(range(len(b) + 1))
    for i, ca in enumerate(a, start=1):
        curr_row = [i]
        for j, cb in enumerate(b, start=1):
            insert_cost  = curr_row[j - 1] + 1
            delete_cost  = prev_row[j] + 1
            replace_cost = prev_row[j - 1] + (ca != cb)
            curr_row.append(min(insert_cost, delete_cost, replace_cost))
        prev_row = curr_row
    return prev_row[-1]

def check_url_for_lookalike(url, legitimate_domain, max_distance=2):
    domain = extract_domain(url)
    legit = legitimate_domain.lower()

    if domain == legit:
        return {"domain": domain, "suspicious": False, "reason": "সম্পূর্ণ মিল — বৈধ ডোমেইন"}

    if domain.endswith("." + legit):
        return {"domain": domain, "suspicious": False, "reason": "বৈধ ডোমেইনের প্রকৃত সাবডোমেইন"}

    if legit in domain:
        return {"domain": domain, "suspicious": True,
                "reason": "আসল ডোমেইন নাম হোস্টনেমের মধ্যে আছে কিন্তু প্রকৃত (শেষের) ডোমেইন নয় — ভুয়া সাবডোমেইন কাঠামো"}

    distance = levenshtein(domain, legit)
    if 0 < distance <= max_distance:
        return {"domain": domain, "suspicious": True,
                "reason": f"বৈধ ডোমেইনের সাথে সাদৃশ্যপূর্ণ (edit distance={distance}) — সম্ভবত ক্যারেক্টার-প্রতিস্থাপন"}

    return {"domain": domain, "suspicious": False,
            "reason": "উল্লেখযোগ্য সাদৃশ্য নেই — তবু অন্য লাল পতাকা (তাড়াহুড়ো, অ্যাটাচমেন্ট) যাচাই করুন"}


legitimate = "paypal.com"
test_urls = [
    "https://www.paypal.com/signin",             # বৈধ সাবডোমেইন
    "https://paypa1.com/signin",                 # ক্যারেক্টার-প্রতিস্থাপন (l -> 1)
    "https://paypal.com.security-verify.ru/login" # ভুয়া সাবডোমেইন কাঠামো
]

for url in test_urls:
    result = check_url_for_lookalike(url, legitimate)
    flag = "সন্দেহজনক" if result["suspicious"] else "নিরাপদ"
    print(f"URL: {url}")
    print(f"  ডোমেইন: {result['domain']} -> [{flag}] {result['reason']}")
    print()

    
যুক্তি ধাপে ধাপে যাচাই করুন — www.paypal.com .paypal.com-এ শেষ হয়, তাই এটি একটি বৈধ সাবডোমেইন হিসেবে পাস করে। paypa1.com-এর সাথে paypal.com-এর এডিট ডিস্ট্যান্স ঠিক ১ (শুধু "l" থেকে "1"), যা max_distance=2-এর মধ্যে পড়ে বলে ফ্ল্যাগ হয়। আর paypal.com.security-verify.ru-এ "paypal.com" স্ট্রিং হিসেবে উপস্থিত থাকলেও এটি .paypal.com-এ শেষ হয় না (এটি শেষ হয় .ru-তে) — তাই "ভুয়া সাবডোমেইন কাঠামো" নিয়ম অনুযায়ী সঠিকভাবে সন্দেহজনক হিসেবে ধরা পড়ে।
সীমাবদ্ধতা · Limitations

এটি একটি শিক্ষামূলক, সরলীকৃত হিউরিস্টিক — বাস্তব অ্যান্টি-ফিশিং সিস্টেম আরও অনেক সিগন্যাল ব্যবহার করে (ডোমেইনের বয়স, হোমোগ্রাফ/Unicode ক্যারেক্টার সাদৃশ্য, রিপুটেশন ডেটাবেস, TLS সার্টিফিকেট তথ্য)। তবুও এটি দেখায় যে শুধু স্ট্রিং তুলনা-ই ইতিমধ্যে দুই ধরনের সাধারণ লুকঅ্যালাইক কৌশল সঠিকভাবে ধরতে পারে — এবং কেন মানুষেরও ঠিকানা বার মনোযোগ দিয়ে পড়া উচিত, শুধু "লক আইকন" বা পরিচিত-দেখতে টেক্সটের উপর নির্ভর না করে।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ স্পিয়ার-ফিশিং কেন সাধারণ ফিশিংয়ের চেয়ে অনেক বেশি সফল হয়, এবং এটি L10-এর OSINT ধারণার সাথে কীভাবে যুক্ত?

সাধারণ ফিশিং জেনেরিক ("প্রিয় গ্রাহক...") — একজন সতর্ক প্রাপক সহজেই সন্দেহ করতে পারেন। স্পিয়ার-ফিশিং OSINT (L10) থেকে সংগৃহীত বাস্তব তথ্য (নাম, পদবি, সাম্প্রতিক প্রজেক্ট, সহকর্মীর নাম) ব্যবহার করে বার্তাটিকে অনেক বেশি বিশ্বাসযোগ্য করে তোলে — প্রাপক ভাবেন প্রেরক সত্যিই তাকে/তার প্রতিষ্ঠানকে চেনে, তাই সতর্কতা কমে যায়।

প্র ০২ কেন legit in domain চেক করার আগে domain.endswith("." + legit) চেক করা জরুরি?

কারণ login.paypal.com-এর মতো একটি সম্পূর্ণ বৈধ সাবডোমেইনেও "paypal.com" স্ট্রিং হিসেবে উপস্থিত থাকে। যদি আগে শুধু legit in domain চেক করা হতো, তাহলে এই বৈধ সাবডোমেইনটিকেও ভুলভাবে সন্দেহজনক হিসেবে ফ্ল্যাগ করা হতো। তাই প্রথমে "এটি কি সত্যিই legit-এর সাবডোমেইন" (এর শেষে .paypal.com আছে কি না) নিশ্চিত করা হয়, তারপরই "ডিকয় হিসেবে embedded" চেক করা হয়।

প্র ০৩ ভিশিং-এ (ভয়েস কলে) কেন "কলার ID যাচাই" যথেষ্ট প্রতিরক্ষা নয়?

কলার ID স্পুফিং (caller ID spoofing) সহজলভ্য এবং একজন আক্রমণকারী কলার ID-তে যেকোনো নম্বর/নাম দেখাতে পারেন, এমনকি একটি বৈধ ব্যাংকের নম্বরও নকল করা সম্ভব। তাই কলার ID কখনোই পরিচয়ের একমাত্র প্রমাণ হতে পারে না — প্রকৃত প্রতিরক্ষা হলো, যেকোনো সংবেদনশীল অনুরোধ পেলে কল কেটে দিয়ে প্রতিষ্ঠানের অফিসিয়াল, স্বাধীনভাবে যাচাই করা নম্বরে নিজে থেকে কল করা (L44-এর "দ্বিতীয় চ্যানেলে যাচাই" নীতি)।

অনুশীলন

  1. চিন্তা করুন: আপনার ইমেইল ইনবক্সে পাওয়া সাম্প্রতিক কোনো সন্দেহজনক বার্তার কথা মনে করুন (বা কল্পনা করুন)। এই পাঠের চারটি লাল পতাকার মধ্যে কোনগুলো সেখানে উপস্থিত ছিল?

    সাধারণ ফিশিং বার্তায় প্রায়ই একাধিক লাল পতাকা একসাথে থাকে — যেমন একটি লুকঅ্যালাইক ডোমেইন থেকে আসা, "২৪ ঘণ্টার মধ্যে যাচাই না করলে অ্যাকাউন্ট বন্ধ" জাতীয় তাড়াহুড়োর ভাষা, এবং সরাসরি লিংকে ক্লিক করে লগইন করার অনুরোধ — এই তিনটি একসাথে থাকলে এটি প্রায় নিশ্চিতভাবেই ফিশিং।

  2. পরীক্ষা করুন: উপরের কোডে test_urls-এ "https://accounts.paypal.com.verify-login.com/secure" যোগ করে Run চাপুন — এটি কোন নিয়মে ফ্ল্যাগ হয় এবং কেন?

    এই ডোমেইন accounts.paypal.com.verify-login.com-এ "paypal.com" স্ট্রিং হিসেবে উপস্থিত, কিন্তু এটি .paypal.com-এ শেষ হয় না (এটি শেষ হয় .verify-login.com-এ) — তাই এটি "ভুয়া সাবডোমেইন কাঠামো" নিয়ম অনুযায়ী সন্দেহজনক হিসেবে ফ্ল্যাগ হবে, এডিট-ডিস্ট্যান্স নিয়ম পর্যন্ত পৌঁছানোর আগেই।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

আগের পাঠ
সোশ্যাল ইঞ্জিনিয়ারিং সাইকোলজি ও কৌশল