一、背景
前段時間在做程式碼審計,發現很多專案都存在安全隱患,大多數是來自於引數未過濾所造成的;為了解決這個問題,我將Web安全開發規範手冊V1.0進行了培訓,但是效果並不是太理想,原因是培訓後開發者的關注點主要在功能完成度上,安全編碼對於他們來說並不是核心指標;
為了能讓開發者時時刻刻關注安全問題,我在gitlab服務端放了一個鉤子,這個鉤子主要是將本次提交的程式碼檔案進行了檢測,遇到可能存在安全風險的問題將其輸出出來,這樣開發者能夠對培訓的內容有更深的感受,更注重編碼時候的安全問題。
二、操作步驟
- 搭建環境
- 建立專案
- 建立鉤子
- 鉤子實驗
三、搭建環境
3.1 安裝gitlab
在正式部署到伺服器之前,我需要在本地搭建一個gitlab服務,用於鉤子的開發和測試,這裡我用docker搭建速度比較快,執行的命令如下
1 | docker run - - detach - - publish 443 : 443 - - publish 80 : 80 - - name gitlab - - restart always gitlab / gitlab - ce
|
命令執行之後,返回的資訊如下所示
在上圖中可以看到容器已經執行成功,使用瀏覽器訪問gitlab的地址
訪問之後需要設定一個管理員的密碼,如下圖所示
填寫密碼之後,確認修改密碼,會跳轉到gitlab的主頁,如下圖所示
這gitlab中建立一個專案用於鉤子測試,如下圖所示
建立專案成功之後,注意留意頁面中的Project ID:2
,把這個2
記錄一下,後續會使用到;接下來需要開始鉤子的開發和部署,鉤子可以使用各種語言開發,這裡我比較熟悉php,因此採用php開發。
3.2 安裝依賴
gitlab的容器預設不支援php語言,需要先安裝php,安裝命令如下所示
1 | apt update - y && apt install php - y
|
命令執行之後,返回的資訊如下所示
在上圖中可以看到php已經安裝成功,為了驗證php命令是否可以執行,這裡我使用如下命令進行驗證
命令執行之後,返回的資訊如下所示
在上圖中可以看到php的版本是7.4.3 ,說明php已經安裝成功。
3.3 安裝semgrep
鉤子程式中需要呼叫semgrep,這個程式gitlab中也沒有安裝,需要安裝一下,這裡採用pip安裝,不過需要先升級pip的版本才行,升級的命令如下所示
1 | pip3 install - - upgrade pip
|
命令執行之後,返回的資訊如下所示
在上圖中可以看到pip的版本已經升級到21.1.2,說明升級成功了
semgrep還依賴setuptools模組,需要用pip先升級一下,升級的命令如下所示
1 | pip3 install - - upgrade setuptools
|
命令執行之後,返回的資訊如下所示
在上圖中可以看到setuptools模組已經升級成功
接下來就可以正式安裝semgrep了,安裝的命令如下所示
1 | cd / usr / local / bin / && python3 - m pip install semgrep
|
命令執行之後,返回的資訊如下所示
在上圖中可以看到semgrep已經安裝完成,這裡我需要再次使用semgrep命令來驗證一下,執行的命令如下所示
命令執行之後,返回的資訊如下所示
在上圖中可以看到semgrep的版本資訊為0.52.0,確認安裝成功了。
3.4 檢視hash
現在我們需要在剛才建立的專案中新增鉤子,這裡需要找到專案的存放路徑,在專案頁中
命令執行之後,返回的資訊如下所示
命令執行之後,返回的資訊如下所示
在上圖中可以看到專案存放的位置,返回了兩個路徑,這兩個路徑其中有一個是軟連線,透過cd
命令進入進入專案的存放位置
1 | cd / var / opt / gitlab / git - data / repositories / @hashed / d4
|
命令執行之後,再次執行ls
命令,得到的資訊如下所示
在上圖中可以看到有一個73的資料夾,這是gitlab的命名規則,進入此資料夾,命令如下所示
1 | cd 73 / d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git /
|
命令執行之後,返回的資訊如下所示
在上圖中可以看到此專案的所有檔案,我需要在這個位置開發鉤子檔案
五、建立鉤子
自定義鉤子需要存放在custom_hooks
目錄下,預設沒有此資料夾所以需要建立此資料夾,執行命令如下所示
1 | mkdir custom_hooks && cd custom_hooks
|
5.1 新建鉤子
建立custom_hooks
資料夾並進入之後,使用vim建立一個鉤子檔案,命令如下所示
進入vim編輯器介面之後,將如下鉤子程式碼新增進去,程式碼如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <?php
fwrite(STDOUT, 'please input:' );
list ($oldVer, $newVer, $ref_name) = explode( " " , fgets(STDIN));
/ / ob_start();
$cmd = "git diff --name-only {$oldVer}..{$newVer}" ;
echo $cmd . PHP_EOL;
exec ($cmd, $result);
$rand = date( "Y-m-d-H-i-s" );
$baseDir = "/tmp/11/$rand/" ;
$ruleFile = "/semgrep-rule.yaml" ;
foreach ($result as $value) {
if (strstr($value, ".php" ) ! = = false) {
$randName = $baseDir . $value;
if (!is_dir(dirname($randName))) {
mkdir(dirname($randName), 0777 , true);
}
$cmd = "git show {$newVer}:$value > $randName" ;
exec ($cmd, $result);
}
}
$cmd = "/opt/gitlab/embedded/bin/semgrep -f '$ruleFile' $baseDir -o /tmp/11.txt" ;
exec ($cmd, $result);
/ / ob_clean();
$notice = file_get_contents( "/tmp/11.txt" );
echo $notice . PHP_EOL;
file_put_contents( "/tmp/11.txt" , "");
exec ( "rm -rf $baseDir" );
echo 0 ;
|
儲存並推出此鉤子檔案,接著需要給自定義鉤子目錄設定許可權,這裡我簡單粗暴的把許可權設定為777,命令如下所示
許可權設定好之後,我還需要建立一個semgrep
的掃描規則檔案,用於判斷程式碼是否正確。
執行的命令如下所示
進入vim編輯器之後,需要將如下規則內容複製進去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | rules:
- id : assert - use
patterns:
- pattern: assert ($ASSERT, ...);
- pattern - not : assert ( "..." , ...);
message: |
使用使用者輸入呼叫 assert 等價於 eval '。
metadata:
references:
- https: / / www.php.net / manual / en / function. assert
- https: / / github.com / FloeDesignTechnologies / phpcs - security - audit / blob / master / Security / Sniffs / BadFunctions / AssertsSniff.php
languages: [ php ]
severity: ERROR
- id : backticks - use
pattern: '`...`;'
message: |
使用反勾號可能導致命令注入漏洞。
metadata:
references:
- https: / / www.php.net / manual / en / language.operators.execution.php
- https: / / github.com / FloeDesignTechnologies / phpcs - security - audit / blob / master / Security / Sniffs / BadFunctions / BackticksSniff.php
languages: [ php ]
severity: ERROR
|
儲存並推出規則檔案後,需要修改此規則檔案的許可權,這裡我以777許可權距離,命令如下所示
1 | chmod 777 / semgrep - rule.yaml
|
設定完規則檔案許可權之後,還有兩個快取地方需要設定許可權,否則會在執行過程當中報錯,首先是semgrep的快取檔案,設定許可權命令如下
1 | mkdir - p / var / opt / gitlab / .cache && chmod - R 777 / var / opt / gitlab / .cache
|
另外一處是鉤子本身的快取檔案,同樣需要設定許可權,執行的命令如下所示
1 | echo '' > / tmp / 11.txt && chmod 777 / tmp / 11.txt
|
5.2 測試鉤子
現在可以正式測試鉤子的可用性,首先需要拉取剛才建立的專案程式碼,命令如下所示
1 | git clone http: / / 127.0 . 0.1 / root / test.git
|
執行命令之後,返回的資訊如下所示
在上圖中可以看到專案已經拉取下來,接下來我需要編輯一個php檔案,命令如下所示
命令執行完畢之後,將測試的程式碼存放進去
1 2 3 4 5 6 7 8 | <?php
phpinfo();
$cmd = "ls {$_GET['x']}" ;
exec ($cmd);
|
儲存並退出之後,將程式碼提交到gitlab中去,命令如下所示
1 | echo ' ' >> index.php && git add . && git commit . - m 'init' && git push
|
但git往gitlab伺服器推送之後,gitlab就會呼叫鉤子,並將鉤子返回的資訊輸出出來,如下圖所示
在上圖中可以看到鉤子提示了 index.php
檔案第8行不安全,此致整個部署完畢。
作者:湯青松
日期:2021-06-03
微信:songboy8888