- AWS डेटा लीक के जोखिमों में S3 bucket पर unauthorized access बार-बार सामने आता है, और पुराने API design व exception जैसे व्यवहारों के कारण इसे सिर्फ “public/private” के रूप में आंकना मुश्किल है
- कई S3 operations सामान्य AWS endpoint के बजाय bucket URL खुद पर call किए जाते हैं, और गलत bucket policy होने पर बिना authentication वाले
curlrequest से भी जोखिम भरे operations संभव हो सकते हैं - सिर्फ
s3:ListBucketblock कर देने से सुरक्षित मानना मुश्किल है;ListBucketVersions,ListMultipartUploads,fetch-ownerजैसे रास्ते object keys और account identifiers उजागर कर सकते हैं - uploader storage class, tags, Object Lock, और redirect से जुड़े कुछ headers जैसी object properties को प्रभावित कर सकता है, इसलिए IAM conditions और lifecycle policies जैसे अतिरिक्त controls की जरूरत होती है
- केवल ACL और public access block settings देखकर bucket को private मान लेने पर कुछ access paths छूट सकते हैं; CloudFront distribution या Cognito identity pool के जरिए internet users S3 objects तक पहुंच सकते हैं
पुराने S3 API design और anonymous calls
- S3, AWS की शुरुआती services में से एक है, इसलिए यह मजबूत और अच्छी तरह tested है, लेकिन standardized design patterns से पहले के निशानों के कारण अन्य AWS services से अलग API form रखता है
- कुछ S3 APIs
s3.us-east-2.amazonaws.comजैसे सामान्य endpoints इस्तेमाल करते हैं, लेकिन कई operations को target bucket URL पर सीधे request करना पड़ता है- bucket list query का उदाहरण
Host: [bucketname].s3.amazonaws.comरूप मेंGET /है - bucket tags query भी उसी bucket host पर
GET /?taggingभेजती है
- bucket list query का उदाहरण
- EC2 या DynamoDB जैसी कई AWS services सामान्य endpoint इस्तेमाल करती हैं, और target resource को HTTP header या parameter के रूप में पास करना आम है
- S3 buckets public access और authenticated access दोनों support करते हैं, इसलिए कौन-सा API operation बिना authentication के संभव है, यह हमेशा स्पष्ट नहीं होता
- अगर example bucket policy bucket resource पर
Principal: "*"औरAction: "s3:*"allow करती है, तो बिना authentication वाले request से भी bucket delete करना संभव है- example request है
curl -X DELETE https://[bucketname].s3-ap-southeast-2.amazonaws.com
- example request है
- कुछ operations anonymous requests support नहीं करते, और
s3:GetBucketOwnershipControls does not support Anonymous requests!जैसी error लौटती है - anonymous API requests CloudTrail में anonymous account के रूप में record होते हैं
- अगर request unauthenticated है, तो यह identify नहीं किया जा सकता कि bucket किसने delete किया, या encryption settings अथवा logging status किसने query किया
/?logging,/?tagging,/?encryptionजैसे paths browser में भी test किए जा सकते हैंGetObjectTorrentजैसे operations भी हैं जिनके docs मौजूद हैं, लेकिन अब उन्हें execute नहीं किया जा सकता
सिर्फ ListBucket block करने से object key exposure रोकना मुश्किल है
- S3 object download करने के लिए हर object की key चाहिए होती है, और key का उपयोग file path की तरह होता है
- root bucket पर
GETrequest कुछ conditions में bucket contents लौटा सकता है, इसलिएs3:ListBucketdeny करना एक आम बचाव जैसा दिखता है public-readACL औरs3:ListBucketdeny policy साथ इस्तेमाल करने पर भी object keys पाने के रास्ते बचे रहते हैंGET /?versions, यानीs3:ListBucketVersions, bucket के अंदर object versions का metadata लौटाता हैGET /?uploads, यानीs3:ListMultipartUploads, चल रहे multipart uploads की list लौटाता है
HeadBucketdocs में bucket के existence और access permissions check करने से जुड़ी wording है, लेकिन व्यवहार में यह check करता है किListBucketoperation करने की permission है या नहीं- केवल
ListBucketdeny है या नहीं, यह verify करने पर S3 object keys expose होने की संभावना छूट सकती है
अधूरे multipart upload की लागत और exposure
- multipart upload
create-multipart-uploadसे शुरू होता है औरupload-partसे parts upload किए जाते हैं - अधूरे multipart uploads को web console में देखना आसान नहीं है; इन्हें
/?uploadsयाaws s3api list-multipart-uploads --bucket [bucket-name]से देखा जा सकता है - अगर completion request सफलतापूर्वक भेजी नहीं जाती, तो Amazon S3 parts को assemble नहीं करता और object भी नहीं बनाता
- uploaded parts तब तक account में रहते हैं जब तक multipart upload complete या abort नहीं होता
- stored parts पर S3 storage cost लगती है
- complete होने से पहले object के parts download करने का तरीका नहीं मिला, लेकिन delete करना संभव है
- AWS एक तय number of days के बाद अधूरे uploads delete करने वाली lifecycle rule apply करने की सिफारिश करता है
/?uploadsसे अधूरे multipart uploads list करने पर upload शुरू करने वाले principal का ARN लौटता है- अगर account ID, ARN जैसे identifiers को non-sensitive मानते हैं, तो यह problem नहीं हो सकती
- अगर attacker के लिए उपयोगी identifiers reveal करना नहीं चाहते, तो इसे exposure माना जा सकता है
ACL और email-based account verification
- S3 ACL docs में उस दौर के निशान बचे हैं जब AWS accounts को root user email से identify किया जाता था
PutBucketACLoperation grantee को email address से specify कर सकता हैType: AmazonCustomerByEmailऔरEmailAddressका उपयोग होता है
- अगर दिए गए email से जुड़ा AWS account नहीं है, तो
UnresolvableGrantByEmailAddresserror आती है- error message इस तरह होता है कि “दिया गया email address records में किसी account से match नहीं करता”
- इस behavior की वजह से यह check किया जा सकता है कि किसी खास email address के पास registered AWS account है या नहीं
uploader द्वारा चुनी जा सकने वाली storage class और object metadata
- S3 की storage class bucket पर नहीं, object पर apply होती है
- bucket level पर desired storage class fix करने की setting नहीं है, और upload करने वाला subject object की storage class specify कर सकता है
- उदाहरण है
aws s3 cp "my.txt" "s3://mybucket/myobject.txt" --storage-class [CLASS]
- उदाहरण है
- uploader predefined list के भीतर ऐसे विकल्प चुन सकता है जो bucket owner द्वारा वहन की जाने वाली per-GB storage और access costs को प्रभावित करें
- IAM policy में
s3:x-amz-storage-classcondition key का उपयोग करके allowed storage classes को restrict किया जा सकता है- example policy
s3:PutObjectके लिए केवलSTANDARDallow करती है
- example policy
- lifecycle policy set करने पर एक निश्चित अवधि के बाद सभी objects को किसी specific storage class में transition किया जा सकता है
- pre-signed URL इस्तेमाल करने वाले uploads में AWS Signature Version 4
X-Amz-से शुरू होने वाले सभी headers की signing require करता है- storage class
x-amz-storage-classheader से specify होती है - अगर application बहुत गलत तरीके से implemented न हो, तो तुरंत manipulate करने का कोई साफ तरीका नहीं दिखता
- storage class
tags, Object Lock, redirect भी uploader के प्रभाव में हैं
- S3 objects से जुड़ी कई properties uploader control करता है
- object tags upload के समय specify किए जा सकते हैं
- उदाहरण है
--tagging "AllYourTags=AreBelong&To=Us"
- उदाहरण है
- tag values के आधार पर automation करने वाले systems uploader द्वारा बनाए गए tag values से प्रभावित हो सकते हैं
- Object Lock bucket में object locking enabled होने पर object retention और legal hold set कर सकता है
- example command
--object-lock-retain-until-date "2099-01-01T00:00:00+0000",--object-lock-legal-hold-status "ON",--object-lock-mode "COMPLIANCE"इस्तेमाल करता है
- example command
- static website hosting enabled buckets में uploaded file settings का उपयोग करके open redirect संभव है
PutObjectद्वारा support किए जाने वाले headers की पूरी list पर भी ध्यान देने की जरूरत है- pre-signed URL में limitations होती हैं
- Cognito identity और IAM policy पर निर्भर configurations में authenticated Cognito context से request sign किया जा सकता है
bucket owner और account identifiers का exposure
- यह confirm करने के लिए कि कोई specific account ID accessible bucket का owner है या नहीं,
ListBucketrequest मेंx-amz-expected-bucket-ownerheader डाल सकते हैं- गलत account ID डालने पर
AccessDeniedलौटता है - सही account ID डालने और caller के पास
ListBucketpermission होने पर normal response लौटता है
- गलत account ID डालने पर
ListBucketAPI केfetch-owner=trueparameter का उपयोग करने पर response में हर key के लिए Owner element शामिल होता हैOwnerके अंदरIDएक 64-character hexadecimal string है, जिसे AWS docs में canonical user ID कहा जाता है- यह AWS account ID का obfuscated form है
- canonical user ID को IAM policy के
PrincipalमेंCanonicalUserके रूप में डालकर save करने और फिर refresh करने पर यह AWS account ID में resolve हो जाता है ListBucketVersionsऔरListMultipartUploadsभीfetch-ownerके बिना मिलते-जुलते तरीके से काम करते हैं
S3 object keys file names जैसी दिखती हैं, लेकिन अलग तरह से काम करती हैं
- S3 object keys case-sensitive होती हैं
- नाम एक जैसे दिखें, फिर भी uppercase/lowercase अलग होने पर कई objects upload किए जा सकते हैं
- अगर application S3 object keys को case-insensitive file names की तरह handle करता है, तो समस्याएं हो सकती हैं
- example application user passwords को S3 file में store करता है, और file name के रूप में username इस्तेमाल करता है
- sign-up के समय केवल file existence check करता है, और password change के समय username को lowercase में बदलकर file में लिखता है
jeffपहले से होने पर भीJEFFsign-up कर सकता है, औरJEFFuser password change करकेjeffकी file overwrite कर सकता है
- S3 object key में कोई भी UTF-8 character इस्तेमाल किया जा सकता है
- कुछ characters कुछ applications और protocols में problem पैदा कर सकते हैं
- spaces, slashes, percent characters आदि भी object key में valid हैं
“private bucket” जैसा दिखने पर भी access paths बचे हो सकते हैं
- ACLs बंद हों, resource policy narrow set हो, और block public access enabled हो, फिर भी bucket publicly accessible हो सकता है
- सबसे common path Amazon CloudFront distribution है
- S3 bucket के आगे CDN रखने के मामलों में आम तौर पर internet content delivery का intent होता है
- security tools bucket resource policy CloudFront तक limited होने पर इसे public नहीं मान सकते
- example में
get-bucket-policy-statusIsPublic: falseलौटाता है- bucket पर direct request करने पर
AccessDeniedलौटता है - CloudFront distribution domain पर वही request भेजने पर object content लौटता है
- bucket पर direct request करने पर
- Cognito identity pool भी restricted resource policy वाले bucket को expose कर सकता है
- Cognito login success के बाद pre-configured role के temporary AWS credentials देता है
- अगर उस role के पास
s3:ListBucketऔरs3:GetObjectpermissions हैं, तो user S3 API call कर सकता है
- public access में आ सकने वाली Cognito settings दो तरह की हैं
- Self-registration: अगर internet users app में sign up और login कर सकते हैं, तो यह effectively public access बन जाता है
- Guest access: unauthenticated users को unique identifier और AWS credentials प्रदान करता है
- guest access example का flow है:
get-idसेIdentityIdलेना,get-credentials-for-identityसे temporary credentials लेना, और फिर उस profile सेaws s3 lsचलाना - CloudFront और Cognito identity pool वास्तव में internet पर अक्सर इस्तेमाल होते हैं, लेकिन security tools में ये public access paths कम ही दिखाए जाते हैं
1 टिप्पणियां
Hacker News राय
दिलचस्प बातें तो कई हैं, लेकिन फ़ाइल सिस्टम के case-sensitive होने को शिकायत की वजह मानने से सहमत होना मुश्किल है
मेरे हिसाब से उसे ऐसा ही होना चाहिए, और macOS का ऐसा न करना उल्टा परेशान करता है
फ़ाइल नामों में case-sensitivity non-technical users को भी अप्रत्याशित लग सकती है। अगर कोई कहे कि उसने “Book Draft 1.docx” भेजा है, लेकिन mailbox में “Book draft 1.docx” हो, तो आमतौर पर कोई यह नहीं कहेगा, “लगता है आपने अलग फ़ाइल भेज दी?”
लिखे हुए टेक्स्ट में भी case आम तौर पर अर्थ नहीं बदलता। “Hi, how are you?” और “hi, how are you?” का मतलब एक ही है, और uppercase से अर्थ बदलना ज़्यादातर proper noun और common noun में फ़र्क करने तक सीमित है, जो फ़ाइल नामों में शायद ही कोई मुख्य चिंता हो
निजी पसंद अलग बात है, लेकिन किसी developer या system administrator का फ़ाइल सिस्टम की case-sensitivity देखकर चौंकना या चिढ़ना समझना मुश्किल है। ज़रूरत हो तो developers इसे end users के लिए abstract कर सकते हैं, जैसे search results में होता है
यह coding जैसा भी नहीं है, जहाँ code style enforce करने से readability में मदद मिलती है। Programming में भी, IDEs के variable name typos पकड़ने लायक smart होने से पहले, यह bugs की वजह बनता था। Pascal की एक अच्छी बात यह थी कि C के उलट case की चिंता नहीं करनी पड़ती थी
आप फ़ाइल नाम अपनी पसंद के style में लिख सकते हैं और वह spelling बची रहती है, लेकिन search या processing करते समय आपको वह style ठीक-ठीक याद रखने की ज़रूरत नहीं होती। क्योंकि search case-sensitive नहीं होता
case-sensitivity तो आसान हिस्सा है; ज़्यादा कम intuitive बात यह है कि S3 paths नकली होते हैं
S3 “/builds/1/installer.exe” upload स्वीकार कर लेता है और /builds के अंदर की listing भी दिखा देता है, लेकिन असल में आपने नाम में '/' शामिल रखने वाली '/builds/1/installer.exe' नाम की एक key upload की होती है
इसलिए “/builds/1//installer.exe” और “/builds//1/installer.exe” भी upload किए जा सकते हैं और वे पूरी तरह अलग फ़ाइलें हैं। वे सिर्फ़ key names हैं; असली directories नहीं हैं
[1] https://docs.aws.amazon.com/AmazonS3/latest/userguide/direct...
इस साल हमारे production system में भी एक अजीब bug आया और 5 लोगों के लगने के बाद ही मिला। कारण एक object था जिसका नाम literal तौर पर “/” था, और software उसे file नहीं बल्कि path की तरह handle करने की कोशिश कर रहा था
S3 या दूसरे AWS services पर भरोसा करके इस्तेमाल करना मुश्किल है। कुछ भी intuitive नहीं है, moving parts बहुत ज़्यादा हैं, और पढ़ने के लिए documentation भी बहुत है
इतना करने पर भी, मूल लेख जैसी गलती से सब कुछ पूरी दुनिया के लिए public कर सकते हैं। मैं इसके बजाय Hetzner Storage Boxes या DigitalOcean Spaces जैसी सचमुच सरल services इस्तेमाल करूँगा
हाल ही में पता चला कि कुछ MB से बड़े video files को pipe करके upload करने पर returned Location में https:// छूट जाता है। इसलिए हर file upload पर check करना पड़ता है कि Location https से शुरू होता है या नहीं, और न हो तो जोड़ना पड़ता है
जाहिर है, S3 Node client के GitHub issue में कहते हैं “लगता है DigitalOcean bug है”, और DigitalOcean forum में कहते हैं “लगता है S3 Node client bug है”
ढेरों features और quirks, जिन्हें मूल रूप से कुछ special cases में मदद के लिए design किया गया था, अब general protocol का हिस्सा बन गए हैं। लगता है business के लिहाज़ से किसी को भी दूर न करने की कोशिश में ऐसा हुआ है
अरबों objects हटाते समय भी सावधानी बरतनी चाहिए। delete API को सीधे call करना महंगा पड़ सकता है
इसके बजाय wildcard या पूरे bucket के लिए expiry time को now सेट करने वाला lifecycle rule मुफ्त में configure किया जा सकता है। तब storage billing तुरंत रुक जाती है और AWS deletion को अपने-आप संभालता है
इससे S3 API servers पर प्रति सेकंड requests की मार पड़ने से भी बचा जा सकता है
असफल multipart uploads का अदृश्य रूप से बचे रहना, और अगर आपने स्पष्ट रूप से lifecycle setting नहीं की तो उन पर storage cost लगना, सच में बहुत खराब है
मुझे लगा था “Simple” में S का मतलब simplicity है
मेरा प्रस्ताव था कि incomplete uploads के parts आखिरी activity के बाद सिर्फ 24 घंटे रहें, और उस दौरान storage cost भी charge न की जाए। ahenry@ ने इसे reject कर दिया
एक बहुत पुराने server पर लगभग 10 साल तक हर रात multipart upload शुरू करने वाली cron script चल रही थी। इसका काम backups को bucket में push करना था, लेकिन उसी bucket में user-uploaded content भी store होता था, इसलिए उसका रोज थोड़ा-थोड़ा बढ़ना सामान्य लगता था
script “काम नहीं कर रही” थी, इसलिए हम backup data पर निर्भर नहीं थे; S3 में भी files नहीं दिखती थीं; और bucket size लगातार, लेकिन बहुत ज्यादा नहीं, बढ़ रहा था। लेकिन इस spring में देखा तो करीब 3TB incomplete multipart uploads store हो रहे थे
जाहिर है, मुझे पता है कि यह किस्सा खराब practices से भरा है
case-sensitive/case-insensitive वाली चर्चा कुल मिलाकर बहुत English-centric लगती है
दूसरे शब्दों में, खासकर IT में language-related discussions अक्सर जरूरत से ज्यादा English-centric होती हैं
non-native English speaker के तौर पर कहूं तो programming में पहले से ही बहुत सारे concepts और elements हैं। बेहतर है कि इसमें 101 अलग-अलग languages को ध्यान में रखकर complexity और न बढ़ाई जाए
Unicode और time zones programming में ज्यादा languages और cultures को ध्यान में रखने की कोशिश के प्रमुख examples हैं, और नतीजे में वे non-English programmers समेत सभी के लिए सबसे बड़ा दर्द बनते हैं
मैं अपनी मातृभाषा में programs लिखना नहीं चाहता। अगर इसके बदले programming करते समय सारी major languages को ध्यान में रखना पड़े, तो और भी नहीं। IT discussions का English-centric होना ठीक है। diversity complexity है, और English कोई ऐसी भाषा नहीं है जिसका मालिक कोई एक हो; यह बस एक tool है जिसे लोग communication के लिए इस्तेमाल करते हैं
उसी common language की वजह से मैं India, China, Japan, South America आदि के कई लोगों तक अपने विचार पहुंचा सकता हूं। जिस क्षण वे English में बोलने का फैसला करते हैं, वे भी English के मालिक हो जाते हैं। IT में diversity politics खींचकर लाने की जरूरत नहीं; इसे technical रखना बेहतर है
एक तरह से ये दो syllabaries uppercase/lowercase alphabets जैसी महसूस होती हैं
कुछ और बातें भी हैं
मल्टीपार्ट अपलोड instance credentials वाले कई मशीनों से नहीं किया जा सकता। वजह यह है कि principals अलग होते हैं, इसलिए वे एक-दूसरे के multipart upload तक access नहीं कर सकते। कई मशीनों से एक multipart upload assemble करना हो तो वास्तविक IAM user चाहिए
LIST requests सिर्फ धीमी ही नहीं, बड़े पैमाने पर बहुत महंगी भी होती हैं। “bucket inventory” जैसे workarounds हैं, लेकिन वे न तो सुविधाजनक हैं और न ही सस्ते
bucket creation अंदरूनी तौर पर DNS का इस्तेमाल करता है, इसलिए write-after-read consistency नहीं होती। इसलिए कभी-कभी bucket बनाने के तुरंत बाद उसे access नहीं किया जा सकता, या changes propagate होने के लिए पर्याप्त इंतजार करने से पहले अभी-अभी बनाए गए bucket को delete नहीं किया जा सकता। https://github.com/julik/talks/blob/master/euruko-2019-no-su... देखें
“foo” नाम का object और “foo/bar” नाम का object एक साथ बनाए जा सकते हैं। तब ऐसी संरचना बन जाती है जहां एक file directory को overwrite कर देती है, और bucket data को filesystem structure में port करना असंभव हो जाता है
S3 case-sensitive है, इसलिए ऐसे objects बनाए जा सकते हैं जिन्हें filesystem structure में port नहीं किया जा सकता। Rails file storage ने case-sensitive storage मान लिया था, इसलिए macOS पर बुरी तरह टूट गया, और बाद में identifiers को हमेशा lowercase में लिखने के लिए fix किया गया
अधिकतर S3 configurations GET की अनुमति देती हैं, लेकिन HEAD की नहीं। लगता है यह object existence probing रोकने का तरीका है, हालांकि पक्का नहीं। किसी भी हाल में, HEAD request से object size जांचने वाला cache-friendly flow, खासकर pre-signed URL में, काम नहीं करता। इसके बजाय बहुत छोटा Range लगाकर GET करना पड़ता है, जैसे सिर्फ पहला byte लाना
अगर आप बहुत सारे pre-signed URLs generate करते हैं, तो generation speed 10–40 गुना बढ़ाने की संभावना है: https://github.com/WeTransfer/wt_s3_signer
अधूरे multipart uploads की storage cost भी फिर भी देनी पड़ती है। अगर आपकी संरचना में users ऐसे uploads शुरू कर सकते हैं, तो खास सावधान रहना चाहिए। एक setting है जो कुछ समय बाद अधूरे multipart uploads को automatically delete कर देती है; परेशानी से बचना हो तो उसे enable करना चाहिए
विडंबना यह है कि S3 क्रांतिकारी था और आज भी कई स्तरों पर शानदार product है। बस, features जितने ज्यादा हैं, pitfalls भी उतने ही ज्यादा हैं
Elixir में Stream.transform(https://hexdocs.pm/elixir/Stream.html#transform/3) का इस्तेमाल करके columns को modify और inject करने वाली streaming CSV post-processing pipeline बनाई थी। Elixir के AWS और CSV modules incoming streaming data को तो process करते हैं, लेकिन outgoing stream का total size 5MiB से छोटा हो तो AWS module multipart upload इस्तेमाल करता है, इसलिए S3 में error आती थी—दुखद था
एक और दिलचस्प problem है, जिसे मैंने एक colleague के साथ कई दिनों तक analyze करके diagnose किया। S3 किसी single TCP connection से 100 HTTP requests भेजे जाने के बाद आगे की requests को चुपचाप drop कर देता है
https://github.com/aws/aws-sdk-go/issues/2825
performance के लिए keep-alive चाहिए, लेकिन client बहुत लंबे समय तक जुड़ा रहकर load balancer पर hotspot न बनाए—ऐसे मामलों में यह common pattern है
यह बात भी है कि standard storage class में S3 की latency ज्यादा है, इसलिए यह web serving के लिए उपयुक्त नहीं है
कई लोग सोचते हैं कि images या fonts जैसे website resources सीधे S3 से host कर देना ठीक है, लेकिन user experience खराब हो सकता है
“applications can achieve consistent small object latencies (and first-byte-out latencies for larger objects) of roughly 100–200 milliseconds.”
स्रोत: https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimi...
CloudFront signed cookies का इस्तेमाल करके किसी specific user को S3 में उसके अपने content तक ही CDN access भी दिया जा सकता है। काफी बढ़िया है
frequently accessed assets को cache करके latency घटाई जा सकती है, और cost भी काफी कम हो सकती है
uploader द्वारा rules तय किया जाना काफी rough है। अगर कोई website की configuration कमजोर हो, तो क्या इसका मतलब है कि पर्याप्त motivation वाला user user content को Amazon Glacier में upload करवा सकता है, और बाद में वहीं से serve भी करवा सकता है?
https://docs.aws.amazon.com/service-authorization/latest/ref...
खास तौर पर condition keys यहां हैं, और storage class या tagging आदि तक access control करने वाली keys देखी जा सकती हैं
https://docs.aws.amazon.com/service-authorization/latest/ref...