EC2に脆弱性を仕込んでパッチ適用してみた!

EC2に脆弱性を仕込んでパッチ適用してみた!
この記事をシェアする

こんにちは!ブログ更新サボり気味な、スカイアーチHRソリューションズのMiyahiraです。

AWSエンジニア経験2年目の私ですが、EC2のパッチ適用を行ったことがありません、、。
なので、今回はEC2に脆弱性を意図的に仕込んで、それを検出し、脆弱性対応としてパッチ適用を行っていきたいと思います!

今回の内容は、書籍「AWSで実践するEC2の脆弱性対応」を参考に行っています。書籍では、脆弱性やパッチ適用ってそもそも何?といったところから記載されているので、ぜひ読んでみてください。

前提事項

本記事は、以下を前提に進めていきます。書籍には、使用するAWSサービスの説明や用途から細かく記載されているので、初心者の方は書籍を購入してみてください!

  • 脆弱性、パッチ適用とは何かを理解している
  • AWSアカウントを作成済み
  • AWSをある程度触ったことがある
  • 各AWSサービスの仕様などについては説明しません

全体の流れ

今回行う内容は、以下の流れとなります。

  • VPC関連、セキュリティグループの作成
  • EC2を作成し、脆弱性を仕込む
  • Amazon Inspectorで脆弱性を検出する
  • Patch Managerでパッチ適用を行う

環境構築

VPC関連、セキュリティグループの作成

まずはVPC関連のリソースを作成します。CloudFormationテンプレートを作成したので、こちらをデプロイしてください。

作成するリソース設定値
VPC10.0.0.0/16
パブリックサブネット×110.0.0.0/24
プライベートサブネット×110.0.10.0/24
インターネットゲートウェイ
NATゲートウェイ
Elastic IPアドレスNATゲートウェイ用
セキュリティグループ自身のセキュリティグループのみ通信可
AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  EnvironmentName:
    Description: An environment name that is prefixed to resource names
    Type: String
    Default: ec2-vulns-handson

  VpcCIDR:
    Description: Please enter the IP range (CIDR notation) for this VPC
    Type: String
    Default: 10.0.0.0/16

  PublicSubnetCIDR:
    Description: Please enter the IP range (CIDR notation) for the public subnet
    Type: String
    Default: 10.0.0.0/24

  PrivateSubnetCIDR:
    Description: Please enter the IP range (CIDR notation) for the private subnet
    Type: String
    Default: 10.0.10.0/24


Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCIDR
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-vpc

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-IGW

  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1a
      CidrBlock: !Ref PublicSubnetCIDR
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-PublicSubnet

  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1a
      CidrBlock: !Ref PrivateSubnetCIDR
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-PrivateSubnet

  NatGatewayEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc

  NatGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt NatGatewayEIP.AllocationId
      SubnetId: !Ref PublicSubnet
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-NGW

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-PublicRoutes

  DefaultPublicRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet

  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-PrivateRoutes

  DefaultPrivateRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway

  PrivateSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      SubnetId: !Ref PrivateSubnet

  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: !Sub ${EnvironmentName}-ec2-sg
      GroupName: !Sub ${EnvironmentName}-ec2-sg
      VpcId: 
        !Ref VPC

  SecurityGroupIgress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      IpProtocol: -1
      GroupId: !Ref SecurityGroup
      SourceSecurityGroupId: !Ref SecurityGroup

Outputs:
  VPC:
    Description: A reference to the created VPC
    Value: !Ref VPC
    Export:
      Name: !Sub ${EnvironmentName}-VPC

  PublicSubnet:
    Description: A reference to the public subnet
    Value: !Ref PublicSubnet
    Export:
      Name: !Sub ${EnvironmentName}-PublicSubnet

  PrivateSubnet:
    Description: A reference to the private subnet
    Value: !Ref PrivateSubnet
    Export:
      Name: !Sub ${EnvironmentName}-PrivateSubnet

  SecurityGroup:
    Description: A reference to the SecurityGroup
    Value: !Ref SecurityGroup
    Export:
      Name: !Sub ${EnvironmentName}-SecurityGroup

脆弱性を仕込んだEC2の作成

次にEC2を作成します。脆弱性を意図的に仕込むために、Apacheの古いバージョンをインストールします。こちらもCloudFormationで脆弱性が仕込まれたEC2を作成できます。

作成するリソース設定値
インスタンスプロファイルEC2にアタッチ(SSMから接続する用)
EC2AMI:Amazon Linux 2
InstanceType:t2.micro
サブネット:プライベートサブネットに配置
キーペア:なし
ユーザデータ:Apacheの「2.4.33-2.amzn2.0.2」バージョンをインストール
AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  EnvironmentName:
    Description: An environment name that is prefixed to resource names
    Type: String
    Default: ec2-vulns-handson
  EC2ImageId:
    Type: String
    Default: ami-0f89bdd365c3d966d
  EC2InstanceType:
    Type: String
    Default: t2.micro

Resources:
  InstanceProfile:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${EnvironmentName}-InstanceProfileForSSM
      Description: EC2 IAM role for SSM access
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

  Ec2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref InstanceProfile

  EC2:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref EC2InstanceType
      ImageId: !Ref EC2ImageId
      IamInstanceProfile: !Ref Ec2InstanceProfile
      SubnetId: 
        Fn::ImportValue: !Sub ${EnvironmentName}-PrivateSubnet
      SecurityGroupIds:
        - Fn::ImportValue: !Sub ${EnvironmentName}-SecurityGroup
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-EC2
      UserData:
        Fn::Base64: |
          #!/bin/bash
          sudo su -
          yum install httpd-2.4.33-2.amzn2.0.2 -y
          systemctl enable httpd.service
          systemctl start httpd.service
          systemctl status httpd.service

Apacheの確認

セッションマネージャーからEC2に接続し、以下のコマンドを実行してApacheの古いパッケージがインストールされているか確認します。

$ rpm -qa | grep httpd

AMIバックアップの作成

脆弱性にパッチ適用を何度も行えるように、脆弱性を仕込んだEC2のAMIバックアップを作成しておきます。

脆弱性を検出する

Amazon Inspectorを有効化する

Amazon Inspectorの画面⇒「使用を開始する」をクリック⇒「Ianpectorをアクティブ化」をクリック

スキャン結果の確認

Amazon Inspectorの画面⇒検出結果⇒インスタンス別

Inspectorを有効化すると最初のスキャンが開始されるので、完了するまで待ちます。

スキャンが完了するとEC2が表示され、脆弱性の数が表示されます。

EC2インスタンスIDをクリックすると、スキャン結果の詳細が表示されます。

パッチを適用する

先ほどAmazon Inspectorで検出したEC2の脆弱性を、Systems Manager Patch Managerでパッチ適用します。

EC2にタグを付与する

パッチ適用対象インスタンスの紐づけを行うために、EC2にタグを付与します。

タグキー
Patch Groupec2-vulns-handson

パッチマネージャーの設定

パッチマネージャーの画面⇒「概要から開始」をクリック⇒「パッチベースライン」をクリック⇒「パッチベースラインを作成する」をクリック

以下のパラメータを入力します。

項目設定値
名前ec2-vulns-handson-patch-baseline
説明ec2-vulns-handson-patch-baseline
オペレーティングシステムAmazon Linux 2
製品All
重要度All
自動承認特定の日付までにリリースされたパッチを適用する
日付の指定実施日の1ヶ月前を入力

作成後、「今すぐパッチ適用」をクリックし、画像と同じように設定して、「今すぐパッチ適用」をクリックします。※今回はスキャンのみなので、パッチは適用されません。

パッチベースラインに戻り、作成したパッチベースラインを選択して、アクションからパッチグループの変更を行います。

パッチグループには、先ほどEC2に付与したタグ「Patch Group」の値「ec2-vulns-handson」を入れます。

パッチを適用する

「今すぐ適用」をクリックします。今回はスキャンのみではなくパッチ適用まで行うので、画像を参考に入力してください。

「今すぐパッチ適用」をクリック後、RunCommandを確認すると、「AWS-RunPatchBaseline」というドキュメントが実行されていることが確認できます。

パッチマネージャーの画面でステータスが「Success」となれば、パッチ適用完了です。

パッチ適用の結果確認

Amazon Inspectorで検出結果を確認すると、脆弱性がなくなったことが確認できます。

まとめ

今回はとりあえずパッチ適用の流れが分かればよかったのでだいぶ簡単に行いましたが、実際の運用を考えると、もっと考慮が必要な点があります。
パッチ適用前にバックアップ取得や、適用後の正常性確認、パッチの定期実行などについても考えなければいけません。

ちょっと長くなってしまったので今回は省きます。が、なんと!参考にした書籍「AWSで実践するEC2の脆弱性対応」では実際の運用を考え、Step Functionsでワークフローを作成し、それを定期実行するところまで詳しく書かれていますので、ぜひ読んでみてください!

この記事をシェアする
著者:みやっち
沖縄出身で仙台在住。2000年生まれのAWS歴2年目エンジニア。趣味は野球、ゴルフ、サウナ。