Theory
Flat Files Scale नहीं करतीं
Portal registrations को एक text file में store करता आया है। यह एक demo के लिए काम करता है और एक real fest के लिए collapse हो जाता है: कोई easy searching नहीं, कोई sorting नहीं, races जब 2 लोग एक साथ register करें। Real data एक DATABASE में रहता है, और आप BCA205 और BCA303 से पहले ही SQL जानते हैं।
यह lesson PHP को MySQL से connect करता है और आपके pages से full CRUD चलाता है। पर यह एक warning से खुलता है, क्योंकि यहीं PHP applications सबसे ज़्यादा HACKED होते हैं: जिस moment user input एक SQL query को touch करता है, आपको SQL injection से defend करना पड़ता है, और defence prepared statements हैं।
Theory
Connecting, और CRUD
PHP MySQL से 2 common interfaces के through बात करती है:
- mysqli: MySQL-specific
- PDO: कई databases के across काम करता है (portable), तो कई लोग इसे prefer करते हैं
Connected होने पर, आप वह SQL चलाते हैं जो आप BCA205 से जानते हैं:
- create करने के लिए INSERT, read करने के लिए SELECT, modify करने के लिए UPDATE, remove करने के लिए DELETE
- clauses: WHERE (rows filter), ORDER BY (sort), LIMIT (count cap)
तो SELECT name FROM regs WHERE event = 'garba' ORDER BY name LIMIT 10 Garba Night के लिए पहले 10 registrants alphabetically fetch करता है। Database heavy lifting करता है; PHP बस query भेजता है और result पढ़ता है। (Tables की बजाय document data के लिए, MongoDB NoSQL alternative है, BCA503-01 में covered।)
Watch out
SQL Injection: वह Attack जो आपको Block करना पड़ता है
मान लीजिए आप user input CONCATENATING करके एक query build करते हैं:
"SELECT * FROM users WHERE name = '" . $_POST['name'] . "'"
एक user अपने name की तरह ' OR '1'='1 type करता है। Query बन जाती है ... WHERE name = '' OR '1'='1', जो ALWAYS TRUE है, हर user dump करते हुए, या इससे भी बुरा। यह SQL injection है: user input SQL की तरह smuggled। यह classic, devastating web vulnerability है, और input को SQL में concatenate करना यह है कि आप इसे कैसे invite करते हैं।
Practical
Fix: एक Prepared Statement (Bound Parameter)
<?php
$db = new mysqli("localhost", "root", "", "portal");
// PREPARED STATEMENT: the query structure is fixed first,
// then the value is bound separately and can NEVER become SQL.
$stmt = $db->prepare("SELECT name FROM regs WHERE event = ?");
$stmt->bind_param("s", $_POST["event"]); // 's' = string param
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo htmlspecialchars($row["name"]) . "<br>";
}
$stmt->close();
// The ? is a PLACEHOLDER. Even if event is "' OR '1'='1",
// it is treated as a literal value, not as SQL. Injection blocked.
?>
Theory
Prepared Statements Safe क्यों हैं
एक prepared statement query STRUCTURE को database को FIRST भेजता है, ? placeholders के साथ जहाँ values जाती हैं। Database उस structure को compile करता है, फिर आप actual values अलग से BIND करते हैं। चूँकि values structure fix होने के AFTER आती हैं, ये सिर्फ़ हमेशा DATA हो सकती हैं, कभी SQL नहीं: ' OR '1'='1 की एक bound value को एक literal string की तरह search किया जाता है, कुछ भी match नहीं करते हुए, query alter करने की बजाय।
वही पूरा defence है: query के SHAPE को इसके VALUES से separate कीजिए। Rule absolute है: कभी user input को SQL में concatenate मत कीजिए; हमेशा bound parameters वाले prepared statements इस्तेमाल कीजिए। Examiners specifically यह देखना चाहते हैं।
Quiz
जब एक query user input इस्तेमाल करती है, तो SQL injection के against correct defence क्या है?
- Input concatenate कीजिए पर पहले इसे uppercase बनाइए
- Bound parameters वाले prepared statements इस्तेमाल कीजिए, तो user input data की तरह treat होता है और कभी SQL alter नहीं कर सकता
- अगर form में client-side validation है तो input trust कीजिए
- सिर्फ़ SELECT queries इस्तेमाल कीजिए, कभी INSERT नहीं
Show the answer
Bound parameters वाले prepared statements इस्तेमाल कीजिए, तो user input data की तरह treat होता है और कभी SQL alter नहीं कर सकता
Bound parameters वाले prepared statements THE defence हैं: query structure placeholders के साथ fix है, values अलग से bound होती हैं, तो ' OR '1'='1 जैसा एक malicious input एक literal value की तरह treat होता है और SQL बदल नहीं सकता। Option A कुछ नहीं करता (uppercase करना injection नहीं रोकता)। Option C fatal myth repeat करता है कि client-side checks security हैं: ये bypass हो सकते हैं, और injection वैसे भी server को target करता है। Option D problem को misunderstand करता है: injection किसी भी query type को affect कर सकता है; SELECT तक restrict करना न तो इसे रोकता है न practical है। Query shape को values से हमेशा separate कीजिए।
Think first
Attack पढ़िए, फिर Fix
Vulnerable query $_POST['name'] concatenate करती है और attacker ' OR '1'='1 enter करता है। Trace कीजिए vulnerable version बनाम prepared version में database को क्या मिलता है। फिर tap कीजिए।
Show the answer
VULNERABLE (concatenated): database को एक merged string मिलती है: WHERE name = '' OR '1'='1', जिसमें attacker का quote intended string CLOSE करता है और OR '1'='1' SQL LOGIC का हिस्सा बन जाता है, हमेशा true, तो हर row return होती है। Input CODE बन गया। PREPARED: database पहले WHERE name = ? receive करता है (structure fixed), फिर अलग से value ' OR '1'='1 को DATA की तरह receive करता है जो ? से bound है; यह literally उस odd string के equal एक name search करता है, कोई नहीं ढूँढता, और कुछ return नहीं करता। Input data रहा। यही पूरा security difference है: concatenation input को SQL बनने देता है; binding input को एक value रखता है। कभी concatenate मत कीजिए।
Watch out
Database Traps
Input को SQL में Concatenating करना: injection hole; हमेशा prepared statements इस्तेमाल कीजिए।
DB Values Raw Echo करना: output पर अभी भी इन्हें htmlspecialchars() कीजिए (XSS injection से अलग है)।
Connection Errors Ignore करना: query करने से पहले connection succeed हुआ है यह check कीजिए।
Plain-Text Passwords Store करना: इन्हें hash कीजिए (password_hash); कभी raw passwords store मत कीजिए।
Big Tables पर LIMIT भूलना: unbounded SELECTs huge result sets return कर सकते हैं।
Theory
Data Stored; अब इसे Live बनाइए
Portal की registrations अब full CRUD और injection-proof queries के साथ safely MySQL में रहती हैं। अगला यह page reloads के बिना INTERACTIVE होता है: AJAX background में आपके PHP को requests भेजता है (BCA405-01 वाली technique) एक live registrant search जैसी features के लिए। फिर final Unit 3 lessons पूरे portal को CodeIgniter MVC framework पर rebuild करते हैं: वह professional structure जो files, database और routing को साथ जोड़ता है।
Summary
Key takeaways
- PHP MySQL से mysqli (MySQL-specific) या PDO (databases के across portable) से connect होती है।
- PHP से CRUD SQL इस्तेमाल करता है: INSERT, SELECT, UPDATE, DELETE, WHERE (filter), ORDER BY (sort), LIMIT (cap) के साथ।
- SQL injection: एक query में concatenated user input SQL alter कर सकता है (' OR '1'='1 conditions को हमेशा true बनाता है)।
- Defence: bound parameters वाले prepared statements: query structure पहले fix है, values अलग से data की तरह bound होती हैं।
- कभी user input को SQL में concatenate मत कीजिए; bound values कभी SQL नहीं बन सकतीं।
- Passwords भी hash कीजिए (password_hash) और output पर DB values को htmlspecialchars कीजिए।
- Memory hook: query के shape को इसके values से separate कीजिए; bind कीजिए, concatenate मत कीजिए।