[Lajos Gerecs:~]

% make a blog

Can not update sources.list in docker?

For unknown reasons to me when you try to run the Dockerfile containing this line, it will not work:

1
RUN echo "deb http://http.debian.net/debian jessie-backports main" >> /etc/apt/sources.list

After the machine is booted however you can insert the line succesfully. You can solve this by running the command below:

1
RUN echo "deb http://http.debian.net/debian jessie-backports main" > /etc/apt/sources.list.d/backports.list

This creates a new file in the sources.list.d and it gets picked up by apt-get update. Make sure the extension is .list.

Solving the Gitcoin Problem – Stripe CTF 3

In this problem we had to write a gitcoin miner or somehow make the bash miner better.

First I thought it would be good to use Scala/Akka to pass the Tasks around. My plan was to fill up an Actor system and let it handle the hashing using the sys.process package and some commands from the supplied bash example. For some reason it was a complete fail, the Actor got full and used up all my memory and never done anything, in the end I had to shoot this idea (and the process too :) ). (It could be configured to act as a mailbox, to block until not full but it was too much PITA in my opinion. )

After this I tried a simple parallel for and calling

1
git hash-object -t commit --stdin -w <<< commit-body

this never used more than a couple of percent CPU, I don’t know why, maybe git locks the files in the repo?

After this I got the idea to rewrite the git hash-object part in scala, and in the end it worked out.

If we visit the git objects documentation we can see that a commit contains 5 things:

1
2
3
4
5
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
parent some-hash
author Scott Chacon <schacon@gmail.com> 1243040974 -0700
committer Scott Chacon <schacon@gmail.com> 1243040974 -0700
first commit (some description)

The first value is the tree, we can obtain this with “git write-tree”. The second value is the parent of the commit, we can obtain this with “git rev-parse HEAD”. The other things in this were just placeholders and the goal was to change the last part of the commit to get a hash with git hash-object which is lower than “000001xxxxxxxxxxxxxxxx…”. This means that the hash must be lower than the string “000001″. This is difficult because the only way to obtain the correct info to get the needed hash to try as many hash as we could in the shortest time possible.

Now we know whats needed by the git hash-object function, we have to know what is the format used to calculate the hash. Turns out git prepends a “commit (body-length)\0″ string to the commit body, so thats what we have to do and we are good to go.

My code looked something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
tree = Seq("git","write-tree").!!.trim
 parent = Seq("git","rev-parse","HEAD").!!.trim
val bode = s"tree ${tree}\n" +
s"parent ${parent}\n" +
s"author CTF user <me@example.com> ${now} +0000\n" +
"""committer CTF user <me@example.com> 1390941203 +0000
Give me a Gitcoin
"""
var eq = 0
val max = 100000000
   for( i <- (0 to max).par) {
       val cbode = bode + i+"\n"
       val fullbode = "commit "+cbode.length+"\0" + cbode
       val hash = digest(fullbode).reverse.padTo(40,"0").reverse.mkString

       if (hash < difficulty){
          println("-----------------------")
          println(fullbode)
          println("-----------------------")
          val cmd = "git hash-object -t commit --stdin -w <<< \""+cbode.trim()+"\";git reset --hard \""+hash+"\" < /dev/null; git push origin master;"
          println(cmd)
          println("-----------------------")
          println("HASH: "+hash)
          println(" GITHASH: "+ commitHash(cbode))
          //System.exit(0)
      }
 }

I imported the scala.sys.process._ methods/packages to easily run commands. You can see the syntax in the first couple of rows. After assembling the body of the commit I started a parallel for to use my all my CPU cores ( 2. gen mobile core i5).

Timing my miner, hashing 100000000 commits:

1
2
../scala-2.10.3/bin/scala ../Scalaminer.scala
1344,73s user 20,31s system 355% cpu 6:23,53 total

Turns out its approximately 261 kHash/sec. I don’t know if it counts as fast, it was enough to get a winner commit.

Here is the gist of the code with the remnants of previous tries: https://gist.github.com/luos/f2c8098be3ef0e49cee9

In the end I committed by hand because there was some trouble with the endline character and sometimes it was needed at the end of the commit, sometimes not. Strange.

Java Set hülyeség

Csodálatos módon, a Java Set megvalósításban, ha az ember vizsgálni szeretné, hogy egy elem benne van-e a halmazban, akkor a contains metódus, objektet vár, ami szerintem tök hülyeség, főleg azért mert nem szól, ha véletlen mást ellenőrzök. Pl:

1
2
3
4
5
Set<ListItem> votma = new HashSet<ListItem>();
...
Node n = getNode(...)
if ( ! votma.contains(n) )
{...}

Ez simán lefordul, ami csak azért baj, mert nem vettem észre, hogy hülyeséget írtam aztán egy óráig kerestem a hibát. Másfelől viszont érthető, hisz bármilyen objektumot meg kell tudni vizsgálni, hogy benne van-e a halmazban, viszont tudható, hogy egy olyan objektum tuti nincs a halmazban, ami nem is lehet benne.

Prestashop modulok fejlesztése

Ezt emailben írtam, de azért gondolom valakinek hasznos lehet:

Egy modul írása alapvetően elég egyszerű. A prestashop biztosít úgynevezett hook-okat, melyek igazából események, és meghívódnak akkor, amikor történik valami: http://www.daveegerton.com/prestashop-guides/Prestashop-Designers-Guide/core-modules-structure/hooks.html Ezekre a hookokra fel lehet iratkozni, így a te kódod is lefut akkor, amikor az esemény megtörténik. Az új verziót annyira én se vágom, de ott már van valami trükközés a modulinstallációnál xml fájlokkal. Nagyjából ennyi a történet. Létrehozol egy mappát a modules mappában, bele egy ugyanolyan nevű phpt és classt és kész a modul. Az install metódusban feliratkozol ezekre a hookokra, majd az adminfelületen felinstallálod és bekapcsolod(!) a modult. Legegyszerűbb ezt kilesni egy már ottlévő modulból. A többi része a fejlesztésnek tiszta php, néha a prestashop Database vagy hasonló classjait felhasználva.

Ha valami új doboz vagy ilyesmi kellett az admin felületre, akkor én azt csak úgy tudtam megoldani, hogy belepiszkálok a viewba. Szerintem erre nem nagyon van más megoldás.

http://www.daveegerton.com/prestashop-guides.html

Az egész nem valami bonyolult. :) Sajna én már rég csináltam ezt, így konkrétabb linkeket nem tudok adni, még 1.3.x-hez fejlesztettem.

Hogyan számoljuk meg a táblák sorait egy MySQL adatbázisban?

Nem tudom, hogy ez a legjobb mód rá, mindenesetre, ha gyorsan kell, működik:

Először is, csináljunk egy lekérdezést:

1
2
3
4
SELECT CONCAT( ' ( SELECT "', table_name, '" as tabla , COUNT(*) as db FROM ', table_name, ') UNION ALL' )
FROM information_schema.tables
WHERE table_schema = 'ADATBAZIS_NEVE'
LIMIT 0 , 300000

Majd ha lefuttattuk, kapunk valami ilyesmit:

1
( SELECT "kutyuk_access" as tabla , COUNT(*) as db FROM kutyuk_access) UNION ALL( SELECT "kutyuk_accessory" as tabla , COUNT(*) as db FROM kutyuk_accessory) UNION ALL( SELECT "kutyuk_address" as tabla , COUNT(*) as db FROM kutyuk_address) UNION ALL( SELECT "kutyuk_alias" as tabla , COUNT(*) as db FROM kutyuk_alias) UNION ALL

A legutolsó SQL végéről töröljük le az UNION ALL-t, és hogy később tudjuk rendezni mondjuk

Hogyan nem tudtam végigvinni a Stripe CTF-et?

A Stripe CTF egy webes biztonságtechnikai verseny, ahogy már írtam róla egyik előző postomban. Nekem nagyon tetszett, még sosem játszottam ilyenen.

Eljutottam az utolsó előtti pályáig, de az teljesen kifogott rajtam.

Nézegettem a kódot, de sehogy sem sikerült rájönnöm, hogy mi a hiba. Persze arra rájöttem, hogy részben ezt a kódot kell kihasználni:

1
2
3
4
5
6
7
8
9
def parse_params(raw_params):
   pairs = raw_params.split('&')
   params = {}
   for pair in pairs:
     key, val = pair.split('=')
     key = urllib.unquote_plus(key)
     val = urllib.unquote_plus(val)
     params[key] = val
 return params

Elég nyilvánvaló volt, hogy az POST request bodyját úgy kell majd módosítani, hogy a hátul lévő paraméterek felülírják az elől lévőket, így tulajdonképpen valahogy túl kéne járni a hash ellenőrző eszén. Ezt jól is gondoltam, de ezen kívül itt el is akadtam. Fel kellett mennem az IRC-re, hogy megkérdezzem, mégis mi a halált kéne csinálnom (note: itt már kb 2 napja nézegettem a kódot). Annyit mondtak kb, hogy “the hashing has some security vulnerabilities. Nah hát ez sem sokat segített, úgyhogy rákerestem a googleban, hogy mi ennek a feladatnak a megoldása. Hát nem csodálom, hogy nem tudtam megoldani, de legalább egy olyan dolgot tanultam, amit egy átlagember nem nagyon tud, legalábbis szerintem. Érdekes, hogy egy félév kódolástechnika után semmit sem tudtam arról, hogy a valóságban hogyan működnek a hash függvények.

A hiba ebben a kódrészletben volt:

1
2
3
4
5
6
7
8
secret = str(row['secret'])

h = hashlib.sha1()
 h.update(secret + raw_params)
 print 'computed signature', h.hexdigest(), 'for body', repr(raw_params)
 if h.hexdigest() != sig:
raise BadSignature('signature does not match')
 return True

Ezt a fajta ellenőrzést, hogy biztosítsuk azt, hogy attól származik az üzenet, akinek ő mondja magát Hash-based message authenticationnak (HMAC) hívják. De “sajnos” ebben az appban ez hibásan volt implementálva Ha jól mgnézzük, akkor ezt a stringet hasheli “secret + raw_params” ahol a raw params a postolt változók és értékek & és = összefűzve, a secret meg minden felhasználónak egyedi. Azért hibás, mert a hash függvények az adat blokkjain mennek végig, az itt használt sha1 konkrétan 512 bitenként “forog” egyet. Minden forgás után vannak regiszterek, ahova az eredmény beíródik. Ha ez az utolsó forgás volt, akkor az lesz a hash függvény kimenete. Az utolsó blokkba pedig belekerül az üzenet mérete. az utolsó 8 bájtra, a maradék pedig 0 bitekkel lesz feltöltve.

Ez konkrétan azt jelenti, hogy ha mondjuk van ez a query stringünk: count=10&lat=37.351&user_id=1&long=-119.827&waffle=eggo

Ha jól számolom ez 52 karakter, ami 416 bit. Ehhez tehát még hozzájön a titkos kulcs (legyen mondjuk most 10 karakter), ahhoz pedig hozzájön még a méret az utolsó 8 bájtra, a maradék 0-kal lesz feltöltve: TITKOS_KULCS + count=10&lat=37.351&user_id=1&long=-119.827&waffle=eggo (ez eddig 62 karakter), ez már 496 bit, ide már nem fér be a 8 bájtos méret, ezért elkezdjük feltölteni a maradékot. Az sha1 algoritmus 0x80-al kezdi a feltöltést (egy egyes bittel), utána 0-k.

Tehát most van két 512 bites blokkunk, az egyik elején a query string + titkos kulcs  + 0x0 és 0-k, a másikban sok 0 és a végén a méret. Az előbb írtam, hogy blokkonként történik a feldolgozás, ami annyit jelent, hogy először feldolgozódik az első 512 bit, ez elmentődik a regiszterekbe (ha 1 blokk lenne, akkor itt lenne az eredmény), majd a második blokk feldolgozása kezdődik, aminek a végén megkapjuk a kimenetet. A lényeg az volt, hogy nekünk van egy ilyen kimenetünk, mert meg tudjuk nézni, hogy mi volt a felhasználók lekérése. Természetesen a titkos kulcsukat nem ismerjük, így nem tudtunk a helyükben üzeneteket küldözgetni. Vagyishogy tudunk:

Ha jól megnézzük, akkor abból kiindulva, hogy blokkonként történik a feldolgozás, ha hozzá tudunk fűzni a lekéréshez még paramétereket (amit tudunk), akkor beállítható a szerver hash funkcióinak regiszterei a kívánt állapotba (tehát, hogy az ismert kimeneti hash legyen a regiszterben), innentől mivel a következő blokk csak az előző blokkon múlik (amit tudunk, hisz vissza tudtuk nézni mások hasheit) és az adott blokkon, az adott blokkot mi adhatjuk meg, és nem kell tudnunk a titkos kulcsot, hogy túljuthassunk a hash ellenőrzésen.

Ehhez le kellett szednem egy sha1 c implementációt, hogy a regisztereket a kívánt kezdeti értékre állíthassam (a hashre, amit ismerek)

Így kellett volna csinálni elvileg, de nekem mégsem sikerült összehozni, hogy valid hasht generáljak. Szóval nem sikerült ezt a pályát teljesítenem. :( Lehet, hogy valamit félreértettem, meg amúgy nem gondolkoztam rajta eleget. Valószínűleg ehhez még kevés voltam most, de majd a következőn. :)

További információ:

http://www.herongyang.com/Cryptography/SHA1-Message-Digest-Algorithm-Overview.html