बिज़नेस लॉजिक और फ़ाइल अपलोड टेस्टिंग
Business logic testing यह जाँचती है कि जब user intended रास्ते पर नहीं चलता तो application अपने rules enforce करता है या नहीं: कोई step छोड़ देना, वह value बदल देना जो browser को set करनी थी, या किसी चीज़ का अनुमति से ज़्यादा बार इस्तेमाल। Code injection और XSS से मुक्त हो सकता है और फिर भी किसी customer को 500 SAR का phone 1 SAR में ख़रीदने दे, क्योंकि server ने browser से भेजे price field पर भरोसा किया।
File upload testing वही idea एक risky input पर लागू है। File का एक नाम, एक declared type, एक size और असली content होता है, और इनमें से हर एक झूठ बोल सकता है। यह lesson दोनों को साथ लेता है क्योंकि method एक है: rule पढ़ें, फिर हर वह तरीक़ा आज़माएँ जिससे बेईमान या लापरवाह user उसे तोड़ सकता है, harmless test data के साथ और ऐसे system पर जिसे test करने की आपको अनुमति है।
यह क्यों ज़रूरी है
ये defects vulnerability scanners को शायद ही कभी मिलते हैं, क्योंकि technically कुछ भी malformed नहीं है: request valid JSON है, file valid upload है। सिर्फ़ वह टेस्टर जो समझता है कि business क्या चाहता है, देख सकता है कि discount: 100 या दूसरा confirm refuse होना चाहिए था। OWASP इस class को दो बार list करता है: Top 10 में Insecure Design (A06:2025) और API Security Top 10 में Unrestricted Access to Sensitive Business Flows (API6:2023), जहाँ purchase, booking या sign-up flow का automated abuse बताया गया risk है।
नुक़सान सीधा पैसा और भरोसा है: free orders, ख़ाली हो चुके coupons, bots द्वारा ख़रीदा गया पूरा stock, और ऐसी uploaded file जो server पर execute हो या किसी दूसरे user के browser में script चलाए। टेस्टर के लिए यह security testing का वह हिस्सा है जिसमें सबसे कम tooling और सबसे ज़्यादा सोच चाहिए, और यहीं functional testing की skills सीधे काम आती हैं।
Workflow abuse: छोड़े गए steps और बदले गए fields
हर multi-step flow एक state machine है: cart, coupon applied, awaiting payment, paid, confirmed। Browser steps क्रम में दिखाता है, लेकिन server को अलग-अलग requests मिलती हैं और उसे हर एक पर जाँचना चाहिए कि order सही state में है। Testing की शुरुआत states और उनके बीच ले जाने वाली requests की सूची से होती है, जैसे state transition testing के lesson में, फिर वे moves आज़माएँ जिनकी design इजाज़त नहीं देती: payment से पहले confirmation request भेजना, steps का क्रम बदलना (pay करने के बाद shipping चुनना), या वह step दोहराना जो एक ही बार होना चाहिए।
Tests का दूसरा group उन values को बदलता है जो server के पास होनी चाहिए। Price, discount, total, currency, role और is_admin fields को client से आना ही नहीं चाहिए; अगर आते हैं, तो उन्हें बदलें और देखें कि server दोबारा compute करता है या उन पर भरोसा करता है। Boundary value analysis से जानी negative और extreme values जोड़ें: quantity -1 (purchase के भेस में refund), 0, 999999, 101 percent का discount, 0.001 का price।
- Skip: आख़िरी step पहले भेजें। Expected:
4xxerror और state में कोई बदलाव नहीं। - Reorder और repeat: दो बार pay, दो बार confirm, ख़ाली cart पर coupon। Expected: दूसरा call refuse हो या harmless no-op रहे।
- Tamper: request में
price,total,discountयाroleबदलें, जैसे नीचे 1,899.00 के order की payment request में। Expected:400या422, या field ignore हो; दोनों हालात में server अपनी values इस्तेमाल करे और response उन्हें दिखाए। सिर्फ़ 1.00 charge करने वाला200ही defect है। - Limits और reuse: एक coupon प्रति customer, तीन attempts प्रति घंटा, पाँच items प्रति order। Expected: server हर इस्तेमाल गिने, ताकि limit sessions, devices और page reload के पार भी टिके, और कुल मिलाकर सिर्फ़ एक बार इस्तेमाल होने वाला code दूसरे account से भी refuse हो।
POST /orders/8841/pay HTTP/1.1
Host: shop.example
Content-Type: application/json
Cookie: session=...
{ "payment_token": "tok_test_123", "total": 1.00, "currency": "SAR" }आज़माएँ: स्टेट ट्रांज़िशन जनरेटर आज़माएँ: API रिक्वेस्ट बिल्डर
Race conditions: एक ही request दो बार, एक साथ
Race condition ऐसा defect है जो तभी दिखता है जब दो या ज़्यादा requests लगभग एक ही पल में एक ही record को छूती हैं। Classic case double spend है: wallet में 100 SAR हैं, 100 SAR की दो withdrawals साथ आती हैं, दोनों balance पढ़ती हैं इससे पहले कि कोई एक उसे लिखे, और दोनों सफल हो जाती हैं। यही आकार "Place order" पर double-click से दो orders, single-use coupon का दो बार redeem होना, या पाँच attempts की ऐसी limit जो छह को निकल जाने दे, पैदा करता है।
इस स्तर पर tooling से ज़्यादा concept मायने रखता है। Expected behaviour यह है कि server check और change एक ही अविभाज्य (atomic) step में करे, आम तौर पर database transaction के अंदर row lock, ऐसे update से जो तभी सफल हो जब balance अब भी काफ़ी हो, या unique constraint से, ताकि ठीक एक request जीते। Test करने के लिए वही request दो या ज़्यादा बार कम-से-कम delay के साथ भेजें (दो tabs, parallel में fire करने वाली script, या intercepting proxy का repeat function) और final state की तुलना उससे करें जो एक request को देना चाहिए था। Payment requests पर idempotency keys, जो आपको Idempotency-Key header के रूप में दिख सकती हैं, retries का design answer हैं और developer से पूछने लायक हैं।
- Double submit: order button दो बार दबा। Expected: एक order, एक charge, एक e-mail।
- Double spend: दो withdrawals या redemptions एक साथ। Expected: ठीक एक सफल हो और balance कभी शून्य से नीचे न जाए।
- Counter limits: किसी limit के ख़िलाफ़ कई parallel attempts। Expected: limit ठीक-ठीक टिके; limit के बाद वाली attempt refuse हो, requests की timing चाहे जो हो।
File uploads: नाम, type, size, content और file कहाँ जाती है
Upload application को तीन चीज़ें देता है जो आपस में असहमत हो सकती हैं: extension सहित file name, multipart part के Content-Type में declared media (MIME) type, और bytes ख़ुद। पहली दो चीज़ें client अपनी मर्ज़ी से चुनता है। report.pdf नाम और application/pdf Content-Type वाली file में HTML page हो सकता है। Secure handling, जैसा OWASP File Upload Cheat Sheet बताती है, है: extensions की allow list, असली content की जाँच (उसका file signature, यानी शुरुआती bytes जो format पहचानते हैं, और images के लिए उन्हें rewrite करना), size limit, server का बनाया file name, और किसी अलग host पर या web root (वह folder जिससे web server files serve करता है) के बाहर storage, जहाँ server file को code की तरह run नहीं करेगा।
Test का दूसरा आधा यह है कि file वापस serve होने पर क्या होता है। Application के अपने origin के URL पर खुली stored HTML या SVG file user के session के साथ script चलाती है: upload से पहुँचा stored XSS। Safe responses server का तय किया exact Content-Type, X-Content-Type-Options: nosniff, और हर उस चीज़ के लिए Content-Disposition: attachment (browser file को दिखाने के बजाय download करता है) भेजती हैं जो PNG या JPEG जैसी raster image नहीं है जिसका content server ने verify किया हो, या user files को अलग domain से serve करती हैं। SVG भी image है, लेकिन उसमें script हो सकती है, इसलिए उसके साथ HTML जैसा ही व्यवहार होता है।
- Type:
.jpgनाम दी गई harmless text file;text/htmlContent-Type से भेजी image; double extensionphoto.jpg.html; uppercase.PHP। Expected: आख़िरी extension, case की परवाह किए बिना, allow list में हो और content उससे मेल खाए; अकेला declared type कभी फ़ैसला न करे। - Size: ठीक limit, एक byte ऊपर, ख़ाली file। Expected: accept; साफ़ message के साथ reject; reject या empty के रूप में handle।
- Name:
../../qa-traversal-test.png, यानी path traversal की कोशिश: अगर server original नाम से storage path बनाता है, तो हर../एक folder ऊपर चढ़कर upload folder से बाहर निकल जाता है (नाम unique है, ताकि defect होने पर कोई मौजूदा file overwrite न हो, बस नई file बने); 300-character नाम, spaces, Arabic letters,%00(encoded null byte), सिर्फ़ extension वाला नाम। Expected: server के बनाए नाम से store; original नाम सिर्फ़ display के लिए, encoded। - Served back: लौटाया URL खोलें। Expected: सही
Content-Type,nosniff,attachmentया अलग origin; कुछ भी run न हो। - Storage और execution: पूछें कि files कहाँ जाती हैं और क्या वह path executable है; अगर
.phpया.aspxनाम वाली text file accept हो भी जाए, तो वह text के रूप में download हो, कभी execute न हो।
आज़माएँ: MIME टाइप लुकअप आज़माएँ: Content-Type वैलिडेटर आज़माएँ: स्पेशल कैरेक्टर डेटासेट जनरेटर
Worked example: single-use coupon वाला checkout
Requirement: "Customer cart में items जोड़ता है, एक coupon लगा सकता है (प्रति customer single-use, minimum order 200 SAR), payment provider से pay करता है और confirmation पाता है। Order confirm होने पर stock घटता है।" Requests हैं POST /cart/items, POST /cart/coupon, POST /orders (order बनाता है और total लौटाता है), POST /orders/{id}/pay और POST /orders/{id}/confirm।
पहले इसे states में model करें, Cart, Coupon applied, Awaiting payment, Paid और Confirmed, फिर हर forbidden move के लिए एक test, हर उस field के लिए एक test जो server के पास होना चाहिए, और हर rule की boundary values निकालें (minimum order के लिए 199.99 और 200.00, और coupon के बाद items हटाने पर दोबारा जाँच)। हर test का साफ़ oracle है: call के बाद order की state और total, GET /orders/{id} से पढ़े गए, और stock count।
| # | से | तक | Request / server का expected behaviour |
|---|---|---|---|
| 1 | Cartशुरुआत | Coupon applied | POST /cart/coupon / server code जाँचता है: valid, इस customer ने इस्तेमाल नहीं किया, order कम-से-कम 200.00 |
| 2 | Coupon applied | Awaiting payment | POST /orders / server अपनी prices और discount से total compute करता है |
| 3 | Awaiting payment | Paid | POST /orders/{id}/pay / payment provider server का total confirm करता है |
| 4 | Paid | Confirmedअंत | POST /orders/{id}/confirm / order confirmed, stock एक बार घटा, एक e-mail |
| 5 | Awaiting payment | Confirmedअंत | Abuse: order अभी awaiting payment में है और /pay छोड़कर confirm भेजा / expected 4xx, order Awaiting payment में ही रहेवैकल्पिक पथ |
| 6 | Awaiting payment | Paid | Abuse: payment body में "total": 1.00 / expected 4xx या field ignore; server का अपना total ही charge होवैकल्पिक पथ |
| 7 | Coupon applied | Coupon applied | Abuse: वही code दोबारा, या ख़र्च होने के बाद / expected 4xx, discount एक ही बार गिनावैकल्पिक पथ |
| 8 | Confirmedअंत | Confirmedअंत | Abuse: confirm replay, या दो parallel में / expected एक confirmation, stock एक बार घटावैकल्पिक पथ |
Simplified model: असल में coupon optional है, और असली checkout में address, shipping, refund और cancellation states भी होती हैं।
# Test Expected
1 POST /orders/{id}/confirm before /pay 4xx; stays Awaiting payment
2 /pay with "total": 1.00 in the body 4xx or ignored; server total kept
3 /cart/coupon twice with the same code second call 4xx; discount once
4 coupon on a 199.99 cart (minimum 200.00) 4xx; no discount
5 coupon on a 200.00 cart accepted; discount applied
6 coupon at 200.00, then an item removed discount dropped, or /orders 4xx
7 /cart/items with "quantity": -1 4xx; cart unchanged
8 /confirm sent twice in parallel one confirmation; stock reduced once
9 /pay on another customer's order 403 or 404 (access control)
10 coupon already used on an earlier order 4xx; no discountआज़माएँ: स्टेट ट्रांज़िशन जनरेटर आज़माएँ: API रिक्वेस्ट बिल्डर
आम गलतियाँ
- सिर्फ़ UI से happy path test करना, जहाँ browser वे steps और fields छिपा देता है जिन्हें attacker सीधे edit करता है।
- बदला हुआ
pricefield defect बताकर report करना, बिना यह जाँचे कि server ने उसे सच में इस्तेमाल किया; server ने जो total store और charge किया, call के बाद दोबारा पढ़ा गया, वही सबूत है। - File extension जाँचकर upload को safe घोषित करना, जबकि content और response headers कभी देखे ही नहीं गए।
- असली malware, exploit files या किसी colleague का personal data test uploads के रूप में इस्तेमाल करना। ग़लत नाम वाली एक text file check साबित करने के लिए काफ़ी है।
- Race-condition या limit tests production या shared environment पर चलाना, जहाँ double orders और ख़ाली हुए coupons असली data पर असर डालते हैं।
- Test का दूसरा आधा भूल जाना: file कहाँ store होती है, कैसे वापस serve होती है और क्या वह कभी execute हो सकती है।
QA का नज़रिया
टीम में business logic testing refinement में शुरू होती है: जब story में कोई limit, discount, step order या upload आता है, टेस्टर पूछता है कि rule टूटने पर server क्या करता है और जवाब acceptance criteria के रूप में लिखता है। फिर tests किसी भी state transition या boundary tests की तरह निकाले जाते हैं और regression suite में रखे जाते हैं, क्योंकि checkout का refactor चुपचाप client field पर भरोसा वापस ला सकता है।
आप सिर्फ़ वे systems test करते हैं जो आपके हैं या जिनके लिए लिखित authorisation है, test accounts, test payment tokens और harmless files के साथ, और shared environment पर parallel requests दागने से पहले टीम को बताते हैं। Finding में request, आपका किया एक बदलाव, response और नतीजे वाली state दर्ज होती है, और severity पैसे और पहुँच से तय होती है: free order या execute होने वाला upload critical है; एक से पार हुई limit आम तौर पर minor।
अभ्यास
Support-ticket attachment के tests plan करें
एक helpdesk signed-in customer को POST /tickets/{id}/attachments से ticket में files जोड़ने देता है: सिर्फ़ PDF, PNG और JPEG, अधिकतम 10 MB, प्रति ticket 3 files तक। Support agents ticket page से attachments खोलते हैं, जहाँ file /attachments/{uuid} से serve होती है।
Harmless files और requests का एक test plan बनाएँ, हर एक के expected result के साथ, जो type, size, name, count limit और file के वापस serve होने के तरीक़े को cover करे। असली system की ज़रूरत नहीं: बताएँ कि आप कौन-सी files बनाएँगे और हर एक क्या साबित करती है।
- Test files की सूची बनाएँ: valid, disguised और oversized, और हर एक को बिना malware कैसे बनाएँगे।
- Rule तोड़ने वाली requests की सूची बनाएँ: limit, state, दूसरे customer का ticket।
- हर एक के लिए लिखें कि response में और served file में क्या जाँचेंगे।
मॉडल उत्तर दिखाएँ
Files: valid.pdf (असली एक-page PDF), valid.png और valid.jpg (असली images), सभी accept हों; ठीक 10 MB की valid PDF accept हो, और वही file एक byte बड़ी होने पर size message के साथ reject हो (पहले पूछें कि 10 MB का मतलब 10,000,000 bytes है या 10,485,760); एक ख़ाली file; page.png नाम दी गई page.html (image के नाम से HTML content); note.pdf.exe नाम दी गई note.txt; script.svg (ऐसे <script> element वाली SVG जो सिर्फ़ alert दिखाती है); text/html Content-Type के साथ भेजी असली PNG; और ../../qa-traversal-test.png नाम की असली PNG, ऐसा unique नाम जो कुछ भी overwrite नहीं कर सकता। Expected: ख़ाली, disguised, SVG और .exe uploads साफ़ message के साथ refuse हों और कुछ store न हो; ग़लत Content-Type वाली PNG refuse हो, या image/png के रूप में store और serve हो; traversal नाम refuse हो या server के बनाए नाम से store हो, और upload folder के बाहर कोई file न दिखे।
Requests: जिस ticket में पहले से तीन हैं उस पर चौथा attachment (expected 4xx); दो files वाले ticket पर, जब सिर्फ़ एक slot बचा हो, parallel में दो uploads (expected ठीक एक accept, चार stored कभी नहीं); दूसरे customer की ticket id पर upload (expected 403 या 404, जैसे access control के lesson में); बंद ticket पर upload अगर rule कहता है कि बंद tickets read-only हैं (expected 4xx, कुछ store न हो)।
Served back: PNG और PDF के लिए /attachments/{uuid} खोलें। Expected: stored type से मेल खाता Content-Type, X-Content-Type-Options: nosniff, PDF के लिए Content-Disposition: attachment, original file name सिर्फ़ ticket page के text में, encoded, URL किसी दूसरी ticket से guess न हो सके, और किसी दूसरे customer के session से माँगने पर 403 या 404 मिले।
दर्ज करने के सबूत: हर request, response का status और body, call के बाद ticket की attachment list, और served file के response headers।
अक्सर पूछे जाने वाले सवाल
क्या business logic testing security activity है या functional?
दोनों। Tests functional tests की तरह rules और states से निकाले जाते हैं, लेकिन oracle यह है कि बेईमान user क्या नहीं कर पाना चाहिए। OWASP इसे Insecure Design के तहत और APIs के लिए Unrestricted Access to Sensitive Business Flows के तहत cover करता है।
क्या मैं race conditions हाथ से test कर सकता हूँ?
आंशिक रूप से। एक साथ submit करते दो browser tabs, या button पर double-click, आम double-submit defect पकड़ लेते हैं। भरोसेमंद नतीजों के लिए script या proxy से parallel में दागी requests और ऐसा test environment चाहिए जहाँ double orders से नुक़सान न हो।
Uploads के लिए कौन-सी test files safe हैं?
Plain text, एक असली छोटी image या PDF, और वही files rename करके या ग़लत Content-Type से भेजी हुई। Alert दिखाने वाले harmless <script> वाली SVG served-back risk साबित करती है। कभी असली malware या किसी और के personal documents इस्तेमाल न करें।
क्या extension जाँचने से upload safe हो जाता है?
नहीं। Extension वह नाम है जो client चुनता है। Safe handling content जाँचती है, size enforce करती है, अपना file name बनाती है, file वहाँ रखती है जहाँ कुछ उसे execute न करे, और उसे fixed Content-Type और nosniff के साथ serve करती है।
संदर्भ
- OWASP Web Security Testing Guide (WSTG)वेब एप्लिकेशन और API की सुरक्षा कमज़ोरियों को परखने की संदर्भ कार्यप्रणाली, एक-एक टेस्ट के रूप में।
- OWASP Cheat Sheet Series: File Uploadअपलोड की गई फ़ाइलों की जाँच: एक्सटेंशन और कंटेंट-टाइप जाँच, साइज़ सीमा, वेब रूट के बाहर स्टोरेज, स्कैनिंग।
- OWASP API Security Top 10 (2023)API की दस सबसे आम कमज़ोरियाँ: ऑब्जेक्ट-लेवल ऑथराइज़ेशन का टूटना, ऑथेंटिकेशन का टूटना, अनियंत्रित रिसोर्स खपत और अन्य।
- OWASP Top 10:2025वेब एप्लिकेशन की दस सबसे गंभीर सुरक्षा जोखिम, हर एक की जाँच और रोकथाम के साथ।
Mutqan tools से अभ्यास करें
states और events परिभाषित करें, फिर transition तालिका, वैध/अमान्य transition टेस्ट और 0-switch/1-switch coverage जनरेट करें।
फ़ील्ड परिभाषा से strings, संख्याओं, तारीख़ों, फ़ाइलों, lists और concurrency के edge case जनरेट करें।
HTTP रिक्वेस्ट (method, URL, हेडर, auth, बॉडी) बनाएँ और भेजें, फिर रिस्पॉन्स जाँचें — आपके ब्राउज़र में हल्का-फुल्का Postman।
किसी फ़ाइल एक्सटेंशन का MIME टाइप, या किसी MIME टाइप के एक्सटेंशन खोजें।
Content-Type हेडर जाँचें और देखें कि रिस्पॉन्स बॉडी सचमुच घोषित मीडिया टाइप से मेल खाती है या नहीं।
स्पेशल कैरेक्टर से भरे इनपुट जनरेट करें: कोट, SQL/HTML/JSON मेटाकैरेक्टर, कंट्रोल कैरेक्टर, emoji और path की चालाकियाँ।
और गहराई से
इस topic में आपकी प्रगति
प्रगति ट्रैक करने के लिए साइन इन करें
Topics पूर्ण चिह्नित करें, जहाँ छोड़ा था वहीं से जारी रखें और specialisation परीक्षाएँ खोलें।