SQL Injection হল অ্যাপ্লিকেশন ডাটাবেসে এক ধরনের আক্রমণ যেখানে আক্রমণকারী কুয়েরি প্যারামিটারে ক্ষতিকারক SQL কোড ইনজেক্ট করে, ডেটাতে অননুমোদিত অ্যাক্সেস বা সেগুলি পরিবর্তনের ক্ষমতা অর্জন করে। OWASP (2025) অনুসারে, SQL Injection এখনও একটি গুরুত্বপূর্ণ দুর্বলতা যা ডাটাবেসের সম্পূর্ণ ক্ষতি করতে সক্ষম। SQL কোড ইনজেকশন আক্রমণকারীকে রেকর্ড পড়তে, পরিবর্তন করতে এবং মুছতে দেয়, এবং কিছু ক্ষেত্রে, সার্ভারের অপারেটিং সিস্টেমে অ্যাক্সেস পেতে দেয়।
মূল বিষয়
SQL Injection হল একটি দুর্বলতা যা ঘটে যখন কোনো অ্যাপ্লিকেশন ব্যবহারকারীর ডেটার সাথে স্ট্রিং কনক্যাটেনেশন করে SQL কুয়েরি তৈরি করে। আক্রমণকারী কুয়েরি প্যারামিটারে একটি বিশেষভাবে তৈরি স্ট্রিং পাস করে যা SQL কমান্ডের গঠন পরিবর্তন করে। ডেটা হওয়ার পরিবর্তে, ইনজেক্ট করা স্ট্রিং SQL কোডের অংশ হয়ে যায়, যা আক্রমণকারীকে ডাটাবেসের বিরুদ্ধে ইচ্ছামতো কুয়েরি চালাতে দেয়। Verizon ডেটা লঙ্ঘন রিপোর্ট (2025) অনুসারে, SQL Injection সমস্ত তদন্তকৃত ডেটা লঙ্ঘনের 8% এ উপস্থিত।
একটি পরিচিত দুর্বলতা হওয়া সত্ত্বেও (প্রথম উল্লেখ ১৯৯০-এর দশকের শেষে), SQL Injection আধুনিক অ্যাপ্লিকেশনগুলিতে এখনও পাওয়া যায়। কারণ হল মানবিক ত্রুটি: ডেভেলপাররা স্ট্রিং কনক্যাটেনেশন সহ কোড লেখেন, লিগ্যাসি কোড রিফ্যাক্টর করা হয় না, এবং ORM ফ্রেমওয়ার্ক ভুলভাবে ব্যবহার করা হয় (যেমন, স্ট্রিং ইন্টারপোলেশন সহ raw কুয়েরি)। Veracode (2026) অনুসারে, সমস্ত স্ক্যান করা অ্যাপ্লিকেশনের প্রায় 14% এ কমপক্ষে একটি SQLi দুর্বলতা রয়েছে।
একটি সফল SQL Injection আক্রমণকারীকে বিস্তৃত ক্ষমতা দেয়: পাসওয়ার্ড হ্যাশ এবং ব্যবহারকারীদের ব্যক্তিগত ডেটা সহ যেকোনো ডাটাবেস টেবিল পড়া; রেকর্ড পরিবর্তন এবং মুছে ফেলা; প্রশাসনিক অপারেশন চালানো (DROP TABLE, TRUNCATE); এবং কিছু কনফিগারেশনে, xp_cmdshell (MSSQL) বা INTO OUTFILE (MySQL) এর মাধ্যমে দূরবর্তী কমান্ড এক্সিকিউশন। ফলাফল ব্যবহারকারীর ডেটা ফাঁস থেকে সিস্টেমের উপর সম্পূর্ণ নিয়ন্ত্রণ হারানো পর্যন্ত হতে পারে।
SQL ইনজেকশন ডাটাবেস থেকে ডেটা নিষ্কাশনের পদ্ধতি অনুসারে শ্রেণীবদ্ধ করা হয়। পদ্ধতির পছন্দ নির্ভর করে অ্যাপ্লিকেশন কীভাবে কুয়েরির ফলাফল এবং ত্রুটির বার্তা পরিচালনা করে। OWASP শ্রেণীবিভাগ তিনটি প্রধান ধরন চিহ্নিত করে: In-band (একই চ্যানেলের মাধ্যমে ডেটা নিষ্কাশন), Inferential/Blind (যৌক্তিক অনুমান), এবং Out-of-band (অন্য চ্যানেলের মাধ্যমে ডেটা প্রেরণ)।
| ধরন | ডেটা নিষ্কাশন পদ্ধতি | জটিলতা | ফ্রিকোয়েন্সি |
|---|---|---|---|
| In-band (ক্লাসিক) | সরাসরি কুয়েরি ফলাফলের মাধ্যমে | নিম্ন | উচ্চ |
| Blind SQLi | সার্ভার প্রতিক্রিয়া থেকে যৌক্তিক অনুমান | উচ্চ | মধ্যম |
| Out-of-band | বাহ্যিক চ্যানেলের (DNS, HTTP) মাধ্যমে | মধ্যম | নিম্ন |
সবচেয়ে সাধারণ ধরন। আক্রমণকারী কুয়েরি প্যারামিটারে SQL কোড ইনজেক্ট করে, এবং ইনজেকশনের ফলাফল সরাসরি সার্ভার প্রতিক্রিয়ায় দৃশ্যমান হয়। দুটি উপপ্রকার: Error-based (DB ত্রুটি বার্তার মাধ্যমে) এবং UNION-based (UNION SELECT অপারেটরের মাধ্যমে)। Error-based ত্রুটি বার্তা থেকে তথ্য ব্যবহার করে, যেমন MySQL সিনট্যাক্স ত্রুটি যা টেবিলের নাম বা কুয়েরির গঠন প্রকাশ করতে পারে। UNION-based বৈধ কুয়েরির ফলাফলকে ডাটাবেসের অন্যান্য টেবিলের ডেটার সাথে একত্রিত করতে দেয়।
যখন অ্যাপ্লিকেশন কুয়েরির ফলাফল বা ত্রুটি বার্তা প্রদর্শন করে না তখন ব্যবহার করা হয়। আক্রমণকারী যৌক্তিক শর্ত সহ কুয়েরি পাঠিয়ে এবং সার্ভার প্রতিক্রিয়ার পার্থক্য (যেমন, প্রতিক্রিয়া সময় বা পৃষ্ঠার বিষয়বস্তু) বিশ্লেষণ করে হ্যাঁ/না প্রশ্ন জিজ্ঞাসা করে। Time-based Blind SQLi শর্ত নিশ্চিত করতে বিলম্ব ফাংশন (SLEEP, WAITFOR DELAY) ব্যবহার করে — যদি পৃষ্ঠা লোড হতে বেশি সময় নেয়, শর্তটি সত্য। এই পদ্ধতি খুবই ধীর — একটি রেকর্ড নিষ্কাশন করতে ঘন্টা সময় লাগতে পারে।
# Blind SQL Injection এর উদাহরণ (সময়-ভিত্তিক)
# যদি SQLi দুর্বল হয়, SLEEP(2) শর্ত পূরণ হলে এক্সিকিউট হয়
import requests
import time
payload = "' OR IF(SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a',SLEEP(2),0) -- "
url = "http://example.com/user?id=1" + payload
start = time.time()
response = requests.get(url)
elapsed = time.time() - start
# যদি প্রতিক্রিয়া >2 সেকেন্ড পরে আসে — পাসওয়ার্ডের প্রথম অক্ষর 'a'
print(f"Time: {elapsed:.2f}s - First letter is 'a'" if elapsed > 2 else "First letter is not 'a'")
ডেটা HTTP প্রতিক্রিয়ার মাধ্যমে নয় বরং বিকল্প চ্যানেলের মাধ্যমে প্রেরিত হয়: DNS কুয়েরি, বাহ্যিক সার্ভারে HTTP অনুরোধ, SMTP। যখন অ্যাপ্লিকেশন কুয়েরির ফলাফল ফেরত দেয় না বা ত্রুটি দেখায় না তখন ব্যবহার করা হয়। MySQL LOAD_FILE() ফাংশন সমর্থন করে, যা DNS অনুরোধ শুরু করতে পারে, এবং MSSQL-এ দূরবর্তী SMB সার্ভারে ডেটা পাঠানোর জন্য xp_dirtree রয়েছে। Out-of-band SQL Injection কার্যকর কিন্তু অতিরিক্ত আক্রমণকারী সার্ভার সেটআপ এবং নির্দিষ্ট DB ফাংশন প্রয়োজন।
SQL Injection প্রক্রিয়াটি SQL স্ট্রিং লিটারেলের জন্য উদ্ধৃতি ব্যবহার করার উপর ভিত্তি করে। যদি কোনো অ্যাপ্লিকেশন ব্যবহারকারীর ইনপুট সরাসরি SQL কুয়েরিতে এস্কেপ না করে সন্নিবেশ করে, তাহলে আক্রমণকারী স্ট্রিংটি “বন্ধ” করে ইচ্ছামতো SQL কোড যোগ করতে পারে। উদাহরণস্বরূপ, কুয়েরি SELECT * FROM users WHERE name = '$input' এ, ' OR '1'='1 সন্নিবেশ করলে এটি SELECT * FROM users WHERE name = '' OR '1'='1' এ রূপান্তরিত হয়, যা সব ব্যবহারকারীকে ফেরত দেয়।
কুয়েরি SELECT * FROM users WHERE username = '$user' AND password = '$pass' সহ একটি লগইন ফর্ম বিবেচনা করুন। যদি আক্রমণকারী ব্যবহারকারীর নাম ক্ষেত্রে admin' -- প্রবেশ করায় এবং পাসওয়ার্ড খালি রাখে, ফলস্বরূপ কুয়েরিটি SELECT * FROM users WHERE username = 'admin' -- ' AND password = '' হয়। -- অক্ষর বাকি কুয়েরি মন্তব্য করে, পাসওয়ার্ড যাচাই অক্ষম করে। সার্ভার অ্যাডমিন ব্যবহারকারীর রেকর্ড ফেরত দেয়, এবং আক্রমণকারী পাসওয়ার্ড না জেনেই লগইন করে।
# SQL Injection এর উদাহরণ — প্রমাণীকরণ বাইপাস
# দুর্বল কোড: সরাসরি স্ট্রিং কনক্যাটেনেশন
def login_vulnerable(username, password):
query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
cursor.execute(query)
return cursor.fetchone() is not None
# username = "admin' --" পাসওয়ার্ড যাচাই বাতিল করে
# নিরাপদ সংস্করণ: প্যারামিটারাইজড কুয়েরি
def login_secure(username, password):
query = "SELECT * FROM users WHERE username = %s AND password = %s"
cursor.execute(query, (username, password))
return cursor.fetchone() is not None
UNION SELECT অপারেটর দুটি SELECT কুয়েরির ফলাফল একত্রিত করতে দেয়। যদি আক্রমণকারী একটি দুর্বল প্যারামিটার খুঁজে পায়, তারা অন্য টেবিল থেকে কুয়েরি সহ UNION SELECT যোগ করে। উদাহরণ: ' UNION SELECT username, password FROM admins --। সাফল্যের শর্ত হল উভয় কুয়েরিতে কলামের সংখ্যা সমান হতে হবে। কলামের সংখ্যা ORDER BY এর মাধ্যমে নির্ধারিত হয় (' ORDER BY 1--, তারপর 2, 3... ত্রুটি না হওয়া পর্যন্ত)। কলামের সংখ্যা জেনে, আক্রমণকারী সমান সংখ্যক ফিল্ড সহ UNION SELECT সন্নিবেশ করে।
মোবাইল অ্যাপ্লিকেশনগুলি সার্ভার সাইড (API) এবং ক্লায়েন্ট সাইড — স্থানীয় ডাটাবেসে (SQLite, Realm) উভয় ক্ষেত্রেই SQL Injection এর সম্মুখীন হয়। যদিও মোবাইল API-তে সার্ভার-সাইড SQLi ওয়েব অ্যাপ্লিকেশনের মতো, স্থানীয় ডাটাবেস একটি অতিরিক্ত ভেক্টর তৈরি করে। যদি কোনো অ্যাপ্লিকেশন SQLite-এ ডেটা সংরক্ষণ করে এবং স্ট্রিং কনক্যাটেনেশন সহ কুয়েরি চালায়, তাহলে API-এর মাধ্যমে স্থানীয় ডাটাবেসে প্রবেশ করা ক্ষতিকারক ডেটা পরবর্তী প্রক্রিয়াকরণের সময় SQLi ট্রিগার করতে পারে।
ডিভাইসের স্থানীয় SQLite ডাটাবেসও SQL Injection-এর জন্য দুর্বল যদি অ্যাপ্লিকেশন স্ট্রিং কনক্যাটেনেশন করে কুয়েরি তৈরি করে। Android-এ Content Providers এবং iOS-এ Core Data ডিফল্টরূপে প্যারামিটারাইজেশন ব্যবহার করে, কিন্তু raw কুয়েরির জন্য ডেভেলপারের মনোযোগ প্রয়োজন। SQLite সেমিকোলন দ্বারা পৃথক করা একাধিক কুয়েরি সমর্থন করে না, যা আক্রমণকারীর বিকল্প সীমিত করে কিন্তু WHERE শর্তের মাধ্যমে ডেটা পড়া থেকে রক্ষা করে না। Android-এ সর্বদা selectionArgs এবং iOS-এ প্যারামিটার সহ NSPredicate ব্যবহার করুন।
মোবাইল অ্যাপ্লিকেশন যে API-এর সাথে যোগাযোগ করে, তা যেকোনো ওয়েব সার্ভারের মতোই দুর্বল। মোবাইল ডেভেলপাররা প্রায়শই মনে করেন SQLi শুধুমাত্র ব্যাকএন্ডের সমস্যা, কিন্তু দুর্বলতা API এন্ডপয়েন্টে ঘটে যা ক্লায়েন্ট থেকে প্যারামিটার গ্রহণ করে। দায়িত্ব পৃথকীকরণ সুরক্ষা দেয় না: যদি ব্যাকএন্ড ডেভেলপার কুয়েরি প্যারামিটারাইজ করতে ভুলে যায়, তাহলে ব্যবহারকারীর মোবাইল অ্যাপ আক্রমণের ভেক্টর হয়ে যায়। ব্যাকএন্ডকে ORM বা prepared statements ব্যবহার করতে বলুন।
// Android-এ স্থানীয় SQLite-এ SQL Injection এর উদাহরণ
// দুর্বল কোড: সরাসরি কনক্যাটেনেশন
fun getUserVulnerable(db: SQLiteDatabase, userId: String): Cursor {
return db.rawQuery(
"SELECT * FROM users WHERE id = $userId", null
)
}
// নিরাপদ সংস্করণ: selectionArgs এর মাধ্যমে প্যারামিটারাইজেশন
fun getUserSecure(db: SQLiteDatabase, userId: String): Cursor {
return db.rawQuery(
"SELECT * FROM users WHERE id = ?",
arrayOf(userId)
)
}
SQL Injection থেকে সুরক্ষা একটি সহজ নীতির উপর ভিত্তি করে: SQL কুয়েরিতে ব্যবহারকারীর ইনপুট কখনই বিশ্বাস করবেন না। একমাত্র নির্ভরযোগ্য পদ্ধতি হল কুয়েরি প্যারামিটারাইজেশন (prepared statements), যেখানে SQL কোড এবং ডেটা আলাদাভাবে পাঠানো হয়। অন্যান্য সমস্ত পদ্ধতি — এস্কেপিং, ভ্যালিডেশন, WAF — অতিরিক্ত সুরক্ষা স্তর কিন্তু প্যারামিটারাইজেশন প্রতিস্থাপন করে না। OWASP (2025) অনুসারে, প্যারামিটারাইজেশন 100% SQL Injection আক্রমণ প্রতিরোধ করে।
Prepared statements ব্যবহার করার সময়, SQL কুয়েরি প্রথমে DB সার্ভার দ্বারা ডেটা ছাড়া কম্পাইল করা হয়, এবং তারপর প্যারামিটার মান আলাদাভাবে পাঠানো হয়। ডাটাবেস প্যারামিটারগুলিকে ডেটা হিসাবে বিবেচনা করে, এক্সিকিউটেবল কোড হিসাবে নয়। এমনকি যদি আক্রমণকারী ' OR '1'='1 পাঠায়, ডাটাবেস এটিকে SQL কোড হিসাবে নয় বরং একটি স্ট্রিং মান হিসাবে ব্যাখ্যা করে। Prepared statements সমস্ত আধুনিক ভাষা এবং ফ্রেমওয়ার্ক দ্বারা সমর্থিত: PHP-তে PDO, Java-তে PreparedStatement, Python-এ cursor.execute।
আধুনিক ORM (Hibernate, Entity Framework, SQLAlchemy, Room) কুয়েরি চালানোর সময় স্বয়ংক্রিয়ভাবে প্যারামিটারাইজেশন ব্যবহার করে, যদি না ডেভেলপার raw কুয়েরি তে স্যুইচ করে। তবে, ORM সম্পূর্ণরূপে সুরক্ষা দেয় না: JPA-তে @Query(value = "SELECT * FROM users WHERE name = :name", nativeQuery = true) এর মতো নির্মাণের জন্য নামযুক্ত প্যারামিটারের মাধ্যমে প্যারামিটার পাঠানো প্রয়োজন, কনক্যাটেনেশন নয়। কুয়েরি বিল্ডার (Knex, jOOQ) ডিফল্টরূপে কুয়েরি প্যারামিটারাইজ করে যদি raw পদ্ধতি ব্যবহার না করা হয়।
বিশেষ অক্ষর এস্কেপ করা (mysql_real_escape_string) একটি পুরানো পদ্ধতি যা সব ধরনের SQL Injection থেকে রক্ষা করে না। সমস্যা: এস্কেপিং এনকোডিংয়ের উপর নির্ভর করে এবং মাল্টি-বাইট এনকোডিং (যেমন, এশিয়ান সিস্টেমে GBK) ব্যবহার করে বাইপাস করা যেতে পারে। শুধুমাত্র লিগ্যাসি কোডে এস্কেপিং ব্যবহার করুন যেখানে প্যারামিটারাইজেশন সম্ভব নয়, এবং সর্বদা কঠোর ইনপুট টাইপ ভ্যালিডেশনের সাথে।
| পদ্ধতি | কার্যকারিতা | সুপারিশ |
|---|---|---|
| Prepared Statements | 100% | সব কুয়েরির জন্য বাধ্যতামূলক |
| ORM (সঠিক ব্যবহার) | 99% | সুপারিশকৃত |
| স্ট্রিং এস্কেপিং | 70% (এনকোডিংয়ের উপর নির্ভর) | শুধুমাত্র লিগ্যাসি |
| ইনপুট ভ্যালিডেশন (white-list) | 50% (শুধুমাত্র সংখ্যা) | অতিরিক্ত |
| WAF (Web Application Firewall) | 60% | অতিরিক্ত |
অ্যাপ্লিকেশন অ্যাকাউন্টে ন্যূনতম প্রয়োজনীয় বিশেষাধিকার থাকা উচিত: SELECT, INSERT, UPDATE, DELETE — শুধুমাত্র সেই টেবিলগুলিতে যা অ্যাপ্লিকেশনের প্রকৃতপক্ষে প্রয়োজন। অ্যাপ্লিকেশন অ্যাকাউন্টের জন্য DROP, TRUNCATE, CREATE ব্যবহার নিষিদ্ধ করুন। এটি সফল SQL Injection এর ক্ষেত্রেও ক্ষতি সীমিত করে: আক্রমণকারী টেবিল মুছতে বা প্রশাসনিক অপারেশন চালাতে পারবে না।
নিয়মিত SQL Injection পরীক্ষা নিরাপদ উন্নয়ন পাইপলাইনের অংশ হওয়া উচিত। স্থির বিশ্লেষণ, গতিশীল স্ক্যানিং এবং ম্যানুয়াল পেনিট্রেশন টেস্টিংয়ের সমন্বয় সর্বোত্তম ফলাফল দেয়। Synopsys সাইবার সিকিউরিটি রিপোর্ট (2025) অনুসারে, স্বয়ংক্রিয় স্ক্যানার 70% পর্যন্ত SQLi দুর্বলতা খুঁজে পায়, কিন্তু জটিল Blind আক্রমণের জন্য ম্যানুয়াল পরীক্ষা প্রয়োজন।
মোবাইল অ্যাপ্লিকেশনের জন্য, স্থানীয় SQLite বিশ্লেষণও গুরুত্বপূর্ণ: সমস্ত rawQuery কল, ContentProvider কুয়েরি এবং rawQuery সহ Room কুয়েরি পরীক্ষা করুন। টুল: Android Studio Lint (SQLite-এ SQLi শনাক্ত করে), APK/IPA-র স্বয়ংক্রিয় স্থির এবং গতিশীল বিশ্লেষণের জন্য MobSF (Mobile Security Framework)। মোবাইল অ্যাপ্লিকেশনের ট্রাফিকের প্রক্সি ইন্টারসেপশন সহ sqlmap-এর মাধ্যমে API এন্ডপয়েন্ট পরীক্ষা করারও সুপারিশ করা হয়।
সচরাচর জিজ্ঞাসিত প্রশ্ন
SQL Injection SQL কুয়েরির মাধ্যমে রিলেশনাল ডাটাবেস আক্রমণ করে। NoSQL Injection তাদের কুয়েরি অপারেটর ($gte, $ne, $where) এর মাধ্যমে নন-রিলেশনাল ডাটাবেস (MongoDB, Couchbase) প্রভাবিত করে। MongoDB-তে, ইনজেকশন সম্ভব যদি অ্যাপ্লিকেশন JSON স্ট্রিং থেকে BSON ডকুমেন্ট তৈরি করে। সুরক্ষা ব্যবস্থা একই: প্যারামিটারাইজেশন এবং টাইপ ভ্যালিডেশন।
সেই সমস্ত জায়গা খুঁজুন যেখানে SQL কুয়েরি ব্যবহারকারীর ডেটার সাথে স্ট্রিং কনক্যাটেনেশন এর মাধ্যমে তৈরি হয়। "SELECT ... WHERE id = " + userId বা f"UPDATE ... SET name = '{name}'" এর মতো প্যাটার্ন দেখুন। এই ধরনের প্রতিটি লাইন একটি সম্ভাব্য SQL ইনজেকশন। সেগুলিকে প্যারামিটারাইজড কুয়েরি বা prepared statements দিয়ে প্রতিস্থাপন করুন।
ORM ফ্রেমওয়ার্ক শুধুমাত্র তখনই স্বয়ংক্রিয়ভাবে রক্ষা করে যখন আপনি তাদের কুয়েরি বিল্ডার পদ্ধতি এবং নামযুক্ত প্যারামিটার ব্যবহার করেন। আপনি যদি raw কুয়েরি (JPA-তে nativeQuery, Room-এ rawQuery) ব্যবহার করেন, সুরক্ষা কাজ করে না — আপনাকে স্ট্রিং কনক্যাটেনেশনের মাধ্যমে নয় বরং প্রস্তুত এক্সপ্রেশনের মাধ্যমে প্যারামিটার পাঠাতে হবে।
সেকেন্ড-অর্ডার SQL Injection হল একটি আক্রমণ যেখানে ক্ষতিকারক ডেটা ডাটাবেসে নিরাপদে সংরক্ষিত হয়, কিন্তু পরে এস্কেপিং ছাড়া অন্য কুয়েরিতে ব্যবহৃত হয়। উদাহরণস্বরূপ, একজন আক্রমণকারী ' OR '1'='1 এর মতো ব্যবহারকারীর নাম দিয়ে নিবন্ধন করে। ডেটা একটি স্ট্রিং হিসাবে সংরক্ষিত হয় — নিবন্ধনে কোনো আক্রমণ নেই। কিন্তু যদি অন্য কোনো কুয়েরি প্যারামিটারাইজেশন ছাড়া SQL-এ ব্যবহারকারীর নাম ব্যবহার করে, তাহলে ইনজেকশন সক্রিয় হয়।
NoSQL Injection কম ডেভেলপার সচেতনতার কারণে সম্ভাব্যভাবে বেশি বিপজ্জনক হতে পারে। ডেভেলপাররা SQL Injection সম্পর্কে জানে এবং বেশিরভাগ ORM ব্যবহার করে, কিন্তু NoSQL Injection সম্পর্কে কম জানে। MongoDB-তে, অনুপযুক্তভাবে গঠিত কুয়েরি একটি কালেকশনের সমস্ত ডকুমেন্ট ফেরত দিতে পারে। সুরক্ষা একই — prepared statements (BSON প্যারামিটারাইজেশন) এবং কঠোর ইনপুট ভ্যালিডেশন।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন