A 52: HTTP Requests with Go (50 pts)

What You Need

A Linux machine with Go installed, which you prepared in a previous project.

Purpose

Learn Go HTTP Methods.

Using HEAD

The HEAD method returns headers showing information about the server.

On your Linux server, in a Terminal window, execute these commands:

mkdir -p work/src/my_project/head1
nano ~/work/src/my_project/head1/head1.go
In nano, enter this code, as shown below.
package main
import ( "net/http"; "fmt"; "io/ioutil" )

func main() {
	resp, err := http.Head("http://target1.bowneconsulting.com")
	if err != nil {
         fmt.Println("Error: ", err)
	}
	defer resp.Body.Close()

	for k, v := range resp.Header {
        fmt.Printf("%s: %s\n", k, v)
	}

	body, err := ioutil.ReadAll(resp.Body)
	fmt.Printf("\nResponse Body:\n%s\n", body)
}

Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:

go install my_project/head1
head1
The program runs, returning header fields, but no body, as shown below.

These are HTTP response headers, showing that my server is running Apache on Ubuntu.

Understanding the GET Method

We'll use the httpbin.org page, which is a diagnostic page that reflects the requests it receives back to the viewer.

On your local computer, in a Web browser, go to:

https://httpbin.org/get

The request your browser sent to the server appears, as shown below.

Notice the "User-Agent" header, which sends information about your browser to the server. I used Mozilla Firefox on a Mac--your User-Agent may be different.

Using GET in Go

The GET method fetches HTML and other files from the server.

On your Linux server, in a Terminal window, execute these commands:

mkdir -p work/src/my_project/get0
nano ~/work/src/my_project/get0/get0.go
In nano, enter this code, as shown below.
package main
import ( "net/http"; "fmt"; "io/ioutil" )

func main() {
	resp, err := http.Get("http://httpbin.org/get")
	if err != nil {
         fmt.Println("Error: ", err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	bodyString := string(body)
	fmt.Printf("Response:\n%s\n", bodyString)
}

Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:

go install my_project/get0
get0
The program runs, returning the page body, as shown below.

It shows the request Go sent to the server, with a User-Agent of "Go-http-client/1.1".

Using Go to Fetch the Target Page

On your Linux server, in a Terminal window, execute these commands:
mkdir -p work/src/my_project/get1
nano ~/work/src/my_project/get1/get1.go
In nano, enter this code, as shown below.
package main
import ( "net/http"; "fmt"; "io/ioutil" )

func main() {
	resp, err := http.Get("http://target1.bowneconsulting.com")
	if err != nil {
         fmt.Println("Error: ", err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	bodyString := string(body)
	fmt.Printf("Response:\n%s\n", bodyString)
}

Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:

go install my_project/get1
get1
The program runs, returning the page body, as shown below.

Simple GET Login

In the form below, enter these credentials and click the "LOG IN" button.

Please Log In

Username:

Password:

A new tab opens, showing the result. The username and password appear in the address bar, as shown below.

This is an unsafe but simple way to transmit credentials.

http://target1.bowneconsulting.com/php/login1.php?u=foo&p=bar
Let's make a Go script to perform this login.

On your Linux server, in a Terminal window, execute these commands:

mkdir -p work/src/my_project/get2
nano ~/work/src/my_project/get2/get2.go
In nano, enter this code, as shown below.
package main

import ( "net/http"; "fmt"; "io/ioutil" )

func main() {

	resp, err := http.Get("http://target1.bowneconsulting.com/php/login1.php?u=foo&p=bar")
	if err != nil {
         fmt.Println("Error: ", err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	bodyString := string(body)
	fmt.Printf("Response:\n%s\n", bodyString)
}

Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:

go install my_project/get2
get2
The program runs, returning the page body, including the "Login Rejected!" message, as shown below.

Password-Guessing Script for GET

Let's make a script that tries various passwords to try to log in.

On your Linux server, in a Terminal window, execute these commands:

mkdir -p work/src/my_project/get3
nano ~/work/src/my_project/get3/get3.go
In nano, enter this code, as shown below.
package main
import ( "net/http"; "fmt"; "io/ioutil" )

func main() {
	username := "dumbo"
	passwords := []string{"goofy", "mickey", "dumbo"}
	url := "http://target1.bowneconsulting.com/php/login1.php?u="

	for i, p := range passwords {
		fmt.Printf("\nGuess %d: %s\n", i, p)
		resp, err := http.Get(url + username + "&p=" + p)
		if err != nil {
			fmt.Println("Error: ", err)
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		bodyString := string(body)
		fmt.Printf("Response:\n%s\n", bodyString)
	}
}

Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:


Flag A 52.1: GET Login (10 pt)

go install my_project/get3
get3
The output includes the flag, as shown below.


Understanding the POST Method

We'll use the httpbin.org page, which is a diagnostic page that reflects the requests it receives back to the viewer.

Log in with a username of foo and a password of bar in the form below:

Please Log In

Username:

Password:

A new tab opens, showing the result.

Notice at the URL no longer includes the username or password. They are transmitted in a separate "form" section, as shown below.

Using POST in Go

On your Linux server, in a Terminal window, execute these commands:
mkdir -p work/src/my_project/post1
nano ~/work/src/my_project/post1/post1.go
In nano, enter this code, as shown below.
package main
import ( "net/http"; "fmt"; "io/ioutil"; "net/url")

func main() {
	target := "http://httpbin.org/post"
	resp, err := http.PostForm( target, url.Values{ "u": {"foo"}, "p": {"bar"} } )
	if err != nil {
         fmt.Println("Error: ", err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	bodyString := string(body)
	fmt.Printf("Response:\n%s\n", bodyString)
}

Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:

go install my_project/post1
post1
The program runs, showing the form parameters, as shown below.

Simple POST Login

In the form below, enter these credentials and click the "LOG IN" button.

Please Log In

Username:

Password:

A new tab opens, showing the result. Notice that the URL ends in login2.php, as shown below.

Password-Guessing Script for POST

Let's make a script that tries various passwords to try to log in.

On your Linux server, in a Terminal window, execute these commands:

mkdir -p work/src/my_project/post2
nano ~/work/src/my_project/post2/post2.go
In nano, enter this code, as shown below.
package main
import ( "net/http"; "fmt"; "io/ioutil"; "net/url" )

func main() {
	username := "dumbo"
	passwords := []string{"goofy", "mickey", "dumbo"}
	target := "http://target1.bowneconsulting.com/php/login2.php?u="

	for i, p := range passwords {
		fmt.Printf("\nGuess %d: %s\n", i, p)
		resp, err := http.PostForm( target, url.Values{ "u": {username}, "p": {p} } )
		if err != nil {
			fmt.Println("Error: ", err)
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		bodyString := string(body)
		fmt.Printf("Response:\n%s\n", bodyString)
	}
}
Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:


Flag A 52.2: POST Login (10 pt)

go install my_project/post2
post2
The output includes the flag, as shown below.



A 52.3: Challenge: POST Brute Force (10 pts)

Make a Go script that logs in to this page:

http://target1.bowneconsulting.com/php/login3.php

with these parameters:

The server will reply with a flag, as shown below.

Hints:


A 52.4: Challenge: Basic Authentication (10 pts)

Make a Go script that GETs this page:

http://target1.bowneconsulting.com/protected/A2.3/index.php

It's protected by Basic authenticatin, with a username of admin and a password of P@ssw0rd

The server will reply with a flag.


A 52.5: Challenge: Brute Force Basic Authentication (10 pts)

Make a Go script that logs in to this page:

http://target1.bowneconsulting.com/protected/A2.4

with these parameters:

The server will reply with a flag.


Sources

Package http
Making HTTP Requests in Golang
Difference between := and = operators in Go
5 basic for loop patterns

Posted: 11-3-19
Challenge numbers fixed 2-22-2020