gobuster, crossbeam, once_cell を試してみた

gobuster

golang 製の dns と url のブルースフォースツール。ドメインとワードリストを指定すると、存在する path, domain の一覧を返してくれる。 ワードリストの量によっては対象に負荷がめちゃくちゃかかるので使用する場合には要注意。

https://github.com/OJ/gobuster

おもしろそうなワードリストを見つけたのでこれを使用して使ってみます。 まずは DNS の方から。

$ curl https://gist.githubusercontent.com/jhaddix/86a06c5dc309d08580a018c66354a056/raw/96f4e51d96b2203f19f6381c8c545b278eaa0837/all.txt > /tmp/memo
$ gobuster dns -d google.com -w /tmp/memo

===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Domain:     google.com
[+] Threads:    10
[+] Timeout:    1s
[+] Wordlist:   /tmp/memo
===============================================================
2021/08/08 15:02:44 Starting gobuster in DNS enumeration mode
===============================================================
Found: 046101219159-5e16f22ca543dc45.clients.google.com
Found: 0.client-channel.google.com
Found: 0.staging.google.com
Found: 1.google.com
Found: 10207.sites.google.com
Found: 109.collard.drive.google.com
Found: 10-for-kids.clients.google.com
Found: 10.sites.google.com
Found: 114.moorehouse.drive.google.com
Found: 11.sites.google.com
Found: 123.sites.google.com
Found: 123.staging.google.com
Found: 125.eden.vale.drive.google.com

適当な箇所で終了しましたが、出力もかなり面白いですね。*.sites.google.com でアクセスすると sites.google.com/new に飛ばされるみたいです。 123.staging.google.com はおそらく google の検証環境でしょうか..? 1.google.com は one.google.com という何やら知らないサービスのページに飛ばされました。 ストレージサービスのようです。初めて知りました...。

次に URL に対しても実行してみます。

$ gobuster dir -u google.com -w /tmp/memo

===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://google.com
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /tmp/memo
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2021/08/08 15:12:40 Starting gobuster in directory enumeration mode
===============================================================
/..                   (Status: 302) [Size: 215] [--> http://google.com/]
/.                    (Status: 302) [Size: 215] [--> http://google.com/]
/104                  (Status: 301) [Size: 223] [--> https://www.google.com/104]
/105                  (Status: 301) [Size: 223] [--> https://www.google.com/105]
/2001                 (Status: 301) [Size: 224] [--> https://www.google.com/2001]
/2002                 (Status: 301) [Size: 224] [--> https://www.google.com/2002]
/2003                 (Status: 301) [Size: 224] [--> https://www.google.com/2003]
/2004                 (Status: 301) [Size: 224] [--> https://www.google.com/2004]
/2005                 (Status: 301) [Size: 224] [--> https://www.google.com/2005]
/2006                 (Status: 301) [Size: 224] [--> https://www.google.com/2006]
/2007                 (Status: 301) [Size: 224] [--> https://www.google.com/2007]
/2008                 (Status: 301) [Size: 224] [--> https://www.google.com/2008]
/2009                 (Status: 301) [Size: 224] [--> https://www.google.com/2009]
/2010                 (Status: 301) [Size: 224] [--> https://www.google.com/2010]
/2011                 (Status: 301) [Size: 224] [--> https://www.google.com/2011]
/2012                 (Status: 301) [Size: 224] [--> https://www.google.com/2012]
/2013                 (Status: 301) [Size: 224] [--> https://www.google.com/2013]
/2014                 (Status: 301) [Size: 224] [--> https://www.google.com/2014]
/2015                 (Status: 301) [Size: 224] [--> https://www.google.com/2015]
/2016                 (Status: 301) [Size: 224] [--> https://www.google.com/2016]
/2017                 (Status: 301) [Size: 224] [--> https://www.google.com/2017]
/2018                 (Status: 301) [Size: 224] [--> https://www.google.com/2018]
/2019                 (Status: 301) [Size: 224] [--> https://www.google.com/2019]
/2020                 (Status: 301) [Size: 224] [--> https://www.google.com/2020]
/2step                (Status: 301) [Size: 225] [--> https://www.google.com/2step]

20XX は 検索で振り返る 20XX という Google Trend の一部みたいです。/104 と /105 は理由は不明ですが、 Google Store に飛ばされました。 /2step は一昔前の 二段階認証サイト? に飛ばされています。びっくりですね 笑。

LT のネタになりそうなネタで面白かったです 笑。

crossbeam

rust の並行処理をより便利にしてくれるライブラリのようです。rust には mpsc (multi-produce-single-consume) という複数 Thread 間でのデータのやり取りを可能にする仕組みが存在します。 しかし、golang の channel と比較すると rust 特有のメモリの縛りや、multi-consume でないを解消してくれる模様。

早速使ってみます。

use crossbeam::channel::unbounded;

use std::thread;
use std::time::Duration;

fn main() {
    let (tx, rx) = unbounded();

    let th_cs: Vec<_> = (0..3)
        .map(|n| {
            let rx = rx.clone();
            thread::spawn(move || loop {
                match rx.recv() {
                    Ok(i) => println!("Get {} on thread {}", i, n),
                    Err(_) => break,
                };
                thread::sleep(Duration::from_secs(1));
            })
        })
        .collect();

    for i in 0..10 {
        tx.send(i).unwrap();
    }
    drop(tx);
    for t in th_cs {
        t.join().unwrap();
    }
}
$ cargo run
   Compiling playground-rust v0.1.0 (/Users/k-jun/source-code/playground-rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.42s
     Running `target/debug/playground-rust`
Get 2 on thread 2
Get 0 on thread 1
Get 1 on thread 0
Get 3 on thread 0
Get 4 on thread 2
Get 5 on thread 1
Get 6 on thread 0
Get 7 on thread 1
Get 8 on thread 2
Get 9 on thread 0

複数 Thread 感でやり取りができているのが素晴らしい...。rust はあまり詳しくありませんが おそらく Reciever に関しても Sync Crate が実装されているので、Thread 感でも Clone ができるのでしょうね。

crossbeam 専用の Thread Scoop というものを用いると、そもそも Clone せずとも変数にアクセスすることができます。 (まあ、ほかライブラリと組み合わせる場合にはほとんど無理そうですが)

use crossbeam::channel::unbounded;
use std::{thread, time};

fn main() {
    let (snd, rcv) = unbounded();
    let n_msgs = 5;
    crossbeam::scope(|s| {
        s.spawn(|_| {
            for i in 0..n_msgs {
                snd.send(i).unwrap();
                thread::sleep(time::Duration::from_millis(100));
            }
        });
    })
    .unwrap();
    for _ in 0..n_msgs {
        let msg = rcv.recv().unwrap();
        println!("Received {}", msg);
    }
}

現在使用しているのは stack できる queue の数に制限がない、unbound ですがきちんと制限がある版の bound も存在しています。

once_cell

rust のグローバル変数宣言を楽にしてくれるライブラリのようです。lazy_static という同様のものが存在しますが同系統のものですね。 よりスマートに記述できるようです。

グローバルで state 変数を宣言して試してみます。

use once_cell::sync::Lazy;
use std::sync::Mutex;
pub type Error = Box<dyn std::error::Error + Send + Sync>;

static state: Lazy<Mutex<Vec<String>>> = Lazy::new(|| Mutex::new(Vec::new()));

fn insert(fruit: &str) -> Result<(), Error> {
    let mut db = state.lock().map_err(|_| "Failed to acquire MutexGuard")?;
    db.push(fruit.to_string());
    Ok(())
}

fn main() -> Result<(), Error> {
    insert("apple")?;
    insert("orange")?;
    insert("peach")?;
    let db = state.lock().map_err(|_| "Failed to acquire MutexGuard")?;
    db.iter()
        .enumerate()
        .for_each(|(i, item)| println!("{}: {}", i, item));
    drop(db);
    insert("grape")?;
    Ok(())
}
0: apple
1: orange
2: peach

良い感じですね。一行でかけて便利そうです。rust がどんどん進化していくのを感じます。