Semgrep結合GitLab實現代碼審計實踐-服務端

一、背景

前段時間在做代碼審計,發現很多項目都存在安全隱患,大多數是來自於參數未過濾所造成的;爲了解決這個問題,我將Web安全開發規範手冊V1.0進行了培訓,但是效果並不是太理想,原因是培訓後開發者的關注點主要在功能完成度上,安全編碼對於他們來說並不是核心指標;

爲了能讓開發者時時刻刻關注安全問題,我在gitlab服務端放了一個鉤子,這個鉤子主要是將本次提交的代碼文件進行了檢測,遇到可能存在安全風險的問題將其輸出出來,這樣開發者能夠對培訓的內容有更深的感受,更注重編碼時候的安全問題。

二、操作步驟

  1. 搭建環境
  2. 創建項目
  3. 創建鉤子
  4. 鉤子實驗

三、搭建環境

3.1 安裝gitlab

在正式部署到服務器之前,我需要在本地搭建一個gitlab服務,用於鉤子的開發和測試,這裏我用docker搭建速度比較快,執行的命令如下

docker run --detach  --publish 443:443 --publish 80:80  --name gitlab --restart always  gitlab/gitlab-ce

命令執行之後,返回的信息如下所示

在上圖中可以看到容器已經運行成功,使用瀏覽器訪問gitlab的地址

http://127.0.0.1

訪問之後需要設置一個管理員的密碼,如下圖所示

填寫密碼之後,確認修改密碼,會跳轉到gitlab的主頁,如下圖所示

這gitlab中創建一個項目用於鉤子測試,如下圖所示

創建項目成功之後,注意留意頁面中的Project ID:2,把這個2記錄一下,後續會使用到;接下來需要開始鉤子的開發和部署,鉤子可以使用各種語言開發,這裏我比較熟悉php,因此採用php開發。

3.2 安裝依賴

gitlab的容器默認不支持php語言,需要先安裝php,安裝命令如下所示

apt update -y && apt install php -y

命令執行之後,返回的信息如下所示

在上圖中可以看到php已經安裝成功,爲了驗證php命令是否可以運行,這裏我使用如下命令進行驗證

php -v

命令執行之後,返回的信息如下所示

在上圖中可以看到php的版本是7.4.3 ,說明php已經安裝成功。

3.3 安裝semgrep

鉤子程序中需要調用semgrep,這個程序gitlab中也沒有安裝,需要安裝一下,這裏採用pip安裝,不過需要先升級pip的版本纔行,升級的命令如下所示

pip3 install --upgrade pip

命令執行之後,返回的信息如下所示

在上圖中可以看到pip的版本已經升級到21.1.2,說明升級成功了

semgrep還依賴setuptools模塊,需要用pip先升級一下,升級的命令如下所示

pip3 install --upgrade setuptools

命令執行之後,返回的信息如下所示

在上圖中可以看到setuptools模塊已經升級成功

接下來就可以正式安裝semgrep了,安裝的命令如下所示

cd /usr/local/bin/ && python3 -m pip install semgrep

命令執行之後,返回的信息如下所示

在上圖中可以看到semgrep已經安裝完成,這裏我需要再次使用semgrep命令來驗證一下,執行的命令如下所示

semgrep --version

命令執行之後,返回的信息如下所示

在上圖中可以看到semgrep的版本信息爲0.52.0,確認安裝成功了。

3.4 查看hash

現在我們需要在剛纔創建的項目中添加鉤子,這裏需要找到項目的存放路徑,在項目頁中

echo -n 2 | sha256sum

命令執行之後,返回的信息如下所示

find / -iname d4

命令執行之後,返回的信息如下所示

在上圖中可以看到項目存放的位置,返回了兩個路徑,這兩個路徑其中有一個是軟連接,通過cd命令進入進入項目的存放位置

cd /var/opt/gitlab/git-data/repositories/@hashed/d4

命令執行之後,再次執行ls命令,得到的信息如下所示

在上圖中可以看到有一個73的文件夾,這是gitlab的命名規則,進入此文件夾,命令如下所示

cd 73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git/

命令執行之後,返回的信息如下所示

在上圖中可以看到此項目的所有文件,我需要在這個位置開發鉤子文件

五、創建鉤子

自定義鉤子需要存放在custom_hooks目錄下,默認沒有此文件夾所以需要創建此文件夾,執行命令如下所示

mkdir custom_hooks  && cd custom_hooks

5.1 新建鉤子

創建custom_hooks文件夾並進入之後,使用vim創建一個鉤子文件,命令如下所示

vim  pre-receive

進入vim編輯器界面之後,將如下鉤子代碼添加進去,代碼如下所示

#!/usr/bin/php
<?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))) {
#        if (file_exists($randName) == false) {
            mkdir(dirname($randName), 0777, true);
        }
        $cmd = "git show {$newVer}:$value > $randName";

#        echo $cmd . PHP_EOL;


        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,命令如下所示

chmod -R 777 ../

權限設置好之後,我還需要創建一個semgrep的掃描規則文件,用於判斷代碼是否正確。

執行的命令如下所示

vim /semgrep-rule.yaml 

進入vim編輯器之後,需要將如下規則內容複製進去

rules:
  - id: assert-use
    patterns:
      - pattern: assert($ASSERT, ...);
      # - pattern-not: assert(<... $ASSERT ...>, ...); - https://github.com/returntocorp/semgrep/issues/2035
      - 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權限距離,命令如下所示

chmod 777 /semgrep-rule.yaml

設置完規則文件權限之後,還有兩個緩存地方需要設置權限,否則會在運行過程當中報錯,首先是semgrep的緩存文件,設置權限命令如下

mkdir -p /var/opt/gitlab/.cache  && chmod -R 777 /var/opt/gitlab/.cache

另外一處是鉤子本身的緩存文件,同樣需要設置權限,執行的命令如下所示

echo '' > /tmp/11.txt  && chmod 777 /tmp/11.txt

5.2 測試鉤子

現在可以正式測試鉤子的可用性,首先需要拉取剛纔創建的項目代碼,命令如下所示

git clone http://127.0.0.1/root/test.git

執行命令之後,返回的信息如下所示

在上圖中可以看到項目已經拉取下來,接下來我需要編輯一個php文件,命令如下所示

vim index.php

命令執行完畢之後,將測試的代碼存放進去

<?php

phpinfo();


$cmd = "ls {$_GET['x']}";

exec($cmd);

保存並退出之後,將代碼提交到gitlab中去,命令如下所示

echo ' ' >> index.php && git add . && git commit . -m 'init' && git push

但git往gitlab服務器推送之後,gitlab就會調用鉤子,並將鉤子返回的信息輸出出來,如下圖所示

在上圖中可以看到鉤子提示了 index.php文件第8行不安全,此致整個部署完畢。


作者:湯青松

日期:2021-06-03

微信:songboy8888

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章